- Add custom list rendering rules in message.tsx for proper flex layout
- Remove flexWrap from list content styles (causes Android clipping)
- Use flex: 1 and flexShrink: 1 for natural text wrapping
- Add minWidth: 0 to content containers for proper shrinking
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Filter undefined values from env record for Codex SDK
- Add string type check for ParsedQs array element
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace SectionList with FlatList in agent list, sorting attention items to top
- Persist server selection preference in create agent modal
- Add bearer token authentication support for agent-control MCP endpoint
- Pass bearer token through Codex wrapper script for MCP auth
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added `parentAgentId` field to `STORED_AGENT_SCHEMA` in agent-registry.ts
- Updated `toStoredAgentRecord()` in agent-projections.ts to include parentAgentId
- This ensures parentAgentId is persisted to agents.json for parent/child hierarchy
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When an agent calls the MCP create_agent tool to spawn a child agent,
the parent-child relationship is now automatically established:
- Added setManagedAgentId() to AgentSession interface (optional method)
- ClaudeAgentSession stores its managed agent ID and includes it as
X-Caller-Agent-Id header when connecting to the agent-control MCP
- AgentManager.registerSession() calls setManagedAgentId() after
registration so the session knows its ID before first prompt
- MCP server extracts X-Caller-Agent-Id header from init request and
stores it as callerAgentId
- create_agent handler auto-injects callerAgentId as parentAgentId
if not explicitly provided
This enables parent agents to spawn child agents that are correctly
associated, so they appear in the parent's Sub-Agents menu instead
of on the homepage.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add parentAgentId optional parameter to the create_agent MCP tool input
schema so agents can create child agents with explicit parent references.
Also update registerSession() to copy parentAgentId from config to the
managed agent object.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add parentAgentId field to enable agent parent/child hierarchy:
- ManagedAgentBase in agent-manager.ts
- AgentSessionConfig in agent-sdk-types.ts
- AgentSnapshotPayloadSchema in messages.ts
- toAgentPayload() in agent-projections.ts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Claude agent model was not showing in the UI ("Model: Unknown") because
refreshRuntimeInfo() updated agent.runtimeInfo but never called emitState()
to notify connected clients of the change.
Fixed by:
1. Adding change detection in refreshRuntimeInfo() to check if model, sessionId,
or modeId changed
2. Calling emitState(agent) when changes are detected
3. Added debug logging in handleSystemMessage() to confirm model capture
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update handleSystemMessage() in claude-agent.ts to read the actual model
from the SDK's init message (message.model) instead of just echoing back
the configured model. This gives us the real runtime model that the SDK
selected.
Also invalidates cached runtime info when the model is updated to ensure
getRuntimeInfo() returns the new value.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements automatic detection and usage of system-installed Codex binary
with transparent fallback to embedded binary.
Changes:
- Add detectSystemCodexPath() to check for codex in PATH using `which`
- Update CodexAgentClient constructor to auto-detect system binary
- Log which binary is being used (system vs embedded) for debugging
- Preserve ability to explicitly override via codexPathOverride option
Benefits:
- No manual configuration required
- Uses latest system codex when available
- Seamless fallback to embedded binary
- Transparent to rest of codebase
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 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>
Added the --isolated flag to the Playwright MCP configuration to ensure
browser instances run in isolated contexts, preventing state leakage
between different agent sessions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Previously, only standard tool_use blocks had their input parameters
captured in upsertToolUseEntry. MCP tools (mcp_tool_use) and server
tools (server_tool_use) were being handled for execution but their
inputs were never stored in the tool cache, resulting in missing input
data in the UI.
Now all three tool types have their inputs properly captured and
normalized, ensuring consistent tool call display across all tool types.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Remove ReadonlyPendingPermissionsMap class and related deep cloning/freezing
methods that were causing "ManagedAgent views returned by AgentManager are
read-only" errors. The bug occurred because Map constructor internally calls
.set() which was overridden to throw.
Replace with simple shallow clones - sufficient because all consumers either
read 1-2 fields or immediately serialize via toAgentPayload() which already
creates safe copies.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Enhance the get_agent_activity tool to provide better context about the activity list:
- Add activity count headers showing "X of Y activities"
- Remove raw format option, always use curated format for consistency
- Simplify implementation by removing unnecessary format branching
- Respect limit parameter to show most recent N activities
This makes it clearer to users when they're viewing a subset of activities versus the full list.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement hard-coded 60-second timeout for agent wait operations in three tools:
- create_agent (when background=false and initialPrompt provided)
- send_agent_prompt (when background=false)
- wait_for_agent (always)
When timeout occurs, returns gracefully with message "Awaiting the agent timed out, await again" instead of throwing an error. Agent continues running after timeout.
Added AGENT_WAIT_TIMEOUT_MS constant and waitForAgentWithTimeout helper function to handle timeout logic with proper cleanup and signal forwarding.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Move mode validation from AgentManager into the individual AgentSession
implementations (ClaudeAgentSession and CodexAgentSession) where it belongs.
Each session validates modes in:
- Constructor (when config.modeId is provided)
- setMode() method (when mode is changed)
This follows the principle that the AgentManager is a coordinator while
the AgentSession is the authority on what modes it supports.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Prevents server crashes when invalid modes are passed to agents by
validating mode IDs before attempting to set them on the SDK.
- Export VALID_CLAUDE_MODES and VALID_CODEX_MODES from provider files
- Add validateMode() function in agent-manager.ts
- Apply validation in createAgent(), resumeAgent(), and setAgentMode()
- Throws clear error listing valid modes when validation fails
This fixes the crash when 'read-only' (Codex mode) was passed to
a Claude agent.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed two fire-and-forget promise patterns that could cause unhandled rejections:
- interruptActiveTurn() in requestCancel closure - now catches errors and logs warning
- forwardPromptEvents() in stream method - now catches errors and logs to console
Both now properly handle promise rejections to prevent Node.js process crashes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- 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>
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>