Commit Graph
2747 Commits
Author SHA1 Message Date
jaygupta17 cda273d69f feat(git): resolve nested repositories in the other git surfaces
Extract GitView's resolution flow into hooks/useNestedGitDirectory (root
probe, discovery, auto-select, stale-selection recovery) so the flow no
longer depends on SessionSidebar probing the root first, and reuse it in
the pull-request view, walkthrough view, and mobile changes surface —
all three now operate on the selected nested repository instead of
dead-ending on a non-repo root. Shared pending/failed/unsupported/empty
states live in git/NestedRepoResolutionStates; desktop changes inherits
the behavior through GitView. Selection stays shared per root, so the
picker's pick carries across surfaces.
2026-08-25 19:15:53 +05:30
jaygupta17 5e3f9d1ba2 fix(git): harden nested repository discovery
- discard an in-flight discovery when the runtime switches, mirroring the
  isRequestCurrent pattern, so a late completion cannot repopulate the
  cleared map and suppress a fresh scan
- treat a 501 from /api/fs/git-dirs as an explicit 'unsupported' marker
  instead of a generic failure; the VS Code webview now answers the route
  with unsupportedWebRouteResponse so non-repo roots show the honest
  not-a-repository state without a futile Retry
2026-08-25 19:15:35 +05:30
jaygupta17 f56b934dc9 Merge remote-tracking branch 'origin/main' into feat/nested-git-repos
# Conflicts:
#	packages/web/server/lib/fs/routes.test.js
2026-08-25 18:39:25 +05:30
Bohdan Triapitsyn 3b7d5e1c34 refactor(header): drop session tab tooltips
The hover info card (project/branch/PR/time) added noise without pull —
the tab title plus the sidebar already cover it. The tooltip body
component, its per-hover subscriptions, and the native title attribute
are gone; right-click/menu and the status dot are untouched.
2026-08-25 00:52:01 +03:00
Bohdan Triapitsyn 8458d2a446 feat(header): session tabs are opt-in
Default off; the changelog entry points at Settings → General →
Navigation → Session tabs and mentions the Alt+W close shortcut.
2026-08-25 00:50:19 +03:00
Bohdan Triapitsyn b6e14cbf21 refactor(settings): always-docked editor toolbar; reorder Navigation
The 'Always show editor toolbar' preference is gone — the docked
toolbar under the file tabs is now the only mode, and the floating
hover toolbar branch in the files editor (with its open-state and
outside-click machinery) is deleted. The stored preference is dropped
by a store migration and removed from desktop settings persistence,
settings search and every locale.

