hasInitializedRef was set to true before confirming the directory
listing request actually succeeded. On page refresh the WebSocket
client is still reconnecting, so requestDirectoryListing returned
early with "Host is not connected" and the ref stayed true —
preventing any retry once the client became available.
Fix: make requestDirectoryListing return Promise<boolean> and reset
hasInitializedRef on failure so the init effect re-runs automatically
when requestDirectoryListing is recreated after the client reconnects.
Fixes#441
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: file preview shows stale content when re-opening a file
The file content query inherits `refetchOnMount: false` and
`gcTime: Infinity` from the global QueryClient defaults, so
re-opening a previously viewed file never re-fetches its content.
Set `staleTime: 0` and `refetchOnMount: true` on the file preview
query so it always fetches the latest content when the component
mounts.
Fixes#351
* fix: keep original staleTime, only add refetchOnMount
staleTime: 5_000 is reasonable — avoids redundant fetches when
quickly toggling the same file. The actual fix only needs
refetchOnMount: true to override the global default of false.
---------
Co-authored-by: muzhi1991 <muzhi1991@limuzhideMac-mini-2.local>
The Create button on the new workspace screen was visible but clicking
it did nothing — submitAgentInput() still rejected empty payloads as
"noop". Thread allowEmptySubmit through Composer into submitAgentInput
so the callback fires and workspace creation + redirect completes.
Adds regression test for the empty-submit path.
Terminal tests (launcher-tab, terminal-performance):
- Terminal creation no longer silently no-ops when workspace metadata
hasn't hydrated. Early clicks are queued and flushed once the workspace
directory is ready, with toast feedback.
- Terminal button is disabled while waiting on workspace readiness.
- Removed isFocused gate from ?open= intent consumption in workspace
layout so deep-linked terminals open reliably on cold startup.
New workspace test:
- New workspace screen now shows a visible Create button even when the
composer is empty, via new allowEmptySubmit and
submitButtonAccessibilityLabel props threaded through Composer and
MessageInput.
Forward-port main's timeline epoch tracking, projected window selection,
and schema updates into dev. Remove aider/amp/gemini providers and
provider-history-compatibility layers that are no longer needed.
The prop represents whether the pane/panel is focused, not whether the
text input is focused. Rename across all 5 files to match the caller
names and reduce confusion.
Show a muted "⌘L to focus" hint in the top-right of the message input
when unfocused and empty on web. Registers Cmd+L (Mac) / Ctrl+L
(non-Mac) bindings for the existing message-input.focus action.
On mobile, the server drops live stream events for backgrounded or
unfocused agents. When the user returns, a seq gap triggers a
catch-up fetch whose canonical entries are appended to the tail —
but the head was never flushed. Stale live items from before the
gap stayed in the head and rendered after the newer catch-up entries,
breaking chronological order. Worse, subsequent live events of the
same kind (e.g. assistant_message) would append to the stale head
item, garbling message content.
Now the incremental path in processTimelineResponse flushes head →
tail before reducing canonical entries, keeping the timeline ordered
and the head clean for new live events.
Always render the GitBranch icon regardless of branch availability so
the layout doesn't shift when the branch name loads. Only the chevron
remains dynamic. Also removes vertical padding on mobile to tighten
the gap between the branch row and project subtitle.
The new-worktree button spinner was hidden when the cursor left the
project row. Force visibility when the mutation is pending so users
see the loading state throughout creation.
Route all git checkout queries through WorkspaceGitService instead of
shelling out to git on every call. This makes fetch_agents_request
instant when warm (cached in-memory snapshots) and deduplicates
concurrent cold-start refreshes via ensureWorkspaceTarget.
- buildProjectPlacementForCwd now uses workspaceGitService.getSnapshot()
- worktree-session call sites use WorkspaceGitService
- Deleted getCheckoutStatusLite and its 4 return types from checkout-git
- Fixed cold-start thundering herd: getSnapshot deduplicates via
ensureWorkspaceTarget instead of spawning parallel git processes
- Extracted checkout-diff logic into WorkspaceGitService
The hasSelectedAgent condition was redundantly gating Cmd+E (toggle right
sidebar) and Cmd+Shift+F (toggle focus mode) behind a pathname check that
Cmd+B and Cmd+. didn't require. The action handler already guards against
invalid states, making the when-clause check unnecessary and broken on the
dev branch's navigation flow.
The `referenceAtOrigin` check in `hasResolvedDesktopPosition` was
accidentally inverted during the provider profiles refactor (6f280276).
`!referenceAtOrigin` made the condition trivially true for all normal
triggers, letting the dropdown show at (0,0) before floating-ui resolved
the real position — visible as a left-side flash on the very first open.
- Unify resolveProviderAndModel across CLI and server, supporting
provider/model syntax (e.g. codex/gpt-5.4) for agent runs and schedules
- Add --provider flag to schedule create CLI and both MCP schedule tools
- Add structured debug logging to workspace fetch hydrate, sidebar
refresh, and real-time update paths
- Update orchestrate skill references
Workspace setup may auto-open a setup tab that steals focus, hiding
the agent panel. Click the agent tab to ensure it's active before
checking the composer textbox.
submitAgentInput returned "noop" for empty messages regardless of
allowEmptySubmit, breaking the new-workspace empty-submit flow.
Now the flag is passed from Composer through to submitAgentInput
so empty submissions are allowed when the prop is set.
The unscoped getByRole("button", { name: "Create" }) matched sidebar
"Create a new workspace" buttons from other test suites. Scoping to
message-input-root targets only the Composer submit button.
clickNewWorkspaceButton now completes the full user flow: after
clicking the sidebar button, waits for the /new route, then clicks
the Create button to submit the empty form and trigger workspace
creation + redirect.
assertNewWorkspaceSidebarAndHeader was scanning all sidebar workspace
rows to find the newly created workspace, but would pick up workspaces
from concurrent test suites (e.g. archive-tab). Use the page URL as
source of truth since the app redirects to the new workspace after
creation.
- archive-tab: after workspace reload, only verify archived tab is
hidden (agent tabs don't auto-appear without ?open= intent). Real-time
archive propagation still fully verified before reload.
- new-workspace: use gotoAppShell + sidebar navigation instead of direct
workspace URL navigation. Matches the pattern of passing tests where
the WebSocket connection and workspace hydration complete before
sidebar interaction.
- archive-tab: replace waitForFunction with waitForURL for ?open= intent
consumption, increase test timeout to 300s for slow rootNavigationState
init on CI
- launcher-tab: use Control+t on Linux instead of Meta+t to match app's
keyboard shortcut definitions for non-Mac platforms
- new-workspace: add waitForSidebarHydration to wait for daemon
connection before checking sidebar rows, add re-navigation fallback
if app redirects during hydration, increase timeouts
- setup-streaming: use waitForTerminalContent (xterm buffer API) instead
of fragile .xterm-rows CSS text matching, wait for terminal attachment
before checking content