Commit Graph
4156 Commits
Author SHA1 Message Date
ba91e3ba7c fix(app): defer composer updates during IME composition (#3462)
* fix(app): defer composer updates during IME composition

* fix(app): read live DOM value from web composer getText

---------

Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-08-18 08:54:46 +00:00
2347242cdf fix(usage): read Cursor plan usage from cursor-agent auth.json (#3486)
Headless hosts only have ~/.config/cursor/auth.json from a CLI login,
not the desktop state.vscdb token. Without that fallback Settings usage
stayed unavailable on VPS-style machines.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 10:46:15 +02:00
Mohamed BoudraandGitHub 4108960709 Manage orchestration skills per host (#3451)
* feat(skills): manage orchestration skills per host

Agent skills execute on the daemon host, so their bundle, selection, and filesystem convergence must share that owner. Preserve the existing install semantics while letting every capable client manage the selected host and migrating the legacy desktop preference once.

* fix(client): keep skill management internal

Keep host skill management on the low-level daemon client used by the app. Do not expose daemon settings or the desktop-only compatibility migration through the shared Paseo API handed to plugins.

* fix(e2e): declare skills fixture dependencies

Use Playwright's required destructuring form for the test-scoped daemon sandbox fixture so CI can collect the real-host skills suite.

* test(skills): use native managed paths

Assert fixed skill targets relative to the daemon user's real home with platform-native path joining so the ownership contract holds on Windows and POSIX hosts.
2026-08-18 09:51:46 +02:00
Mohamed Boudra eb3591cee8 refactor(app): split the workspace header menu per form factor
Wide layouts make tabs from the tab strip's + menu, so the header menu
listing new agent / new terminal / new browser duplicated it. Compact has
no tab strip, so those actions have to live in the header there.

One menu with an isMobile prop could not express that: the prop only sized
the trigger, and the item list was shared. Two components now, with the
workspace actions (import, copy path, copy branch name, show setup) in one
component both render from the same callbacks so they cannot drift.
2026-08-18 09:38:30 +02:00
Mohamed Boudra ff6424fa4e feat(app): hide the editor settings section on native
The editor section configures the code editor, and the editor view on native is
a "not available here" stub — every control in it was dead. `webOnly` mirrors
the existing `desktopOnly` flag: the sidebar drops the item, and the section
renders nothing if a stale restored route still points at it.

Electron counts as web, so `isWeb` is the gate — desktop keeps the section.
2026-08-18 09:25:42 +02:00
Mohamed Boudra a87c11e8ac fix(app): drop the track panel divider when the list is empty
Bulk archive keeps the panel mounted with zero rows while it is archiving or
after a failure — that is the state it lands in once it has archived every
finished subagent. The divider under the action then had nothing beneath it and
read as a hairline stranded at the bottom of the panel.
2026-08-18 09:21:51 +02:00
Mohamed Boudra b880a70e73 feat(app): lift bulk archive above the subagents list
The archive-finished action sat at the foot of the track panel with nothing
between it and the subagent rows, so it read as one more subagent.

It now sits above the list behind a divider. The pointer enters the panel from
the pill below it, so the top edge is the far end of the trip: reaching a bulk
action costs a pass over every row it affects, and it can't land under a thumb
that was aiming for the nearest subagent.

It stays a row rather than becoming a Button. The panel is a menu surface, and
a bordered control inside a list of menu items reads as a foreign object — the
divider does the separating, not the chrome.
2026-08-18 09:17:34 +02:00
Mohamed Boudra f9633dd359 fix(server): stop background speech downloads 2026-08-18 01:28:21 +02:00
Mohamed Boudra 78629f92ef test(server): isolate reload smoke speech runtime 2026-08-18 01:24:34 +02:00
Mohamed Boudra 17f06443dc test(app): prebundle browser JSX runtime 2026-08-18 01:03:42 +02:00
Mohamed Boudra 3003ae25d5 test(app): isolate track menu assertions from layout animation 2026-08-18 01:01:27 +02:00
Mohamed Boudra 63a8b28e63 test(desktop): preserve one-step font scale regression 2026-08-18 00:46:52 +02:00
Mohamed Boudra 6290c2f8ac fix(desktop): align font size regression with base scale 2026-08-18 00:43:33 +02:00
Mohamed Boudra 405c6e07a9 fix(app): retain workspace pull request status across reloads 2026-08-18 00:32:03 +02:00
Mohamed Boudra 2538dd1e7b fix(app): restore tabs without layout flicker 2026-08-18 00:21:51 +02:00
Mohamed Boudra ed8371d083 fix(app): count what the subagents pill's mark is showing
The pill drew the most urgent state of the fan-out next to the size of
the fan-out. Two questions, one pill, 8pt apart: a spinning ring beside
"2 subagents" reads as two agents running when one is. The mark is the
thing the eye lands on, so its state gets read onto whatever number is
next to it.

While anything is happening the pill now names that state and counts the
children in it — "1 running", "2 failed" — and falls back to naming the
total once nothing is. The total is a tap away in the panel, and the
running count is the number worth glancing at anyway.

Label and mark are built by one function so they cannot disagree; the
call site takes both or neither. Every non-done bucket gets copy, not
just the two that are reachable today, because needs_input and attention
become reachable the moment a subagent row carries requiresAttention,
and the failure mode is silently the bug this commit fixes.
2026-08-18 00:18:53 +02:00
Mohamed Boudra 3cc8749437 feat(plugins): split plugin code by runtime
Keep the entry point focused on contribution wiring so client UI and daemon handlers can use their own runtime APIs safely. Surface compilation failures and lifecycle transitions in the retained plugin log tail.
2026-08-17 23:45:19 +02:00
Mohamed Boudra 5ed1a852d1 fix(app): enlarge dictation overlay timer 2026-08-17 23:43:18 +02:00
Mohamed Boudra c859b59c99 fix(app): dismiss the composer track panel when a row is chosen
Track pills became menu surfaces when the trackers moved out of stacked
cards, but ComposerTrackRow kept the raw Pressable it had as an inline
card row. Nothing in that path reaches selectItem, so the popover or
sheet stayed parked over the transcript after opening a subagent, and on
iOS the action fired while UIKit was still tearing the sheet down. Rows
now hand the press to the engine and take closeOnSelect, as MenuItem
does; bulk archive opts out because its progress lands in the panel.

The running mark is the shared StatusRing rather than a still dot the
pill drew for itself, and the remaining dots read their colour from the
one bucket-to-colour map. The slot is sized for the ring in every state
so the label does not step sideways when the last child finishes.

Mounting the real menu engine in a test needed harness work: stubs for
two packages that ship untranspiled Flow, reanimated left out of Vite's
prebundle so its .web files win, and the gaps filled in the unistyles
test theme.
2026-08-17 23:43:01 +02:00
Mohamed Boudra 1cc6712e51 fix(app): make composer track clearance deterministic
Layout measurement excluded pill margin on some renderers, collapsing the intended gap above visible tracks. Keep the two-pill rail on one line and derive its complete tail clearance from shared geometry so chat switching and layout callbacks cannot change the result.
2026-08-17 23:23:51 +02:00
Mohamed Boudra a6a533bc6a fix(app): simplify workspace add-tab labels
Use noun labels in the add-tab menu so creation targets read consistently alongside Changes, Files, and Pull request. Keep verb-oriented labels in shortcut and command surfaces.
2026-08-17 23:18:55 +02:00
Mohamed Boudra f469223b76 fix(app): tune composer pill clearance by layout
Keep the roomier 16px separation on compact layouts while using 10px on wide layouts. Apply the same breakpoint contract to track and import-session pills so their spacing stays consistent.
2026-08-17 23:13:48 +02:00
Mohamed Boudra 75ccae13be perf(app): add explorer toggle profiling harness 2026-08-17 22:55:46 +02:00
Mohamed Boudra 7a61a642a9 fix(app): theme pull request empty state
The empty-state text inherited the platform default color, making it unreadable on dark surfaces. Use the app foreground tokens so it follows the active theme.
2026-08-17 22:55:46 +02:00
Mohamed Boudra 3948bf4fd6 fix(app): resolve terminal profiles at creation boundary
Profile placeholders were reaching spawned processes because each menu decided whether to resolve them. Keep UI callers profile-only and perform empty-prompt resolution once when the workspace terminal is created.
2026-08-17 22:55:46 +02:00
Mohamed Boudra 5ec26f0c09 feat(app): align interface typography to base size
Treat the appearance setting as the rendered base size so the type ramp scales predictably. Native starts one pixel larger while web and desktop preserve the authored 14px base, with legacy values migrated on load.
2026-08-17 22:55:46 +02:00
Mohamed Boudra df3e646fbe fix(app): float composer track pills consistently
Keep agent and task pills as a transparent transcript overlay while measuring their rendered height for scroll-tail clearance. Share geometry and spacing with the import-session pill so borders, type, corners, and composer separation match across platforms.
2026-08-17 22:55:45 +02:00
Mohamed Boudra 331bbd9faa test(app): align Changes regressions with canvas geometry 2026-08-17 21:15:17 +02:00
Mohamed Boudra 311eb48922 fix(android): clean generated projects before prebuild
Local Android builds now regenerate native projects from configuration instead of carrying stale prebuild output across variants.
2026-08-17 21:15:17 +02:00
Mohamed Boudra 851dcb8d4a fix(app): preserve static context-menu trigger styles
Passing a static style through a dynamic callback prevented the native press highlight from inheriting the trigger's corners.
2026-08-17 21:15:17 +02:00
Mohamed Boudra 53ba0f0a26 fix(app): align workspace chrome controls 2026-08-17 21:15:16 +02:00
Mohamed Boudra 1e50f895f0 fix(app): keep retained terminal streams attached
A hidden tab in the focused workspace must keep consuming output, but only the presented pane may claim focus or terminal geometry.
2026-08-17 21:15:16 +02:00
Mohamed Boudra 6ea1067bff feat(app): maximize the Explorer pane
Maximization isolates the existing Explorer split without entering workspace focus mode, and automatically restores the split if that pane disappears.
2026-08-17 21:15:16 +02:00
Mohamed Boudra 60bafad3ee feat(app): make the New tab launcher keyboard-first
Cmd/Ctrl+T now opens the focused pane's launcher, while explicit target shortcuts bypass the menu. Dispatcher ownership is scoped to the app tree so retained workspaces cannot intercept commands.
2026-08-17 21:15:16 +02:00
Mohamed Boudra 8655722296 refactor(app): simplify Changes controls 2026-08-17 21:15:16 +02:00
Mohamed Boudra 5110e6e92a fix(app): align diff headers with canvas borders 2026-08-17 21:15:16 +02:00
Mohamed Boudra a54b6c2020 fix(app): retain Explorer tab state 2026-08-17 21:15:16 +02:00
Mohamed Boudra b97993f866 fix(app): stabilize retained canvas diff rendering 2026-08-17 21:15:16 +02:00
Mohamed Boudra 7d3212e365 fix(desktop): show browser element annotation editor
The editor was trapped below the resident webview's body-level paint plane in split layouts. Render it through the shared overlay root while tracking the owning pane's bounds.
2026-08-17 21:15:15 +02:00
Mohamed Boudra ac6a0afdc7 fix(app): calm the segmented control's selected segment
The selected segment was an inverted fill — theme foreground behind
surface0 text — which in dark mode dropped a white slab into thin
chrome like the file toolbar, and the fully rounded corners made it
read as a lozenge rather than a tab. It now uses a surface3 fill with
foreground text, and each segment takes the corner radius of the
button at its size tier.

Segments also drop one padding step below the equivalent button. The
gap between segments already supplies the visual padding, so matching
button padding made the track wider than it needed to be and ate the
breathing room around it in a 32px toolbar row.

Selection changes colour only. No weight or size change, so labels
never reflow as you switch segments.

Carries the buttonControlHeight extraction that was already sitting in
control-geometry.ts, since the two files could not be split apart
cleanly for this commit. Its callers stay uncommitted.
2026-08-17 21:15:15 +02:00
Mohamed Boudra 58fe405801 fix(app): keep pull requests in the explorer pane
Pull request auto-placement was using the current location of Changes as a proxy for pane ownership. Keep the registered explorer pane authoritative so moving Changes cannot redirect automatically discovered pull requests.
2026-08-17 21:14:39 +02:00
Mohamed Boudra b362af6e32 fix(app): prevent diff canvas resize stretching
Keep the last painted canvas width while a pane resize is active, then repaint during layout before the settled width reaches the screen. This avoids scaling the bitmap during the drag or on its final handoff frame.
2026-08-17 21:14:39 +02:00
Mohamed Boudra 9e6e148ba2 fix(app): stabilize canvas refresh and borders
Fast Refresh preserves refs while rerunning effects, so canceled paint requests must release their retained IDs or unseen diff regions stop rendering. Paint the final expanded body’s reserved boundary pixel because no following header owns that seam.
2026-08-17 21:14:38 +02:00
Mohamed Boudra 8f7b3e8d75 fix(app): stabilize diff reviews and workspace tabs
Reuse measured diff geometry when review controls open, keeping the interaction responsive on large changes. Preserve complete tab-track snapshots while exact content widths settle so new tabs and retained workspaces do not flash or truncate.
2026-08-17 21:14:38 +02:00
Mohamed Boudra c7b103a2cd fix(app): stabilize canvas diff rendering
Keep diff headers and painted content on the same scroll clock while preserving native scrolling and independent per-file horizontal offsets.

Complete review, selection, typography, tree, and palette parity without returning line rendering to React.
2026-08-17 21:14:38 +02:00
Mohamed Boudra 4d23905587 fix(app): use small text for queued messages 2026-08-17 21:14:37 +02:00
Mohamed Boudra d03cf14703 refactor(app): implement canvas-based diff rendering 2026-08-17 21:14:37 +02:00
Mohamed Boudra 75adf53893 feat(app): polish workspace tabs and changes
Size tabs from rendered labels and switch to horizontal overflow once minimum click targets are reached, keeping the add-tab action adjacent until it must remain fixed.

Make Changes an always-expanded document with an optional desktop navigation tree, keep Git actions in their platform-owned headers, remove pinned and inline split shortcuts, and place review tabs beside Changes.
2026-08-17 21:14:37 +02:00
Mohamed BoudraandGitHub 6d7606160e Let plugins add contextual workspace tools (#3465)
* feat(plugins): add workspace panels and command center contributions

Give local plugins contextual UI entry points without making the daemon interpret client placement or callbacks. Panels receive stable IDs and read cached client state through required selectors with shallow equality, avoiding unrelated guest rerenders and context-discovery RPCs.

* fix(plugins): align shared client state ownership

Workspace panels and Command Center callbacks consume the same frozen client snapshots, so their adapter belongs to the plugin boundary rather than either contribution surface. Refresh the Nix dependency hash for the selector-store dependency added by this feature.
2026-08-17 19:26:40 +02:00
Mohamed BoudraandGitHub 1e2089cef7 Summarize pull request checks and group them by status (#3483)
* fix(app): keep check rows the same height with and without "Add to chat"

A check row was minHeight 32 plus 8pt of vertical padding, but the xs
Button in its trailing slot is 28pt tall. The button stacked on the
padding rather than fitting inside the row, so a row grew to 44pt the
moment "Add to chat" appeared and the list visibly shifted as rows
gained the button.

Rows are single-line by construction, so the row now declares a fixed
height instead of a floor a child can outgrow. That height comes from
CONTROL_HEIGHTS, the same source the button sizes from, so the two
cannot drift apart later. GitLab pipeline rows share this style and get
the fix too.

* feat(app): summarize pull request checks and group them by status

The checks section listed every check inline under a bare "Checks"
header with three count pills. On a repo with a real matrix that meant
a wall of undifferentiated rows that pushed the activity timeline off
the pane, and the pills made the reader add up numbers to work out
whether the run was actually in trouble.

The section now leads with the answer — a headline that names the
outcome, a one-line count breakdown, and a ring showing the statuses in
proportion — then groups the rows by status with failures first, and
scrolls in place past roughly eight rows instead of growing without
bound. Groups collapse individually.

The derivation lives in checks-summary.ts as one pure function, so the
headline, the ring, and the group labels cannot disagree about the same
run. The rendering, the row, and the check identity move out of pane.tsx
into an owned module; the pane now wires it and nothing more.

Running checks also gain a timing. formatCheckRunDuration required both
a start and a completion, so anything still going showed nothing at all.
It now measures an unfinished run to now. The wire deliberately carries
formatted strings rather than raw timestamps — there is a test asserting
check timestamps are stripped — so the daemon does the measuring and the
client only decides how to say it: a bare "2m" on a running row would
read as "took 2m", so those rows say "running 2m".
2026-08-17 17:23:03 +02:00