Commit Graph
1261 Commits
Author SHA1 Message Date
Mohamed BoudraandGitHub 42ee5a5949 Restore archived agents from History (#2316)
* fix(app): restore archived agents from History

History navigation lost the explicit archived-agent intent during tab reconciliation, and workspace recovery stopped after restoring the workspace. Preserve the selected tab and recover its provider session as one action while serializing provider resume with timeline hydration.

* fix(app): preserve archived agent recovery invariants

* fix(server): preserve timeline hydration call shape

* fix(app): retain agent tabs through lookup

* fix(server): upgrade in-flight timeline broadcast
2026-07-22 15:03:09 +02:00
Mohamed Boudra 97cfcf8306 fix(app): stop markdown lines joining
Custom line-break rules dropped the resolved full-width break style, allowing adjacent native text spans to collapse onto one line. Preserve the break styles in both chat and shared Markdown renderers.
2026-07-21 23:56:23 +02:00
Mohamed Boudra 9603397aed perf(app): limit initial sidebar workspace rendering
Large project, status, and pinned groups now render 20 rows until expanded. Newly discovered workspaces are prepended without disturbing the saved order.
2026-07-21 23:56:22 +02:00
Mohamed Boudra 5c93ac4aa5 fix(app): balance sidebar divider spacing 2026-07-21 19:10:59 +02:00
Mohamed Boudra a8fb40e689 fix(app): align sidebar section spacing 2026-07-21 15:59:55 +02:00
Mohamed Boudra 25cdda9492 feat(app): label sidebar add project action 2026-07-21 15:46:53 +02:00
Mohamed Boudra d6dc309408 fix(app): keep pinned workspace labels aligned
Reserve the leading status slot for idle pinned rows so labels do not shift when workspace status changes.
2026-07-21 15:32:22 +02:00
Mohamed Boudra fd4e13735c fix(app): prevent duplicate web menu actions 2026-07-21 14:04:26 +02:00
Mohamed Boudra 8aa55db1e8 feat(app): improve workspace service controls
Keep service route choices independent of daemon transport and persist the selected route per host. Use the shared web overlay stack so menus, tooltips, and toasts layer predictably.

Track proxy route changes from the Git branch rather than the workspace title to avoid transient service health changes.
2026-07-21 13:44:23 +02:00
Mohamed BoudraandGitHub 4bda2dfea9 Edit workspace files directly on web (#2270)
* feat(files): edit workspace files on web

Keep source buffers synchronized with host file changes and require an explicit overwrite or reload when revisions diverge.

* feat(panels): surface and protect modified tabs

Expose tooltip and modification state through the generic panel boundary so tabs can show stable metadata and guard every close route consistently.

* fix(tests): use portable fake timeout handle

* fix(files): harden editor conflict handling

Preserve modified panel state across tab eviction, use precise revisions for optimistic writes, coalesce concurrent file watchers, and localize the editor interface.

* fix(files): close editor concurrency gaps

Coalesce clean reloads, preserve subscriber identities and file permissions, suspend pending saves during close confirmation, and carry precise revisions through file reads.

* test(files): expect read revision metadata
2026-07-21 04:41:19 +08:00
Mohamed BoudraandGitHub 2185779d6c fix(settings): highlight changes that apply next turn (#2201)
Permission and thinking changes made during an active turn do not affect that turn. Use setting-specific warnings so the timing is harder to miss.
2026-07-18 18:45:23 +02:00
Mohamed Boudra e0e50c9a8e fix(app): preserve persisted theme styles after startup
Module-level style composites could materialize the temporary adaptive theme before persisted settings loaded. Keep Unistyles reads in render and guard against eager module-scope access.
2026-07-18 17:45:02 +02:00
Michał KędrzyńskiGitHubClaude Opus 4.8greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>Mohamed Boudra
45bbb973a3 Switch models from the Command Center (#2147)
* Switch models from the Command Center

Add a model switcher to the Command-K Command Center. Typing surfaces a
flat, filterable list of "Model › Provider › Name" breadcrumb rows with
provider icons:

- Running agent: its own provider's models (a live agent can't change
  provider); selecting calls setAgentModel.
- New draft tab: every available provider's models in one flat list;
  selecting sets provider + model on the draft via a focused-draft
  controller published to a global store (the draft form state is local
  to the composer subtree and otherwise unreachable from the global
  Command Center).

Models only appear once the user starts typing, so the default palette
view is unchanged. Reuses useProvidersSnapshot and the existing
setAgentModel RPC — no protocol changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Update packages/app/src/components/command-center.tsx

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Update packages/app/src/hooks/use-command-center.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* refactor(app): make Command Center extensible

Let focused features register stable actions while the palette owns search, selection, and a single virtualized result projection.

* fix(app): save model preference after agent switch

Persist the shared model choice only after the daemon confirms the live agent switched successfully.

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-07-18 16:54:41 +02:00
Mohamed BoudraandGitHub 7917532716 Keep focused agent timelines live and catch up instantly (#2196)
* fix(app): keep focused agent timelines live

Window focus was conflated with app visibility, so switching OS windows could remove the selected timeline subscription. Separate those signals, grace every visibility-driven removal, and cover retained history until authoritative catch-up completes.

* fix(app): keep timeline catch-up failures non-blocking

* fix(app): surface timeline catch-up failures

* fix(app): preserve file preview refocus

* fix(app): preserve optimistic catch-up flow
2026-07-18 16:30:59 +02:00
Mohamed BoudraandGitHub ffe76a7e57 Make workspace, agent, and schedule automation consistent (#2186)
* feat(workspaces): align agent and schedule automation

Make workspace identity the shared placement boundary for MCP and CLI, while caller identity determines parentage. Keep heartbeats minimal and cron-based without changing legacy rolling interval semantics.

* test(cli): expect canonical schedule cadence

* fix(automation): preserve workspace and schedule compatibility

* fix(automation): preserve compatibility edges

* fix(workspaces): align MCP lifecycle resolution

* fix(workspaces): preserve creation intent

* fix(workspaces): preserve branch and schedule identity
2026-07-18 14:04:48 +02:00
Mohamed BoudraandGitHub 745e8afe45 Make keyboard shortcuts searchable (#2160)
* feat(app): make keyboard shortcuts searchable

* test(app): cover shortcut search empty state

* fix(app): index shortcut modifier aliases
2026-07-18 11:54:49 +02:00
Slava GoltserandGitHub a1de743ef6 fix(app): align thinking section scroll layout with other detail sections (#1884)
* feat(app): make thinking sections scrollable when expanded

* fix(app): align thinking section scroll layout with other detail sections
2026-07-18 03:07:44 +08:00
Mohamed BoudraandGitHub 39cb3dbb9c Treat every added folder as an independent project (#2098)
* fix(projects): detect when projects become Git repositories

Project identity was coupled to Git placement, while non-Git roots were dropped by session-scoped observation. Keep identity tied to the selected root and observe Git transitions daemon-wide so empty projects update without rehoming workspaces.

* fix(projects): preserve metadata across Git read failures

Refresh archived workspace facts before persistence and treat only confirmed non-repositories as non-Git so transient failures cannot rewrite stored project metadata.

* fix(projects): close project update races

* fix(projects): refresh checkout metadata when reopening folders

Persist worktree ownership separately from workspace kind and gate exact-root project creation on stable host identity. Refresh active and archived records so missed Git transitions cannot return stale checkout descriptors.

* test(projects): accept Windows aliases for repaired roots

* test(server): retry transient Windows cleanup locks

* fix(projects): propagate project metadata refreshes

Project-only Git transitions now fan out workspace updates for legacy clients. Explicit project creation refreshes stored kind, and equivalent cwd spellings reuse existing workspace records.

* fix(projects): refresh worktree source project kind

* fix(projects): preserve exact-folder runtime isolation

* fix(projects): preserve exact cwd across worktree lifecycle

* fix(projects): harden exact-folder worktree flows

* fix(projects): derive exact cwd from matched path identity

* fix(projects): preserve nested worktree lifecycle

* refactor(projects): centralize workspace placement

* test(e2e): verify isolated server ports

* fix(projects): preserve placement reshape compatibility

* fix(projects): validate created worktree placement

* fix(projects): preserve placement through workspace lifecycle

Archive and recovery were rediscovering or guessing checkout roots instead of consuming the persisted workspace placement. Make the record authoritative for exact cwd, backing worktree, and source repository, and classify stale paths before Git reconciliation.

* fix(worktrees): preserve source checkout root

Convert Git's common administrative directory back to the source checkout root when legacy archive placement is reconstructed.

* fix(worktrees): compare filesystem identities

Resolve discovered worktrees and teardown locations through the shared realpath-aware matcher so Windows short and long path spellings cannot split placement identity.

* fix(worktrees): centralize path containment

Route worktree ownership, listing, resolution, and deletion through the realpath-aware containment primitive so Windows path aliases cannot be filtered by an earlier raw prefix check.

* fix(worktrees): remove duplicate ownership discovery

* test(e2e): isolate daemon restart ownership

* fix(worktrees): make lifecycle operations transactional

* fix(workspaces): share git watches by cwd

* test(worktrees): make teardown proof portable

* fix(sync): integrate project updates with directory owner

* fix(workspaces): close reconciliation edge cases

* refactor(sync): remove duplicate project reconciliation

Keep workspace and project deltas behind the host directory transaction, with owner-boundary coverage for snapshot replay and queued full reconciliation.

* fix(sync): buffer project updates before hydration

Start the workspace transaction with the online connection epoch so project broadcasts cannot publish a partial directory before the authoritative snapshot commits.
2026-07-17 19:30:17 +02:00
Mohamed BoudraandGitHub 1977d330ed Reduce workspace, agent, and chat sync traffic (#2028)
* feat(sync): keep live data scoped and current

Only viewed chats receive live timeline rows, while directory state now uses one subscribed bootstrap followed by ordered deltas. Legacy clients and daemons retain their existing behavior through centralized compatibility gates.

* fix(sync): preserve selective delivery boundaries

Keep selective timeline capability app-owned, union viewed sets across shared sockets, and reconcile directory side effects from accepted state. Visibility and archive suppression now follow their existing authoritative boundaries.

* test(app): align browser fixtures with runtime contracts

* fix(sync): preserve mixed-client delivery guarantees

* fix(sync): finish paged history before advancing

* fix(sync): replay live deltas after refresh failures

* test(server): model socket capability lookup

* test(app): use platform shortcut for split-pane coverage

* fix(app): keep hidden timelines dormant

* test(app): normalize split-pane shortcut setup

* fix(app): preserve sync state across retries

* fix(app): preserve background sync state across races

* fix directory bootstrap reconciliation edge cases

* fix selective timeline compatibility races

* fix superseded directory sync races

* fix(sync): centralize directory replica ordering

Own agent and workspace refresh transactions in HostRuntime so reconnect epochs, buffered updates, and lifecycle invalidation share one ordering boundary. Route timeline metadata and mixed-capability stream delivery through their authoritative runtime sources.

* fix(app): keep timeline requests runtime-scoped

* fix(app): close directory bootstrap races
2026-07-17 17:03:34 +02:00
Mohamed Boudra dfada2a556 fix(app): update provider icon 2026-07-17 14:03:43 +02:00
Mohamed Boudra 263ccc2a19 Merge branch 'main' of github.com:getpaseo/paseo 2026-07-17 13:06:31 +02:00
Mohamed BoudraandGitHub 388f1d426c Keep agent browser tabs connected across workspace switches (#2156)
* fix(desktop): keep browser tabs connected across workspaces

Electron can replace a guest WebContents when a retained browser tab is reparented. Re-register each attachment and keep background actionability checks running so agent browser tools retain the tab through workspace eviction.\n\nCover the full app, daemon, Electron, and MCP path in the existing desktop CI job.

* fix(desktop): launch Electron E2E reliably on Linux

CI Electron must receive --no-sandbox before the app starts because the hosted runner cannot use Electron's bundled SUID sandbox helper. Forward explicit dev-runner arguments and fail readiness waits as soon as a child exits.

* fix(desktop): preserve active browser on repeated registration

* fix(desktop): keep browser keyboard attachment idempotent

* fix(desktop): wait for E2E bridge readiness

* fix(desktop): close E2E logs after output drains
2026-07-17 19:02:09 +08:00
Mohamed Boudra a7cbf4f61d fix(app): make sidebar reordering respond immediately
Mouse input inherited the touch hold delay. Split activation by input so mouse dragging begins after deliberate movement while touch retains long-press arbitration.
2026-07-17 13:00:47 +02:00
Mohamed Boudra 266d54463b feat(app): highlight sidebar resize handles 2026-07-17 12:27:15 +02:00
Mohamed BoudraandGitHub bce2c50b9e Keep terminal sizing reliable through focus changes (#2154)
* fix(terminal): retry size claims until sent

A focus resize could consume its once-per-focus latch before the renderer handed the size to the client. Keep the claim pending across visibility, connection, and renderer readiness changes, and only commit it after the resize is sent.

* fix(terminal): keep disconnected claims retryable

A retained runtime client can outlive its active connection. Require the connection at delivery time so a delayed resize callback cannot commit a claim that was never sent.

* test(terminal): await PTY resize observation

Prove the terminal starts at 80x24 while blurred, then probe through the daemon until its own reported size matches xterm after focus returns. This avoids racing a one-shot stty sample against the asynchronous resize claim.
2026-07-17 10:07:50 +02:00
a8ebd390fa feat(forge): pluggable forge abstraction + GitLab and Gitea/Forgejo/Codeberg (#1913)
* refactor(forge): forge-neutral foundation (GitHub-only)

Decouple git-hosting from GitHub behind a neutral abstraction (issue #1616), GitHub-only for now; existing GitHub behaviour is unchanged.

- Forge manifest, neutral ForgeService contract, forge registry + resolver, and a client forge-module registry.
- GitHub code renamed to the neutral shape; PR/Issue attachment wording preserved.
- forge.search.response enums parse tolerantly (unknown kind/auth state degrade instead of breaking the client).
- createPullRequest reports typed CLI/auth errors instead of a generic message.
- forge-resolver host/remote caches are LRU-bounded.
- Forge host trust is explicit: only a known cloud host or a CLI-authenticated host is ever talked to; an unauthenticated GitHub Enterprise host fails resolution instead of routing to github.com.
- Docs: forge-providers guide, glossary and i18n forge-copy conventions, architecture and rpc-namespacing terminology.
- Vitest React Native mocks (unistyles, svg, linking, lucide) consolidated into shared aliased test-stubs.

* feat(forge): GitLab adapter, forge-aware UI, pipelines and approvals

GitLab adapter over the glab CLI on the neutral contracts: MR status, forge-aware UI, pipeline tree, and N-of-M approvals.

- threadIsResolved is part of the neutral timeline item.
- Pipeline load failures show an error instead of an empty section.
- Manual pipeline jobs render as pending.
- Fork/detached MR head pipelines are fetched by MR iid (glab ci get --merge-request).

* feat(forge): Gitea family adapter (Gitea, Forgejo, Codeberg)

One adapter over the tea CLI serving Gitea, Forgejo, and Codeberg on the neutral contracts.

- CI status aggregates commit statuses and Actions runs together.
- Gitea's terminal "warning" state maps to failure on server and client.
- Gitea Actions check details are reachable from the PR pane by workflowRunId.

* refactor(forge): localize compatibility handling

* test(forge): expect normalized GitLab facts

---------

Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-07-17 15:03:26 +08:00
Mohamed BoudraandGitHub 04d1ebdce0 Keep browser input from submitting Paseo prompts (#1982)
* fix(desktop): keep browser input out of the composer

Unhandled webview keys could be redispatched into the active host window, allowing agent Enter to submit a draft prompt. Give pages first refusal for ordinary shortcuts and contain automation at the guest boundary.

* fix(desktop): tighten browser shortcut validation

* fix(desktop): respect browser shortcut ownership

* fix(desktop): retain browser keys across windows

* fix(desktop): scope browser webviews by host

* Reshape browser shortcut ownership

Use the browser webview registry as the single guest identity authority, scope browser operations to their host window, publish chord continuations only while pending, and restore focus to the originating browser after command center dismissal.

* Fix host-scoped browser shortcut follow-ups

* Fix browser keyboard review follow-ups

* Fix browser keyboard lifecycle regressions

* Fix browser shortcut review regressions

* Fix desktop browser review regressions

* Fix browser shortcut frame regressions

* Fix rebase integration regressions

* Preserve browser-native shortcut ownership

* Isolate browser shortcuts and automation by context
2026-07-17 14:29:19 +08:00
Christoph LeiterandGitHub 9f5f5fce62 Fix terminal resize race (#2059) 2026-07-16 23:47:09 +02:00
Mohamed BoudraandGitHub a622860a3e Keep workspace focus mode scoped and easy to exit (#2151)
* fix(workspace): keep focus mode scoped and easy to exit

Route focus mode through the active workspace so persisted state cannot hide chrome on settings or other screens. Add a visible exit control and keep desktop window chrome aligned and visually quiet.

* fix(app): clarify muted chrome semantics
2026-07-16 23:46:24 +02:00
Ethan GreenfeldandGitHub d2308f4835 feat(omp): add native OMP provider (#2067)
Pi and OMP share only the JSONL child-process transport while retaining provider-owned launch, RPC, runtime, session, history, and permission behavior. Removes captured fixtures in favor of typed harnesses and real-provider coverage.

Closes #2006
Closes #2060
2026-07-16 23:20:59 +02:00
Mohamed BoudraandGitHub a1cd50c2ae Reimport archived sessions into the current workspace (#2123)
* fix(sessions): reimport archived sessions in their workspace

Archived agent records were treated as active imports, hiding their provider sessions permanently. Workspace-originated imports also discarded their workspace identity and created a duplicate workspace.

* fix(sessions): validate archived session restores

Restore archived imports under their existing Paseo agent identity, reject stale workspace ownership, and gate workspace targeting when the host cannot honor it.

* fix(sessions): roll back failed archived imports

If provider resume or history hydration fails, close any partial runtime, re-archive the provider session, and restore the original stored agent record.

* fix(sessions): validate restored import ownership

* fix(sessions): serialize concurrent restores

* fix(sessions): harden archived import recovery

* fix(sessions): validate archived import placement

* refactor(sessions): centralize provider session imports

Keep workspace placement rollback and stored-agent activation behind their existing owners so Session remains the wire boundary.
2026-07-17 02:25:50 +08:00
Mohamed BoudraandGitHub 5da6548aff Improve the archived workspace restore flow (#2002)
* fix(app): restore missing workspaces from History

Workspace and agent archival are separate lifecycles. Carry restore intent from History so closed agents can reopen archived workspaces without changing ordinary navigation.

* fix(app): wait for workspace hydration before restore

* fix(app): preserve History agent unarchive

* fix(app): reopen archived History agents outside active directory

History entries are not merged into the active session maps. Carry the row archive state through explicit restore intent so live workspaces still reopen without broadening ordinary navigation.

* fix(app): ignore stale History archive state for active agents

A cached History row can outlive a successful reopen. When the workspace exists, live session state now wins so an active agent is not interrupted by another refresh.

* fix(app): reopen every selected archived History agent

History entries without workspace IDs returned before restoration, and a second archived agent sharing an in-flight workspace restore was dropped. Preserve both agent-only and deferred reopen intent.

* fix(app): require explicit workspace recovery

* fix: preserve workspace recovery contracts

* fix: preserve workspace recovery compatibility

* fix: preserve recovered workspace session state

* fix: preserve terminal navigation timing

* fix(server): preserve successful workspace recovery

* fix: preserve workspace recovery intent
2026-07-16 17:22:37 +02:00
Mohamed BoudraandGitHub f4509fe044 Open files in more installed editors (#2119)
* feat(desktop): open files in more installed editors

Detect bundled app commands as well as PATH launchers and preserve file positions through editor-specific launches.

* fix(desktop): preserve editor target compatibility

Keep existing file-manager preference ids, retain project context for file launches, and recognize Windows 64-bit IDE commands.
2026-07-16 14:39:55 +02:00
Mohamed Boudra 943d03ad99 fix(projects): separate registration from workspace setup
Adding or cloning a project now registers it and opens workspace setup
instead of creating a workspace implicitly. Keep Add Project independently
mounted from Search so closing one cannot control the other.
2026-07-15 23:13:55 +02:00
Mohamed BoudraandGitHub dfe3330ef8 Add a keyboard-driven project setup flow (#2097)
* feat(projects): add keyboard-driven project setup

* test(app): update add project loading assertion

* fix(projects): harden GitHub project setup
2026-07-15 21:16:10 +02:00
Mohamed BoudraandGitHub 90e0a0e353 Find and open workspaces from the command center (#2096)
* feat(app): add workspaces to command center

* fix(app): scale down command center typography

* fix(app): avoid workspace theme subscription

* fix(app): theme command center bottom sheet

* fix(app): tighten command center workspace results
2026-07-15 20:40:24 +02:00
Mohamed BoudraandGitHub 328361667f Keep browser sign-ins across tabs and restarts (#2089)
* feat(desktop): share persistent browser data across tabs

Keep browser sign-ins and site storage across tabs and app restarts, with a Settings action to clear the shared profile.

* fix(settings): prevent duplicate browser data clears

* fix(desktop): complete browser data cleanup

Clear legacy per-tab profiles after upgrades and localize the browser data settings in every supported language.

* fix(desktop): close browser profile cleanup races
2026-07-16 00:40:24 +08:00
Mohamed BoudraandGitHub 04e893417e Allow failed agent turns to be forked (#2063)
* fix(chat): allow failed turns to be forked

Failed turns can end in Paseo-generated timeline items without provider
message IDs. Anchor forks to canonical timeline positions while retaining
legacy boundaries for compatibility.

Place the fork summary before the new prompt and delimit it as structured
chat history.

* fix(chat): tighten fork boundary handling
2026-07-15 16:30:42 +02:00
Mohamed Boudra 5ddd5f3726 perf(app): keep desktop sidebar ready to reopen
Retain the hidden sidebar tree so common toggles preserve local UI state while existing activity gates pause expensive hidden work.
2026-07-15 12:05:08 +02:00
Mohamed Boudra 38e4d9ad5d feat(app): polish sidebar and tool call summaries 2026-07-15 11:24:05 +02:00
Mohamed BoudraandGitHub 77f6069ec1 Keep desktop sidebar controls stable across panel changes (#2078)
* fix(app): stabilize desktop sidebar controls

Keep the left-window-controls toggle mounted across sidebar state changes so its position and tooltip state remain stable. Preserve browser placement and show an explicit Explorer close control only where native right-side controls do not provide one.

* fix(app): suppress inactive sidebar chrome
2026-07-15 15:30:57 +08:00
Mohamed BoudraandGitHub 50ed0d0ab1 Fix desktop layout and window controls at half-screen width (#1983)
* fix(app): preserve desktop layout in half-screen windows

Treat native window controls as physical corner obstructions instead of deriving clearance from compact layout state. Keep 751px windows in desktop mode while preserving usable content when persisted sidebars are wide.

* fix(app): retain sidebar width across window resizes

* fix(app): yield app sidebar to narrow settings

* test(app): wait for mobile sidebar motion to settle

* fix(app): yield navigation to narrow workspace explorer

* fix(app): mark sidebar sizing helpers as worklets

* fix(app): hide app navigation when space is constrained
2026-07-14 23:01:14 +02:00
Mohamed BoudraandGitHub 1b8af2e58e Refine tool call summaries and scrolling (#2069)
* feat(app): refine tool call summaries and scrolling

Keep summary groups stable from the first tool call, preserve live activity feedback, and scroll expanded groups to the latest entry. Consolidate web scrollbar styling around the native browser mechanism.

* refactor(app): reuse tool call height constant

* fix(app): preserve tool call summary state

* fix(app): refresh web tool groups on expand

* fix(app): preserve grouped tool errors
2026-07-14 21:16:29 +02:00
Mohamed BoudraandGitHub d781b68711 Polish release notes and in-app help (#2070)
* feat(ui): improve changelog and help navigation

Make release notes easier to scan and reach from the app. Also keep the homepage marquee within the layout viewport so it cannot create horizontal scrolling.

* fix(website): reject duplicate release anchors
2026-07-14 21:06:25 +02:00
Matt CowgerandGitHub 9ea58aae0c fix(server): stop OpenCode daemon crash on session close, fix #2014 (#2027)
* fix(server): patch OpenCode SDK unhandled rejection on stream abort

The SDK's SSE abort handler calls reader.cancel() without handling
its rejection. When Paseo aborts the event stream during normal
session close, that promise can reject and crash the daemon with an
unhandled rejection outside any Paseo-owned code path.

Patches both copies the SDK ships (dist/gen and dist/v2/gen, the
latter being what Paseo actually imports). Extends
postinstall-patches.mjs to support patch-package running from a
non-root cwd, since @opencode-ai/sdk lives in packages/server's own
node_modules rather than the hoisted root.

* fix(server): stop assuming OpenCode's default agent is "build"

OpenCode users can rename or delete any agent, including the built-in
"build"/"plan" defaults. Paseo was injecting a hardcoded "build"
agent in several places whenever no mode was explicitly requested:

- The protocol manifest declared defaultModeId: "build" for opencode,
  which AgentManager.normalizeConfig applied to every session
  (including internal metadata-generation sessions) before any
  provider-level logic ran.
- OpenCode's own normalizeOpenCodeModeId defaulted an empty/"default"
  modeId to "build" rather than omitting the agent field.
- Unattended child creates (e.g. subagents spawned by an unattended
  parent) forced modeId: "build" to express unattendedness, even
  though that's already carried by the auto_accept feature.

Now an unset mode stays unset end-to-end: the "agent" field is
omitted from OpenCode prompt/command calls entirely, letting OpenCode
fall back to its own configured default agent instead of Paseo
guessing one that may not exist.

* fix(server): validate agent create mode on the WebSocket session path

resolveAndValidateCreateAgentMode already rejects modes unknown to a
provider's discovered mode list, but it was only wired into the MCP
create path. App-created agents (create_agent_request) skipped it
entirely, so a client's remembered mode preference — which can go
stale when a user renames or deletes OpenCode agents — sailed through
to the provider and failed mid-turn with an opaque error instead of a
clear rejection at creation time.

resolveSessionCreateAgent now calls
providerSnapshotManager.resolveCreateConfig, matching the MCP path,
so an invalid mode now throws 'Invalid mode ... Available modes: ...'
immediately on create.

* chore: address review feedback on create-agent and postinstall script

- Document the cleanup-ordering constraint in resolveSessionCreateAgent:
  mode validation runs after buildSessionConfig (cwd isn't known until
  that completes), so a thrown validation error leaves any
  worktree/workspace buildSessionConfig created for the caller to clean
  up. session.ts already handles this for the worktree path; the
  directory-only workspace path has a pre-existing gap, not introduced
  by this validation.
- Log spawn errors from patch-package in postinstall-patches.mjs
  (e.g. ENOENT if it's missing from PATH) instead of failing silently.

* fix(server): don't fabricate OpenCode modes when discovery finds none

fetchModesFromClient and mergeOpenCodeModes fell back to
DEFAULT_MODES ([build, plan]) whenever OpenCode discovery returned
nothing — e.g. for a freshly-created worktree whose OpenCode server
hasn't loaded the project config yet. That fabricated list let
create-time mode validation accept a stale 'plan' preference that the
provider then rejects at prompt time (Agent not found: 'plan').

Return an empty list instead: OpenCode users can rename or delete any
agent, so any hardcoded fallback risks validating a mode that doesn't
exist. DEFAULT_MODES is retained only for description enrichment and
sort ordering.

* fix(app): reconcile stale selected mode against discovered modes on create

The mode picker displays modeOptions[0] when the stored modeId isn't
in the discovered list (e.g. a globally-remembered 'plan' that a
workspace's OpenCode config no longer defines), but the create request
still submitted the raw stored modeId. Result: UI showed 'Build' while
the request sent 'plan', which the daemon then rejected.

Reconcile the selected mode against the discovered mode ids when
building the create config (both the workspace draft composer and the
workspace-setup dialog), so the submitted mode matches what the picker
shows — falling back to the first available mode when the stored one is
absent. Mirrors the existing resolveEffectiveModel reconciliation for
models.

* test(server): fix opencode mode tests after fallback change + rebase

- Replace 'available modes include build and plan' (which relied on the
  removed [build, plan] discovery-failure fallback) with two tests:
  one asserting discovered agents map to modes, one asserting empty
  discovery yields no fabricated modes.
- Restore messageId fields in the four provider-subagent timeline
  assertions. These were accidentally dropped during rebase conflict
  resolution; the #2013 subagent code legitimately emits messageId, so
  the expectations must include it.

* test(app): fix e2e seed helper using invalid opencode mode

createIdleAgent seeded an OpenCode agent with modeId
'bypassPermissions' — a Claude mode OpenCode never had. This worked
before only because the session create path silently coerced unknown
modes to 'build'. Now that create-time mode validation rejects modes
the provider doesn't define, use 'build' + auto_accept (OpenCode's
unattended full-access equivalent), matching the rewind-flow helper.

Fixes the e2e failures across archive-tab, command-center-host,
settings-toggle-tab-regression, workspace-agent-tab-rename,
workspace-pane-remount, workspace-navigation-regression, and
worktree-restore specs, which all seed via this helper.
2026-07-14 19:00:53 +08:00
Matt CowgerandGitHub 81113d1582 feat(app): add tool call detail levels (#2031)
* feat(app): compact tool call sequences

* feat(app): summarize compact tool activity

* feat(app): add tool call detail levels

* fix(app): stabilize compact tool groups

* fix(app): address compact tool review feedback
2026-07-14 18:55:06 +08:00
Mohamed BoudraandGitHub 5e2a8b6633 Make help easier to find and cloned workspaces open reliably (#2045)
* feat(app): add sidebar help and support menu

Give users a single place to run diagnostics, find shortcuts, and reach the support channels. Share one global diagnostic sheet between Settings and the sidebar so both entry points collect the same report.

* fix(app): keep cloned workspace navigation atomic

A newly merged clone flow still used the previous navigation signature and opened its draft tab separately. Route the cloned workspace and its draft target through the unified navigation command so attention selection cannot replace the intended tab.

* test(app): harden sidebar help coverage

Accept both the Discord invite URL and its canonical redirect, assert placement through real element geometry, and remove an unnecessary diagnostic-host callback.

* test(app): cover support redirect variants

Keep the help-menu E2E stable across prerelease versions and the valid redirect forms returned by Discord and GitHub.
2026-07-14 00:02:53 +08:00
Mohamed BoudraandGitHub f350c716b9 Keep forked chats focused in new tabs (#2038)
* fix(app): focus explicitly opened workspace tabs

Explicit tab navigation could be overwritten by attention-aware workspace
navigation when the visible agent had just finished. Make workspace navigation
own both normal attention selection and explicit targets so callers cannot
sequence them inconsistently.

* test(app): strengthen forked tab focus assertion
2026-07-13 15:38:09 +02:00
218097b7cc feat: clone GitHub repo into a workspace (#1331)
* feat: clone GitHub repo into a workspace

Add an end-to-end "clone a GitHub repo and register it as a Paseo
workspace" flow: a new workspace.github.clone RPC, daemon handler,
client method, CLI `paseo clone` command, and a GitHub-repo mode in
the project picker modal. Gated behind the workspaceGithubClone
server capability flag.

- protocol: workspace.github.clone request/response schemas + feature flag
- server: handleWorkspaceGithubCloneRequest, normalizeCloneRepository
- client: DaemonClient.cloneGithubWorkspace
- cli: `paseo clone <repo> --dir <path> [--protocol https|ssh]`
- app: GitHub-repo mode, clone-protocol picker, error surfacing

Review fixes:
- CLI clone now checks the workspaceGithubClone capability and fails
  fast with a clear "update the host" error instead of hanging for the
  full request timeout against an older daemon.
- Replace the duplicated client-side URL-detection regex (app + CLI)
  with a shared isCompleteGitRemote() in @getpaseo/protocol/git-remote,
  backed by parseGitRemoteLocation so clients classify remotes
  identically to the daemon (fixes confusing errors for git://, ftp://,
  file:// inputs).
- Add git-remote.test.ts covering the shared classifier.

* Fix GitHub clone failure handling

---------

Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-07-13 11:15:40 +00:00
b6d49da4df Support F-Droid Android builds (#1768)
* fix(android): support source-based APK builds

Co-authored-by: Anton Lazarev <22821309+antonok-edm@users.noreply.github.com>

* fix(android): address fdroid review feedback

Co-authored-by: Anton Lazarev <22821309+antonok-edm@users.noreply.github.com>

* fix(android): complete the F-Droid build profile

* fix(app): isolate the F-Droid runtime flag

---------

Co-authored-by: Anton Lazarev <22821309+antonok-edm@users.noreply.github.com>
2026-07-13 17:18:19 +08:00