`window` exists on React Native (aliased to `global`) but `window.location` is
undefined, so reading `window.location.pathname` threw and killed the redirect
effect — leaving the host index route stuck rendering null (blank screen).
Use the `pathname` from `usePathname()` directly, restoring the pre-refactor
behavior that worked on both web and native.
Images and GitHub issues/PRs now live in one draft-store list (ComposerAttachment union) with cwd persisted on the draft. Paperclip becomes a + drop-up menu; queue button removed. Each pill uses a shared AttachmentPill wrapper with a corner-X that mirrors the auto-update toast spec. Pill body opens the attachment: GitHub via openExternalUrl, images via a new fullscreen AttachmentLightbox. GitHub picker auto-closes on select.
If a first archive attempt removed git's admin dir but failed to clean the
working tree (e.g. due to file churn during setup), retrying the archive
failed the ownership gate with "Worktree is not a Paseo-owned worktree"
because isPaseoOwnedWorktreeCwd required the worktree to still appear in
git worktree list.
- isPaseoOwnedWorktreeCwd now decides ownership by path shape
($PASEO_HOME/worktrees/<hash>/<slug>[/...]) and treats git as
best-effort for resolving repoRoot.
- deletePaseoWorktree tolerates a missing admin dir: it skips teardown
when the tree is absent, swallows a failing git worktree remove so
the rmSync fallback always runs, and follows up with git worktree
prune to clear stale admin refs.
- Relabel the post-creation setup failure log as
"Background worktree setup failed" since the worktree itself already
exists at that point.
Assistant markdown images with ~-prefixed paths hit ENOENT because
path.resolve doesn't expand ~, leaving paths like
workspaceRoot/~/rest-of-path that never resolve. Reuse the existing
resolvePathFromBase helper so tilde paths inside the workspace load
instead of getting stuck on the image spinner; the sandbox check still
rejects tilde paths that resolve outside the workspace.
Adds claude-opus-4-7 and claude-opus-4-7[1m] alongside the existing 4.6
entries (4.6 stays default). Opus 4.7 introduces a new "xhigh" effort
level between high and max; the option only surfaces on 4.7 models.
The SDK 0.2.71 effort union doesn't yet include xhigh, so the value is
cast at the assignment site.
Tightens transparent icon gaps to 4px and gives filled action buttons
(send, interrupt) a 4px left margin so they sit 8px from neighbors.
Shrinks context-window meter SVG from 20 to 16 to match the visual
weight of surrounding icons.
The selector returned a freshly constructed authority object each call, so
useSyncExternalStore saw a new reference every render and force-rerendered,
producing a maximum update depth crash. Select the specific workspace
descriptor (stable reference) and derive the authority via useMemo.
The opaque-workspace-identifier refactor (e6044264) added a `b64_` prefix
to base64-encoded workspace IDs in route builders. Two app tests still
expected the unprefixed form and failed in CI.
Session.unarchiveAgentState(id) and the direct agentManager.unarchiveSnapshotByHandle
delegation were removed when main's 86bb5cc8 + a11c246b refactors moved unarchive
through the shared mcp-shared helper. Remove the now-dead test assertions so the
suite reflects the real ownership boundary.
Split the OpenCode reliability bullet into four per-PR entries, shorten
the Windows and provider-models bullets, and drop low-signal qualifiers.
Add a "Changelog conciseness" section to the release playbook so the
next agent knows bullets must be scannable in one glance.
Extract `unarchiveAgentState` and `sendPromptToAgent` into `mcp-shared`
so every surface (app/WS, MCP, CLI-through-MCP) runs the same sequence:
unarchive → ensureAgentLoaded → optional mode change → recordUserMessage
→ startAgentRun. MCP `send_agent_prompt` previously skipped unarchive and
cold-agent rehydration, so sending to an archived agent over MCP left it
hidden from `paseo ls` and failed entirely when the agent wasn't already
in memory. Session now delegates to the shared function and its private
`unarchiveAgentState` is gone.
Some status output (e.g. "Not logged in") goes to stderr. Capture both
stdout and stderr, including when the command exits non-zero, so the
diagnostic surfaces the full picture.
Return stdout verbatim instead of parsing JSON fields. Parser was fragile
to upstream schema changes and added no value — users can read the raw
output directly.
Explicit `undefined` keys on optional snapshot fields were converted
to `null` by `ensureValidJson`, failing `AgentSnapshotPayloadSchema`
validation on the wire. Stop writing those keys so they remain absent,
which is what `.optional()` expects.
Also adds a test that parses `list_agents` output through the schema
to catch this class of bug.
* fix(server): harden Codex/Windows startup and provider resolution
Addresses #452, #443, #353, #418, #403, #221, #307, and locks in #284.
- Replace custom where.exe/which output parsing with npm `which@^5` plus a
spawn probe. findExecutable now enumerates all PATH+PATHEXT candidates
and returns the first invokable one. A WindowsApps-ACL'd codex.exe no
longer wins over a working codex.cmd (#452).
- Make default provider isAvailable() check the binary instead of always
returning true. Codex/Claude/OpenCode default isAvailable() now defer
to isCommandAvailable() so missing CLIs surface as unavailable instead
of throwing later from spawn (#221, #443).
- Gate AgentManager.resumeAgentFromPersistence on isAvailable() so a
persisted agent record with a missing binary cannot reach provider
spawn during rehydration. The daemon stays up and the agent reports
unavailable (#443, #353, #418, #403).
- Drop --path-format=absolute from rev-parse callers and validate stdout
through a shared parser that rejects multi-line output and unknown-flag
echoes. --show-toplevel is absolute by default in modern Git;
--git-common-dir is resolved against the command cwd. Fixes workspace
registration on pre-2.31 Git that echoed the unknown flag and produced
a two-line "path" (#307).
Tests:
- Real-FS executable.test.ts using temp PATH fixtures, covering the .cmd
fallback after .exe pre-spawn failure (Windows-only) plus the
null-on-no-invokable-candidate case.
- provider-availability.test.ts builds real provider clients against a
temp-dir-only PATH for Codex/Claude/OpenCode.
- bootstrap-provider-availability.test.ts builds the daemon and triggers
ensureAgentLoaded so it actually exercises resumeAgentFromPersistence.
- claude-agent.spawn.test.ts asserts shell: false reaches spawnProcess
from the Claude SDK spawn override, locking in 39b56af4 for #284.
- checkout-git-rev-parse.test.ts covers nested-checkout resolution and
the old-Git multi-line stdout case via a tightly-scoped runGitCommand
fake.
CI:
- server-tests-windows now also runs the new and modified test files so
the Windows behaviors are exercised on windows-latest.
* fix: update lockfile signatures and Nix hash
* fix(server): handle synchronous spawn UNKNOWN on Windows
On Windows, child_process.spawn() throws synchronously when invoked on
a corrupt or invalid .exe (e.g., a WindowsApps stub the current user
cannot execute, or a zero-byte file). The executable probe did not
guard the spawn call, so the synchronous throw rejected the probe
promise instead of resolving false, preventing findExecutable() from
trying the next candidate. This is the root cause of the daemon-crash
pattern in #452: codex.exe from WindowsApps would hard-fail before the
.cmd shim ever got a chance.
Wrap spawn() in try/catch and settle false on sync throw. The existing
error-event and exit-event handlers already cover async failure modes;
sync throw just needed one more guard.
Also adjust three Windows-only test comparisons that were asserting
platform-dependent string equality:
- executable.test: compare .cmd paths case-insensitively (which@5
preserves PATHEXT casing, which is uppercase in production).
- workspace-registry-model.test: expect normalizeWorkspaceId(path),
not the hardcoded POSIX form.
- checkout-git-rev-parse.test: normalize separators/case when
comparing git's Windows forward-slash output against realpathSync.
* test(server): canonicalize repo root via git on Windows to fix short-name mismatch
realpathSync on Windows preserves 8.3 short names (e.g. RUNNER~1) while git's
rev-parse --show-toplevel always returns the long-name form (runneradmin).
Use git as the canonicalizer on both sides of the assertion so the comparison
holds regardless of how Windows exposes the temp directory path.
* fix(server): Claude is always available in default mode; SDK bundles cli.js
The Phase 2 change wrongly tied Claude's default-mode isAvailable() to
isCommandAvailable("claude"). Claude's default runtime does not use an
external `claude` binary — @anthropic-ai/claude-agent-sdk ships its own
cli.js and spawnClaudeCodeProcess runs it via process.execPath. The
previous `return true` was correct; restore it.
Update provider-availability.test.ts to assert the truthful behavior:
Claude reports available even when no `claude` binary is on PATH.
Codex and OpenCode genuinely require their binaries on PATH, so their
availability checks remain unchanged.
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Gate the GitBranch icon behind isGitCheckout, and keep the header
skeleton visible until the checkout status query resolves so the icon
doesn't pop in and cause layout shift.
* feat: add server-side TTL for provider snapshots and model list UI
Provider snapshots cached forever, causing newly available models
(e.g. OpenCode Go minimax, glm) to never appear in the picker.
Server: ProviderSnapshotManager now returns stale data immediately
and kicks off a background re-warm when the snapshot is older than
5 minutes. Injectable TTL/clock for testing.
App: Provider settings rows show model count and are tappable to
open a diagnostic sheet with a read-only model list (label + ID).
* feat: add per-provider refresh for models and diagnostic
* refactor: await refresh completion and clean up diagnostic sheet state
- ProviderSnapshotManager.refresh is now async; session.ts awaits it so
the RPC ACK reflects real completion instead of just queuing work.
- Preserve models/modes/fetchedAt on entries during targeted refresh so
the list no longer flashes empty mid-refresh.
- Show "Updated Xs ago" next to the Models count, plus loading and
error states for the list body.
- Split resetSnapshotToLoading into full vs targeted branches.
- Flatten nested ternary in model list rendering into renderModelsBody.
- Drop redundant local refreshing state and cargo useMemo wrappers.
* fix(app): widen isImeComposingKeyboardEvent type to accept optional fields
TextInputKeyPressEventData has isComposing and keyCode as optional, so
Pick<KeyboardEvent, ...> was too narrow and broke typecheck on main.
Add `selectable` prop to the code line Text component so users can
long-press to select and copy text on iOS. On web/desktop this is
already the default behavior via CSS user-select.
Markdown file preview has a similar issue but requires a different
fix (custom rules for react-native-markdown-display), left for a
follow-up.
Refs #238
Related #21
Co-authored-by: muzhi1991 <muzhi1991@limuzhideMac-mini-2.local>
- Add attribution format requiring PR link and contributor GitHub for each bullet
- Skip attribution for core team (@boudra); changelog highlights community work
- One bullet can reference multiple PRs and contributors; de-duplicate names
- Document ordering: user-facing features first, then QoL, then internal-with-user-benefit
Surface structured permission detail for OpenCode requests so clients can show command intent and richer context instead of generic placeholders. Humanize permission titles and include scope/reason metadata to make approval decisions clearer.
* style(app): theme native scrollbars in tool call detail views
Apply CSS scrollbar-color to all ScrollViews in ToolCallDetailsContent
and DiffViewer so the browser scrollbar matches the app's dark theme
instead of showing the default white native scrollbar.
* refactor: split useWebScrollbarStyle into .web.ts/.native.ts platform files
- Native shim returns undefined without calling useUnistyles
- Web variant uses properly typed WebScrollbarStyle interface instead of `as any`
- Add .d.ts for TypeScript module resolution
---------
Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
Extract shared functions from session.ts (toAgentPersistenceHandle,
buildStoredAgentPayload, ensureAgentLoaded) so both CLI/WebSocket
handlers and MCP tools use the same code paths for agent lookup.
Fix get_agent_status, get_agent_activity, and list_agents MCP tools
to fall back to persistent storage for archived agents. Add
includeArchived param to list_agents. Fix setupFinishNotification
to not wake archived callers. Delete dead agent-management-mcp.ts.
Allow providers to specify tools that should be disabled via a
disallowedTools array in config.json. This is useful for providers
that extend "claude" but point to third-party API endpoints that
don't support Anthropic-only server-side tools like WebSearch.
Closes#390
Detect .md and .markdown files in the shared file pane and render them as markdown instead of syntax highlighted code. This makes README-style files easier to read without changing the existing preview flow for other text files or .mdx.
Keep the change focused to the app renderer by reusing the existing markdown stack and adding a narrow extension check with targeted coverage.
Translate OpenCode todo and compaction events into Paseo timeline items so issue #106 uses the existing todo list and compaction UI without changing the client model.
Keep session.status handling limited to existing terminal states and add focused translator coverage for each mapped event.
Fixes#106
Co-authored-by: OpenCode <noreply@openai.com>