Commit Graph
1954 Commits
Author SHA1 Message Date
Bohdan Triapitsyn 1c281df3b7 Move changes toggle before mini chat 2026-06-14 01:48:59 +03:00
Bohdan Triapitsyn 93bc5b2858 Move changes toggle before mini chat 2026-06-14 01:45:29 +03:00
Bohdan Triapitsyn 8174ede976 Improve Changes diff experience 2026-06-14 01:39:49 +03:00
Bohdan Triapitsyn 2538a08370 Fix git worktree root normalization 2026-06-14 01:07:11 +03:00
Bohdan Triapitsyn fa128afdb5 Refine changes panel controls 2026-06-14 00:51:12 +03:00
Bohdan Triapitsyn 8b318d2776 Polish diff view hunk controls 2026-06-14 00:03:02 +03:00
Bohdan Triapitsyn 876738229f Improve diff rendering pipeline 2026-06-13 23:55:50 +03:00
Bohdan Triapitsyn cf8eac966e Refine stacked diff view 2026-06-13 22:30:03 +03:00
Bohdan Triapitsyn 676f0b3898 Add message role counts to memory debug panel 2026-06-13 16:40:29 +03:00
Tom Rochette 560e24cbc2 fix: prevent worktree modal from disappearing after opening (#1585)
The worktree dialog state was local React state in SessionSidebar,
which gets destroyed when the component unmounts (mobile drawer close,
VSCode view switch). This caused the modal to briefly appear then
disappear.

Three changes:
- Move newWorktreeDialogOpen from local state to useUIStore so it
  survives component unmount
- Guard useProjectSessionSelection layout effect to skip when the
  worktree dialog is open (prevents auto-session-selection from
  closing the sidebar)
- Remove setSessionSwitcherOpen(false) from worktree button handler
  on mobile (prevents drawer close that unmounts the sidebar)

Fixes #1414
2026-06-13 08:55:17 +03:00
Tom RochetteandReproduction Bot e74ce993d5 fix: auto-fetch branches when opening create worktree dialog (#1572)
* repro: add test reproducing issue #1564 - empty branch list in create worktree dialog

The NewWorktreeDialog does not auto-fetch branches when it opens
if branches haven't been cached yet. Branches only get populated
if the Git tab has been opened or a draft session has been started,
both of which call fetchBranches/fetchAll independently.

The test demonstrates:
1. Branches are null (empty list) for directories not yet fetched
2. Branches are available after fetchBranches is called
3. The ChatInput's draft session branch fetch explains why the
   issue says 'list gets populated after starting a draft session'
4. The missing auto-fetch call when dialog opens

* fix: auto-fetch branches when opening create worktree dialog

---------

Co-authored-by: Reproduction Bot <repro-bot@openchamber.dev>
2026-06-13 08:50:11 +03:00
Bohdan Triapitsyn b8dc25c7c8 fix: show about settings only on mobile
Hides About from desktop settings navigation and command palette
Keeps About available in mobile settings
2026-06-13 01:59:33 +03:00
Bohdan Triapitsyn ca87428216 fix: harden file previews and downloads 2026-06-13 01:44:03 +03:00
Bohdan Triapitsyn 823cefd4b5 fix: preserve inline comment drafts on focus changes
Keeps typed or pasted comment text when the editor remounts
Prevents focus changes from dismissing active inline comments
Allows cancelling by pressing the selected line number again
2026-06-13 00:48:42 +03:00
Nicolas Charpentier 20db4cbb27 chore: pin GitHub Actions to SHAs (#1625) 2026-06-13 00:44:12 +03:00
HearingSmileandBohdan Triapitsyn 3bbd42587e fix: stabilize question custom textarea resizing (#1614)
* fix: stabilize question custom textarea resizing

* fix: preserve custom question answer state

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-13 00:28:42 +03:00
Roberto BertóandBohdan Triapitsyn 8fbaa5df9c feat: show previews in context messages breakdown. (#1563)
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-13 00:17:36 +03:00
Roberto BertóandBohdan Triapitsyn 15813b61c3 feat: add opt-in docked editor toolbar (#1562)
* feat: add opt-in docked editor toolbar

* fix: align docked editor toolbar actions

* fix: move docked toolbar setting to navigation

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-13 00:01:07 +03:00
Bohdan Triapitsyn 1235e4db71 fix: restore ArrowUp caret movement and clean up virtual list lints
ArrowUp in chat input now moves caret instead of recalling history when the field has text
Removed manual cache-busting workaround and eslint-disable in favor of idiomatic onChange state sync
2026-06-12 23:40:08 +03:00
Bohdan Triapitsyn 563a4cf9b7 fix: preserve code block file reference locations 2026-06-12 23:20:43 +03:00
Roberto Bertó f71deeb04a feat: linkify file paths inside fenced code blocks (#1560)
Extends existing file-reference detection (currently only inline code and
anchor tags) to also wrap path-like tokens inside <pre><code> blocks,
making shell-output paths like 'src/foo.ts:42' clickable just like
inline ones.

Implementation in MarkdownRendererImpl.tsx:
- New regex BLOCK_PATH_TOKEN_RE matches paths with mandatory extension
  and optional :line[:col] suffix.
- New helper wrapBlockCodePathTokens() walks text nodes in each
  rendered <pre><code>, wraps matches in
  <span data-openchamber-block-path-token="true">, and marks the
  block as scanned (data-openchamber-block-paths-scanned) to avoid
  re-walking.
- annotateFileLinks() invokes the wrapper and extends its selector
  to include the new tokens; the rest of the pipeline (stat check,
  click handler) is reused unchanged.
- Code blocks longer than 200KB are skipped to keep large outputs
  (git log, build logs) cheap.
2026-06-12 23:17:48 +03:00
Paolo InsognaandBohdan Triapitsyn b1810013e5 feat: Add delete session in the sessions menu. (#1557)
Signed-off-by: Paolo Insogna <paolo@cowtech.it>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-12 23:13:41 +03:00
Tom a0597b1065 fix: prevent cascade rollback from restoring deleted session descendants (#1555)
The OpenCode server cascade-deletes all child sessions when a parent
is removed. The client was sending individual DELETE requests for each
descendant, which returned 404 after the parent's cascade removed them.
The 404 triggered rollback in deleteSessionAction, restoring already-
deleted sessions back into the global store.

Changes:
- executeDeleteSession: only send the root session delete; the server
  cascade handles descendants.
- deleteSession / deleteSessionInDirectory: treat 404 in catch as
  success, acting as a safety net for remaining paths (e.g. sidebar
  bulk action bar when parent and child are both selected).
2026-06-12 22:54:39 +03:00
Bohdan Triapitsyn 201c7014d7 chore: updated macOS app icon with new glass effect
Updated generated macOS icon asset catalog
Includes latest AppIcon source metadata
2026-06-12 20:34:48 +03:00
Tom db3558f906 fix: prevent blank chat viewport when switching sessions (#1553)
When switching to a session with long context (especially in Electron
desktop when changing servers), the chat viewport could render blank
until the user scrolled. Two interacting issues caused this:

1. historyVirtualRows memo never recomputed after the first render
   because historyVirtualizer (from useVirtualizer's useState) is a
   stable reference. Frozen range meant items rendered at the top
   while paddingBottom filled the visible viewport after scrolling.

2. pendingInitialRestoreRef replay ran in useEffect (after paint),
   showing a frame at scrollTop:0 with the stale virtualizer range.

Fixed by: adding a virtualVersion counter driven by useVirtualizer's
onChange to bust the memo; switching the replay to useLayoutEffect
so scroll position is set before the browser paints.
2026-06-12 20:31:32 +03:00
Tom 85d4e2d319 fix: use effectiveDirectory in ToolPart to fix empty ContextPanel iframe for sub-tasks (#1552)
Replace useDirectoryStore.currentDirectory with useEffectiveDirectory() in
both TaskToolSummary and ToolPartContent to align the directory key used for
ContextPanel tab storage/lookup. Previously ToolPart used the global project
root while ContextPanel resolved session/worktree-scoped directories via
useEffectiveDirectory(), causing a key mismatch that left the iframe blank
when opening sub-tasks from chat messages.
2026-06-12 20:22:13 +03:00
Quat3rnion 5a2781f970 fix: stop tab-complete from also swapping the selected agent (#1544)
Skill/snippet/command/file-mention autocomplete branches in ChatInput
called preventDefault()+return but not stopPropagation(). The Tab key
bubbled to the global window keydown listener in useKeyboardShortcuts,
whose cycle_agent shortcut (default 'tab') then ran setAgent().

Add e.stopPropagation() to all four autocomplete branches so the
synthetic event no longer reaches the window-level handler when an
autocomplete consumes the key.
2026-06-12 20:13:36 +03:00
Bohdan Triapitsyn 1a623f9b1c Add inline PDF file preview 2026-06-12 20:08:19 +03:00
Bohdan Triapitsyn 33522a0d58 fix: clamp collapsed markdown user messages
Keep markdown user messages limited to two lines when collapsed
Preserve full markdown rendering after expanding
2026-06-12 19:45:16 +03:00
Bohdan Triapitsyn 5272b95be7 fix: extend session row selection highlight to cover gutter area
Selection highlight now visually wraps status indicators and chevrons
Active session gets a subtle primary background tint
Multi-select rows use the interactive-selection token
2026-06-12 19:32:40 +03:00
Bohdan Triapitsyn 6cc3a93547 chore: update unreleased changelog 2026-06-12 18:54:35 +03:00
Bohdan Triapitsyn 782bc92b15 Forget unmanaged orphan worktrees safely 2026-06-12 18:36:06 +03:00
Bohdan Triapitsyn ea3bb103eb Restrict orphan worktree cleanup 2026-06-12 18:33:22 +03:00
Bohdan Triapitsyn 106b31a407 Harden remote API security boundaries 2026-06-12 18:24:07 +03:00
Bohdan Triapitsyn c281937406 refactor(recent): replace active-now tracking with recent session window
Replace persisted 'active now' tracking with 48-hour recency window
Remove Zustand ActiveNowStore and localStorage persistence
Simplify session sidebar data flow
2026-06-12 14:34:33 +03:00
Bohdan Triapitsyn 28aeb4950b refactor: simplify session list display
Makes minimal session rows the default
Removes session diff stat badges from navigation surfaces
Keeps expanded session rows in VS Code
2026-06-12 12:38:31 +03:00
Bohdan Triapitsyn c703db2745 fix: stop forwarding client auth to OpenCode and harden home/session state
Packaged desktop showed no sessions in 1.12.4. Root cause: the sanitized
session-list proxy path added in #1538 forwarded the renderer's
"authorization" header (the OpenChamber UI client token) to the managed
OpenCode upstream alongside the managed "Authorization" credential.
OpenCode does not recognize UI client tokens, so every session-list
request answered 401 — only in the packaged app, because only its
renderer (openchamber-ui:// origin) attaches a bearer token; dev web and
dev Electron run same-origin without one. The legacy http-proxy path
overwrote the header correctly, which is why everything except session
lists kept working.

Proxy fix:
- proxy-headers: filter the client "authorization" header out of
  forwarded request headers; the OpenCode upstream must only ever see
  its own managed credentials. Covered by tests.

Desktop cwd:
- electron: launch the managed OpenCode CLI from the user home instead
  of app userData, matching upstream desktop behavior. userData-as-cwd
  made OpenCode treat the app-data folder as a separate empty workspace.

Home directory poisoning loop:
- directoryPersistence: stop replaying localStorage homeDirectory
  through synchronizeHomeDirectory on boot/auth resync. The persisted
  value is only a boot-time cache; replaying it re-wrote stale values
  (e.g. a project path) into desktop settings on every start, overriding
  the authoritative /api/fs/home resolution.
- persistence: never overwrite an injected window.__OPENCHAMBER_HOME__
  with a persisted value.
- useDirectoryStore: host switches happen in place (no reload), so
  re-resolve home from the new runtime's /api/fs/home on endpoint
  change instead of keeping the previous host's value.
- opencode client: only short-circuit to the injected desktop home when
  the active runtime is local; remote runtimes ask /api/fs/home.

Settings hygiene:
- persistSettings: log field names only — change payloads can carry
  credentials (UI password, client tokens, tunnel tokens) that must not
  reach the log file; drop step-by-step log chatter.
- validateProjectEntries: only stat project paths when the incoming
  update actually touches the projects list, not on every settings save.
- remove the write-only approvedDirectories setting everywhere and add
  a migration that strips the stale key from persisted settings.

Tests:
- usePluginsStore.test: register an own runtime-fetch module mock so the
  suite is independent of process-global mock.module leakage from other
  files, and restore globalThis.fetch after the suite.
- persistence.test: clean up the window global created for the suite.
2026-06-12 01:53:38 +03:00
Hristo KaramanlievandBohdan Triapitsyn 9685630436 fix: lighten session list payloads (#1538)
* lighten session list

* fetch full session on open

* sanitize session list

* sanitize global sessions

* preserve revert markers in session lists

* fix: preserve session metadata in list sanitizers

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-11 23:06:19 +03:00
youzini 1c274d0a56 fix(docker): stabilize workspace dependency install (#1533)
* fix(docker): pin bun image

* fix(docker): copy electron workspace manifest

* fix(docker): remove stale desktop manifest copy
2026-06-11 22:00:28 +03:00
youzini abda2bc42b fix(mcp): import opencode mcp config snippets (#1532) 2026-06-11 21:55:38 +03:00
lilyzhaunandlilyzhaun c9cd25d18f fix(ui): keep a close control in empty mobile changes states (#1525)
The newer mobile Changes surface returns early for non-interactive list states (no directory selected, repository status still loading, or current directory is not a Git repository). Those branches rendered only MobileChangesState and skipped the standard header row entirely.

On Android PWA this leaves the sheet with no visible close/back affordance. Because the surface is hosted inside MobileSurfaceShell as a modal sheet, the browser/system back gesture does not reliably dismiss it, so users were forced to tap sparse overlay whitespace to escape.

Fix the regression by wrapping those early-return states in the same top header used by the normal Changes list, including the close button and current path label. This keeps dismissal available even when the new mobile UI is showing an empty/error state. While touching the file, switch the remaining direct @remixicon/react usages in this component to the shared Icon system to match current UI conventions.

Validated with packages/ui type-check and a packages/web build.

Co-authored-by: lilyzhaun <lilyzhaun@users.noreply.github.com>
2026-06-11 21:51:01 +03:00
raz123andBohdan Triapitsyn e20cfa2dbc feat(ui): add cache hit rate to context sidebar last-message token breakdown (#1524)
* feat(ui): add cache hit rate to context sidebar with verified formula

Add a Cache Hit row to the last-assistant-message token breakdown in
the context sidebar. The percentage is computed by the new
computeCacheHitRate utility:

  cache.read / (input + cache.read + cache.write) x 100

The formula was verified against the SDK source
(packages/opencode/src/session/session.ts:getUsage), which reports
input as the non-cached portion only
(totalInputTokens - cacheReadInputTokens - cacheWriteInputTokens).

Also export sumTokenBreakdown from tokenUtils for reuse, and fix the
event-reducer test type errors (setDelta/getText helpers, toBeCloseTo
replacement).

Closes: #

* fix: wire i18n key for Cache Hit label, fix formatNumber type, drop unintended event-reducer changes

* chore: remove unused cacheHitRate and cacheHitRateTooltip i18n keys from en.ts

* fix: correct cache hit token display

* fix: add French cache hit label

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-11 21:43:41 +03:00
284d72bef2 Keep notification SSE stream alive behind proxies (#1516)
* fix: keep notification SSE stream alive

* Fix PR comments

* fix: cover notification stream error cleanup

---------

Co-authored-by: Konstantin Zolin <zolin_ka@vk.com>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-11 19:48:06 +03:00
Bohdan Triapitsyn f26950fa4e fix: treat gh CLI token as GitHub account 2026-06-11 19:30:19 +03:00
Bohdan Triapitsyn 465732858f fix: clarify GitHub token settings 2026-06-11 18:59:58 +03:00
Bohdan Triapitsyn 6ca99a3d5e fix: add French gh CLI settings translations 2026-06-11 18:46:31 +03:00
Tom Rochette 33e614c76b Fallback to gh CLI credentials if available (#1515)
Adds `gh` CLI as a GitHub credential fallback for users who already have
`gh auth login` configured locally. OpenChamber-owned OAuth credentials
remain the primary source of truth; the `gh` token is only used when no
stored OpenChamber GitHub access token exists and the fallback is not
disabled.

The fallback is implemented as a credential provider only: GitHub features
continue to use the existing Octokit/GitHub API paths for issues, pull
requests, checks, merges, and related operations. The PR does not replace
those endpoints with `gh issue` or `gh pr` CLI commands.

Server changes:
- Add `gh-cli-credential.js` to read `gh auth token` with a bounded timeout.
- Cache the `gh` token lookup for 30 seconds, including negative results,
  to avoid repeated subprocess spawning on status/polling paths.
- Hide the subprocess window on Windows via `windowsHide: true`.
- Clear the gh CLI token cache when the fallback setting changes.
- Update `getOctokitOrNull()` to prefer stored OpenChamber OAuth tokens and
  fall back to the `gh` token only when enabled.
- Add `ghCliDisabled` persistence in the existing settings file with atomic
  writes and `0o600` file permissions.
- Add `POST /api/github/auth/gh-cli` to enable or disable the fallback.
- Extend `/api/github/auth/status` with `ghCli` metadata: availability,
  disabled state, active state, and active user when applicable.

UI/runtime changes:
- Extend `GitHubAuthStatus` and `GitHubAPI` with gh CLI fallback metadata
  and toggle support.
- Add web RuntimeAPI support for toggling the gh CLI fallback through
  `runtimeFetch`, preserving active runtime/remote target behavior.
- Add deterministic VS Code unsupported handling for the gh CLI toggle.
- Update GitHub Settings to show gh CLI availability and active status.
- When gh CLI is the active auth source, show it in the connected account
  card and offer Disable instead of Disconnect.
- Keep Add Account available so users can still connect an OpenChamber OAuth
  account, which then takes priority over gh CLI.
- Add localized gh CLI settings strings across supported settings locales.

Fixes addressed during review:
- Removed unreachable UI branches in the inactive gh CLI card.
- Avoided duplicate and repeated `gh auth token` subprocess calls.
- Hardened settings file permissions for the new persisted flag.
- Routed the gh CLI toggle through the RuntimeAPI/runtimeFetch path instead
  of direct browser `fetch`.
- Added targeted tests for hidden subprocess options and negative-result
  cache behavior.
- Fixed a VS Code webview Response body typing issue that blocked type-check.
2026-06-11 18:43:41 +03:00
Bohdan Triapitsyn 6386b4a404 fix: avoid home cwd for VS Code OpenCode startup 2026-06-11 16:44:45 +03:00
Bohdan Triapitsyn a01b7a982f fix: align VS Code subsession chevrons in metadata row
Moves VS Code subsession chevrons into the metadata row
Centers the chevron with session metadata
Keeps web and desktop sidebar layout unchanged
2026-06-11 13:19:14 +03:00
Gautam0507 4198246671 fix(docker): update COPY path after Tauri desktop removal (#1606)
The Tauri desktop package was renamed to electron in commit c7bc026b.
Update the Dockerfile so workspace paths match bun.lock.
2026-06-11 02:02:51 +03:00