Navigation section order now reads: file editor keymap, auto-save,
terminal shell + login shell, Terminal Quick Keys, and the Session
tabs group last.
2026-08-25 00:32:09 +03:00
Bohdan Triapitsyn f40a247be9 fix(settings): include the Session tabs toggle in the General page's visible list
The General section renders OpenChamberVisualSettings with an explicit
visibleSettings allowlist, so the new control was searchable but never
rendered.
2026-08-25 00:20:37 +03:00
Bohdan Triapitsyn ce90e7e24f feat(settings): Session tabs toggle in General → Navigation
A new Session tabs group (web/desktop only) turns the header session
tabs off; disabled, the header renders the exact pre-tabs view — plain
session title with meta row and the always-visible session menu (the
same block VS Code uses). The Alt+W close-tab shortcut no-ops while
tabs are off. Registered in settings search with a matching anchor;
labels translated in all locales.
2026-08-25 00:05:45 +03:00
Bohdan Triapitsyn 2c1d8d592e feat(header): Alt+W closes the active session tab, customizable in Settings
The close-with-neighbour-activation logic moved into a shared helper
(the strip and the shortcut use the same path). Alt+W is the default
because the browser owns Cmd/Ctrl+W on web; desktop users can rebind it
— the action is registered as customizable, so it appears in the
Settings shortcuts section and the shortcuts help automatically. VS
Code is excluded (it has no session tabs).
2026-08-24 20:57:01 +03:00
Bohdan Triapitsyn 71bfb3c8e0 fix(header): cap session tabs at 10 2026-08-24 20:50:22 +03:00
Bohdan Triapitsyn dcacf4b3fc perf(header): cap session tabs at 20; tooltip data loads on hover only
Auto-add means the strip only grows, so past 20 tabs the oldest one
leaves the working set (the newly opened tab is always the survivor).
The branch/worktree/PR/project subscriptions that feed the hover
tooltip moved into the tooltip body component, which mounts only while
the tooltip is open — a resting tab now subscribes only to its status
dot's session status and unread count.
2026-08-24 20:47:51 +03:00
Bohdan Triapitsyn 275d381bd0 docs: changelog entry for header session tabs 2026-08-24 20:41:42 +03:00
Bohdan Triapitsyn a53c78b54a fix: adjust light theme selection color 2026-08-24 20:37:25 +03:00
Bohdan Triapitsyn 4b2ad01b4a fix(header): inactive-tab rename actually starts; snappier tab state change
Rename from another tab's menu stored only a boolean that the
session-switch reset effect wiped before the menu finished closing, so
the tab activated but rename never began. The pending rename now
carries the target session id and begins exactly when that session
becomes active (whether the menu closes before or after the switch),
without the reset effect cancelling it — and without an in-flight
rename being cancelled by unrelated re-renders. Tab background/text
state changes animate at 75ms so activation reads immediate.
2026-08-24 20:18:45 +03:00
Bohdan Triapitsyn b1023b87e7 fix(header): tab title fade is resting-state only; clearer separators
The title fade no longer sits on controls: it lifts while the tab is
hovered or its controls/menu are open (hard clip instead) and is not
applied at all while the active tab renames. The active tab clips its
title instead of showing an ellipsis, matching inactive tabs. Tab
separators drop the extra transparency that made them nearly
invisible.
2026-08-24 20:16:06 +03:00
Bohdan Triapitsyn aad9c25164 fix(vscode): adjust expanded layout threshold for showing sessions sidebar
Keeps enough space for the chat panel when the sessions sidebar stays visible
Bases the expanded layout breakpoint on the sidebar width instead of a fixed value
2026-08-24 20:11:18 +03:00
Bohdan Triapitsyn c47c7190f4 feat(header): session tab tooltips, status dots, cursor context menu
Right-click now opens the session menu under the cursor (the sidebar's
context-menu pattern; the same header-supplied items back both the
"..." dropdown and the context menu via injected menu primitives) and
still never changes the active tab. Hovering a tab shows the sidebar's
session tooltip — title, last-activity time, project, branch and PR
status — after a delay, suppressed while a menu is open or a drag is in
flight. Each tab carries the sidebar's status dot at its end (accent
while the session runs, info-blue for unread), hidden while the hover
controls overlay it. Tab titles fade out instead of ending in "...",
and while the active tab is renaming its hover controls stay hidden so
only the rename controls show.
2026-08-24 20:02:59 +03:00
Bohdan Triapitsyn 338dc73e96 fix(header): one session-tab menu, hidden scrollbar, right-click, control order
The strip now owns a single dropdown per tab, fed by the header with
items bound to that tab's session — rename (activates the tab first),
copy id, share/copy link/unshare, export and move-to-worktree (active
tab only, they need the loaded directory), close other tabs, archive
and delete with the confirm dialog targeting the right session. The
separate inactive-tab menu is gone, and there is no Close item — the
tab's close button covers it, now placed after the menu button.

Right-click opens that menu without activating the tab. The menu's
anchor overlay stays mounted until the close animation finishes, which
removes the popup flashing in the top-left corner on close. The
scroller hides its scrollbar via a dedicated CSS class (the bar was
shifting the header content vertically).
2026-08-24 19:24:17 +03:00
Bohdan Triapitsyn 97ddab73a1 fix(header): session tabs span to the right controls, close buttons, even padding
The old flex spacer split the header in half, boxing the strip into the
middle while tabs shrank to slivers; the spacer now renders only for
the VS Code and surface-title layouts, tabs keep a fixed width (w-44)
and the strip scrolls behind the right-side buttons. Every tab gains a
hover-revealed close button next to the menu; the active tab's menu is
hover-revealed too (it was always visible) — the header passes it into
the strip so both overlays behave identically. The active tab's inner
padding matches inactive tabs.
2026-08-24 19:08:33 +03:00
Bohdan Triapitsyn 447e43eac5 style(header): session tabs follow the titlebar tab design language
Uniform compact tabs (h-7, 6px radius, 13px medium) that share the strip
width and shrink before scrolling, thin separators between inactive
neighbours that disappear around the active or hovered tab, a
hover-revealed menu button anchored to the tab's end, a soft selection
pill for the active tab, and hidden scrollbars with fade edges. The
active tab is single-line: the project/branch meta row stays only in the
VS Code header, which keeps the plain title.
2026-08-24 17:41:34 +03:00
Bohdan Triapitsyn a3813f57e9 feat(header): session tabs — a horizontal working set of open sessions
Web/desktop header replaces the single session title with a strip of
soft pill tabs, one per session the user has opened (sidebar, palette
or deep link — opening anywhere adds a tab once). The active tab is the
familiar title block — rename, meta row and the full session menu —
inside a gently selected pill; a brand-new draft shows as a transient
pill until its session exists. Inactive tabs show the title with a
hover-revealed "..." menu (close tab, close other tabs, copy id) that
nudges the text like sidebar rows, and close by middle-click too.

