Commit Graph
118 Commits
Author SHA1 Message Date
Mohamed Boudra 070314fa5f Fix bottom sheet dark theme background 2025-12-22 04:05:19 +00:00
Mohamed BoudraandClaude Opus 4.5 56a287a85d fix: tool call bottom sheet text visibility
Replace react-native-gesture-handler ScrollView with React Native's
built-in ScrollView to fix text rendering issues inside @gorhom/bottom-sheet.
The gesture handler's ScrollView was causing text to render nearly invisible.

Also add explicit background colors to scroll containers for consistent
appearance.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 03:37:17 +00:00
Mohamed BoudraandClaude Opus 4.5 253af9988c fix: wrap orchestrator messages view with ToolCallSheetProvider
The ToolCall component requires the ToolCallSheetProvider context to
function properly. The orchestrator messages view was rendering ToolCall
components without this provider, which would cause a crash when tapping
tool call badges.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 18:36:11 +00:00
Mohamed BoudraandClaude Opus 4.5 a8053bc0b5 feat: integrate ToolCallSheetProvider in AgentStreamView
Wrapped AgentStreamView content with ToolCallSheetProvider to enable
tool call details to open in a bottom sheet on tap instead of expanding
inline. This improves mobile UX for viewing tool call information.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 18:24:07 +00:00
Mohamed BoudraandClaude Opus 4.5 09b7360a7e feat: update ToolCall to open bottom sheet on tap
- Import useToolCallSheet hook from new tool-call-sheet component
- Replace inline expansion with openToolCall() to show details in bottom sheet
- Remove ~300 lines of unused code (toolCallStylesheet, formatFullValue,
  buildLineDiffFromStrings, isStructuredToolResult, and inline rendering)
- Clean up unused imports (ScrollView, DiffViewer, DiffLine)
- Badge display unchanged - still shows icon, label, loading/error state

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 18:22:29 +00:00
Mohamed BoudraandClaude Opus 4.5 676125a732 feat: add ToolCallSheet component with bottom sheet and context
Create a new component for displaying tool call details in a bottom sheet
on mobile devices. Includes:
- ToolCallSheetProvider and useToolCallSheet hook for state management
- BottomSheetModal with snap points at 50% and 90%
- Header with tool icon, name, and status badge
- Content sections for args, commands, file diffs, file reads, and errors
- Reuses rendering logic from existing ToolCall component

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 18:18:10 +00:00
Mohamed Boudra fb30160cda feat: add batch clear attention and orchestrator mode instructions 2025-12-20 05:57:54 +00:00
Mohamed BoudraandClaude 0f1758709d feat: add "Requires Attention" agent grouping feature
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>
2025-12-04 11:27:08 +00:00
Mohamed BoudraandClaude 98c24f22a0 refactor: simplify footer architecture by removing global footer pattern
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>
2025-12-03 22:25:30 +07:00
Mohamed BoudraandClaude 644c654274 perf: prevent HomeScreen rerenders during agent streaming
- Add top-level agentLastActivity Map to store (prevents cascade rerenders)
- Remove lastActivityAt updates from agent_stream handler (only status changes update timestamps)
- useAggregatedAgents now uses agent.lastActivityAt directly
- Remove investigation logging from previous debug session

The root cause was that every stream event updated agent.lastActivityAt,
causing useAggregatedAgents to recalculate, which caused HomeScreen to
rerender even when not visible. Now timestamps only update on meaningful
events (agent status changes), not individual stream tokens.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 17:34:07 +07:00
Mohamed BoudraandClaude 4c1ba8f1b1 chore: remove investigation logging from performance work
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>
2025-12-03 17:33:23 +07:00
Mohamed BoudraandClaude 21d43bc249 perf: eliminate cascading rerenders with granular Zustand selectors
- 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>
2025-12-03 16:37:23 +07:00
Mohamed BoudraandClaude 74c82a312e perf: move drafts to top-level store to prevent session rerenders
Previously, drafts were nested inside each session object, which caused
the entire session to be recreated on every keystroke. This triggered
rerenders in all components subscribed to the session.

Now drafts are stored at the top level of the Zustand store, keyed by
agentId (not serverId:agentId since agent IDs are globally unique).
This means draft updates only trigger rerenders in components that
subscribe to drafts specifically.

