Commit Graph

253 Commits

Author SHA1 Message Date
Mohamed Boudra
7a024ce7fd Migrate image encoding to expo-file-system File API 2025-12-29 10:51:06 +07:00
Mohamed Boudra
1200bce7e3 Fix Codex image prompt data URLs 2025-12-29 10:34:43 +07:00
Mohamed Boudra
0ffac203af Test Codex image attachment temp path 2025-12-29 10:28:24 +07:00
Mohamed Boudra
b559422cb0 Write Codex image attachments to temp files 2025-12-29 10:13:00 +07:00
Mohamed Boudra
a087b085e6 Add multimodal prompt blocks for agent prompts 2025-12-29 09:15:09 +07:00
Mohamed Boudra
6160d96716 Fix web image base64 encoding 2025-12-29 09:09:53 +07:00
Mohamed Boudra
d5f5351d37 Add image attachments to agent creation 2025-12-29 09:07:54 +07:00
Mohamed Boudra
5d24e0eee8 Investigation: Image attachments are broken
Tested image attachment flow via Playwright MCP. Found three issues:

1. Agent creation silently drops images (by design - TODO in code)
2. Web platform fails base64 encoding (expo-file-system not available)
3. Server buildAgentPrompt only creates text summary, never sends bytes

Added fix tasks to plan.md and detailed report in
REPORT-image-attachment-investigation.md.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 09:03:58 +07:00
Mohamed Boudra
62181e1f4c Review daemon test coverage 2025-12-29 00:23:35 +07:00
Mohamed Boudra
db9887d723 Validate new agent URL params 2025-12-29 00:22:40 +07:00
Mohamed Boudra
890708a55a Checkpoint typecheck and code quality review 2025-12-29 00:19:30 +07:00
Mohamed Boudra
5325240b26 Remove host label from git diff screen 2025-12-29 00:16:38 +07:00
Mohamed Boudra
ffc6bd3ba5 Fix inline path linking for absolute cwd paths 2025-12-29 00:15:21 +07:00
Mohamed Boudra
025fd97143 Fix file explorer back loader 2025-12-29 00:10:23 +07:00
Mohamed Boudra
5120f73f49 Add host selector to import agent modal 2025-12-29 00:06:06 +07:00
Mohamed Boudra
265caaf140 Fix gallery image timeout crash 2025-12-29 00:02:00 +07:00
Mohamed Boudra
29d561725c Fix Codex import list 2025-12-28 23:59:09 +07:00
Mohamed Boudra
e5ea77e961 Filter internal Claude import history 2025-12-28 23:48:41 +07:00
Mohamed Boudra
8ce8eb5652 Test 2 passed: Permissions mode display verified via Playwright MCP
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 23:42:34 +07:00
Mohamed Boudra
1cbb219207 Test 1 passed: Config persistence verified via Playwright MCP 2025-12-28 23:40:35 +07:00
Mohamed Boudra
7c97dc18fb Show permissions mode in agent trigger 2025-12-28 23:38:02 +07:00
Mohamed Boudra
1269edcb6e Persist new agent form config 2025-12-28 23:36:05 +07:00
Mohamed Boudra
40835bbe9d Fix Codex history persistence after daemon restart
- Modified loadPersistedHistoryFromDisk() to use sessionId or conversationId as fallback
- Added rollout path and session dir persistence in agent metadata
- Added fallback to default Codex session root when metadata path is empty
- Cleaned up create-agent-modal.tsx (removed 800+ lines of dead code)
- Updated app routing and home-footer cleanup

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 11:39:20 +07:00
Mohamed Boudra
e65ee140f2 Mark new agent page UI redesign task as completed in plan.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 21:41:15 +07:00
Mohamed Boudra
26da925de6 Redesign new agent page UI layout
- Move host selector to header (right side) with icon + name + status dot
- Combine provider/model/mode into single "Agent" dropdown
- Replace Git branch/worktree toggles with segmented IsolationControl (None/Branch/Worktree)
- Only show Git section for git repositories (hide for non-git directories)
- Wrap config section in ScrollView for proper scrolling
- Simplify layout: Working Directory → Agent → Git (when applicable)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 21:40:35 +07:00
Mohamed Boudra
4cf0ea73a1 Mark attention bug fix task as completed in plan.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 21:22:56 +07:00
Mohamed Boudra
5d20129a33 Mark Git Options Section task as completed in plan.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 21:17:49 +07:00
Mohamed Boudra
58769e7ece Review new agent page vs old modal - produce specific fix tasks
Deep comparison completed between:
- new.tsx (600 lines) - new agent page
- create-agent-modal.tsx (~2700 lines) - old modal
- [agentId].tsx (1152 lines) - agent screen

