import { View, Text, Platform, Pressable } from "react-native"; import { StyleSheet, useUnistyles } from "react-native-unistyles"; import { ChevronDown, SlidersHorizontal } from "lucide-react-native"; import { useSessionStore } from "@/stores/session-store"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { AdaptiveModalSheet } from "@/components/adaptive-modal-sheet"; import { useMemo, useState } from "react"; import { useQuery } from "@tanstack/react-query"; interface AgentStatusBarProps { agentId: string; serverId: string; } export function AgentStatusBar({ agentId, serverId }: AgentStatusBarProps) { const { theme } = useUnistyles(); const IS_WEB = Platform.OS === "web"; const [prefsOpen, setPrefsOpen] = useState(false); // Select only the specific agent (not all agents) const agent = useSessionStore((state) => state.sessions[serverId]?.agents?.get(agentId) ); const client = useSessionStore((state) => state.sessions[serverId]?.client ?? null); if (!agent) { return null; } const canFetchModels = Boolean(client) && Boolean(agent.provider) && (IS_WEB || prefsOpen); const modelsQuery = useQuery({ queryKey: ["providerModels", serverId, agent.provider, agent.cwd], enabled: canFetchModels, staleTime: 5 * 60 * 1000, queryFn: async () => { if (!client) { throw new Error("Daemon client unavailable"); } const payload = await client.listProviderModels(agent.provider, { cwd: agent.cwd }); if (payload.error) { throw new Error(payload.error); } return payload.models ?? []; }, }); const models = modelsQuery.data ?? null; function handleModeChange(modeId: string) { if (!client) { return; } void client.setAgentMode(agentId, modeId).catch((error) => { console.warn("[AgentStatusBar] setAgentMode failed", error); }); } const selectedModel = useMemo(() => { if (!models || !agent.model) return null; return models.find((m) => m.id === agent.model) ?? null; }, [models, agent.model]); const displayModel = selectedModel?.label ?? agent.model ?? "default"; const thinkingOptions = selectedModel?.thinkingOptions ?? null; const selectedThinkingId = agent.thinkingOptionId ?? selectedModel?.defaultThinkingOptionId ?? "default"; const selectedThinking = thinkingOptions?.find((o) => o.id === selectedThinkingId) ?? null; const displayThinking = selectedThinking?.label ?? selectedThinkingId ?? "default"; return ( {/* Agent Mode Badge */} {agent.availableModes && agent.availableModes.length > 0 && ( [ styles.modeBadge, pressed && styles.modeBadgePressed, ]} accessibilityRole="button" accessibilityLabel="Select agent mode" testID="agent-mode-selector" > {agent.availableModes?.find((m) => m.id === agent.currentModeId) ?.label || agent.currentModeId || "default"} Mode {agent.availableModes.map((mode) => { const isActive = mode.id === agent.currentModeId; return ( handleModeChange(mode.id)} > {mode.label} ); })} )} {/* Desktop: inline dropdowns for model/thinking */} {IS_WEB && ( <> [ styles.modeBadge, pressed && styles.modeBadgePressed, ]} accessibilityRole="button" accessibilityLabel="Select agent model" testID="agent-model-selector" > {displayModel} Model {models?.map((model) => { const isActive = model.id === agent.model; return ( { if (!client) { return; } void client.setAgentModel(agentId, model.id).catch((error) => { console.warn("[AgentStatusBar] setAgentModel failed", error); }); }} > {model.label} ); })} {thinkingOptions && thinkingOptions.length > 1 && ( [ styles.modeBadge, pressed && styles.modeBadgePressed, ]} accessibilityRole="button" accessibilityLabel="Select thinking option" testID="agent-thinking-selector" > {displayThinking} Thinking {thinkingOptions.map((opt) => { const isActive = opt.id === selectedThinkingId; return ( { if (!client) { return; } void client .setAgentThinkingOption(agentId, opt.id === "default" ? null : opt.id) .catch((error) => { console.warn("[AgentStatusBar] setAgentThinkingOption failed", error); }); }} > {opt.label} ); })} )} )} {/* Mobile: preferences button opens a bottom sheet */} {!IS_WEB && ( <> setPrefsOpen(true)} style={({ pressed }) => [ styles.prefsButton, pressed && styles.prefsButtonPressed, ]} accessibilityRole="button" accessibilityLabel="Agent preferences" testID="agent-preferences-button" > setPrefsOpen(false)} testID="agent-preferences-sheet" > Model [ styles.sheetSelect, pressed && styles.sheetSelectPressed, ]} accessibilityRole="button" accessibilityLabel="Select agent model" testID="agent-preferences-model" > {displayModel} Model {models?.map((model) => { const isActive = model.id === agent.model; return ( { if (!client) { return; } void client.setAgentModel(agentId, model.id).catch((error) => { console.warn("[AgentStatusBar] setAgentModel failed", error); }); }} > {model.label} ); })} {thinkingOptions && thinkingOptions.length > 1 && ( Thinking [ styles.sheetSelect, pressed && styles.sheetSelectPressed, ]} accessibilityRole="button" accessibilityLabel="Select thinking option" testID="agent-preferences-thinking" > {displayThinking} Thinking {thinkingOptions.map((opt) => { const isActive = opt.id === selectedThinkingId; return ( { if (!client) { return; } void client .setAgentThinkingOption(agentId, opt.id === "default" ? null : opt.id) .catch((error) => { console.warn("[AgentStatusBar] setAgentThinkingOption failed", error); }); }} > {opt.label} ); })} )} )} ); } const styles = StyleSheet.create((theme) => ({ container: { flexDirection: "row", alignItems: "center", gap: theme.spacing[3], }, modeBadge: { flexDirection: "row", alignItems: "center", backgroundColor: theme.colors.surface2, gap: theme.spacing[1], paddingHorizontal: theme.spacing[3], paddingVertical: theme.spacing[2], borderRadius: theme.borderRadius["2xl"], }, modeBadgePressed: { backgroundColor: theme.colors.surface0, }, modeBadgeText: { color: theme.colors.foregroundMuted, fontSize: theme.fontSize.xs, fontWeight: theme.fontWeight.semibold, textTransform: "capitalize", }, prefsButton: { width: 32, height: 32, borderRadius: theme.borderRadius["2xl"], alignItems: "center", justifyContent: "center", backgroundColor: theme.colors.surface2, }, prefsButtonPressed: { backgroundColor: theme.colors.surface0, }, sheetSection: { gap: theme.spacing[2], }, sheetLabel: { color: theme.colors.foregroundMuted, fontSize: theme.fontSize.sm, fontWeight: theme.fontWeight.semibold, }, sheetSelect: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", gap: theme.spacing[3], paddingHorizontal: theme.spacing[4], paddingVertical: theme.spacing[3], borderRadius: theme.borderRadius.lg, borderWidth: 1, borderColor: theme.colors.surface2, backgroundColor: theme.colors.surface0, }, sheetSelectPressed: { backgroundColor: theme.colors.surface2, }, sheetSelectText: { flex: 1, color: theme.colors.foreground, fontSize: theme.fontSize.sm, fontWeight: theme.fontWeight.semibold, }, }));