diff --git a/packages/app/src/app/_layout.tsx b/packages/app/src/app/_layout.tsx
index 88efbfeeb..a166c880a 100644
--- a/packages/app/src/app/_layout.tsx
+++ b/packages/app/src/app/_layout.tsx
@@ -1,4 +1,4 @@
-import { Stack, useLocalSearchParams, usePathname } from "expo-router";
+import { Stack, usePathname } from "expo-router";
import { SafeAreaProvider } from "react-native-safe-area-context";
import { KeyboardProvider } from "react-native-keyboard-controller";
import { GestureHandlerRootView } from "react-native-gesture-handler";
@@ -72,17 +72,21 @@ function ProvidersWrapper({ children }: { children: ReactNode }) {
function AppWithSidebar({ children }: { children: ReactNode }) {
const pathname = usePathname();
- const params = useLocalSearchParams<{ agentId?: string }>();
- const selectedAgentId = useMemo(() => {
- if (pathname.startsWith("/agent/") && params.agentId) {
- return params.agentId;
+ // Parse selectedAgentKey directly from pathname
+ // useLocalSearchParams doesn't update when navigating between same-pattern routes
+ const selectedAgentKey = useMemo(() => {
+ // Match /agent/[serverId]/[agentId] pattern
+ const match = pathname.match(/^\/agent\/([^/]+)\/([^/]+)$/);
+ if (match) {
+ const [, serverId, agentId] = match;
+ return `${serverId}:${agentId}`;
}
return undefined;
- }, [pathname, params.agentId]);
+ }, [pathname]);
return (
- {children}
+ {children}
);
}
diff --git a/packages/app/src/app/settings.tsx b/packages/app/src/app/settings.tsx
index 25403029c..892cac23d 100644
--- a/packages/app/src/app/settings.tsx
+++ b/packages/app/src/app/settings.tsx
@@ -18,7 +18,7 @@ import { useDaemonRegistry, type DaemonProfile } from "@/contexts/daemon-registr
import { useDaemonConnections, type ConnectionStatus } from "@/contexts/daemon-connections-context";
import { formatConnectionStatus, getConnectionStatusTone } from "@/utils/daemons";
import { theme as defaultTheme } from "@/styles/theme";
-import { BackHeader } from "@/components/headers/back-header";
+import { MenuHeader } from "@/components/headers/menu-header";
import { useSessionStore } from "@/stores/session-store";
import type { UseWebSocketReturn } from "@/hooks/use-websocket";
@@ -575,7 +575,7 @@ export default function SettingsScreen() {
return (
-
+
diff --git a/packages/app/src/components/agent-list.tsx b/packages/app/src/components/agent-list.tsx
index 5fdd1ba03..f0035d8d8 100644
--- a/packages/app/src/components/agent-list.tsx
+++ b/packages/app/src/components/agent-list.tsx
@@ -57,9 +57,12 @@ export function AgentList({ agents, isRefreshing = false, onRefresh, selectedAge
to: "agent",
params: { serverId, agentId },
});
+
const shouldReplace = pathname.startsWith("/agent/");
const navigate = shouldReplace ? router.replace : router.push;
+
onAgentSelect?.();
+
navigate({
pathname: "/agent/[serverId]/[agentId]",
params: {
@@ -91,7 +94,8 @@ export function AgentList({ agents, isRefreshing = false, onRefresh, selectedAge
({ item: agent }) => {
const timeAgo = formatTimeAgo(agent.lastActivityAt);
const isRunning = agent.status === "running";
- const isSelected = selectedAgentId === agent.id;
+ const agentKey = `${agent.serverId}:${agent.id}`;
+ const isSelected = selectedAgentId === agentKey;
const statusColor = isRunning ? "#3b82f6" : agent.requiresAttention ? "#22c55e" : null;
return (
@@ -225,7 +229,6 @@ const styles = StyleSheet.create((theme) => ({
paddingHorizontal: theme.spacing[3],
borderRadius: theme.borderRadius.lg,
marginBottom: theme.spacing[2],
- backgroundColor: theme.colors.palette.zinc[950],
},
agentItemSelected: {
backgroundColor: theme.colors.palette.zinc[800],
diff --git a/packages/app/src/components/sliding-sidebar.tsx b/packages/app/src/components/sliding-sidebar.tsx
index 61c0fc12f..7960af9bd 100644
--- a/packages/app/src/components/sliding-sidebar.tsx
+++ b/packages/app/src/components/sliding-sidebar.tsx
@@ -234,17 +234,12 @@ export function SlidingSidebar({ selectedAgentId }: SlidingSidebarProps) {
+ {/* Header: New Agent button */}
-
-
-
+
+ {/* Middle: scrollable agent list */}
+
+ {/* Footer: Settings button */}
+
+
+
+ Settings
+
+
@@ -283,10 +291,8 @@ export function SlidingSidebar({ selectedAgentId }: SlidingSidebarProps) {
return (
+ {/* Header: New Agent button */}
-
-
-
+
+ {/* Middle: scrollable agent list */}
+
+ {/* Footer: Settings button */}
+
+
+
+ Settings
+
+
);
}
@@ -336,19 +355,11 @@ const styles = StyleSheet.create((theme) => ({
backgroundColor: theme.colors.background,
},
sidebarHeader: {
- flexDirection: "row",
- alignItems: "center",
paddingHorizontal: theme.spacing[4],
paddingTop: theme.spacing[4],
paddingBottom: theme.spacing[2],
- gap: theme.spacing[2],
- },
- headerIconButton: {
- padding: theme.spacing[2],
- borderRadius: theme.borderRadius.lg,
},
newAgentButton: {
- flex: 1,
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
@@ -360,4 +371,23 @@ const styles = StyleSheet.create((theme) => ({
fontSize: theme.fontSize.base,
fontWeight: theme.fontWeight.normal,
},
+ sidebarFooter: {
+ paddingHorizontal: theme.spacing[4],
+ paddingTop: theme.spacing[2],
+ paddingBottom: theme.spacing[4],
+ borderTopWidth: 1,
+ borderTopColor: theme.colors.border,
+ },
+ settingsButton: {
+ flexDirection: "row",
+ alignItems: "center",
+ gap: theme.spacing[3],
+ paddingVertical: theme.spacing[2],
+ paddingHorizontal: theme.spacing[2],
+ },
+ settingsButtonText: {
+ fontSize: theme.fontSize.base,
+ fontWeight: theme.fontWeight.normal,
+ color: theme.colors.mutedForeground,
+ },
}));