Desktop (macOS, Windows, Linux with AppImage/DEB/RPM), Mobile (Android/iOS),
and Web & CLI sections. Simplify homepage download button to a single link
with "All download options" text link below.
Delete unused system-prompt.ts, agent-prompt.md, and the entire
terminal-mcp/ directory (tmux-based MCP server) — nothing imports
any of these. The codebase uses src/terminal/ (node-pty) instead.
When interrupting a Claude agent mid-tool-call and sending a replacement
message, the SDK's abort error result was being attributed to the new
foreground turn, causing [System Error] banners and displaced replies.
Root cause: pendingInterruptAbort was cleared by visible activity from
the new turn before the stale result arrived (timing race), and the
stale result then poisoned the replacement turn.
Fix:
- Suppress stale non-success results at the top of routeSdkMessageFromPump
before any turn attribution, using both flag-based (pendingInterruptAbort)
and content-based (isAbortError) detection
- Stop clearing pendingInterruptAbort on visible activity — only consume
it when a result message arrives
- Prevent idle flash during replacement by checking pendingReplacement
in agent-manager turn_completed/turn_canceled handlers
- Fix vitest env loading to use import.meta.url instead of process.cwd()
- Load .env.test eagerly in agent-configs.ts for collection-time availability
Includes regression tests covering the exact f160a2a3 daemon log ordering.
Commander's --no-* pattern sets options.wait = false, not
options.noWait = true. The check was always falsy so every
send waited up to 10 minutes for the agent to finish.
When a foreground message interrupts an autonomous turn, the notification
content has already been dispatched to subscribers. Canceling says "this
turn didn't happen" — but it did. Complete it instead, preserving the
lifecycle semantics and preventing notification loss.
- Change interrupt() to call completeAutonomousTurn instead of
cancelAutonomousTurn, with flushPendingToolCalls before completion
- Remove dead cancelAutonomousTurn method (no remaining callers)
- Fix autonomous wake tests B and C to handle notification/foreground
timing race: when task_notification arrives during a foreground turn,
there is no separate autonomous running edge afterwards
Remove `pendingInterruptAbort = false` from startTurn() and
`queryRestartNeeded = true` from requestCancel(). Both violated the
existing coordination contracts:
- pendingInterruptAbort must only be cleared by the stream pump at its
safe consumption points, not eagerly by the turn lifecycle
- queryRestartNeeded is for transport-level restarts (config changes,
rewind), not for normal interrupt/cancel flows — setting it on every
cancel killed the Claude process and destroyed background tasks
The actual fix for the send-during-tool-call bug was the manager-side
pendingForegroundRun settlement wait added in the previous commit.
- Add per-provider preference storage: model, mode, thinkingByModel
- resolveFormState reads stored prefs as fallback between initial
values and provider defaults
- setProviderFromUser seeds model/mode/thinking from stored prefs
when switching providers
- persistFormPreferences writes full per-provider state on agent create
- Remove workingDir and serverId from stored preferences (redundant
with workspace tab context)
- Simplify settings.tsx by removing preference-based server resolution
- Fix race in agent-manager where pendingRun wasn't fully cleaned up
before the next streamAgent call, causing "already has an active run"
- Fix Claude agent query restart: null out query/input before awaiting
old iterator return so the old pump skips failActiveTurns
- Reset pendingInterruptAbort on new foreground turn
- Add system error assertion to send-during-tool-call e2e test
- Rename mode color tiers: drop "default", rename "readonly" to
"planning", update color assignments across providers and UI
Strips onnxruntime-node (linux/win32), claude-agent-sdk ripgrep
(non-target platforms), node-pty prebuilds, and sharp libvips from
the app.asar.unpacked directory during afterPack. Saves ~80 MB on
macOS arm64 builds.
Strip parent Claude Code session env vars (CLAUDECODE, CLAUDE_CODE_ENTRYPOINT, etc.)
from child agent environments so spawned agents don't fail with "cannot be launched
inside another Claude Code session". Centralize isProviderAvailable to check both
binary and credential availability. Add red e2e test for send-during-tool-call bug
and force-cancel stale foreground turns in cancelAgentRun.
Narrow zustand selectors to only subscribe to fields each component
actually uses. Split nested objects (availableModes, projectPlacement)
into separate selectors with structural equality checks. Remove the
updatedAt processing-spinner hack in agent-input-area — the server
already guarantees agent status is "running" before ACKing the send
request, so isProcessing can clear on submit success directly.
Replace three competing event paths (foreground stream, live event pump,
JSONL history poller) with a single push-based subscribe() + startTurn()
contract. This fixes duplicate user messages and stuck running state caused
by timing-based routing between concurrent event sources.
Key changes:
- AgentSession interface: remove stream(), add subscribe() and startTurn()
- All providers (Claude, Codex, OpenCode): single subscribers Set with
notifySubscribers() for push-based event delivery and turnId stamping
- Agent manager: identity-based turn ownership via activeForegroundTurnId
replacing pendingRun async generator
- Delete: dual queues, routeSdkMessageFromPump, startLiveHistoryPolling,
snapHistoryOffsetToEnd, liveEventBacklog, Pushable
- Fix Codex provider not clearing activeForegroundTurnId on turn completion
- Add real-provider integration tests for event stream invariants
* Expose PASEO_AGENT_ID to managed agents
* refactor(server): make managed agent launch context explicit
* refactor(server): pass launch env through agent providers
* fix: use workspace-agnostic root tsconfig
* fix(server): align CI tests with current agent behavior
* fix(server): restore Claude history and sidechain CI coverage
* fix(app): move keyboard focus to target pane on keyboard navigation (#137)
Add a pane focus registry so each panel type can expose its own focus
callback. When keyboard shortcuts navigate between panes, the workspace
screen calls the target panel's registered focus function, moving DOM
focus to the correct input element.
- Agent panels register a callback that focuses the message input
- Terminal panels register a callback that triggers terminal focus
- Panel-internal focus logic stays inside each panel type
- No DOM selectors or panel knowledge in shared infrastructure
* fix(app): simplify workspace pane focus handoff
- Add detail card above command list showing full description and argument hint
- Compact command rows to single line (label + truncated description)
- Match dropdown component styling (surface1 bg, borderAccent border, shadow)
When packaged, Electron's process.execPath points to the main app
binary which inherits the full app entitlements and UI lifecycle.
Resolve to the Helper binary instead so daemon child processes run
without inheriting the main app's entitlement/UI baggage.
Remove private flag, add publishConfig with public access, point
types to dist output, and include highlight in release:check,
release:publish, and dry-run scripts.
The scoped package name @getpaseo/desktop was leaking into the tar.gz
artifact name. GitHub sanitizes the / to . on upload, causing a name
mismatch that prevents electron-builder's overwrite logic from finding
the existing asset on rebuild.