Commit Graph
294 Commits
Author SHA1 Message Date
Mohamed BoudraandGitHub d4435bd016 perf(app): keep warm workspace switching responsive (#3447)
* perf(app): reduce warm workspace switch work

Retained workspaces avoided mounts but pane activity still rerendered the full composer, message input, and agent-control presentation. Keep the activity contract intact while moving focus-sensitive behavior behind small context consumers, and add a Playwright benchmark that measures rapid retained workspace switching on one browser clock.

* perf(app): accelerate retained workspace switching

Avoid repeated retained-stream layout reconciliation and unrelated workspace structure recomputation. Use the lightweight route transition while the host is already focused, while preserving targeted root POP_TO for returns from app-wide routes where it prevents duplicate hidden decks.

* perf(app): defer composer focus during workspace switches

* perf(app): retain recently used workspaces longer

Keep up to ten workspace screens warm so normal multi-workspace navigation does not repeatedly rebuild recently used timelines. Inactive screens expire after ten minutes, while the active screen remains protected and capacity eviction stays least-recently-used.

* fix(app): reconcile retained timeline geometry

* fix(app): refresh retained reading position
2026-08-16 12:40:28 +02:00
Mohamed BoudraandGitHub 23853a1515 Add managed local plugin lifecycle (#3222)
* feat(plugins): add local plugin surfaces and RPCs

Keep plugin execution scoped to its daemon while allowing one local TypeScript entry point to contribute validated RPCs and native client surfaces. Paseo owns host selection, navigation chrome, and per-installation query caches.

* feat(plugins): add Linear attachment source

* fix(nix): refresh npm dependency hash

* test(server): exclude internal sessions from Hub counts

* test(server): distinguish Hub execution sessions

* feat(plugins): make local plugins explicitly opt-in

Keep plugin loading dormant until configuration enables it, and collect unsupported examples under one directory.

* refactor(plugins): establish host boundaries

* fix(nix): refresh plugin dependency hash

* fix(plugins): complete packaging and startup rollback

* feat(plugins): add managed local lifecycle

Make trusted local plugins recoverable and authorable through daemon-owned lifecycle operations, host settings, and a capability-gated CLI. Reloads fully stop the previous plugin before starting new code, while generated projects provide strict TSX checking without changing runtime dependency ownership.

* fix(nix): refresh plugin dependency hash
2026-08-14 17:12:49 +02:00
30195d3bd1 fix(app): make composer input IME-safe and paste-aware (#3343)
* fix(app): preserve native composer input semantics

Native text was round-tripped through application state on every keystroke, which could overwrite an input method's in-flight edits. Keep native text ownership inside the input and reserve application-driven replacement for explicit draft mutations.\n\nRoute native clipboard images through the existing persisted attachment pipeline so keyboard and system paste actions behave like other image sources.

* fix(nix): refresh dependency hash

The native composer dependency changes the fixed npm dependency closure used by desktop builds.

* fix(app): keep composer locked across image pastes

Count concurrent native image persistence operations so submit remains disabled until every pasted image is attached.

* fix(app): replace composer text through the DOM on web

Web TextInput refs are DOM elements, so application-driven draft replacement must update their value and selection without native setNativeProps.

* fix(app): preserve web IME composition

Carry the Chinese IME fix from #2990 into the web composer input boundary.

Co-authored-by: Jimmy Lee <jimersylee+github@gmail.com>

---------

Co-authored-by: Jimmy Lee <jimersylee+github@gmail.com>
2026-08-14 11:52:24 +02:00
Mohamed Boudra b44bb63cf4 chore(release): cut 0.4.0 2026-08-13 21:31:47 +02:00
Mohamed Boudra 44b9980a70 chore(release): cut 0.4.0-beta.2 2026-08-12 23:18:28 +02:00
Mohamed Boudra 0c6dbefa40 chore(release): cut 0.4.0-beta.1 2026-08-12 20:39:35 +02:00
Mohamed BoudraandGitHub 23d7a8eaf9 Improve Markdown file preview readability (#3240)
* feat(app): improve markdown file previews

Keep rendered documents on the chat reading rail, surface YAML front matter as readable metadata, and make shared Markdown links retain the chat accent and hover treatment.

* fix(app): preserve unsafe frontmatter source

* test(app): cover markdown link behavior
2026-08-12 00:18:30 +02:00
7253228dc5 feat(app): render mermaid diagrams in agent chat with pan/zoom (#2306)
* feat(app): render mermaid diagrams in agent chat with pan/zoom

Fenced mermaid blocks in assistant messages now render as diagrams
instead of code blocks.

Web: mermaid renders inline via dynamic import (code-split, loads on
first diagram). Drag to pan, ctrl/cmd+wheel or trackpad pinch to zoom
about the cursor, double-click to reset; plain wheel still scrolls the
chat. Rendered SVGs are cached across virtualization remounts.

iOS/Android: diagrams render in a WebView running a self-contained
generated bundle (build:mermaid-webview, mirrors the native terminal's
xterm pattern — no CDN, mermaid ships in the app). The inline preview
is touch-shielded and height-driven by a bridge message; tapping opens
a fullscreen viewer where the platform WebView owns pinch-zoom.

Streaming source that doesn't parse yet falls back to the highlighted
code block and keeps the last good render; renders are serialized
through one queue with stale-task skipping so token-by-token updates
cost at most one in-flight layout.

Security: mermaid can fetch external resources during layout (image
shapes, CSS url()) before output sanitization runs — see
mermaid-js/mermaid#7645 — so resource-bearing source is rejected
up front (containsUnsafeMermaidSource) on every platform, htmlLabels
stay off, securityLevel is strict, and the mermaid secure list is
extended so directives can't override app theming or themeCSS.

The lockfile diff includes npm 11.17 normalization churn beyond the
mermaid closure; a no-op npm install produces the same rewrite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(app): serialize native mermaid renders and pin viewer to last good source

Serialize render messages inside the mermaid webview entry so a newer
streamed update can't re-initialize global mermaid state (e.g. flip the
theme) while a prior layout is still running; superseded queued renders
are skipped. Track the last successfully rendered source on the RN side
and open the fullscreen viewer with that, so tapping mid-stream while
the latest chunk is still invalid can't show a blank viewer.

Addresses PR review feedback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(app): pair native mermaid renders with their source via request id

A "rendered" bridge event was credited to the newest sent source, but an
older render can complete while a newer (possibly invalid) chunk's send
is in flight, mis-crediting the older render's success to the newer
source. Render messages now carry a request id that the entry echoes on
rendered/renderError; the RN side resolves the source by id, so the
fullscreen viewer always opens the exact source that produced the
visible render.

Addresses PR review feedback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(app): harden mermaid guard and native preview per adversarial review

- Guard bypass (blocker): mermaid accepts quoted and unicode-escaped
  object keys, so quoted "img": evaded the resource denylist while
  still parsing into a real img property. The guard now decodes u/x
  escapes and strips quoting characters before matching, and tests
  both raw and normalized source.
- structuredClone polyfill banner in the webview bundle: the app's iOS
  floor is 15.1 but structuredClone exists only from 15.4; esbuild
  targets don't polyfill runtime APIs.
- Preview height sizes the inner content view so fence padding/borders
  no longer clip the reported SVG height, and measurement happens at
  the final content width (measuring overlay keeps the fence insets).
- The invisible measuring overlay is hit-test transparent, so an
  invalid diagram's fallback code block keeps its copy button and
  gestures.
- renderError now prunes all superseded source-map entries, matching
  the rendered path, so a long broken stream can't accumulate sources.
- The entry's render chain can no longer be poisoned: the whole task
  body is inside try/catch and the chain appends a trailing catch.
- "Mermaid diagram" accessibility label is translated in all locales
  (message.mermaidDiagram) on web and native.
- esbuild pinned in packages/app devDependencies so the generated
  webview artifact doesn't depend on hoisting layout; </script is
  escaped in the generated JS.

Addresses adversarial review round 2.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(app): mermaid source toggle and visible zoom controls

Web: a hover control cluster on the diagram (zoom in/out anchored to
the viewport center, reset view, view source) mirroring the code
block's hover-copy idiom; always visible on compact form factors where
hover doesn't exist. View source swaps to the highlighted code block
(with its own copy button) and a view-diagram button swaps back.

Native: the fullscreen viewer gains a source toggle beside the close
button, swapping the webview for the highlighted source in a
scrollable view.

All control labels are translated in every locale under
message.mermaid.*; the flat mermaidDiagram key from the previous
commit is folded into the same group.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(app): align mermaid control icons with the app's icon vocabulary

Network is the settings Connections icon — reusing it for "view
diagram" gave one glyph two meanings; use Workflow instead. RotateCw is
the app's established reset/reload glyph (RotateCcw had no precedent).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(app): use Scan for mermaid reset-view control

RotateCw is the app's reload glyph (19 uses) — a reset-zoom button
wearing it invites a reload misread. Scan (corner-bracket fit-to-frame)
is unused and carries the intended fit/reset semantics.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(app): remove raw NUL byte from mermaid cache key separator

A literal 0x00 in the template string made git classify the file as
binary, rendering the PR diff for it unreviewable. Use the escaped
sequence instead — identical runtime key, plain-text source.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(app): align mermaid source-view toggle with the copy button

The source view wrapped the code block while the fence margins stayed
inside it, so the floating view-diagram toggle hung in the margin
whitespace above the visible box — misaligned with the code block's
copy button and outside its hover region. Hoist the margins onto the
wrapper (both buttons now share the box edge) and render the toggle in
the copy button's plain style so the pair reads as one control row.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(app): close mermaid review findings

* chore(app): finish Mermaid PR rebase cleanup

* refactor(app): isolate diagram rendering and stabilize streaming

* fix(app): keep Mermaid previews stable while streaming

* fix(nix): update npm dependency hash

* fix(app): preserve streamed rows through completion

---------

Co-authored-by: Damon Meledones <dmeledon@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-08-11 14:46:05 +08:00
Mohamed Boudra bfec7ac3ad chore(release): cut 0.3.1 2026-08-09 13:30:33 +02:00
Mohamed Boudra 7392e1b767 chore(release): cut 0.3.0 2026-08-08 10:56:30 +02:00
Mohamed Boudra a7c7a6e482 chore(release): cut 0.3.0-beta.4 2026-08-07 23:59:18 +02:00
Mohamed Boudra 86ff0a18c4 chore(release): cut 0.3.0-beta.3 2026-08-07 18:09:43 +02:00
Mohamed BoudraandGitHub c1f7ed3198 Improve reconnect status feedback (#2931)
* fix(app): debounce reconnect status toast

Keep reconnect transport immediate while delaying the visible status toast so brief outages stay quiet. Scope the toast to the active retained panel, keep its copy and status dot consistent across locales, and add a manual real relay deployment journey that verifies streaming recovery without user action.

* fix(app): isolate manual relay deployment check

Keep the deployment journey out of the provider-wide real test project so it runs only when its local relay prerequisites are explicitly requested. Also keep the relay teardown active when packaged daemon startup or later cleanup fails.

* fix(app): preserve reconnect toast across tabs

Keep reconnect presentation timing at the host level so switching between retained panels does not restart the debounce or flash the toast. Add a browser regression covering a visible outage across retained tab switches.

* fix(app): anchor reconnect debounce to host status

Record host connection status transitions independently of mounted agent panels and preserve the outage start across reconnecting states. Use that host-level timestamp when a visible agent panel appears, with runtime coverage for the transition lifecycle.

* fix(app): reset reconnect toast state per outage

* test(app): build relay journey prerequisites
2026-08-06 13:45:34 +02:00
Mohamed Boudra d227ff3e83 chore(release): cut 0.3.0-beta.2 2026-08-05 15:30:50 +02:00
Mohamed Boudra 9916e3d185 chore(release): cut 0.3.0-beta.1 2026-08-04 21:27:12 +02:00
Mohamed Boudra 98c9878c57 fix(app): keep composer above Android keyboard
Pin the keyboard controller to the release that prevents stale keyboard positioning from leaving the composer underneath a keyboard that is still visible.
2026-08-04 09:33:20 +02:00
Mohamed BoudraandGitHub adf33930b3 Preserve assistant selection formatting when copying (#2808)
* fix(app): preserve formatting when copying assistant selections

Browser selection serialized React Native Web layout nodes instead of the assistant message semantics. Recover semantic markup from renderer-owned metadata and reuse the rich clipboard generator used by Copy turn.

* fix(app): preserve assistant copy semantics

Carry source-only Markdown metadata through the selection copy boundary, unwrap generated code links, and cover ordered starts, hard breaks, and fence languages in Playwright. Refresh the Nix dependency hash for the added clipboard dependency.

* fix(app): preserve partial selection context

Wrap selected fragments with their shared semantic ancestor chain and enable GFM table and strikethrough conversion. Cover partial nested selections and GFM output through the browser clipboard.

* fix(app): preserve copied list and autolink text

Adjust partial ordered-list starts for omitted siblings, strip parser-generated anchors before Markdown reconstruction, and refresh the Nix dependency hash computed by CI.

* fix(app): normalize partial selection context

Normalize cloned ordered lists across block boundaries, degrade incomplete table fragments to selected text, and preserve table alignment provenance through Markdown reconstruction.

* fix(app): escape copied table delimiters

Rendered table cells no longer retain source escape characters. Escape literal pipes during DOM-to-Markdown conversion so copied tables preserve their column structure.

* fix(app): preserve authored link semantics

The rendered link boundary conflated parser-generated links with authored autolinks and discarded authored titles. Carry title semantics into the anchor and unwrap only links with explicit generated provenance.

* fix(app): preserve nested copy structure

Blank-line splitting separated loose nested lists before Markdown rendering, leaving no nesting for clipboard serialization to preserve. Derive protected separators from the Markdown block structure and keep copy metadata independent from monospace surface styling.

* fix(app): preserve selected file links

Assistant messages and rich clipboard HTML must apply the same link validation policy. A shared parser keeps file links semantic in both MIME representations while retaining markdown-it's unsafe-scheme rejection.

* fix(app): preserve partial table content

A selected body row wider than its retained header cannot be represented as GFM and is truncated when rich HTML is regenerated. Treat only those over-wide fragments, plus headerless fragments, as incomplete while preserving valid short rows.
2026-08-03 19:02:31 +08:00
Mohamed BoudraandGitHub 5a30affd7f Skip unrelated required checks without losing their names (#2542)
* fix(ci): skip unrelated required checks cleanly

Matrix jobs had to start no-op runners to preserve interpolated required-check names. Static named jobs let GitHub report genuine skipped conclusions while keeping those names stable.

* fix(ci): gate changes to install patching script

* fix(ci): route cross-package test contracts narrowly

* fix(ci): keep routed contracts merge-blocking

* fix(server): exclude nested test utilities from builds

* fix(ci): cover app-owned native and browser domains

* refactor(ci): align tests with runtime domains

Own browser specs, desktop specs, and Electron-only app code by stable directories so PR routing does not depend on filename conventions. Keep desktop integration coverage inside the required desktop check.

* fix(ci): keep routing and desktop suites isolated

The routing regression must run before dependency installation, and desktop Vitest must not collect Playwright-owned specs.

* fix(ci): isolate desktop e2e runtime

* perf(test): isolate Playwright workers

* perf(test): parallelize Playwright within specs

* fix(test): keep Playwright file scheduling

* fix(test): share dynamic Metro fixture

* fix(test): preserve own-host restart fixtures

* fix(ci): preserve routed contracts after rebase

* Stabilize Playwright wheel-scroll assertions
2026-08-02 00:56:05 +08:00
Mohamed BoudraandGitHub 79fccb368d chore(app): ship mobile updates through stores only (#2708)
Paseo does not publish EAS updates, so remove the update runtime and channel metadata from native builds.
2026-08-01 03:28:26 +08:00
Mohamed Boudra 6fc491e622 chore(release): cut 0.2.5 2026-07-30 13:22:40 +02:00
Mohamed Boudra 2f913736fa chore(release): cut 0.2.4 2026-07-30 01:48:57 +02:00
Mohamed Boudra 43cf858c37 chore(release): cut 0.2.3 2026-07-27 19:46:38 +02:00
Mohamed BoudraandGitHub c9fb31f709 Fix Claude 5 context window selection (#2433)
* fix(claude): select the correct Opus 5 context window

Bare Opus 5 IDs resolve to 200K behind third-party gateways. Expose explicit context variants and require a Claude Code version that recognizes the model.

* fix(claude): add Fable and Sonnet context variants

* test(cli): expect Claude context variants

* test(cli): compose Claude catalog expectations

* fix(claude): preserve catalog on version probe failure

* fix(claude): preserve parsed context variants

* chore(release): cut 0.2.2
2026-07-26 10:03:44 +02:00
Mohamed Boudra 36f38245ca chore(release): cut 0.2.1 2026-07-24 19:40:41 +02:00
Mohamed Boudra d98c5e77f7 chore(release): cut 0.2.0 2026-07-24 13:27:13 +02:00
Mohamed Boudra b02acb882c chore(release): cut 0.2.0-beta.4 2026-07-24 00:16:25 +02:00
Mohamed Boudra 8a1243e8d3 chore(release): cut 0.2.0-beta.3 2026-07-22 23:26:47 +02:00
Mohamed Boudra 89a022e853 chore(release): cut 0.2.0-beta.2 2026-07-22 10:56:55 +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 Boudra 0bec06c2db chore(release): cut 0.2.0-beta.1 2026-07-17 15:10:06 +02:00
Mohamed BoudraandGitHub 6db7e53b6e Record the 0.1.110 ACP hotfix release (#2150)
Sync the 0.1.110 release metadata and changelog back to main.
2026-07-16 23:01:31 +02:00
Mohamed Boudra 42e101c81e chore(release): cut 0.1.109 2026-07-16 09:46:41 +02:00
Mohamed Boudra 75ea0d4534 chore(release): cut 0.1.108 2026-07-16 00:15:57 +02: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
Mohamed Boudra 9553f4b328 chore(release): cut 0.1.107 2026-07-13 00:27:43 +02:00
Mohamed Boudra a1821d5863 chore(release): cut 0.1.106 2026-07-12 10:42:56 +02:00
Mohamed Boudra e98ba1beb1 chore(release): cut 0.1.106-beta.1 2026-07-11 20:45:30 +02:00
Mohamed Boudra 4c72bf0209 chore(release): cut 0.1.105 2026-07-10 12:58:31 +02:00
Mohamed BoudraandGitHub 61a9117a6b Restore fuzzy project folder search and desktop browsing (#1968)
* fix(projects): restore folder search and browsing

* fix(projects): preserve fuzzy search edge cases

* test(projects): move picker cleanup into fixture

* fix(projects): preserve absolute path descendants

* test(server): compare canonical search paths

* fix(projects): anchor root path suggestions

* fix(projects): anchor Windows root suggestions

* fix(projects): anchor directory search paths

* test(server): canonicalize directory search root

* fix(app): anchor rooted basename suggestions

* refactor(search): unify directory suggestions

Use one parameterized daemon search engine for project paths and workspace entries. Keep local recommendations as a small client overlay and remove unnecessary response metadata.

* fix(search): preserve filesystem root semantics

Accept absolute queries through configured root aliases while keeping traversal and output canonical. Keep blank suffix browsing matcher-independent and avoid metadata-keyed listing caches where Windows cannot invalidate them reliably.
2026-07-10 17:52:55 +08:00
Mohamed Boudra f3fdeab131 chore(release): cut 0.1.104 2026-07-08 12:47:07 +02:00
Mohamed Boudra a85139c3f3 chore(release): cut 0.1.104-beta.5 2026-07-07 23:01:34 +02:00
Mohamed Boudra 391cf75ece chore(release): cut 0.1.104-beta.4 2026-07-06 09:58:20 +02:00
Mohamed Boudra b3eb77981a chore(release): cut 0.1.104-beta.3 2026-07-04 10:22:14 +02:00
Mohamed Boudra 75b11ac93e chore(release): cut 0.1.104-beta.2 2026-07-03 11:58:21 +02:00
Mohamed Boudra a13fa4e614 chore(release): cut 0.1.104-beta.1 2026-07-03 08:27:07 +02:00
Mohamed Boudra f41dde8c72 chore(release): sync Sonnet 5 stable release to main 2026-07-01 22:36:37 +02:00
Mohamed Boudra e32c50f2d7 chore(release): cut 0.1.102 2026-06-30 12:00:31 +02:00
Mohamed Boudra 8eb9640f28 chore(release): cut 0.1.102-beta.2 2026-06-30 00:02:06 +02:00
Mohamed Boudra c7e27fdd5b chore(release): cut 0.1.102-beta.1 2026-06-27 05:08:20 +00:00
huiliaoningandGitHub 26a8a04651 fix(projects): make freshly-added projects editable
Make workspace-less projects flow through aggregated project fetching and keep the settings screen editable immediately after adding one.
2026-06-27 12:44:16 +08:00