FINDINGS:
1. Loading state: Has isLoading but NO visual feedback (needs fix)
2. Input area styling: MATCHES (both use AgentInputArea)
3. Git options: MISSING (~200 lines) - needs feature task
4. Error handling: FIXED (all validation in place)
5. Visual parity: GOOD (verified with Playwright screenshots)

Added specific fix tasks to plan:
- FIX: Add visual loading indicator during creation
- FEATURE: Add Git Options Section (base branch, new branch, worktree)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 21:04:06 +07:00
Mohamed Boudra
a398f67527 Fix new agent page bugs and add error handling
- Add errorMessage and isLoading states for proper UX feedback
- Add validation for working directory, prompt, host, and connection
- Display error messages in red container below config section
- Handle agent_create_failed status with error display
- Add loading state management during agent creation
- Log warning for image attachments (server API doesn't support yet)

Tested with Playwright MCP:
- Error message "Working directory is required" displays correctly
- Agent creation with valid config succeeds and redirects

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 20:53:31 +07:00
Mohamed Boudra
7e9e685a14 Fix Claude agent race condition in forwardPromptEvents
The race condition occurred when overlapping stream() calls (e.g., during
message interrupt) corrupted shared instance-level flags:
- streamedAssistantTextThisTurn
- streamedReasoningThisTurn

This caused Turn 2 to reset flags while Turn 1 was still reading them,
leading to garbled text or suppressed responses.

Fix:
- Created TurnContext interface to track per-turn streaming state
- Moved flags from instance variables to turn-local context
- Pass TurnContext through translateMessageToEvents, mapBlocksToTimeline,
  and mapPartialEvent call chains

Also fixed:
- session.ts interruptAgentIfRunning() now polls for agent to become
  fully idle (not just cancelled) before starting new run, matching
  the fix from MCP handler

Test:
- Added E2E test that sends overlapping messages and verifies Turn 2
  responds with its own content, not Turn 1's

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 20:43:42 +07:00
Mohamed Boudra
5a7d16b10f Review new agent page feature gaps vs old modal
WHAT:
- Reviewed packages/app/src/app/agent/new.tsx (560 lines)
- Compared with packages/app/src/components/create-agent-modal.tsx (~2700 lines)
- Analyzed packages/app/src/components/home-footer.tsx entry points

KEY FINDINGS:
1. CRITICAL: Image attachments silently fail (new.tsx:216-218 early returns)
2. CRITICAL: Creation failures silently ignored (new.tsx:269-271)
3. Missing: errorMessage state and UI display
4. Missing: isLoading state and button disable
5. Missing: Daemon offline error handling
6. Missing: Git Options Section (~200 lines)
7. Dead code: CreateAgentModal in home-footer.tsx never shown

Full analysis in REPORT-new-agent-page-review.md

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 20:24:13 +07:00
Mohamed Boudra
0406720d4b Add review task: New agent page missing features from old modal
Investigated the new /agent/new page vs old create-agent-modal.tsx:

MISSING FROM NEW PAGE:
1. Git options (branch selection, worktree creation)
2. Dictation/voice input support
3. Image attachment handling
4. Error message display
5. Loading state during creation
6. Daemon availability checks
7. Import flow

ALSO FOUND:
- CreateAgentModal in home-footer.tsx:206-209 is dead code
  (showCreateModal is never set to true)
- Import flow still uses old modal (works correctly)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 20:21:33 +07:00
Mohamed Boudra
219411d3ee Add E2E test for long-running Claude agent streaming integrity
Investigated server-side streaming for Claude agents to determine if
chunks are being lost during transmission. Created a new E2E test that:

1. Creates a Claude agent with bypassPermissions mode
2. Sends 3 back-and-forth messages to simulate long-running agent
3. On the 3rd message, captures all streaming chunks
4. Verifies chunks are complete, coherent, and contain expected content
5. Checks for UTF-8 corruption and abnormal word concatenation

RESULT: Test passes. Server correctly forwards all text_delta chunks
from Claude SDK. No chunks are dropped or corrupted.

CONCLUSION: The original bug report (REPORT-garbled-text-bug.md) observed
missing chunks at the client level, but server-side code is NOT the cause.
The issue must be elsewhere (possibly React Native WebSocket differences
or a transient network issue).

Files:
- packages/server/src/server/daemon.e2e.test.ts:1883-2028 - New test

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 20:17:45 +07:00
Mohamed Boudra
b1bcb8e6df Fix send_agent_prompt to interrupt running agent before sending new prompt
Problem: When calling send_agent_prompt on an agent that already has an
active run, it errored with "Agent {id} already has an active run"
instead of interrupting and sending the prompt (like the app does).

Solution: Modified the send_agent_prompt MCP handler in mcp-server.ts to:
- Check if agent has an active run (lifecycle === "running" || pendingRun)
- If running, call cancelAgentRun() to interrupt the current run
- Poll wait (max 5s, 50ms interval) for agent to become idle
- Then start the new run

This matches the behavior of session.ts:interruptAgentIfRunning().

The polling wait is necessary because cancelAgentRun() only initiates
cancellation (fires and forgets via void promise.catch()) and doesn't
wait for the pendingRun to be cleared.

Added E2E test "send_agent_prompt interrupts running agent and processes
new message" that verifies the fix works correctly.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 20:10:44 +07:00
Mohamed Boudra
5e041c47a3 Investigate Claude agent garbled text bug - app-side analysis complete
Investigation findings:
- Added debug logging to appendAssistantMessage to trace state transitions
- Reproduced bug with Playwright MCP on running Claude agent
- Client-side state management works correctly
- Root cause: Server sends incomplete text chunks to client

The app-side code is NOT causing the garbled text. The issue is
server-side in the Claude agent streaming implementation.

See REPORT-garbled-text-bug.md for full analysis.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 20:00:29 +07:00
Mohamed Boudra
d107ba0f0c Add E2E test for Claude agent streaming text integrity
Added test in daemon.e2e.test.ts that verifies server-side streaming
text is not garbled during Claude agent responses. Test passes - the
server emits clean, non-corrupted text chunks.

Investigation determined the reported garbled text bug is in the
React Native app rendering layer, not the server.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 19:50:03 +07:00
Mohamed Boudra
db8c100448 Mark SESSION_HISTORY refactor task complete
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 19:27:04 +07:00
Mohamed Boudra
f22f76c56b Fix Codex MCP timeline persistence after daemon restart
When daemon restarts, SESSION_HISTORY is lost because it's an in-memory
Map. This fix adds disk-based timeline loading from Codex rollout files.

Changes:
- Add loadPersistedHistoryFromDisk() method to load from rollout files
- Add helper functions for finding and parsing rollout JSONL files
- Call disk loading in connect() when resumeHandle exists but SESSION_HISTORY is empty
- Add E2E test for timeline persistence across daemon restart

The rollout files are stored at ~/.codex/sessions/<date>/rollout-*.jsonl
and contain JSONL entries with response_item and event_msg types.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 19:14:51 +07:00
Mohamed Boudra
ab9c133d0e fix: allow null parentAgentId in agent schemas and projections 2025-12-25 18:51:18 +07:00
Mohamed Boudra
7b8d032bbc Add sendImages E2E tests for DaemonClient
Add two E2E tests that verify image attachment support in sendMessage():
- "sends message with image attachment to Claude agent" - tests single image
- "sends message with multiple image attachments" - tests multiple images

Tests use minimal 1x1 PNG base64 and verify:
- Server logs image attachments received
- Agent processes message and completes turn
- Assistant response is generated

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 18:24:29 +07:00
Mohamed Boudra
26ec7d20f0 Add getGitDiff() to DaemonClient + E2E tests
- Add getGitDiff(agentId) method to DaemonClient that sends git_diff_request
  and waits for git_diff_response
- Add 3 E2E tests covering:
  1. Modified file in git repo returns correct diff
  2. Clean repo returns empty diff
  3. Non-git directory returns error

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 18:10:00 +07:00
Mohamed Boudra
46ddb5a20c Add temp Claude config isolation to daemon E2E tests
- Create shared useTempClaudeConfigDir() helper in test-utils/claude-config.ts
- Export from test-utils/index.ts for reuse across test files
- Update daemon.e2e.test.ts to use beforeAll/afterAll hooks with temp config
- Remove .skip from "permission flow: Claude" describe block
- Refactor claude-agent.test.ts to use shared helper instead of local copy

This fixes the daemon E2E Claude permission tests that were skipped due to
the user's real ~/.claude/settings.json having "Bash(rm:*)" in the allow
list, which caused rm commands to auto-execute without permission prompts.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 18:06:44 +07:00
Mohamed Boudra
78dec91bdf Investigate Claude permission test failures in daemon E2E tests
Root cause: daemon E2E tests read user's real ~/.claude/settings.json
which has Bash(rm:*) in allow list, causing rm commands to auto-execute
without permission prompts. Direct claude-agent.test.ts works because
it uses useTempClaudeConfigDir() to create isolated settings with
ask: ["Bash(rm:*)"] and sets CLAUDE_CONFIG_DIR env var.

Fix: Add temp config setup to daemon tests (same pattern as direct
tests) or use settingSources: [] for SDK isolation mode.

See REPORT-claude-permission-tests.md for full analysis.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 17:57:40 +07:00
Mohamed Boudra
d2587d0c6a Add daemon E2E test for listAgents()
- Add E2E test that creates two agents, verifies both are returned by
  listAgents(), deletes one, and verifies only the remaining agent is
  returned
- Update listAgents() in DaemonClient to compute current agent list from
  session_state, agent_state, and agent_deleted messages in the queue
- Fix createAgent() to use skipQueueBefore option so second agent creation
  doesn't match stale messages from first agent

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 17:53:29 +07:00
Mohamed Boudra
18cc63fa39 Add daemon E2E test for setAgentMode()
- Added E2E test that verifies mode switching (auto → read-only → full-access)
- Test verifies mode persists across messages
- Fixed bug: setMode() now updates cachedRuntimeInfo so getRuntimeInfo()
  returns correct modeId after mode change

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 17:48:02 +07:00
Mohamed Boudra
5ce0a742e7 Add daemon E2E test for cancelAgent()
Test verifies:
- Agent cancel request is processed correctly
- Agent reaches idle/error state within 2 seconds
- No zombie processes left after cancel

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 17:44:52 +07:00
Mohamed Boudra
6ba5c466a1 Add timestamp behavior E2E tests and verify bug is fixed
WHAT:
- Added initializeAgent() and clearAgentAttention() methods to DaemonClient
  (packages/server/src/server/test-utils/daemon-client.ts:268-304)
- Added E2E tests for timestamp behavior
  (packages/server/src/server/daemon.e2e.test.ts:482-570):
  - "opening agent without interaction does not update timestamp"
  - "sending message DOES update timestamp"

RESULT:
Bug verified as already fixed in commit 32e111e (Dec 2, 2025) which removed
timestamp thrashing - previously lastActivityAt/updatedAt was updated on
every agent_stream event (15+ times/second during streaming).

Server only sets agent.updatedAt in:
- recordUserMessage (agent-manager.ts:436)
- handleStreamEvent (agent-manager.ts:864)
NOT in clearAgentAttention or initializeAgent flows.

EVIDENCE:
- npm run test --workspace=@paseo/server -- daemon.e2e.test.ts -t "timestamp"
  (2 passed in 9.08s)
- Playwright test showed agent stayed in position 4 with unchanged timestamp
  after clicking

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 17:42:33 +07:00
Mohamed Boudra
3459354e45 Add daemon E2E test coverage audit report
Created REPORT-daemon-e2e-audit.md with comprehensive analysis:
- Current test coverage: 5 passing tests (Codex provider)
- DaemonClient API coverage: 11/16 methods tested
- Message protocol coverage: 6/15 inbound, 5/17 outbound
- Prioritized recommendations for additional tests

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 17:33:23 +07:00
Mohamed Boudra
5f642f12ea Add multi-agent E2E test (DaemonClient Phase 4)
Adds test that verifies parent agent can create child agent via
agent-control MCP. Test creates Codex parent, prompts it to call
create_agent tool, and verifies both agents are visible.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 17:28:52 +07:00
Mohamed Boudra
1fb73b1045 Add DaemonClient persistence E2E test (Phase 3)
- Add E2E test "persists and resumes Codex agent with conversation history"
  that creates agent, sends message, deletes, and resumes from persistence handle
- Fix resumeAgent() in daemon-client.ts to properly wait for NEW agent's idle
  state using skipQueueBefore option (avoids matching stale cached messages)
- Verify persistence round-trip works: agent can be resumed and responds to
  follow-up messages with conversation context preserved

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 17:23:06 +07:00