diff --git a/packages/app/src/app/agent/[serverId]/[agentId].tsx b/packages/app/src/app/agent/[serverId]/[agentId].tsx index 12655ddb2..ef597b93a 100644 --- a/packages/app/src/app/agent/[serverId]/[agentId].tsx +++ b/packages/app/src/app/agent/[serverId]/[agentId].tsx @@ -14,7 +14,7 @@ import { useSafeAreaInsets } from "react-native-safe-area-context"; import { useReanimatedKeyboardAnimation } from "react-native-keyboard-controller"; import ReanimatedAnimated, { useAnimatedStyle, useSharedValue } from "react-native-reanimated"; import { StyleSheet, useUnistyles } from "react-native-unistyles"; -import { MoreVertical, GitBranch, Folder, RotateCcw, PlusCircle, Download } from "lucide-react-native"; +import { MoreVertical, GitBranch, Folder, RotateCcw, PlusCircle, Download, Users, ChevronRight } from "lucide-react-native"; import { BackHeader } from "@/components/headers/back-header"; import { AgentStreamView } from "@/components/agent-stream-view"; import { AgentInputArea } from "@/components/agent-input-area"; @@ -153,6 +153,20 @@ function AgentScreenContent({ serverId, agentId, onBack }: AgentScreenContentPro resolvedAgentId ? state.sessions[serverId]?.agents?.get(resolvedAgentId) : undefined ); + // Select child agents (agents where parentAgentId === current agentId) + const childAgents = useSessionStore((state) => { + if (!resolvedAgentId) return []; + const agents = state.sessions[serverId]?.agents; + if (!agents) return []; + const children: Array<{ id: string; title: string | null }> = []; + for (const [id, a] of agents) { + if (a.parentAgentId === resolvedAgentId) { + children.push({ id, title: a.title }); + } + } + return children; + }); + // Select only the specific stream state - use stable empty array to avoid infinite loop const streamItemsRaw = useSessionStore((state) => resolvedAgentId ? state.sessions[serverId]?.agentStreamState?.get(resolvedAgentId) : undefined @@ -439,6 +453,20 @@ function AgentScreenContent({ serverId, agentId, onBack }: AgentScreenContentPro setShowImportAgentModal(false); }, []); + const handleNavigateToChildAgent = useCallback( + (childAgentId: string) => { + handleCloseMenu(); + router.push({ + pathname: "/agent/[serverId]/[agentId]", + params: { + serverId: serverId, + agentId: childAgentId, + }, + }); + }, + [handleCloseMenu, router, serverId] + ); + const createAgentModal = ( + {/* Sub-Agents Section */} + + + + Sub-Agents + + {childAgents.length === 0 ? ( + No sub-agents + ) : ( + childAgents.map((child) => ( + handleNavigateToChildAgent(child.id)} + style={styles.menuSubAgentItem} + > + + {child.title || "Untitled Agent"} + + + + )) + )} + + + + View Changes @@ -830,4 +888,40 @@ const styles = StyleSheet.create((theme) => ({ color: theme.colors.foreground, fontWeight: theme.fontWeight.normal, }, + menuSubAgentsSection: { + gap: theme.spacing[1], + }, + menuSubAgentsHeader: { + flexDirection: "row", + alignItems: "center", + gap: theme.spacing[2], + paddingHorizontal: theme.spacing[1], + paddingBottom: theme.spacing[1], + }, + menuSubAgentsLabel: { + fontSize: theme.fontSize.xs, + color: theme.colors.mutedForeground, + letterSpacing: 0.5, + textTransform: "uppercase", + }, + menuSubAgentsEmpty: { + fontSize: theme.fontSize.sm, + color: theme.colors.mutedForeground, + paddingHorizontal: theme.spacing[3], + paddingVertical: theme.spacing[2], + }, + menuSubAgentItem: { + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", + paddingVertical: theme.spacing[2], + paddingHorizontal: theme.spacing[3], + borderRadius: theme.borderRadius.md, + }, + menuSubAgentText: { + fontSize: theme.fontSize.sm, + color: theme.colors.foreground, + flex: 1, + marginRight: theme.spacing[2], + }, })); diff --git a/plan.md b/plan.md index 43b68a3c1..5d1da8309 100644 --- a/plan.md +++ b/plan.md @@ -324,7 +324,7 @@ Files requiring modification: - Run typecheck after changes. - **Done (2025-12-21 21:45)**: Added filter in `use-aggregated-agents.ts:66-68` to skip agents with `parentAgentId` when building the aggregated agents list. Also included `parentAgentId` in the aggregated agent object. Typecheck passes. -- [ ] **Implement**: Add sub-agents section to agent info menu. +- [x] **Implement**: Add sub-agents section to agent info menu. - In `[agentId].tsx:536`, add a "Sub-Agents" section to the menu - Query the session store for agents where `parentAgentId === currentAgentId` @@ -332,6 +332,7 @@ Files requiring modification: - Tapping a child agent navigates to that agent's screen - Show "No sub-agents" if none exist - Run typecheck after changes. + - **Done (2025-12-21 22:00)**: Added Sub-Agents section to agent info menu in `[agentId].tsx`. Added `childAgents` selector to query agents with matching `parentAgentId`. Added `handleNavigateToChildAgent` callback for navigation. UI shows "No sub-agents" when empty, or clickable list of child agents with chevron icons. Typecheck passes. - [ ] **Test**: Verify parent/child hierarchy end-to-end.