Commit Graph
2095 Commits
Author SHA1 Message Date
PMandpaseo-bot[bot] b0ce40804d fix(acp): enable terminal client capability by default (#3910)
* fix(acp): enable terminal client capability by default (#3812)

* test(acp): remove non-asserting Kimi coverage

---------

Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
2026-08-27 08:10:25 +00:00
Mohamed Boudra ecfb77b014 feat(plugins): install and update Git sources (#3920)
Make every trusted Git repository directly distributable without introducing a registry or package manager. Managed checkouts retain their resolved commit, track branches explicitly, and stage validation before activation so failed updates restore the running version.
2026-08-27 15:24:01 +08:00
4de913fb82 fix(server): plugin daemon sessions see all providers by pinning the daemon appVersion (#3902)
* fix(server): expose all providers to plugin sessions

* fix(app): route workspace actions semantically (#3896)

* fix(app): route workspace actions semantically

Separate Explorer visibility from view navigation, and give composer changes and pull request opens semantic routing owners. Unify diff destinations, keep compact PR navigation in Explorer, and derive maximize availability from visible workspace panes.

* test(app): cover composer changes routing

Update the browser journey for the Explorer-first composer action, then assert the second press follows the shared diff destination.

* test(server): track plugin runtime dependency parameter

---------

Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
2026-08-26 20:57:22 +00:00
paseo-bot[bot] 96cf0f2ae5 chore(server): upgrade Claude Agent SDK to 0.3.246 (#3893)
* chore(server): upgrade Claude Agent SDK to 0.3.246

Bumps @anthropic-ai/claude-agent-sdk from 0.3.220 to 0.3.246, keeping the
pinned exact version so fresh installs stay reproducible.

The SDK's peer requirements are unchanged (@anthropic-ai/sdk >=0.93.0,
@modelcontextprotocol/sdk ^1.29.0, zod ^4.0.0) and already satisfied, so
nothing else in the tree moves.

Nothing Paseo imports was removed or narrowed. The type surface Paseo
touches is additive; the removed ExitReason member
'bypass_permissions_disabled' and the OnElicitation/OnUserDialog signature
changes are unused here.

* chore(nix): refresh npm deps hash for the SDK bump

---------

Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
2026-08-26 20:32:56 +08:00
Mohamed Boudra 59e6232784 fix(server): resolve canceled permission requests (#3792)
Provider callbacks can be canceled without a user response. Publish a terminal resolution for that path so every surfaced request has a matching lifecycle event, while preserving the existing interruption cleanup.
2026-08-26 09:53:41 +02:00
nllptrxandMohamed Boudra 4a5716360b Feat/forge check semantics and followup fixes (#2337)
* feat(protocol): add forge check presentation metadata

Expose optional rawStatus, isManual, and requiresAction fields while keeping older check payloads backward-compatible.

* fix(gitea): model Actions jobs as tasks

Gitea's /actions/tasks endpoint returns individual jobs rather than workflow runs. Preserve sibling tasks from the latest execution, avoid collapsing same-name jobs, and enrich blocked tasks with run-level approval metadata.

* feat(app): distinguish forge check presentation states

* fix(gitlab): preserve pipeline job semantics

* refactor(app): centralize forge check presentation policy

Use one canonical category order, count shape, visual policy, and translated copy mapping across sidebar, hover-card, PR-pane, and GitLab pipeline surfaces.

* refactor: consolidate forge check handling

* feat(forge): auto-attach pasted forge references

* docs(compat): correct forge rollout metadata

* refactor(forge): model check nuances as traits

* fix(forge): harden checks from branch review

Structural Gitea Actions shadow dedup by run id (verified upstream),
rerun grouping without workflow_id, shared trait/status constants and
Gitea state mapping in the protocol package, all cloud host aliases in
pasted-link matching, logged glab job-detail failures, concurrent
approvals/pipeline fetch, checks aggregate from the same pipeline as
the job list, and removal of the unread check-level rawStatus. The
released pipeline-level rawStatus is staged for removal under
COMPAT(pipelineRawStatus).

* fix(gitea): detect fork-PR Actions approval hold as action_required

gitea.com represents a fork PR awaiting Actions approval as a run in
status "waiting" with no tasks and pending shadow commit statuses; it
does not expose need_approval. The previous mapping only set
action_required from a task with blocked+need_approval, so the gate
never surfaced (0 tasks -> early return; need_approval absent). Detect
the hold from /actions/runs: a waiting/blocked run whose PR is
cross-repo (head.repo.id != base.repo.id), or one that does expose
need_approval (self-hosted). Tag the run's pending shadow statuses
action_required. Runs are only fetched when a pending shadow has no
covering task, keeping the common path at two requests. Verified live
against gitea.com fork PR (run 715170, waiting, cross-repo).

* fix(gitea): resolve cross-fork PRs by head sha

The current-PR matcher gated candidates on the checkout owner
(giteaHeadOwner === expectedHeadOwner), which excludes every fork PR:
its head carries the fork owner while the checkout is the base repo, so
a fork PR - the only shape that can be approval-held on Gitea - never
resolved and its checks never showed in-app. GitLab has no such gate
(it resolves fork MRs from the target project by source branch). Accept
a recent PR whose head sha equals the workspace head sha regardless of
owner; the sha is an unambiguous identity, so the anti-collision owner
gate still applies when no sha match is available. Verified live against
gitea.com fork PR #6 (resolves + renders action_required).

* fix: resolve forge rebase drift

* fix: type forge auto-attach boundary

* fix(i18n): add Korean check status copy

---------

Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-08-25 23:37:50 +02:00
e22ad117fd Stream assistant text at a steady rate instead of in arrival lumps (#3612)
* Stream assistant text at a steady rate instead of in arrival lumps

Assistant text arrived in lumps and was painted that way. The daemon
coalesces one message per 60ms window, and that window carries however
many characters the model produced in it, which swings by an order of
magnitude within a turn. Painting each delta as it landed made the size
of those lumps visible.

Three changes:

- The agent stream coalescer is now leading + trailing. The first delta
  after an idle window flushes synchronously instead of waiting a full
  window, matching the invariant TerminalOutputCoalescer already
  documents. The window stays at 60ms; shrinking it would raise message
  rate on a loop that already contends with terminal frames and relay
  encryption, without making the stream smoother.

- The client reducer queue commits on a frame instead of an arbitrary
  48ms timer, with the timer kept as a ceiling so a hidden tab still
  advances.

- Assistant and reasoning text are revealed at a rate derived from the
  backlog rather than from arrival timing. Arrival changes the target,
  not the rate. The store keeps the full text and only the rendered
  slice is paced, so copy, selection, the chat outline, and scroll
  geometry all stay consistent with what is on screen.

The leading flush means a burst's first chunk lands as its own timeline
row. The projection already merges contiguous same-turn rows and clients
read the projected timeline, so history is unchanged; the server tests
that assert on raw rows were updated for the extra row.

Measured on Expo web against a local dev daemon. Mock bursty-stream
provider, 6s samples, paint-on-arrival vs paced: frames that advanced
the text 55 -> 244, chars-per-frame CV 2.66 -> 1.44, gap p50 100ms ->
17ms. Real Claude Haiku agent over 52s: 84% of frames advance the text,
CV 1.29, gap p50 and p95 both 17ms (one frame at 60Hz).

Adds a bursty-stream mock model with seeded burst sizes, a gated browser
perf spec, and docs/agent-stream-performance.md.

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

* Address review: safe reveal boundaries and a testable seam

Two findings from the PR review.

Unicode boundaries. Slicing the revealed text at an arbitrary index could
strand a lone surrogate, which paints as a replacement glyph, or split an
emoji ZWJ sequence so a family briefly rendered as its members. Both were
visible for a frame or two mid-stream — the exact flicker the paced reveal
exists to remove. The rendered cut is now pulled back off surrogate pairs,
combining marks, variation selectors, skin tone modifiers, and ZWJ joins.
The reveal counter stays monotonic and only the painted boundary moves, so
a long cluster cannot stall the reveal.

Test placement. The hook test used JSDOM, @testing-library renderHook, and
monkey-patched requestAnimationFrame, all of which docs/testing.md rules
out; it prescribes fixing the missing seam instead. The reveal policy is
now a pure state machine in text-reveal.ts (begin/retarget/advance/
complete/visible) covered by plain unit tests with no environment, and the
hook is reduced to the frame-clock binding. Rendered behavior is left to
the browser spec, which no longer carries frame sampling and statistics in
its body — those moved to e2e/support/helpers/stream-smoothness.ts.

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

* Measure total painted text, not the tail message

The smoothness sampler read the length of the last assistant-message
element. A real turn emits many assistant messages, so that element keeps
changing identity and its length is not monotonic — handovers read as
resets, and a stream that was plainly moving on screen reported almost no
growth at all. Sampling the total across every assistant message fixes it.

This invalidated the numbers previously recorded for the real-agent run,
so the doc table is replaced with a fresh A/B taken with the corrected
sampler against a Claude Haiku agent: frames that advanced the text 6% ->
87%, chars-per-frame CV 4.11 -> 1.86, gap p50 317ms -> 17ms, p95 383ms ->
17ms. The paced column also reported zero Unicode defects across a stream
containing emoji, which exercises the reveal boundary clamp end to end.

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

* perf(agent-stream): harden paced text reveal

Use standards-compliant grapheme segmentation when available and preserve full arrivals on older runtimes. Cap reveal commits at 60Hz and measure the real browser rendering path so high-refresh displays stay smooth without rendering at hardware frame rate.

* Hold back trailing fragments split by arrival boundaries

The reveal boundary is not the only place a grapheme gets cut. The
daemon's coalescing window ends a delta wherever the window closes, so a
caught-up reveal can be handed half a cluster and paint it. Measured on a
mixed-script Haiku stream: five frames in ~350 ending in a single regional
indicator, i.e. half a flag on screen for a frame.

While the turn is streaming, a trailing fragment that cannot stand alone —
a dangling high surrogate, a trailing joiner, an odd regional indicator —
now waits for the rest of its cluster. Once the turn ends everything
received is painted, because nothing more is coming. Complements the
grapheme-boundary clamp, which handles the reveal cut; this handles the
arrival cut.

The same stream now measures one such frame in ~400 rather than five. The
remainder is a flush boundary that coincides with the end of an assistant
message, putting the two halves in different messages, which the client
cannot rejoin — that one belongs in the coalescer.

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

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-08-25 23:37:46 +02:00
Mohamed Boudra e19d3914ae fix(rewind): replace long timelines without replay (#3642)
* fix(rewind): refresh canonical timeline after rewind

A rewind replaces the daemon timeline and epoch, but replaying the rebuilt history made long conversations visibly reload from the beginning. Capable clients now refresh the existing bounded tail path after a replacement signal while legacy clients retain replay compatibility.

* test(rewind): cover coherent timeline replacement

Hold rewind completion in the browser regression so it can verify the existing pending state and detect any reconstructed timeline rows before the normal tail refresh is allowed to finish.
2026-08-25 23:37:12 +02:00
Mohamed Boudra 20d7efc46a chore(release): cut 0.6.1 2026-08-25 21:50:24 +02:00
Mohamed Boudra 4bfb682cd9 Cut Playwright feedback time without losing behavioral coverage (#3852)
* test(app): consolidate Playwright journeys

* test(app): stabilize consolidated Playwright flows

* test(app): make streaming dependencies explicit

* test(app): await profile feature persistence

* test(app): sample only actual workspace tabs
2026-08-25 20:55:05 +02:00
Mohamed Boudra 8bfae15855 Keep current pull requests visible without wrongful auto-archive (#3799)
* fix(server): keep current PR visible without unsafe archival

PR discovery and merge-triggered archival answer different questions. Follow the checked-out branch for status, while requiring the daemon to observe the same PR move from open to merged before archiving a workspace.

* test(server): align managed worktree PR lookup expectation

Managed metadata without a matching PR target must not hide the unambiguous PR identity from the current branch tracking configuration.
2026-08-25 19:43:18 +02:00
Mohamed Boudra 6da9fa43fa chore(release): cut 0.6.0 2026-08-25 15:58:11 +02:00
Mohamed Boudra 6f6466d4cb Wait for authoritative provider readiness before prompting (#3821)
* fix(server): trust provider connection lifecycle events

Readiness now waits for the upstream connection event, and later connection events directly trigger the existing gap repair. This removes the parallel synthetic reconnection contract while preserving transport ownership and prompt gating.

* test(server): model OpenCode global event envelopes
2026-08-25 15:28:06 +02:00
Mohamed Boudra 54299a2e6c fix(server): let event-stream startup recover once (#3814)
The readiness wait expired at the same boundary as the producer watchdog, so a reconnect already initiated by the event consumer could never benefit the pending turn. Keep dispatch gated, allow that retry to land, and preserve the actual SDK failure details for logs and user-visible reports.
2026-08-24 19:31:11 +02:00
Mohamed Boudra 4092c29265 chore(release): cut 0.5.2 2026-08-24 14:30:57 +02:00
Mohamed Boudra 88f410567d Revert "fix(server): honor Claude bypass permission mode (#3732)"
This reverts commit f998ee1691.
2026-08-24 11:05:19 +02:00
wongangandMohamed Boudra f998ee1691 fix(server): honor Claude bypass permission mode (#3732)
Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-08-24 10:49:12 +02:00
Mohamed Boudra f517493591 chore(release): cut 0.5.1 2026-08-23 19:37:03 +02:00
Mohamed Boudra b8a31034ca chore(release): cut 0.5.0 2026-08-23 15:42:11 +02:00
Mohamed Boudra 3979371901 fix(server): recover already-settled interrupts (#3742)
* fix(server): recover already-settled interrupts

Provider state can drift from Paseo’s tracked run. Treat an authoritative already-idle interrupt as settled and retire the captured run token so retrying can start new work without weakening ambiguous-cancellation protection.

* fix(codex): fence interruption during turn startup

Reserve foreground-start ownership before asynchronous provider setup. An interrupt can now cancel preflight before turn/start or wait for an issued start to become interruptible, preventing acknowledged cancellation from leaving unmanaged work.
2026-08-23 14:59:36 +02:00
Dan Berindei 71e375c2bc fix(server): stop quota fetcher from writing provider credentials (#3442) 2026-08-23 14:24:18 +02:00
Mohamed Boudra acad9f6881 chore(release): cut 0.5.0-beta.5 2026-08-22 23:35:40 +02:00
Mohamed Boudra a687c42f33 Keep released agent SDK versions reproducible (#3678)
Pin the validated provider and protocol SDK dependency pair so fresh installs cannot silently float after a Paseo release. Refresh the Nix npm dependency hash for the resulting lockfile.
2026-08-22 11:10:20 +02:00
Mohamed Boudra c763b80824 fix(files): keep large source previews responsive (#3665)
Large read-only files bypassed the editor's virtualization and eagerly mounted every highlighted token, which could stall the renderer for seconds and consume gigabytes of memory. Route source previews through bounded platform renderers and reject reads above their display budgets before accumulation.
2026-08-22 10:13:31 +02:00
Mohamed Boudra 8905ad4160 fix(relay): validate handshake keys (#3669) 2026-08-22 02:32:13 +02:00
BrianAguilarWascoandMohamed Boudra 60a5344cc6 fix(server): stop short start gates from undercutting provider startup budgets (#3621)
* fix(server): stop short start gates from undercutting provider startup budgets

Agent creation still failed on contended cold starts after #3578, because two
shorter gates on the same path fire before the event-stream readiness budget can
apply. A traced creation reached session.create twelve seconds in, past the 10s
session.create gate, and the agent was then killed by a bare "timeout" at fifteen
seconds from AGENT_RUN_START_TIMEOUT_MS while the SSE connect was still running.

A run-start bound of 15s wraps a path that is deliberately allowed 30s, so the
outer gate always wins and the inner budget is unreachable.

Give session.create the shared OPENCODE_SERVER_STARTUP_TIMEOUT_MS budget, since
creating the first session for a directory is part of OpenCode coming up, and
derive its error message from the constant instead of hardcoding "10s". Raise
AGENT_RUN_START_TIMEOUT_MS to 60s with a comment recording that it must stay
above the slowest provider startup budget; it stays a literal because that module
is provider-agnostic.

Related to #3571.

* test(server): drive the run start budget through a real AgentManager

The run start boundary tests replaced AgentManager.waitForAgentRunStart with a
bare timer, so they never exercised the production run-state transition or the
agent_state subscription the real wait depends on. That path could regress while
the tests stayed green.

Build the scenario on a real AgentManager with a provider session that holds its
turn start open for a configurable span, so pendingRun.started, the lifecycle
change to "running", and the agent_state notification are what the wait actually
observes. Budgets stay independent literals and the settled-before/after
assertions are unchanged.

* fix(server): describe agent run start timeouts

---------

Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-08-22 02:06:16 +02:00
Mohamed Boudra 956f6ea7ad fix(server): keep agent timelines in memory (#3647)
The filesystem timeline store rewrote each agent's full transcript on every buffered update, causing write amplification that grew with conversation length. Return production timelines to runtime memory and provider-history hydration while preserving the dormant storage interface for a future intentional design.
2026-08-21 18:59:09 +02:00
Mohamed Boudra f660fcf2e5 chore(release): cut 0.5.0-beta.4 2026-08-21 16:35:11 +02:00
Mohamed Boudra c032df5b3d Keep Pi chats active through retry recovery (#3639)
* fix(server): preserve Pi turns through retries

Pi reports each provider attempt with agent_end, while agent_settled marks the final user-turn boundary. Keeping modern streams active until settlement prevents a recovered attempt from leaving the chat in an error state.

* fix(server): show Pi provider retries

Automatic retries keep the turn alive, but users still need to understand the delay. Surface Pi's retry-start signal through the existing non-terminal error activity row without changing terminal lifecycle handling.

* refactor(server): clarify Pi retry boundaries

Use the server's object-parameter convention for the retry boundary helpers so their event, turn, and retry semantics stay explicit as the lifecycle evolves.
2026-08-21 12:16:19 +02:00
Okan YILDIRIM e1805ef542 feat(plugins): add theme contributions
Adds plugin-contributed light and dark app themes, including persistence, host-aware coalescing, fallback behavior, documentation, examples, and browser/iOS QA.
2026-08-21 11:48:12 +02:00
Matt CowgerandMohamed Boudra bc02cfd8cd feat(opencode): steer active turns without interrupting (#3580)
* feat(opencode): add active-turn steering via native V2 prompt

Add OpenCode support for active-turn steering (PR #3394) using the
native V2 session prompt with delivery: steer. Implements
steerActiveTurn, pending steer echo correlation for multiple steers,
prompted event handling, and definitive vs ambiguous error handling.
Updates docs and SDK to 1.18.18 for typed V2 access.

* fix(opencode): use V1 prompt for steer so model sees it

V2 prompt was admitted to a separate inbox not visible to the V1
processor, so "How old is bigbird?" was shown inline but never in
the LLM context. Switch steer to session/prompt_async (V1) which
queues while busy and is included in the next LLM call's history.
Update tests to expect V1 and keep the timeline grouping.

* fix(opencode): honor steering permission contract

Admit the steer before denying permissions that block its delivery, matching the provider steering contract. Remove the abandoned V2 path and SDK upgrade because active-turn delivery uses the existing prompt endpoint.

* chore(opencode): preserve SDK patch metadata

---------

Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-08-21 10:38:36 +02:00
efa25ad3fe fix(server): show Claude usage again on macOS (#3597)
* fix(server): show Claude usage again on macOS

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

* fix(server): keep an incomplete Keychain item from hiding a working one

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

* chore(server): tighten Claude keychain fix

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-08-20 23:02:25 +02:00
BrianAguilarWasco 28a963795b fix(server): extend OpenCode event stream readiness timeout to match server startup budget
Closes #3571.
2026-08-20 22:56:18 +02:00
Mohamed Boudra 3f7188bc1c fix(codex): restore externally archived active threads (#3334)
Codex threads can be archived outside Paseo while their Paseo agent remains active. Repair that provider-state drift during interactive resume while preserving the existing read-only history path for Paseo-archived agents.
2026-08-21 04:39:26 +08:00
c6b04f302a fix(server): stop a steered prompt from deadlocking on a permission (#3585)
* fix(server): stop a steered prompt from deadlocking on a permission

Claude parks its turn inside the blocking canUseTool callback while a
plan approval or a tool prompt waits for an answer. The SDK stops to
read its input stream there, so a message sent at the open card is
queued and never read. The user must reject the card or interrupt the
agent by hand, and then send the message a second time.

Deny the pending permissions after the steer is admitted. The prompt is
already in the SDK input queue when the permission callback returns, so
Claude reads it in the same turn. Plan mode stays on and no turn
restarts.

One pass is not enough. A turn that made several tool calls opens its
next request 10 to 300 milliseconds after the previous one is answered,
so a single snapshot advances the batch by one and parks the turn again.
The Claude adapter already tracks the steers the SDK has not read, so
expose that as an optional AgentSession.hasUnreadSteer and answer each
new request while that method reports the prompt as unread. The release
stops the moment the prompt is read, so a permission the agent asks for
after it acts on the message still reaches the user.

Only the two entrypoints that carry a message from a person set the
flag. A scheduled prompt, a child-finished notification, and an
agent-to-agent prompt must not answer a card the user is looking at.

Denial left no timeline row, so a denied plan disappeared from the
transcript. Claude and Codex now push a plan_approval row with
approved: false. For Codex the row comes from resolvePlanPermission,
which is the path that dismissPendingPlanApprovals also uses.

In the app, queue mode held the message until the turn ended, and a
parked turn never ends. The composer now sends while a permission is
pending, and the button label agrees with the submit path.

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

* fix(server): keep a post-prompt permission out of the release

The release loop answered the pending requests before it asked whether
the agent had read the prompt. The agent can read the prompt during a
poll interval and then open a permission request because of it. The next
pass denied that request, so a decision that belongs to the user was
made for them.

The loop now asks first and answers second. The first pass stays
unconditional, because a provider that does not report unread steers
must still get one release.

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

* fix(server): make steer permission clearing provider-owned

Keep the daemon policy explicit while letting each provider queue the steer and release permissions that block it. This removes timing-based polling and preserves rejected plans as canonical timeline rows.

* fix(server): preserve omitted steer options

Only construct provider steer options when permission clearing is requested. System prompts otherwise keep the existing undefined options contract.

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-08-20 14:02:00 +02:00
Mohamed Boudra 4dbd26c88c fix(server): accept Git-valid worktree branch names (#3591)
Branch-off creation reused the filesystem slug validator even when callers supplied a separate branch name and worktree slug. Validate branch refs with Git at the worktree boundary so exact valid refs are preserved while path slugs remain restricted.
2026-08-20 09:44:29 +02:00
Mohamed Boudra dd8efba552 chore(release): cut 0.5.0-beta.3 2026-08-20 09:12:30 +02:00
Matt Cowger bed5d2b1be fix(server): add upstream remote fallback to GitHub PR checkout refs (#2997) 2026-08-20 02:54:30 +08:00
Mohamed Boudra ccd991b3e3 chore(release): cut 0.5.0-beta.2 2026-08-19 16:30:43 +02:00
Mohamed Boudra 929d2b717e fix(plugins): publish the plugin SDK under the @getpaseo scope
The daemon imports the plugin SDK at runtime, but the workspace was named
@paseo/plugin and marked private, so it was never published. 0.5.0-beta.1
shipped @getpaseo/server depending on a package that does not exist and
`npm install @getpaseo/cli@beta` failed with a 404 for every user.

Two things hid it. sync-workspace-versions only rewrites deps matching
@getpaseo/*, so the "*" range on @paseo/plugin survived untouched into the
published tarball. And `npm pack --dry-run`, which is all release:check and
CI run, lists files without ever resolving the dependency graph.

Renaming to @getpaseo/plugin rather than publishing the old name: @paseo is
not our scope on npm, so that name could never have been published at all.
The rename also brings the package under the version-sync filter, which is
what pins it correctly from here on.

Plugins scaffolded against the old name still import @paseo/plugin. Both
spellings resolve through plugin-sdk-specifiers.ts, tagged COMPAT with a
removal date, so existing plugins keep loading.

This does not repair 0.5.0-beta.1 — a published tarball's dependencies
cannot be changed. The package publishes with the next release.
2026-08-19 15:52:51 +02:00
Mohamed Boudra e12bdc2fc5 test(server): align directory search expectations 2026-08-19 13:06:06 +02:00
Mohamed Boudra e883b692b0 chore(release): cut 0.5.0-beta.1 2026-08-19 12:40:33 +02:00
Mohamed Boudra ab619f982e fix(server): isolate esbuild binary override
Esbuild reads its binary override during module evaluation, but the previous global environment mutation leaked that host-only path into desktop-launched agents. Scope the compatibility bridge to module loading and scrub the variable from external process environments.
2026-08-19 12:20:32 +02:00
Mohamed Boudra e55dd5a212 fix(search): match complete paths in file and project search
Treat slash-separated fragments as searchable text and use the same full-path fuzzy matcher for daemon results and remembered project paths.
2026-08-19 12:18:23 +02:00
Mohamed Boudra 91024bc029 fix(plugins): install local plugins on packaged desktop
The plugin compiler spawned esbuild through app.asar, and the subprocess
imported the React client barrel. Point esbuild at the unpacked binary,
add a react-free @paseo/plugin/server entry, and pass a typed PluginTheme
so plugin UI follows the active theme on desktop and mobile.
2026-08-19 11:54:55 +02:00
Mohamed BoudraandSlava Goltser 9c9a85a0cf feat(pi): emit live usage updates during turns (#3532)
Port the OMP usage poller into the Pi provider so context/token usage
updates during active turns instead of only at completion.

- Add PiUsagePoller with 3s throttle, dedup, and generation-based cancellation
- Wire poller into PiRpcAgentSession turn lifecycle
- Add unit tests for polling, dedup, error handling, and turn completion

Co-authored-by: Slava Goltser <slavikg@gmail.com>
2026-08-19 07:42:19 +02:00
Mohamed Boudra f9e1def954 fix(server): keep interrupt-window Claude output from starting a turn
After an interrupt, Claude keeps emitting messages about the request it
was told to kill — the notification for the tool it just stopped,
trailing assistant output. The router classified them as new work and
opened an autonomous turn, but the only message that could close that
turn is the interrupt result shouldSuppressStaleResult drops, so the
agent reported running forever.

Pre-existing, but masked until the steer-discard fix: the undiscarded
steer used to resume the turn and its result accidentally closed the
phantom one. pendingInterruptAbort already marks the window where
messages belong to the dying request, so the router now refuses to open
a turn while it is set.
2026-08-18 22:15:19 +02:00
Mohamed Boudra f7e4606452 fix(server): discard unread Claude steers on interrupt
A steer pushed into the live SDK query input survived query.interrupt():
the SDK dequeued it afterwards and resumed the turn the user had just
stopped. Codex clears pending turn input when it aborts a turn; Claude
does not, so its adapter now cancels the SDK messages it queued before
interrupting.

Interrupt-discards is the deliberate ceiling for steer cancellation:
Codex exposes no un-steer operation, so a cross-provider take-back
cannot exist. A steer the model never read keeps its transcript row.
2026-08-18 21:51:38 +02:00
Mohamed Boudra 403a32ad9f fix(server): steer autonomous agent turns
A running autonomous turn was excluded from steer admission because only foreground ownership was considered. That silently degraded steering into interruption and could race a provider-initiated restart, dropping the prompt.\n\nUse the provider's canonical active-turn identity for admission so autonomous work receives steering on its existing stream without replacement.
2026-08-18 15:59:13 +02:00
Mohamed Boudra c09be7efa2 fix(server): preserve resumed subagent identity
A resumed native child can be announced under a fresh tool call while retaining its session-scoped task identity. Treat later tool-call identifiers as aliases so lifecycle, usage, and timeline events continue through the original descriptor instead of splitting into contradictory rows.
2026-08-18 15:20:06 +02:00