Tabs drag to reorder, scroll behind the right-side header buttons with
soft fade edges, respect the reserved window-controls inset, and
persist across reloads. Closing the active tab activates its neighbour
(or opens a new draft when it was the last). Tab ids whose session is
not in the loaded list stay stored but hidden, so a partial session
list never destroys the working set. VS Code keeps the plain title;
mobile is untouched.
2026-08-24 17:07:09 +03:00
Bohdan Triapitsyn 7bd27d44d6 fix(vscode): bundle syntax worker imports 2026-08-24 16:58:45 +03:00
Bohdan Triapitsyn c82f188fc8 refactor(surface): remove the main-area surface concept entirely
activeSurface was permanently 'chat' after the legacy mobile layout
removal, so the whole concept is gone: the store field, surfaceGuard,
setActiveSurface/setSurfaceGuard, the per-runtime surface memory in
prepare/restoreForRuntimeSwitch, and WorkspaceSurface itself. All ~30
setActiveSurface('chat') call sites were no-ops and are deleted;
always-true 'is the chat active' checks in keyboard shortcuts, Header
and ChatContainer are unconditional now. FilesView's dirty-file guard
kept its file-switch and close protection but drops the surface-switch
branch nothing could trigger. TerminalView visibility comes only from
its callers. The router keeps parsing legacy ?tab= links (they open the
matching context-panel surface) via its own RouteTab type and no longer
serializes a tab or diff file into URLs — desktop URLs never carried
them anyway.
2026-08-24 16:36:41 +03:00
Bohdan Triapitsyn c6e39f15fe docs: changelog entry for the app-shell viewport switch 2026-08-24 16:21:13 +03:00
Bohdan Triapitsyn 4da7604d7d refactor(surface): drop the deprecated main-tab aliases and dead diagram surface
MainTab/activeMainTab/setActiveMainTab/setMainTabGuard were deprecated
mirrors of the surface names — every call site now uses
activeSurface/setActiveSurface/setSurfaceGuard directly and the aliases
are gone, including the persisted mirror field.

The 'diagram' surface had no way to open it (navigateToDiagram had no
callers except a .drawio attachment click that navigated to a surface
nothing rendered); the surface, DiagramView, and its store plumbing are
removed, and a .drawio attachment now opens in the file panel.

?tab= deep links map to the matching context-panel surface instead of
setting a main-area surface nothing renders, and a persisted non-chat
surface can no longer rehydrate into a blank main area.
2026-08-24 16:21:05 +03:00
Bohdan Triapitsyn 8b7d7803de refactor(layout): remove the legacy mobile layout from MainLayout and Header
Phone viewports run the separate MobileApp shell (and a viewport crossing
now reloads into it), so the desktop layout's mobile branch was
unreachable: the drawer machinery, the full-screen secondaryView surface
switch (including the terminal/diagram desktop carve-out nothing could
trigger), the mobile header with its tab bar, the Cmd+number tab
shortcuts, the mobile quota panel, and the surface guard that reset
non-chat tabs. DrawerContext had no consumers left and is deleted.
Header drops from 2630 to 1853 lines; the desktop render is unchanged.
2026-08-24 16:15:16 +03:00
Bohdan Triapitsyn 841eca5720 feat(surface): switch app shells when the viewport crosses the phone threshold
The mobile-vs-desktop surface is stamped once at boot, so a browser
window narrowed past the phone threshold kept the desktop shell (and
its legacy squeezed layout) until a manual reload. A viewport watcher
now reloads into the other shell once the resize settles — the same
mechanism the old Settings toggle used. Fixed shells (Capacitor,
desktop, VS Code) and ?surface= overrides never switch.

