* feat: add live model and thinking option preferences UI
* refactor: remove agent variant support and clean up thinking options
* feat: live model + thinking presets (RPC)
Replace separate sidebar stores with a unified panel store that uses a
discriminated union state machine on mobile. This makes it impossible
for both the agent list and file explorer sidebars to be open at the
same time on mobile.
Mobile state machine (mobileView):
- 'agent': Main agent view (no overlay panel)
- 'agent-list': Agent list sidebar (left overlay)
- 'file-explorer': File explorer sidebar (right overlay)
Desktop retains independent boolean toggles since sidebars sit
alongside content rather than overlaying it.
Key changes:
- Created stores/panel-store.ts with unified state
- Deleted stores/sidebar-store.ts and explorer-sidebar-store.ts
- Updated all components to use new panel store
- Animation contexts derive isOpen from unified state
- Add dedicated draft-store with AsyncStorage persistence for drafts
that survive app refresh/crash
- Reduce markdown bold weight from bold to medium (500)
- Various theme and component style updates
- Server bootstrap and config improvements
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Add MAX_CONTENT_WIDTH (820px) constant for consistent chat/form widths
- Bump theme font sizes (base now 16px) for better readability
- Apply max width to stream view, input area, and new agent form
- Position new agent form at bottom of scroll area
- Remove working directory helper text
- Add cmd+b sidebar toggle when textarea is focused
- Add task store with dependency tracking and CLI (packages/server/src/tasks/)
- Extract principal param logic to shared util for server/app reuse
- Improve activity curator: collapse timeline, dedupe tool calls, simpler output
- Add MessageInput ref for focus control after agent cancel
- Include recent activity in wait timeout messages
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Add FileDropZone component with overlay for web drag-and-drop
- Add useFileDropZone hook using native addEventListener for web
- Wire up drag-drop to agent screen to add images to input
- Improve image preview styling with visible border
- Show X button on hover with dark overlay for removal
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Add autoFocus prop to MessageInput and AgentInputArea
- Auto-focus input on web when entering agent or new agent screens
- Add Cmd+Enter (Mac) / Ctrl+Enter (Windows) to bypass queue and send immediately
- Add forceSend property to MessagePayload interface
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Dictation now appends transcribed text to input instead of auto-sending
- Voice button stays visible even with attachments or existing text
- Dictation works on create agent screen (not just agent chat)
- Input auto-grows when dictation appends text
- New agent screen input has solid background (no transparency)
- Timer preserves duration after confirming (no scary reset to zero)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add isSubmitLoading prop to AgentInputArea component to allow parent
to control loading state externally
- When isSubmitLoading is true:
- Show ActivityIndicator instead of ArrowUp icon in send button
- Disable send button with reduced opacity
- Pass isLoading state from new.tsx to AgentInputArea via isSubmitLoading prop
Files changed:
- packages/app/src/components/agent-input-area.tsx:53-54, 98, 1050-1060
- packages/app/src/app/agent/new.tsx:472
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix agent chat bottom scroll padding by adding overflow hidden to inputAreaContainer
- Create shared markdown-styles.ts with comprehensive styling for tables, headings, code blocks, blockquotes, and horizontal rules
- Enable text selection in AssistantMessage and AgentThoughtMessage by overriding markdown render rules with selectable={true}
- Path chips remain non-selectable to preserve onPress navigation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement a new UI section that surfaces agents requiring user attention at the top of the agent list. This includes agents that are running, have pending permissions, or have errors.
**Backend changes:**
- Add `requiresAttention` field to agent projections and SDK types
- Implement logic in AgentManager to detect attention states (running, pending permissions, errors)
- Add WebSocket message handler to notify clients of attention state changes
- Update session state to include attention tracking
**Frontend changes:**
- Add "REQUIRES ATTENTION" section in agent-list component with visual prominence
- Update useAggregatedAgents hook to expose `requiresAttention` agents
- Enhance session store to track and update attention states
- Add real-time updates via WebSocket for attention state changes
- Update type definitions across agent directory and stream types
Verified working via Playwright MCP testing on localhost:8081.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replace portal/registry pattern with direct rendering where each screen
owns its footer. This eliminates FooterControlsContext indirection and
makes the code follow standard React composition patterns.
- Remove GlobalFooter and FooterControlsProvider from _layout.tsx
- Add HomeFooter component rendered directly in home screen
- Render AgentInputArea directly in agent screen (not via registration)
- Add keyboard animation and safe area handling to AgentInputArea
- Move FOOTER_HEIGHT constant to shared constants/layout.ts
- Delete footer-controls-context.tsx and global-footer.tsx
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Remove debug logging and render counters added during performance investigation.
All performance issues have been resolved by:
- Moving drafts to top-level store
- Moving agentLastActivity to top-level store
- Using granular Zustand selectors throughout
- Eliminating useDaemonSession hook
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Delete useDaemonSession hook that selected entire session object
- Move drafts to top-level store (not nested in sessions)
- Refactor all components to use granular useSessionStore selectors
- Fix infinite loop bugs from selector fallbacks (use stable constants)
Before: 15-20 component rerenders per keystroke
After: ~1-2 rerenders per keystroke
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Backend fixes:
- Fix server crash when logging large session_state messages (186 agents)
- Use safe logging that extracts only message/stack properties
- Prevents TypeError in util.inspect on circular refs or deep objects
Frontend loading state fixes:
- Add reactive WebSocket update to prevent stale session.ws references
- Add timeout/retry wrapper for session_state loading (3 retries × 15s)
- Add hasEverReceivedSessionState flag to track cached data across reconnects
- Implement data-aware loading (isInitialLoad vs isRevalidating)
- Show reconnecting badge instead of hiding agents on reconnect
Debug improvements:
- Add detailed connection state logging in useAggregatedAgents
- Add connection status logging in AgentInputArea
- Track connecting reasons for easier debugging
Fixes:
- Agent screen no longer shows false "Offline" toast on reconnect
- Home screen shows loading immediately (no empty state flash)
- Home screen keeps agents visible during reconnect with badge
- Stuck loading has timeout protection with graceful degradation
- Server no longer crashes when sending session_state with many agents
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replace direct `agentId` prop usage with `agentIdRef.current` to prevent
messages from being sent to the wrong agent during navigation.
Fixed 3 instances:
- handleSendMessage: Line 383
- handleSendQueuedNow: Line 869
- handleCancelAgent: Line 834
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Problem: After migrating to pure Zustand, useDaemonSession returned only
SessionState from the store, but components need both state AND imperative
APIs (like sendAgentMessage, createAgent, etc.).
Solution: Create DaemonSession type that combines:
- SessionState (from Zustand store)
- Imperative APIs (from SessionContext)
- Wrapped store actions (getDraftInput, setFocusedAgentId, etc.)
Changes:
- Added DaemonSession type to use-daemon-session.ts
- useDaemonSession now merges sessionState + context + store actions
- Wraps store actions to bind serverId automatically
- Updated prop types in components to use DaemonSession
- Fixed use-session-directory.ts to use SessionState
This restores component compatibility while keeping pure Zustand architecture.
Still TODO: Fix remaining components that use SessionContext directly
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- add shared useDictation hook to prevent double-stop races
- refactor modal + agent chat to consume shared API
- improve web recorder errors with secure-context messaging
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Introduce DaemonRegistry and DaemonConnections contexts for managing multiple server connections. Add session directory for aggregating agents across daemons, with automatic routing based on agent/server context.
Key changes:
- Add daemon profile management (add/edit/remove/set default)
- Implement connection state tracking with reconnection and exponential backoff
- Create useAggregatedAgents hook for unified agent list across daemons
- Add useDaemonSession and useDaemonRequest hooks for daemon-scoped operations
- Update agent routes to include serverId for proper session routing
- Add connection health indicators on home screen and settings
- Persist session snapshots per daemon for faster hydration on reconnect
- Guard screens gracefully when target daemon is offline
- Add React Query for consistent loading/error state management
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add cancel button during agent runs, real-time mode toggle in all states, and agent deletion via long-press action sheet. Server now handles cancel_agent_request and delete_agent_request messages, cleaning up agent state and notifying clients.