Merge branch 'main' of github.com:boudra/voice-dev
This commit is contained in:
@@ -2,6 +2,7 @@ import { View, Text, Pressable, SectionList, Modal, RefreshControl, type Section
|
|||||||
import { useCallback, useState, useMemo } from "react";
|
import { useCallback, useState, useMemo } from "react";
|
||||||
import { router } from "expo-router";
|
import { router } from "expo-router";
|
||||||
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
||||||
|
import { Check } from "lucide-react-native";
|
||||||
import { formatTimeAgo } from "@/utils/time";
|
import { formatTimeAgo } from "@/utils/time";
|
||||||
import { getAgentStatusColor, getAgentStatusLabel } from "@/utils/agent-status";
|
import { getAgentStatusColor, getAgentStatusLabel } from "@/utils/agent-status";
|
||||||
import { getAgentProviderDefinition } from "@server/server/agent/provider-manifest";
|
import { getAgentProviderDefinition } from "@server/server/agent/provider-manifest";
|
||||||
@@ -102,6 +103,24 @@ export function AgentList({ agents, isRefreshing = false, onRefresh }: AgentList
|
|||||||
setActionAgent(null);
|
setActionAgent(null);
|
||||||
}, [actionAgent, deleteAgent]);
|
}, [actionAgent, deleteAgent]);
|
||||||
|
|
||||||
|
const handleClearAllAttention = useCallback((agentsInSection: AggregatedAgent[]) => {
|
||||||
|
// Group agents by serverId for batch clearing
|
||||||
|
const agentsByServer = new Map<string, string[]>();
|
||||||
|
for (const agent of agentsInSection) {
|
||||||
|
const agentIds = agentsByServer.get(agent.serverId) || [];
|
||||||
|
agentIds.push(agent.id);
|
||||||
|
agentsByServer.set(agent.serverId, agentIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send one batch request per server
|
||||||
|
for (const [serverId, agentIds] of agentsByServer) {
|
||||||
|
const session = useSessionStore.getState().sessions[serverId];
|
||||||
|
if (session?.ws) {
|
||||||
|
session.ws.clearAgentAttention(agentIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
const renderAgentItem = useCallback<SectionListRenderItem<AggregatedAgent, AgentSection>>(
|
const renderAgentItem = useCallback<SectionListRenderItem<AggregatedAgent, AgentSection>>(
|
||||||
({ item: agent }) => {
|
({ item: agent }) => {
|
||||||
const statusColor = getAgentStatusColor(agent.status);
|
const statusColor = getAgentStatusColor(agent.status);
|
||||||
@@ -183,9 +202,20 @@ export function AgentList({ agents, isRefreshing = false, onRefresh }: AgentList
|
|||||||
({ section }: { section: AgentSection }) => (
|
({ section }: { section: AgentSection }) => (
|
||||||
<View style={styles.sectionHeader}>
|
<View style={styles.sectionHeader}>
|
||||||
<Text style={styles.sectionTitle}>{section.title}</Text>
|
<Text style={styles.sectionTitle}>{section.title}</Text>
|
||||||
|
{section.title === "Requires Attention" && (
|
||||||
|
<Pressable
|
||||||
|
style={({ pressed }) => [
|
||||||
|
styles.clearAllButton,
|
||||||
|
pressed && styles.clearAllButtonPressed,
|
||||||
|
]}
|
||||||
|
onPress={() => handleClearAllAttention(section.data)}
|
||||||
|
>
|
||||||
|
<Check size={16} color={theme.colors.mutedForeground} />
|
||||||
|
</Pressable>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
),
|
),
|
||||||
[]
|
[handleClearAllAttention, theme.colors.mutedForeground]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -267,6 +297,9 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
paddingBottom: theme.spacing[4],
|
paddingBottom: theme.spacing[4],
|
||||||
},
|
},
|
||||||
sectionHeader: {
|
sectionHeader: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
paddingTop: theme.spacing[2],
|
paddingTop: theme.spacing[2],
|
||||||
paddingBottom: theme.spacing[2],
|
paddingBottom: theme.spacing[2],
|
||||||
paddingHorizontal: theme.spacing[2],
|
paddingHorizontal: theme.spacing[2],
|
||||||
@@ -277,6 +310,14 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
color: theme.colors.mutedForeground,
|
color: theme.colors.mutedForeground,
|
||||||
textTransform: "uppercase",
|
textTransform: "uppercase",
|
||||||
},
|
},
|
||||||
|
clearAllButton: {
|
||||||
|
padding: theme.spacing[1],
|
||||||
|
borderRadius: theme.borderRadius.md,
|
||||||
|
},
|
||||||
|
clearAllButtonPressed: {
|
||||||
|
opacity: 0.5,
|
||||||
|
backgroundColor: theme.colors.muted,
|
||||||
|
},
|
||||||
agentItem: {
|
agentItem: {
|
||||||
paddingVertical: theme.spacing[4],
|
paddingVertical: theme.spacing[4],
|
||||||
paddingHorizontal: theme.spacing[4],
|
paddingHorizontal: theme.spacing[4],
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export interface UseWebSocketReturn {
|
|||||||
) => () => void;
|
) => () => void;
|
||||||
sendPing: () => void;
|
sendPing: () => void;
|
||||||
sendUserMessage: (message: string) => void;
|
sendUserMessage: (message: string) => void;
|
||||||
clearAgentAttention: (agentId: string) => void;
|
clearAgentAttention: (agentId: string | string[]) => void;
|
||||||
subscribeConnectionStatus?: (listener: (status: ConnectionStatusSnapshot) => void) => () => void;
|
subscribeConnectionStatus?: (listener: (status: ConnectionStatusSnapshot) => void) => () => void;
|
||||||
getConnectionState?: () => ConnectionStatusSnapshot;
|
getConnectionState?: () => ConnectionStatusSnapshot;
|
||||||
}
|
}
|
||||||
@@ -291,7 +291,7 @@ export function useWebSocket(url: string, conversationId?: string | null): UseWe
|
|||||||
);
|
);
|
||||||
|
|
||||||
const clearAgentAttention = useCallback(
|
const clearAgentAttention = useCallback(
|
||||||
(agentId: string) => {
|
(agentId: string | string[]) => {
|
||||||
send({
|
send({
|
||||||
type: "session",
|
type: "session",
|
||||||
message: {
|
message: {
|
||||||
|
|||||||
@@ -76,6 +76,133 @@ const VALID_CLAUDE_MODES = new Set(
|
|||||||
DEFAULT_MODES.map((mode) => mode.id)
|
DEFAULT_MODES.map((mode) => mode.id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns orchestrator mode instructions to append to the system prompt.
|
||||||
|
* These instructions are from CLAUDE.md and guide agents on how to work
|
||||||
|
* effectively in this repository.
|
||||||
|
*/
|
||||||
|
function getOrchestratorModeInstructions(): string {
|
||||||
|
return `
|
||||||
|
|
||||||
|
## Orchestrator Mode Instructions
|
||||||
|
|
||||||
|
When asked to go into orchestrator mode, you must **only accomplish tasks by managing other agents**. Do NOT perform the work yourself.
|
||||||
|
|
||||||
|
### Agent Control Best Practices
|
||||||
|
|
||||||
|
- **When agent control tool calls fail**, make sure you list agents before trying to launch another one. It could just be a wait timeout.
|
||||||
|
- **Always prefix agent titles** so we can tell which ones are running under you (e.g., "🎭 Feature Implementation", "🎭 Design Discussion").
|
||||||
|
- **Launch agents in the most permissive mode**: Use full access or bypass permissions mode.
|
||||||
|
- **Set cwd to the repository root** - The agent's working directory should usually be the repo root.
|
||||||
|
|
||||||
|
### Agent Use Cases
|
||||||
|
|
||||||
|
You can run agents to:
|
||||||
|
- **Implement a task** - Spawn an agent to write code and implement features
|
||||||
|
- **Have a design discussion** - Discuss architecture and design decisions
|
||||||
|
- **Have a pairing session** - Collaborate on problem-solving
|
||||||
|
- **Test some feature** - Run tests and verify functionality
|
||||||
|
- **Do investigation** - Research and explore the codebase
|
||||||
|
|
||||||
|
### Clarifying Ambiguous Requests
|
||||||
|
|
||||||
|
**CRITICAL:** When user requests are ambiguous or unclear:
|
||||||
|
|
||||||
|
1. **Research first** - Spawn an investigation agent to understand the current state
|
||||||
|
2. **Ask clarifying questions** - After research, ask the user specific questions about what they want
|
||||||
|
3. **Present options** - Offer multiple approaches with trade-offs
|
||||||
|
4. **Get explicit confirmation** - Never assume what the user wants
|
||||||
|
|
||||||
|
### Investigation vs Implementation
|
||||||
|
|
||||||
|
**CRITICAL:** When asked to investigate:
|
||||||
|
|
||||||
|
- **Investigation agents MUST NOT fix issues** - They should only identify, document, and report problems
|
||||||
|
- **Always ask for confirmation** - After investigation, present findings and ask: "Should I proceed with implementing fixes?"
|
||||||
|
- **Only implement if explicitly requested** - Don't auto-fix without user approval
|
||||||
|
|
||||||
|
### Strategic Planning and Task Breakdown
|
||||||
|
|
||||||
|
**CRITICAL:** For large or complex tasks, you MUST plan strategically before spawning agents:
|
||||||
|
|
||||||
|
1. **Break down the work** into small, focused tasks
|
||||||
|
2. **Design the agent workflow**: What agents will you need? In what order?
|
||||||
|
3. **Plan checkpoints**: Where do you need review agents? Test agents? Integration points?
|
||||||
|
4. **Ensure each agent commits their work** before moving to the next phase
|
||||||
|
5. **Plan for validation**: How will you verify each piece works before proceeding?
|
||||||
|
|
||||||
|
Example workflow for a large feature:
|
||||||
|
- Investigation agent → Design discussion agent → Multiple implementation agents (one per component) → Test agent → Review agent → Integration agent
|
||||||
|
|
||||||
|
### Rigorous Agent Interrogation
|
||||||
|
|
||||||
|
**CRITICAL:** Agents start with ZERO context about your task. You must always provide complete context in your initial prompt.
|
||||||
|
|
||||||
|
When working with agents, you must dig deep and challenge them rigorously:
|
||||||
|
|
||||||
|
#### For Implementation Agents
|
||||||
|
|
||||||
|
- **Don't accept surface-level completion**: Ask them to show you the code they implemented
|
||||||
|
- **Trace the implementation**: Ask them to walk through the code flow step by step
|
||||||
|
- **Uncover gaps**: Dig hard to find possible gaps in their understanding
|
||||||
|
- "Show me exactly where you handle error case X"
|
||||||
|
- "What happens if the user does Y before Z?"
|
||||||
|
- "Walk me through the data flow from input to output"
|
||||||
|
- **Ask for alternatives**: "Provide 3 different solutions to this problem and explain the trade-offs of each"
|
||||||
|
- **Rank and compare**: "Rank these approaches by performance, maintainability, and complexity"
|
||||||
|
- **Challenge their decisions**: Play devil's advocate on their architectural choices
|
||||||
|
- "Why not use approach X instead?"
|
||||||
|
- "What are the downsides of your solution?"
|
||||||
|
- "How will this scale?"
|
||||||
|
|
||||||
|
#### For Investigation/Debugging Agents
|
||||||
|
|
||||||
|
- **Don't stop at the first answer**: Keep digging deeper
|
||||||
|
- **Explore different angles**: "What are 3 other possible causes?"
|
||||||
|
- **Request proof**: "Show me the specific code that proves this hypothesis"
|
||||||
|
- **Challenge assumptions**: "How do you know that's the root cause? What else could it be?"
|
||||||
|
- **Ask for comprehensive analysis**: "What are all the places in the codebase that could be affected?"
|
||||||
|
|
||||||
|
#### For Review Agents
|
||||||
|
|
||||||
|
- **Security review**: "What are the security implications? Any OWASP vulnerabilities?"
|
||||||
|
- **Edge cases**: "What edge cases are not handled?"
|
||||||
|
- **Performance**: "Where are the performance bottlenecks?"
|
||||||
|
- **Maintainability**: "How maintainable is this code? What would make it better?"
|
||||||
|
|
||||||
|
### Debugging with Logging and Playwright
|
||||||
|
|
||||||
|
**CRITICAL:** When debugging frontend or server issues:
|
||||||
|
|
||||||
|
- **Frontend debugging**: Use Playwright MCP to interact with the app at \`http://localhost:8081\`
|
||||||
|
- Take screenshots to verify UI state
|
||||||
|
- Click through flows to reproduce issues
|
||||||
|
- Use browser console to check for errors
|
||||||
|
- Verify network requests and responses
|
||||||
|
- **Server debugging**: Add strategic logging to trace execution
|
||||||
|
- Log request/response payloads
|
||||||
|
- Log state transitions
|
||||||
|
- Log error conditions
|
||||||
|
- Use server logs to correlate with frontend behavior
|
||||||
|
- **Full-stack debugging**: Combine both approaches
|
||||||
|
- Use Playwright to trigger frontend actions
|
||||||
|
- Check server logs to see backend behavior
|
||||||
|
- Verify data flow from client → server → client
|
||||||
|
|
||||||
|
### Agent Management Principles
|
||||||
|
|
||||||
|
- **Keep agents focused** - Each agent should have a clear, specific responsibility
|
||||||
|
- **You can talk to them** - Send prompts and guidance as they work
|
||||||
|
- **Monitor progress** - Check status and provide feedback
|
||||||
|
- **Always provide context** - Remember: agents start with zero knowledge of your task
|
||||||
|
- **Verify work rigorously** - Don't trust, verify. Ask agents to prove their work
|
||||||
|
- **Commit frequently** - Ensure each agent commits their changes before moving on
|
||||||
|
- **Plan for quality gates** - Use test and review agents as checkpoints
|
||||||
|
|
||||||
|
**CRITICAL: ALWAYS RUN TYPECHECK AFTER EVERY CHANGE.**
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
type ClaudeAgentConfig = AgentSessionConfig & { provider: "claude" };
|
type ClaudeAgentConfig = AgentSessionConfig & { provider: "claude" };
|
||||||
|
|
||||||
export type ClaudeContentChunk = { type: string; [key: string]: any };
|
export type ClaudeContentChunk = { type: string; [key: string]: any };
|
||||||
@@ -518,9 +645,11 @@ class ClaudeAgentSession implements AgentSession {
|
|||||||
agents: this.defaults?.agents,
|
agents: this.defaults?.agents,
|
||||||
canUseTool: this.handlePermissionRequest,
|
canUseTool: this.handlePermissionRequest,
|
||||||
// Use Claude Code preset system prompt and load CLAUDE.md files
|
// Use Claude Code preset system prompt and load CLAUDE.md files
|
||||||
|
// Append orchestrator mode instructions for agents
|
||||||
systemPrompt: {
|
systemPrompt: {
|
||||||
type: "preset",
|
type: "preset",
|
||||||
preset: "claude_code",
|
preset: "claude_code",
|
||||||
|
append: getOrchestratorModeInstructions(),
|
||||||
},
|
},
|
||||||
settingSources: ["project", "user"],
|
settingSources: ["project", "user"],
|
||||||
stderr: (data: string) => {
|
stderr: (data: string) => {
|
||||||
|
|||||||
@@ -459,7 +459,7 @@ export const FileExplorerRequestSchema = z.object({
|
|||||||
|
|
||||||
export const ClearAgentAttentionMessageSchema = z.object({
|
export const ClearAgentAttentionMessageSchema = z.object({
|
||||||
type: z.literal("clear_agent_attention"),
|
type: z.literal("clear_agent_attention"),
|
||||||
agentId: z.string(),
|
agentId: z.union([z.string(), z.array(z.string())]),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
||||||
|
|||||||
@@ -1851,13 +1851,16 @@ export class Session {
|
|||||||
/**
|
/**
|
||||||
* Handle clearing agent attention flag
|
* Handle clearing agent attention flag
|
||||||
*/
|
*/
|
||||||
private async handleClearAgentAttention(agentId: string): Promise<void> {
|
private async handleClearAgentAttention(agentId: string | string[]): Promise<void> {
|
||||||
|
const agentIds = Array.isArray(agentId) ? agentId : [agentId];
|
||||||
console.log(
|
console.log(
|
||||||
`[Session ${this.clientId}] Clearing attention for agent ${agentId}`
|
`[Session ${this.clientId}] Clearing attention for ${agentIds.length} agent(s): ${agentIds.join(", ")}`
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.agentManager.clearAgentAttention(agentId);
|
await Promise.all(
|
||||||
|
agentIds.map((id) => this.agentManager.clearAgentAttention(id))
|
||||||
|
);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error(
|
console.error(
|
||||||
`[Session ${this.clientId}] Failed to clear agent attention:`,
|
`[Session ${this.clientId}] Failed to clear agent attention:`,
|
||||||
|
|||||||
Reference in New Issue
Block a user