* feat(git): add manual refresh button to diff controls
Adds a checkout_refresh RPC that forces a hard re-read of the git and
GitHub snapshot plus the diff, bypassing polling. The diff controls now
show a refresh button (feature-gated) that triggers it and surfaces
errors via a toast — an escape hatch when the polled state goes stale.
* refactor(git): address review — dotted RPC name + withUnistyles
- Rename checkout_refresh RPC to the dotted convention
(checkout.refresh.request/response) per docs/rpc-namespacing.md.
- Replace the banned useUnistyles() call in DiffRefreshButton with
withUnistyles wrappers for the icon/spinner color, per docs/unistyles.md.
* refactor(git): move refresh into the checkout actions store
Per the feature audit: the manual refresh was the one checkout action
whose UI logic lived inline in the component instead of alongside its
siblings (commit/pull/push) in useCheckoutGitActionsStore. Move it into
the store so there's one home for "UI triggers a checkout RPC" — it now
reuses runCheckoutAction's pending/success status and query invalidation.
The component just reads status and shows an error toast.
* fix(git): size refresh loader to the icon to stop layout shift
ActivityIndicator size="small" renders ~20px regardless of platform,
wider than the 14px refresh icon, so swapping to it grew the button and
shifted the controls row. Use SyncedLoader at the same iconSize — it
renders into a size×size box, so both states share one footprint.
* fix(git): match file-explorer refresh control (RotateCw + LoadingSpinner)
Mirror the file-explorer pane's refresh button exactly: RotateCw icon,
LoadingSpinner while refreshing, both centered in a fixed icon-sized box
so the spinner can't grow the control or shift the row. Replaces the
ad-hoc RefreshCw + SyncedLoader pairing.
* Move local speech work out of daemon
Run local speech models in a lazily spawned worker so native model memory and blocking synthesis/transcription work stay out of the daemon process. The worker exits after idle time so local speech RSS can be reclaimed.
* Update supervisor stop test for process title
Opus 4.8 (and its 1M-context variant) become the default Claude
models, pushing Opus 4.6 off the default slot. Opus 4.7 stays in
the list as the previous release.
* Archive agents on worktree archive; clean up schedules on archive
Worktree archive used to hard-delete every agent inside it (storage
removed, agent_deleted emitted), losing history along with the worktree.
It now archives those agents instead, so they remain in storage with an
archivedAt timestamp and stay visible in the archived list.
Schedules targeting an archived agent were left as dead records that the
schedule service rejected at run time. AgentManager now fires an
onAgentArchived callback from every archive path (live, stored snapshot,
cascade-to-children), and bootstrap wires it to
ScheduleService.deleteForAgent so those schedules are cleaned up
automatically.
* Push agent_state when archiving stored-only agents; tolerate schedule delete errors
Greptile review on PR #1206 flagged two issues:
1. archiveSnapshot persisted archivedAt to storage but did not emit an
agent_state event for stored-only agents. Connected clients would
keep showing them as active until a full reload. Mirror the dispatch
logic from markRecordArchived: notifyAgentState for live agents,
dispatchArchivedStoredAgent for off-memory non-internal agents.
2. ScheduleService.deleteForAgent used Promise.all, which short-circuits
on the first store error and abandons the rest. Switch to
Promise.allSettled, count fulfilled deletions, and log rejections.
* Tighten agent-manager archive tests after /audit-tests review
- Split "fires onAgentArchived for live, stored, and cascaded archives"
into two single-behavior tests with independent fixtures, so the assertion
array isn't reset mid-test.
- Strict equality on the cascade hook assertion (no more arrayContaining).
- "archiveSnapshot dispatches archived state" now captures the full agent
state event, asserts a dispatch happened, asserts the dispatched agent
id, and asserts the lifecycle is closed.
The app must not import @getpaseo/server. Moving the slug validation
and slugify helpers into @getpaseo/protocol (already a shared dep of
app, client, server) gives every package a legitimate home for the
import. Drops the corresponding ./utils/branch-slug subpath from
@getpaseo/server's exports map.
Unblocks the Deploy App workflow, which only builds protocol/client/
audio for the app — server's dist never exists in that pipeline.
* Align MCP provider controls with app provider state
* Deepen provider snapshot routing
* Make provider snapshots the daemon authority
* Move provider shutdown behind a generic AgentClient seam
OpenCodeServerManager is now owned entirely by the OpenCode provider.
ProviderSnapshotManager.shutdown() and provider-registry.shutdownProviders()
materialize enabled clients and call an optional shutdown() per client; the
OpenCode client forwards to its runtime. Other providers ignore it.
Also wires providerSnapshotManager into the remaining Session-constructing
tests that were missing it (server-tests CI failure).
* Use platform-native cwd in change-event test
The seven Map-based caches in WorkspaceGitServiceImpl had no eviction —
the 15s TTL only marked entries stale before refetching in place. Long-
lived daemons accumulated entries for every ephemeral worktree cwd that
ever ran, with checkoutDiffCache holding multi-MB highlighted diffs.
Switch to LRUCache. checkoutDiffCache caps at 64 (heavy values); the
other six aux caches cap at 256. Stale-in-place TTL semantics are
unchanged.
* Extract client SDK package
* Polish SDK client identity defaults
* Build client before dependent CI jobs
* Restore daemon client server export
* Extract protocol and client SDK packages
* Fix provider override schema validation
* Fix app test daemon client imports
* Simplify workspace build targets
* Fix CLI test server build bootstrap
* Run SDK package tests in CI
* Fix rebase package split drift
* Restore lockfile registry metadata
* Update SDK config test for prompt default
* Move terminal stream router test to client package
* Fix rebase drift for protocol imports
* Fix SDK agent capability fixture
* Restore legacy server client exports
* Fix server export compatibility test
* Advertise custom mode icon client capability
* Remove server daemon-client exports
* Format rebased mode control import
* Fix rebase drift for protocol imports
Files added by upstream PRs (#893, #1147, #1154) referenced the pre-split
shared/ paths that this branch moves into @getpaseo/protocol. Redirect
those imports to the protocol package so typecheck stays green after the
rebase.
opencode's Edit tool sends camelCase input keys (filePath, oldString,
newString) and a plain-string success ack on output. The shared edit
schemas expect snake_case input and an object output, so calls fell
through to the generic "unknown" renderer (raw JSON Input/Output).
Normalize both at the opencode boundary so the quirk does not leak into
the cross-provider schema.
Tests stubbed the old dep set and asserted on call signatures
that no longer match after the getCheckoutSnapshotFacts work was
threaded through refresh/observation/getPullRequestStatus.
Surface all enabled providers in the model selector with inline loading
and error states instead of silently hiding non-ready ones. Tap any row
to drill in; loading and error states show in the drill-down body, with
a Retry button on error. Providers with no models render a synthetic
"Default" row so every provider's drill-down has symmetric structure.
Redesign the per-provider settings sheet: search lives in the header,
discovered and custom models share one scrolling list, and the footer
hosts action buttons. Diagnostic and "Add model" each open as their own
sub-sheet, so neither expands inline or shifts the surrounding layout.
Snapshot refresh now keeps cached data visible: setQueryData replaces
the cache atomically and sibling-scope caches are invalidated (not
removed), so refreshing a provider no longer blanks its row. Search
inputs across the app are uncontrolled — onChangeText drives parent
state, and resetKey remounts the field when an explicit reset is needed
— to avoid RN's controlled-input flicker.
Adds a dev-only mock-slow provider whose discovery never resolves, so
the 30s snapshot timeout produces a real error and lets loading and
timeout-error UI be exercised end to end.
* Extract permission response command
* Extract create agent command
* Extract agent lifecycle commands
* refactor(server): extract worktree archive command
* refactor(server): share worktree create list commands
* test(server): update close items lifecycle fakes
* Fix MCP command stack CI regressions
* Restore MCP update_agent no-op success semantics
After the rebase, MCP `update_agent` was returning `success: false` for empty/no-op calls (no name, no labels, no settings). Origin/main returned `success: true` unconditionally. The audit flagged the change as out of scope for this stack — restore the old behavior at the MCP boundary.
Session WS path keeps its accepted/rejected semantics (it surfaces an error when nothing was provided so the client can prompt the user).
* Fix agent metadata delegation and mode persistence
* Update MCP update_agent test for metadata delegation
* Fix stored agent metadata timestamps
Wildcard listen addresses are bind targets, not client endpoints. Inject loopback for agent MCP URLs and surface OpenCode MCP add failures returned in data payloads.
Old clients pinned AgentModeIcon to a closed enum and rendered
undefined for unknown values, crashing the route in production
Hermes with no stack trace. Loosen the type to a plain string,
let the client skip rendering when an icon is unregistered, and
add the customModeIcons capability so the daemon downgrades
non-legacy icons to ShieldCheck for clients that pre-date the
open-string contract.
Wait for the initial background turn to actually start before create returns a snapshot, without waiting for completion.
Freshly created agents now surface start failures as create failures, and both the WS/client and MCP surfaces reflect the shared create-agent lifecycle helper.
Treat undefined, blank, whitespace-only, and /__omit__ cadence values as absent at the MCP boundary for schedule create and update.
That keeps placeholder inputs from tripping cadence validation while preserving the real invalid cases for conflicting or missing cadence values.
System-injected prompts (finish notifications, schedule fires) are wrapped
in a <paseo-system> envelope and dispatched as regular user messages to
the provider. The app was showing them as user-message turns. Detect the
envelope at the manager boundary and skip them during live runs and
history replay so only real user input renders.
config.title is now strictly the caller's creation intent and is never
mutated. The prompt-derived placeholder lives only in record.title at
creation, so the metadata generator's upfront gate (hasExplicitTitle) is
the only one and writes unconditionally when it runs. Drops the two
projection fallbacks to record.config.title that were the second
hidden path for the prompt to surface as a title.
OpenCode emits session.error with MessageAbortedError when the user
interrupts a running turn. Paseo was mapping every session.error to
turn_failed, which set the agent lifecycle to error and appended a
raw JSON system error message to the timeline.
Now MessageAbortedError translates to turn_canceled (same as an
explicit cancel), so the agent returns to idle with no error state.
Real errors still produce turn_failed.
* Add Pi extension-launch plumbing for in-process tree primitives
* Add Rewind controls for agent sessions
* Preserve SDK checkpoint env var so Claude file rewind works
The SDK injects CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING=true when file checkpointing is enabled. The earlier parent-env stripping from c4782ec71c was too broad and removed that child flag along with real parent-session markers.
Keep stripping parent markers, but preserve the checkpoint flag so the SDK rewind path can run directly. With that boundary fixed, the JSONL file-rewind fallback is no longer needed.
* Update OpenCode history replay tests for rewind state
* Show Rewind actions in an adaptive sheet
* Fix rewind semantics across providers
* Refactor Pi IDs through extension capture
* Restore user message to composer after rewind
* Fix Claude rewind tool result mapping
* Fix Claude rewind session switch roundtrip
* Fix rewind and optimistic message regressions
* Tighten rewind test discipline
* Fix OpenCode optimistic message reconciliation
* Reconcile optimistic user messages by marker
* Reorder user message actions
* Unify provider user message contract
* Add Claude rewind flow Playwright contract
* Add Codex rewind flow Playwright contract
* Add OpenCode rewind flow Playwright contract
* Add Pi rewind flow Playwright contract
* Remove real-provider rewind Playwright contracts
* Gate real-provider rewind specs from CI Playwright