diff --git a/packages/app/src/app/agent/[serverId]/[agentId].tsx b/packages/app/src/app/agent/[serverId]/[agentId].tsx
index 01c638bb9..c300f3068 100644
--- a/packages/app/src/app/agent/[serverId]/[agentId].tsx
+++ b/packages/app/src/app/agent/[serverId]/[agentId].tsx
@@ -19,6 +19,8 @@ import { MoreVertical, GitBranch, Folder, RotateCcw, PlusCircle, Download, Users
import { BackHeader } from "@/components/headers/back-header";
import { AgentStreamView } from "@/components/agent-stream-view";
import { AgentInputArea } from "@/components/agent-input-area";
+import { AgentList } from "@/components/agent-list";
+import { useAggregatedAgents } from "@/hooks/use-aggregated-agents";
import { CreateAgentModal, ImportAgentModal, type CreateAgentInitialValues } from "@/components/create-agent-modal";
import { useDaemonConnections } from "@/contexts/daemon-connections-context";
import type { ConnectionStatus } from "@/contexts/daemon-connections-context";
@@ -133,11 +135,17 @@ type AgentScreenContentProps = {
onBack: () => void;
};
+const SIDEBAR_WIDTH = 280;
+const LARGE_SCREEN_BREAKPOINT = 768;
+
function AgentScreenContent({ serverId, agentId, onBack }: AgentScreenContentProps) {
const { theme } = useUnistyles();
const insets = useSafeAreaInsets();
const router = useRouter();
const { width: windowWidth, height: windowHeight } = useWindowDimensions();
+ const isLargeScreen = windowWidth >= LARGE_SCREEN_BREAKPOINT;
+
+ const { agents: aggregatedAgents, isRevalidating, refreshAll } = useAggregatedAgents();
const [menuVisible, setMenuVisible] = useState(false);
const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 });
const [menuContentHeight, setMenuContentHeight] = useState(0);
@@ -531,43 +539,60 @@ function AgentScreenContent({ serverId, agentId, onBack }: AgentScreenContentPro
return (
<>
- {/* Header */}
-
-
-
-
-
- }
- />
-
- {/* Content Area with Keyboard Animation */}
-
-
- {isInitializing ? (
-
-
- Loading agent...
-
- ) : (
-
+ {/* Sidebar - only on large screens */}
+ {isLargeScreen && (
+
+
- )}
-
-
+
+ )}
- {/* Agent Input Area */}
- {!isInitializing && agent && resolvedAgentId && (
-
- )}
+ {/* Main agent panel */}
+
+ {/* Header */}
+
+
+
+
+
+ }
+ />
+
+ {/* Content Area with Keyboard Animation */}
+
+
+ {isInitializing ? (
+
+
+ Loading agent...
+
+ ) : (
+
+ )}
+
+
+
+ {/* Agent Input Area */}
+ {!isInitializing && agent && resolvedAgentId && (
+
+ )}
+
+
{/* Dropdown Menu */}
({
flex: 1,
backgroundColor: theme.colors.background,
},
+ mainLayout: {
+ flex: 1,
+ },
+ mainLayoutRow: {
+ flexDirection: "row",
+ },
+ sidebar: {
+ borderRightWidth: 1,
+ borderRightColor: theme.colors.border,
+ },
+ agentPanel: {
+ flex: 1,
+ },
contentContainer: {
flex: 1,
overflow: "hidden",
diff --git a/packages/app/src/components/agent-list.tsx b/packages/app/src/components/agent-list.tsx
index 8cc213488..79d91db40 100644
--- a/packages/app/src/components/agent-list.tsx
+++ b/packages/app/src/components/agent-list.tsx
@@ -12,9 +12,10 @@ interface AgentListProps {
agents: AggregatedAgent[];
isRefreshing?: boolean;
onRefresh?: () => void;
+ selectedAgentId?: string;
}
-export function AgentList({ agents, isRefreshing = false, onRefresh }: AgentListProps) {
+export function AgentList({ agents, isRefreshing = false, onRefresh, selectedAgentId }: AgentListProps) {
const { theme } = useUnistyles();
const [actionAgent, setActionAgent] = useState(null);
@@ -87,11 +88,13 @@ export function AgentList({ agents, isRefreshing = false, onRefresh }: AgentList
const timeAgo = formatTimeAgo(agent.lastActivityAt);
const providerLabel = getAgentProviderDefinition(agent.provider).label;
const isRunning = agent.status === "running";
+ const isSelected = selectedAgentId === agent.id;
return (
[
styles.agentItem,
+ isSelected && styles.agentItemSelected,
pressed && styles.agentItemPressed,
]}
onPress={() => handleAgentPress(agent.serverId, agent.id)}
@@ -157,7 +160,7 @@ export function AgentList({ agents, isRefreshing = false, onRefresh }: AgentList
);
},
- [handleAgentLongPress, handleAgentPress, theme.colors.muted, theme.colors.mutedForeground, theme.colors.primary, theme.colors.primaryForeground]
+ [handleAgentLongPress, handleAgentPress, selectedAgentId, theme.colors.muted, theme.colors.mutedForeground, theme.colors.primary, theme.colors.primaryForeground]
);
const keyExtractor = useCallback(
@@ -247,6 +250,12 @@ const styles = StyleSheet.create((theme) => ({
borderRadius: theme.borderRadius.lg,
marginBottom: theme.spacing[2],
backgroundColor: theme.colors.muted,
+ borderWidth: 1,
+ borderColor: "transparent",
+ },
+ agentItemSelected: {
+ backgroundColor: theme.colors.accent,
+ borderColor: theme.colors.primary,
},
agentItemPressed: {
opacity: 0.7,