With the new mobile app reachable this way, the old/new mobile layout
preference is gone: phones always get the mobile app.
2026-08-24 16:08:04 +03:00
Bohdan Triapitsyn 98c2a616c3 docs: extend dropdown search changelog bullet with sidebar filters 2026-08-24 15:04:23 +03:00
Bohdan Triapitsyn da309a2a8d refactor(search): session sidebar and project-context filters use the shared matcher
Sidebar session/folder/group search and the Todos, Memory, Plans and
Notes filters required the whole query as one literal substring; they
now match tokens in any order and ignore punctuation via
matchesRankQuery, keeping their own list order and tree structure.
2026-08-24 15:04:14 +03:00
Bohdan Triapitsyn c02d7ff399 docs: changelog entry for unified dropdown search 2026-08-24 15:01:11 +03:00
Bohdan Triapitsyn b8716fe808 refactor(search): unify dropdown filtering on the shared ranked matcher
Branch, project, agent, model, provider, stash, SSH-host, skill-catalog
and archive filters each had their own toLowerCase().includes (or no
ordering at all); the git branch and gitmoji pickers also let cmdk
re-filter and reorder on top of the manual filter, silently dropping
rows. All of them now go through rankByQuery/matchesRankQuery: results
are relevance-ordered, multi-word queries match in any order, matching
ignores punctuation, and cmdk filtering is disabled where the ranked
list is already final. rankBranchesForQuery keeps relevance order
instead of re-sorting matches alphabetically; the model picker now also
matches model ids.
2026-08-24 15:00:52 +03:00
Bohdan Triapitsyn 081056e6e5 feat(search): canonical rankByQuery matcher for searchable dropdowns
One matcher for every dropdown filter: multi-token queries match in any
order, matching is punctuation-insensitive, single-token queries
tolerate typos, and results come back relevance-ordered (prefix, then
word-boundary, then substring, original order on ties). matchesRankQuery
is the boolean companion for lists that keep their own grouping.
2026-08-24 14:54:14 +03:00
Bohdan Triapitsyn 2eefd46b70 docs: changelog entries for search, terminal, and mobile keyboard fixes 2026-08-24 14:50:03 +03:00
Bohdan Triapitsyn d9f4b4b6cc fix(terminal): stop mobile keyboards auto-capitalizing terminal input
ghostty-web marks the terminal container contenteditable but only its
hidden textarea opts out of IME text mangling, so iOS and Android
keyboards uppercased the first letter of every command. Set
autocapitalize/autocorrect/spellcheck off on the container after open.
2026-08-24 14:30:00 +03:00
Bohdan Triapitsyn 2f27f0ec4b fix(terminal): reconcile tabs with server sessions and keep shown terminals alive
The tab list lived only in per-tab sessionStorage, so a new browser
tab, another device, or cleared storage showed an empty terminal
sidebar while PTYs kept running server-side, and orphans leaked until
the idle sweep. Add GET /api/terminal/sessions and adopt unknown
server sessions into the local tab projection (additive only; a failed
listing changes nothing).

The idle sweep also reaped terminals in background tabs because only
the active tab holds a WebSocket attachment. Add POST
/api/terminal/touch and have open clients periodically refresh
activity for every session their tabs reference.
2026-08-24 14:30:00 +03:00
Bohdan Triapitsyn 0918bee566 fix(chat): rank @ mention files and directories together by match quality
Directories and files were rendered as fixed category blocks, so an
exact file match sat below unrelated directories. Merge both result
sets and rank them with the shared fuzzy scorer against the full
relative path. Multi-word queries now match tokens in any order
(longest token queries the server, the rest filter client-side), and
path truncation keeps the parent segments next to the file name so
index.md-heavy trees stay distinguishable.
2026-08-24 14:30:00 +03:00
Bohdan Triapitsyn 279fa8b691 fix(command-palette): match file results against the full relative path
Cmd+P scored server file hits by basename only, so a query like
"solo-is-a" returned nothing for solo-is-a-team-size/index.md.
Score by relativePath and widen the server candidate limit to 40
so client-side reranking has enough to work with.
2026-08-24 14:19:25 +03:00
Bohdan Triapitsyn 97edd033f9 fix(relay): stop bystander instances from capturing the relay host
Two mitigations for local multi-instance contention over the shared relay
identity:

- A standby instance now waits a 2-minute grace period after the host claim
  frees before taking over, so a cleanly restarting host (app update or
  relaunch) — which reclaims at boot with no wait — always wins the restart
  window instead of stranding paired devices on another process.
- Dev instances never host the relay passively: dev scripts set
  OPENCHAMBER_RELAY_HOST=off and the Electron dev shell is detected via
  OPENCHAMBER_ELECTRON_DEV. Explicit enable/pairing on such an instance still
  force-claims; OPENCHAMBER_RELAY_HOST=on overrides.