Changes:
- Move drafts from SessionState to SessionStoreState (top-level)
- Add createModalDraft for future use by the create agent modal
- Update getDraftInput/saveDraftInput to work with agentId only
- Update session-context to clear drafts using new API
- Remove investigation console.log statements

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 15:46:45 +07:00
Mohamed Boudra d5f8091d66 refactor: simplify modal mounting with lazy wrapper and add read-only git env 2025-12-03 14:09:56 +07:00
Mohamed Boudra f4f7790d07 fix: improve terminal init error handling and websocket debug logging 2025-12-03 13:26:28 +07:00
Mohamed BoudraandClaude e346b4c026 Replace reconnecting badge with pull-to-refresh
UX improvements:
- Remove misleading "Reconnecting..." badge overlay
- Implement native pull-to-refresh gesture on agent list
- Add manual refresh capability via pull gesture

Technical changes:
- Add refreshSession() method to session context
- Add refreshAll() to useAggregatedAgents hook
- Integrate RefreshControl in AgentList component
- Use isRevalidating state for refresh indicator
- Apply theme colors to RefreshControl for consistency

Benefits:
- Familiar iOS/Android UX pattern
- No UI overlays blocking content
- Clear user action (pull) → clear feedback (refresh)
- Accurate state representation (syncing vs reconnecting)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 02:57:38 +00:00
Mohamed BoudraandClaude 348cb9d637 Fix loading state bugs and server crash
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>
2025-12-03 02:45:16 +00:00
Mohamed BoudraandClaude 5ddaea7352 Complete Zustand migration: fix component access to session APIs
Finalizes the pure Zustand refactor by ensuring all components properly access both session state and imperative methods through useDaemonSession. Moves CLAUDE.md to root and ignores local overrides.

Changes:
- Fix useDaemonSession to return stable combined state + methods object
- Update components to use useDaemonSession instead of direct context
- Fix realtime context to work with session state only
- Move CLAUDE.md to root, ignore CLAUDE.local.md for local config
- Add proper null checks and type safety throughout

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 17:42:49 +00:00
Mohamed BoudraandClaude 473e11d25f Fix stale closure bug in agent-input-area message handlers
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>
2025-12-02 17:17:54 +00:00
Mohamed BoudraandClaude e8aa08159a Fix useDaemonSession to return combined state + APIs
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>
2025-12-02 14:27:57 +00:00
Mohamed Boudra 0ba5e481f4 fix: Phase 2 review issues 2025-12-02 10:33:49 +00:00
Mohamed Boudra 6e259c37db refactor: SessionProvider to use Zustand setters directly (Phase 2b) 2025-12-02 10:13:25 +00:00
Mohamed Boudra 34e0e21657 chore: add session perf instrumentation 2025-12-02 09:20:02 +00:00
Mohamed Boudra 755b314e51 Use FlatList for home agent list 2025-12-02 08:17:53 +00:00
Mohamed Boudra dc26bf713e feat(dictation): add resilient rpc retries and status toasts 2025-12-02 08:12:02 +00:00
Mohamed BoudraandClaude 27ec2b5c67 fix: share dictation hook across surfaces
- 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>
2025-12-01 12:25:58 +00:00
Mohamed BoudraandClaude 7c1517d830 feat(server): add Playwright MCP with headless mode to spawned Claude agents
Spawned agents now get Playwright browser automation capabilities by default.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 05:08:56 +00:00
Mohamed BoudraandClaude 53d91a319e fix(app): use pre-parsed props for Codex file edit diffs
ToolCall component had parsedEditEntries, parsedReadEntries, and
parsedCommandDetails props defined but never used them. Now prefers
these pre-parsed props when available, enabling Codex apply_patch
diffs to render correctly in the expanded view.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 01:04:33 +00:00
Mohamed BoudraandClaude 4001b7dc0a refactor: remove heuristic parsing, use pure type-based tool rendering
- Remove all heuristic parsing code from message.tsx (hasCommandDetails,
  commandSection, editSections, readSections, hasStructuredContent, etc.)
- Replace with simple raw JSON fallback for tools without structured results
- Fix server-side support for Claude SDK's old_string/new_string params
  (in addition to old_str/new_str)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 19:38:42 +00:00
Mohamed BoudraandClaude 38b08fec0c feat: add structured tool result types for better rendering
Server-side:
- Add StructuredToolResult discriminated union type with command, file_write,
  file_edit, file_read, and generic variants
- Implement buildStructuredToolResult in claude-agent.ts to detect tool types
  and emit properly structured results
- Update codex-agent.ts to emit structured command results

Client-side:
- Add type guard and extraction functions for structured results
- Render tool calls based on result.type when available:
  - command: show command, output, exit code
  - file_write/file_edit: show diff viewer with proper +/- format
  - file_read: show file content
  - generic: show raw JSON
- Fall back to heuristic parsing for backwards compatibility

