Commit Graph
1558 Commits
Author SHA1 Message Date
yangyaofeiandBohdan Triapitsyn ba95e13b36 feat(tts): add TTS buttons to PlanView and FilesView markdown preview with configurable input mode (#1443)
Add TTS controls to markdown preview surfaces so users can listen to plans
and markdown files directly from the preview toolbar.

Changes:
- Add read-aloud / stop buttons to PlanView markdown preview.
- Add read-aloud / stop buttons to FilesView markdown preview for markdown files.
- Respect the existing showMessageTTSButtons preference in both preview views.
- Add a persisted ttsInputMode setting with sanitized/raw modes.
- Keep sanitized mode as the default for backward compatibility.
- Allow raw markdown only for server TTS providers that can handle markdown.
- Always use sanitized text for browser and macOS say fallback paths.
- Add Voice Settings controls for TTS input mode.
- Add i18n keys for the new preview buttons and setting labels.
- Merge latest main and preserve newer FilesView toolbar/editor changes.

Validation:
- bun test packages/ui/src/stores/useConfigStore.test.ts packages/ui/src/components/chat/message/parts/ToolPart.test.ts packages/web/server/lib/tts/routes.test.js
- bun run type-check
- bun run lint
- git diff --check

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-08 19:31:21 +03:00
yangyaofeiandBohdan Triapitsyn a6bf73b245 fix(tts): allow remote custom provider URLs on desktop runtime (#1439)
* 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

* fix(tts): allow remote custom provider URLs on desktop runtime

## Problem
Custom OpenAI-compatible TTS/STT provider URLs are restricted to
localhost addresses only. Remote URLs are silently rejected at the
server boundary, making custom cloud-based TTS/STT providers unusable
in the desktop app.

## Root Cause
`base-url.js` rejects non-localhost URLs unless
`OPENCHAMBER_ALLOW_REMOTE_OPENAI_COMPAT_URLS=true` is set, but this
env var is never set by desktop shells and is not exposed in settings.

## Solution
Use the existing `OPENCHAMBER_RUNTIME` env var (already set to
`'desktop'` by both Electron and Tauri shells) to auto-allow remote
custom URLs on desktop. Web deployments retain SSRF protection by
default. The explicit env var override still works for either direction.

Closes openchamber/openchamber#1438

* fix(tts): respect explicit env var override on desktop runtime

## Problem
The previous implementation used `|| isDesktop` which unconditionally
allowed remote URLs on desktop, making `OPENCHAMBER_ALLOW_REMOTE_OPENAI_COMPAT_URLS=false`
a no-op. The PR description documented this as supported but it didn't work.

## Fix
Changed precedence logic: explicit env var (set or unset) takes absolute
priority in both directions. When no explicit flag exists, desktop runtime
defaults to allowing remote URLs. This lets operators tighten desktop
deployments with env var =false.

## Test
Added test case: desktop + env var =false → remote URLs denied (8 pass, 0 fail).

Addresses PR review: P1 (env var precedence) and P2 (missing deny test).

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-08 19:15:54 +03:00
ChampiiandBohdan Triapitsyn f45fe05f33 feat: add file editor vim mode (#1437)
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-08 19:10:32 +03:00
nerdosaurusandBohdan Triapitsyn d9b9b56599 Diagram editor pr (#1432)
* feat: add draw.io diagram editor integration

Embed draw.io editor via react-drawio (MIT, zero deps) for inline
editing of .drawio files. Changes auto-save to disk. Includes
inline editor in FilesView with Visual/Source toggle, dark mode
support, template picker for new files, and chat file attachment
integration.

* fix: debounce diagram autosave to prevent reload loop

* fix: ignore watcher-triggered xml prop changes to prevent reload loop

* fix: remove auto-save-to-disk, add manual save button for diagrams

Autosave writes triggered file watcher cascade that reloaded the
draw.io iframe and reset zoom. Replaced with explicit Save button
in the toolbar (floppy disk icon). Editor XML is stable on mount
and ignores watcher-triggered prop changes.

* fix: remove auto-save write from DiagramView, add save button

* fix: hide draw.io save/exit buttons in editor

* fix: also hide save-and-exit button

* fix: brighten save button styling, add saved confirmation

* fix: remove autoSaveStatus toggle on diagram save to prevent toolbar collapse

* fix: add local save confirmation state for diagram button

* fix: remount drawio iframe on theme change, persisting XML across mounts

* fix: clear persisted xml on mount to prevent leaking between files

* fix: initialize dark mode synchronously, preserve edits across theme remount

* fix: auto-focus drawio iframe on mount/theme-change for keyboard shortcuts

* fix: add diagram i18n keys to Traditional Chinese locale

* fix: restore upstream HMR host and LAN address support

* fix: load sub-agent sessions on bootstrap for sidebar visibility

Two-phase session load: first fetch root sessions (for accurate
sessionTotal), then fetch all sessions and include child sessions
(sub-agent delegations). This ensures sub-agent sessions appear
in the sidebar immediately instead of relying on the async global
session store.

* remove opencode-drawio from PR branch

* fix: atomic file writes to prevent concurrent read/write truncation

Three-layer defense against the O_TRUNC race:

1. Write side (server): replace direct writeFile with write-to-temp-
   then-rename. fs.rename is atomic on POSIX.

2. Read side (server): retry up to 3 times with 50ms backoff when
   readFile returns empty but stat reported non-zero size.

3. FilesView client: refuse to save empty draftContent when the
   original fileContent was non-empty.

* fix(dev): clean up orphaned OpenCode processes on Ctrl+C

* fix: allow empty file saves, log warning instead of blocking

Replaces the hard block on saving empty content with a console.warn.
The atomic write + read retry on the server side handle the O_TRUNC
race properly. The previous guard caused a UX regression by silently
preventing users from clearing a file and saving.

* fix: remove time window from sub-agent fallback for live tasks

While a task tool is active, the fallback now matches any session
with the correct parentID regardless of creation time. This allows
late-appearing child sessions to be found when the OpenCode server
is slow or the SSE event pipeline is delayed. The time window is
still applied once the task tool has completed, as a final sanity
check.

* fix: three diagram editor bugs from Greptile review

1. stableXmlRef now resets when xml prop changes — switching
   between .drawio files renders the correct content.

2. Focus effect only runs on mount, not on isDark changes —
   theme toggle no longer steals keyboard focus 600ms later.

3. saveDiagram updates xml state after writing — dirty-check
   guard works correctly for subsequent saves.

* fix: route session.created SSE events to correct directory

Three-layer fix for sub-agent sessions not appearing in sidebar and
inline chat:

1. protocol.js: parseSseEventEnvelope now extracts directory from
   properties.info.directory (where session.created/updated events
   carry it) in addition to properties.directory. WS frames relayed
   to the browser now carry the real directory instead of 'global',
   so child sessions routed to the correct directory store.

2. event-pipeline.ts: same fallback in resolveEventDirectory for
   defense-in-depth when SSE events bypass the WS relay.

3. resolveFallbackTaskSessionId.ts: time window lower bound now
   allows 2s grace before taskStartTime to accommodate server timing
   jitter (child session creation timestamps consistently precede the
   tool's recorded start by ~6-9ms), fixing the 'Open subtask'
   button not rendering in OpenChamber's inline chat.

* fix: sub-agent sidebar visibility, file zeroing guard, inline badge fallback

- Sync watchdog: periodic child session discovery poll (every 15s) detects
  sessions created by other OpenCode instances, triggers parent materialization
- protocol.js: parseSseEventEnvelope extracts directory from
  properties.info.directory for session.created/updated events
- event-pipeline.ts: same fallback in resolveEventDirectory for defense-in-depth
- resolveFallbackTaskSessionId: don't require taskStartTime (cross-OpenCode);
  pick most recent child when multiple idle candidates exist
- readTaskSessionIdFromOutput: parse <task id="ses_xxx"> format from output
- FilesView: reinstate empty-draft guard (block save when draftContent='' but
  fileContent had content) to prevent file zeroing on tab switch

* Fix diagram autosave reload loop

* Highlight drawio files as XML

* Use diff-compatible highlighting for drawio files

* Restore drawio file icon mapping

* Stabilize drawio source preview toggle

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-08 18:50:56 +03:00
9b52222ef1 Add folder-level revert action in Git changes tree (#1390)
* feat: add folder-level revert for git changes

* Fix bot comments. Fix confirmation dialog for mobile view.

* fix

---------

Co-authored-by: Konstantin Zolin <zolin_ka@vk.com>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-08 15:55:56 +03:00
Tom RochetteandBohdan Triapitsyn 7b1b3167a4 feat: server-side GitHub search for issue/PR pickers (#1352)
Replace local-only filtering in GitHub issue/PR picker dialogs with
server-side GitHub Search API queries. Search text is sent as a query
parameter to the server, which uses the GitHub Search API
(issuesAndPullRequests endpoint) with repo: qualifiers including fork
network support. Results are debounced at 350ms to respect API rate
limits.

- Add query parameter to GitHubAPI issuesList/prsList interface
- Server routes use Search API when query is present, standard list
  endpoint when absent
- Fork networks handled via repo:owner/repo OR repo:owner/upstream
- PR search fetches full PR details after Search API for head/base/draft
  fields
- Remove local filter memos from all three picker dialogs
- Add debounced search effect with abort controller cleanup
- Update VS Code backend and webview API for parity
- Update search placeholders in all locales

Closes #1350

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-08 15:37:42 +03:00
JakeandBohdan Triapitsyn 5589ca991a feat(vscode): add archive all sessions action (#1262)
* feat(vscode): add archive all sessions action

* Update packages/ui/src/components/layout/VSCodeLayout.tsx

Signed-off-by: Jake <101855602+jjdubski@users.noreply.github.com>

* fix: Fail-open default archives all sessions when workspace can't be resolved

* fix: Already-archived descendants are included in the archive call

* fix: add i18n for the newly added toasts

* Restore icon name from 'add-line' to 'add'

Signed-off-by: Jake <101855602+jjdubski@users.noreply.github.com>

* update: fix merge conflict and update code structure into components

---------

Signed-off-by: Jake <101855602+jjdubski@users.noreply.github.com>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-08 15:11:05 +03:00
Bohdan Triapitsyn bba4b02dca fix: refresh provider cache from live config
OpenChamber could show stale providers in Settings after users changed opencode.json because provider lists were restored from the persisted config-store cache. OpenCode itself was already correct, but the UI could keep showing old providers across app or machine restarts.

Stop persisting provider lists/defaults, strip old persisted provider snapshots during hydration, and invalidate provider cache before startup/config reload fetches. Provider config changes now refresh all known project directories immediately with capped concurrency, so switching projects later uses fresh cached data instead of triggering a refetch on navigation.

Also validate the selected provider/model after every provider reload, fall back to a live valid model when the old one was removed, and preserve a still-valid current model variant. Add regression coverage for hydration stripping, multi-directory provider refresh, and variant preservation.
2026-06-08 14:54:02 +03:00
Bohdan Triapitsyn ef71a997a8 fix: save agent prompt and reload changes reliably
Agent settings now correctly save an emptied system prompt instead of silently keeping the old text.

After saving agent, command, or skill settings, OpenChamber refreshes the updated configuration instead of showing stale values from a short-lived cache.

Reload actions now surface refresh failures consistently while avoiding noisy background errors.
2026-06-08 13:43:45 +03:00
Bohdan Triapitsyn b2b71198ca fix: persist agent permission edits
Prevents permission changes from being overwritten by other agent fields
Writes built-in and custom agent permissions to the correct config source
Refreshes agent state after permission saves
2026-06-08 00:12:53 +03:00
Bohdan Triapitsyn 14e75359a5 fix: forward Inertia headers through preview proxy
Preserves Inertia navigation inside preview panel
Forwards request and response Inertia headers
Adds preview proxy header passthrough tests
2026-06-07 09:53:39 +03:00
Bohdan Triapitsyn 3b4d4e7caa fix: replace placeholder localization text
Fixed placeholder text in Git view toasts and dialogs
Updated Polish Git view translations
Cleaned up a settings label fallback
2026-06-07 09:19:46 +03:00
Bohdan Triapitsyn 26eb89e0ce fix: refresh session share state after unsharing
Updates live session state after share and unshare actions
Preserves session directory metadata while applying share changes
Adds regression coverage for unshare and sanitized share responses
2026-06-07 09:09:51 +03:00
Bohdan Triapitsyn 78c851f7cd feat: open isolated multirun sessions before setup completes
Open isolated Multi-Run sessions while worktree setup continues in the background
Apply the faster flow to VS Code Agent Manager isolated runs
Document the new Multi-Run and Agent Manager behavior
2026-06-07 02:05:10 +03:00
Bohdan Triapitsyn 3db5a3cc0b perf: avoid per-message review metadata checks
Compute review transfer state once per chat render
Hide transfer actions when linked review sessions are inactive
Remove session-list scans from individual message rows
2026-06-07 01:47:59 +03:00
Bohdan Triapitsyn 2e77376ca0 fix: clean up review metadata when archiving sessions
Treat archived sessions like deleted sessions for review metadata cleanup
Preserve linked review session state consistency
2026-06-07 01:28:02 +03:00
Bohdan Triapitsyn 1f9769a932 feat: add session review handoff flow
Introduce a desktop/web-only /handoff-review flow that generates a handoff from the active implementation session, creates or reuses a separate review session in the same directory, and links the pair through hidden OpenChamber session metadata.

Add review flow orchestration, metadata helpers, magic prompts, localized command/action labels, session metadata create/update support, and assistant message transfer actions for sending reviewer feedback back to the implementer or implementation responses back to the reviewer.

Review sessions are ordinary sessions, not child sessions. The flow avoids exposing session IDs or routing metadata to agents, hides review controls on mobile and VS Code, hides unrelated assistant actions inside review sessions, cleans up stale metadata where possible, and uses the optimistic send path so cross-session sends scroll like normal composer messages.
2026-06-07 01:22:40 +03:00
Bohdan Triapitsyn e0113c637d feat: support fast worktree-backed session flows
Add a directory-created fast path for worktree creation so session and send flows can continue once the target directory exists while Git attachment and bootstrap finish in the background.

Track bootstrap status explicitly in shared UI contracts, including pending, ready, and failed states. Background watchers now surface failures and timeouts, update stored worktree metadata, and keep web and VS Code runtime behavior in parity.

Move GitHub issue/PR worktree sessions and assistant-answer fork sessions onto the unified send path so provider, model, agent, and variant selections are preserved. The assistant-answer fork dialog can optionally create a worktree outside VS Code.

Make worktree deletion dialogs close after linked-session cleanup while removing the worktree in the background, and clean up failed fast-create artifacts safely without recursively deleting user or agent-written files.

Validation: bun test packages/ui/src/lib/worktrees/worktreeBootstrap.test.ts packages/ui/src/lib/worktrees/worktreeManager.test.ts; bun run type-check; bun run lint.
2026-06-06 23:25:39 +03:00
Tom Rochette d4ef1fd8c0 Setup stale issue/pr cleanup workflow (#1546) 2026-06-06 10:58:06 +03:00
Bohdan Triapitsyn 1ad3d553c7 chore: updated main screenshot in readme 2026-06-06 00:01:02 +03:00
Bohdan Triapitsyn 45bad4c12b docs: update desktop platform docs
Document macOS and Windows desktop support
Add Electron desktop development README
Refresh contributing scripts and platform notes
2026-06-05 23:58:43 +03:00
Bohdan Triapitsyn 48b0a4f292 fix: preserve chat folder assignments on reload
Prevents folder cleanup before sessions finish loading
Keeps saved chat folder memberships after desktop reload
2026-06-05 20:58:54 +03:00
Bohdan Triapitsyn 3bfb7ba6aa release v1.12.3 2026-06-05 20:42:29 +03:00
Bohdan Triapitsyn 341a4ac296 fix: drop WSL OpenCode binary support on Windows 2026-06-05 20:35:53 +03:00
Bohdan Triapitsyn 4548477b14 fix: detect WSL OpenCode installs on Windows
Finds OpenCode in common WSL install paths
Avoids picking Windows shims from WSL PATH
Adds coverage for WSL detection
2026-06-05 19:09:42 +03:00
Bohdan Triapitsyn de0ebbac8b fix: make file tree loading more reliable
Avoid gitignore filtering during folder browsing
Show folder load errors instead of empty folders
Add timeout fallback for gitignore checks
2026-06-05 18:58:50 +03:00
Bohdan Triapitsyn 3e0a105dfe fix: restore OpenCode health compatibility for startup (#1542) 2026-06-05 18:43:13 +03:00
Bohdan Triapitsyn 0f6602aabd docs: add SSH hosts and proxying guide
Adds desktop SSH hosts and proxying documentation
Includes translations for all supported locales
Requires translations for new docs pages
2026-06-05 18:38:39 +03:00
Bohdan Triapitsyn a5628b20df release v1.12.2 2026-06-05 15:32:13 +03:00
Bohdan Triapitsyn e192359da9 fix: improve startup readiness performance 2026-06-05 15:09:24 +03:00
Bohdan Triapitsyn 0b881fec8e docs: update validation guidance
Mention longer validation timeouts for slower machines
2026-06-05 15:03:39 +03:00
Bohdan Triapitsyn 16fdff530b fix: improve Windows tunnel support 2026-06-05 15:01:22 +03:00
Bohdan Triapitsyn e823497cf1 feat: add Windows-specific app icon
Replace the macOS-derived icon.ico with a Windows-tailored design:
isometric cube filling the canvas edge-to-edge on a transparent
background, solid-gray faces, and a black hexagon outline framing
the silhouette. Add icon-win.svg as the source for regeneration.
2026-06-05 13:58:45 +03:00
Bohdan Triapitsyn f1675d27da fix: improve desktop resize responsiveness 2026-06-05 13:36:39 +03:00
Bohdan Triapitsyn 4e1560a10e fix: improve auto-accept and Windows opencode upgrades 2026-06-05 13:36:39 +03:00
Tom Rochette ebc2168ceb Create and push branches in reproduce-issue and update reproduction labels (#1541) 2026-06-05 09:57:14 +03:00
Bohdan Triapitsyn f40be80c4b fix: default project directory selection to not show hidden files
Show hidden starts disabled when opening Add project directory
Keeps the setting local to the dialog
2026-06-04 18:49:37 +03:00
Bohdan Triapitsyn 6db08251ff fix: support Windows file paths in editor opens 2026-06-04 18:47:33 +03:00
Bohdan Triapitsyn 3214b79854 fix: integrate mini chat window controls on Windows 2026-06-04 18:43:07 +03:00
Bohdan Triapitsyn 697dc7a041 fix: improve Windows open-in app support
Load native Windows app icons for open-in menu
Open Explorer and Terminal to the selected project directory
Resolve Windows Terminal icon from installed app assets
2026-06-04 18:11:51 +03:00
Bohdan Triapitsyn e26f87a57c fix(vscode): improve opencode binary detection 2026-06-04 14:59:33 +03:00
Bohdan Triapitsyn 83d8ca3c74 fix(vscode): enhance Windows executable detection in opencode path resolution 2026-06-04 14:13:14 +03:00
Bohdan Triapitsyn e9d7f913d9 fix: route new prompt sync to target directory
Keeps optimistic prompt state in the session directory
Routes live assistant part updates using upstream event payloads
Adds regressions for startup session switch races
2026-06-04 13:32:16 +03:00
Bohdan Triapitsyn 5d7b5c89f2 ci: add automated opencode PR review workflow
Adds safe PR review automation for pull requests and /oc-review comments
Supports fork PR review without checking out or executing untrusted code
Defines a dedicated read-only PR review agent
2026-06-04 03:50:05 +03:00
Bohdan Triapitsyn 6466708078 release v1.12.1 2026-06-03 23:30:11 +03:00
Bohdan Triapitsyn e65739d900 fix: prevent double-Esc abort while dropdowns are open
Keeps Escape focused on closing active dropdowns first
Avoids accidental session aborts from menu interactions
2026-06-03 23:29:52 +03:00
Bohdan Triapitsyn 84df7fa24f fix: show time format setting in vscode 2026-06-03 23:10:58 +03:00
Bohdan Triapitsyn 04c9aa57dd fix: show streaming chat messages after startup
Read chat state from the active session directory
Align status rows with the active session
2026-06-03 22:38:15 +03:00
Bohdan Triapitsyn 04b1425c2e feat: show changed files after completed turns
Add changed-file pills with per-file diff stats
Add a chat setting to disable the feature fully
Avoid changed-file projection work when disabled
2026-06-03 22:11:37 +03:00
Bohdan Triapitsyn 9087950f1a fix: preserve message summary updates
Keep user message diff summaries from being skipped
Preserve late message updates for tokens, errors, and structured output
2026-06-03 18:49:27 +03:00