2026-08-24 14:03:18 +03:00
Bohdan Triapitsyn 3aa45805bc fix(devices): keep the existing device name on re-pair and re-login
A dedupe-keyed client re-mint (QR rescan, password/passkey re-login) replaces
the stored record, which also reset the operator-visible name to the app's
hardcoded default ('OpenChamber Mobile'). The app-reported name is now only a
fallback: an explicit pairing label wins, otherwise the replaced record's
label is kept, and the default applies only to a first-ever pairing.
2026-08-24 14:03:18 +03:00
Bohdan Triapitsyn 5fa6f2c159 fix(chat): center the read-only subagent banner text 2026-08-24 12:49:58 +03:00
Bohdan Triapitsyn 080bd0a969 fix(chat): center the read-only subagent banner in the composer column 2026-08-24 12:49:03 +03:00
Bohdan Triapitsyn 83ea72de0e feat(chat): messenger-style context cards with message-level collapse 2026-08-24 12:46:14 +03:00
Bohdan Triapitsyn cd2a3efcdf fix(chat): keep selection comment popup below the desktop drag header 2026-08-24 12:17:13 +03:00
Bohdan Triapitsyn 58a193aa87 feat(ui): glass surfaces for selection menus and comment popovers
The chat selection menu (desktop pill and mobile sheet), the chat
comment input, the file-preview Comment pill, the shared inline comment
editor, and the composer's context chip preview popover now use the
same translucent blurred glass surface as the btw panel, keeping their
borders and soft shadow.
2026-08-24 01:49:10 +03:00
Bohdan Triapitsyn d678a4244e fix(mobile): knowledge panel tabs, autocomplete height floor, status row gap
The project knowledge panel's section sidebar becomes a horizontal pill
strip on mobile, where a half-width side column left no room for
content. The autocomplete popups get their 120px minimum height back —
browser keyboard panning could put the anchor above the measured
boundary and collapse them to nothing. The status row's 24px footer-swap
reservation now applies only to the assistant-status instance; the
accessory-only row above the composer (pending changes) takes the
normal 8px instead of floating a stray gap.
2026-08-24 01:44:15 +03:00
Bohdan Triapitsyn a547f83ebe docs: draft Unreleased changelog entries 2026-08-24 01:28:53 +03:00
Bohdan Triapitsyn eb03ffaa80 feat(files): comment on selection in read-only markdown previews
Selecting text in a rendered markdown preview shows a Comment pill;
attaching stores a file-quote context draft carrying the file path, the
selected fragment (not whole lines), the user's comment, and a
best-effort source line range resolved by anchoring the fragment's
first and last lines in the raw content — a partially located fragment
gets no range rather than a misleading one. The fragment stays
highlighted while the comment input is open, using the selection
overlay rects shared with chat quote comments, and the preview's
native selection color now matches chat messages. file-quote flows
through the same context contract: composer chip previews, the message
context card, and the metadata round-trip.
2026-08-24 01:21:35 +03:00
Bohdan Triapitsyn e47c027ea0 feat(diff): unified comment UI with gutter plus and content-drag selection
The diff comment editor is restyled as the shared comment pill (context
line inside the box, auto-growing textarea, round attach button;
Cmd/Ctrl+Enter attaches, Enter breaks the line) and the saved-comment
card matches the composer preview entries. Pierre's gutter utility is
enabled: hovering a line shows a small primary-colored plus that opens
a comment for the line, dragging from it selects a range, and it rides
the bottom of an active selection. Clicking a diff line toggles a
single-line comment, and dragging over content maps to the same line
selection the number column produces — the native text selection is
suppressed once a drag crosses a line boundary — opening the editor for
the range on release. Placeholders and meta lines are dimmed relative
to typed text.
2026-08-24 01:02:33 +03:00
Bohdan Triapitsyn 538b532fb1 feat(composer): context chip previews with inline comment editing
Hovering (or tapping) a context chip opens a stacked preview of its
pending items above the composer: numbered entries with a muted header
band, the captured selection, and the user's comment, which can be
edited in place (save/cancel) or removed before sending. The chips
component now subscribes to the draft store itself; the per-kind count
plumbing in ChatInput is gone.
2026-08-24 00:16:26 +03:00
Bohdan Triapitsyn c3f89e0106 fix(ui): soften btw panel shadow
Replace the floating-glass elevation stack with the composer pill's
soft shadow and a plain theme border; the glass background and blur
stay.
2026-08-23 23:40:41 +03:00