This fixes file writes showing as "Command: success message" - they now
properly show as diffs with +line additions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 19:24:52 +00:00
Mohamed BoudraandClaude a7df671144 fix(app): deduplicate tool call expansion sections
Command output was being shown three times: as "Command", as "Read Result",
and as raw JSON "Result". Now:
- Skip "Read Result" when command output is already shown
- Skip raw JSON "Result" when we have structured content to display

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 19:05:41 +00:00
Mohamed BoudraandClaude e80989ea78 perf: remove raw field from timeline items to reduce payload size
Remove the `raw` field that was duplicating provider data in timeline
items, reducing WebSocket payload sizes by 64-85%:
- session_state: ~320KB → ~48KB
- agent_stream_snapshot: ~320KB → ~114KB

Changes:
- Remove raw from AgentTimelineItem, AgentStreamEvent, AgentPermissionRequest
- Remove raw assignments from claude-agent.ts and codex-agent.ts
- Remove provider_event handling from stream.ts (only used for Codex raw)
- Update tests to reflect new behavior

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 18:20:33 +00:00
Mohamed BoudraandClaude 2c84447ec2 fix(app): resolve create agent dictation confirm handler timing issue
Fixed a state management bug where clicking the checkmark in create agent dictation mode would not trigger processing. The issue was that setIsDictationProcessing(true) was called after stopping the recorder, causing a race condition where the UI never showed the processing state.

Changes:
- Move setIsDictationProcessing(true) to execute immediately at the start of the confirm handler
- Add proper cleanup when audioData is null
- Ensure UI shows loading spinner when checkmark is clicked

This aligns the create agent dictation behavior with the working agent chat dictation implementation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 10:10:31 +00:00
Mohamed Boudra bf58e81ce8 refactor(app): simplify session directory with direct snapshots and add sessionReady state
Replace subscription-based session accessor pattern with direct snapshot updates in daemon connections context. Add sessionReady flag to connection state to track when initial agent list has been received. Auto-select first ready host in create agent modal. Migrate from app.json to app.config.js. Add android:release script and Playwright testing docs.
2025-11-27 21:06:48 +01:00
Mohamed BoudraandClaude a01c3f9b73 Flatten home screen agent list and sort by activity
The agent list on the home screen now displays all agents in a single flat
list rather than grouped by host. Each row shows a host badge next to the
agent title so users can still identify which host an agent belongs to.
Agents are sorted globally by status (running first) then by most recent
activity, providing a unified view across all hosts.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 20:18:49 +01:00
Mohamed BoudraandClaude 135bcf13a8 Fix create agent modal incorrectly showing hosts as offline
The availability check was failing for online hosts due to a timing
issue: connectionStates would show "online" before SessionProvider
registered its session accessor, causing session to be null.

Changed selectedDaemonIsUnavailable to selectedDaemonIsOffline which
only checks connectionStates status (the single source of truth for
connection state), removing the redundant session and ws.isConnected
checks. isTargetDaemonReady still requires session for actual operations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 20:12:11 +01:00
Mohamed Boudra 0db0e1ad23 Clarify automatic host reconnection 2025-11-26 19:33:43 +01:00
Mohamed Boudra 4f00e07284 Eliminate hidden host defaults 2025-11-26 19:02:47 +01:00
Mohamed Boudra 670c38ab8c Remove legacy host auto-connect state 2025-11-26 18:53:53 +01:00
Mohamed Boudra db87f331fb Remove primary host plumbing 2025-11-26 18:30:04 +01:00
Mohamed Boudra 5807f62f1a Remove active host dependency from UI actions 2025-11-26 18:04:40 +01:00
Mohamed Boudra 04d51fbe10 Rename daemon UI copy to host 2025-11-26 17:26:25 +01:00
Mohamed Boudra 59967aad87 chore: land multi-daemon rollout 2025-11-26 08:47:49 +00:00
Mohamed BoudraandClaude 4ab79b1a50 feat: add multi-daemon support with session routing and connection management
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>
2025-11-26 08:25:02 +01:00
Mohamed Boudra 30d1b63b2b chore: typecheck and build readiness 2025-11-24 22:31:41 +01:00
Mohamed Boudra 3b20cf0654 Capture Cmd+D dictation on web 2025-11-23 14:36:01 +01:00
Mohamed Boudra 6aa9b1c72e Add web dictation recorder and shortcuts 2025-11-23 14:32:08 +01:00
Mohamed Boudra 47a99f5668 Fix reasoning timeline UI and type errors 2025-11-23 14:12:53 +01:00
Mohamed Boudra 95bacf8fc7 feat: add git branch/worktree setup, message queueing, file explorer improvements, and server restart 2025-11-22 23:20:42 +01:00
Mohamed Boudra b046dae799 refactor: rebrand project from voice-dev to paseo across all packages and configs 2025-11-15 20:45:09 +01:00