import { useCallback, useEffect, useMemo, useState } from "react"; import { useNavigate } from "react-router-dom"; import { listProjects } from "../api/projects"; import { getUserSessions } from "../api/sessions"; import { listToolTypes } from "../api/tool-types"; import { getUserConfig } from "../api/settings"; import { Icon } from "../components/ui/Icon"; import { LoadingState, ErrorState } from "../components/ui"; import { CreateSessionForm, SessionList } from "../components/features/session"; import type { Project } from "../types/project"; import type { Session } from "../types/session"; import type { ToolType } from "../types/tool-type"; type SessionsStatus = "loading" | "ready" | "error"; export const SessionsPage = () => { const navigate = useNavigate(); const [status, setStatus] = useState("loading"); const [sessions, setSessions] = useState([]); const [lastSessionId, setLastSessionId] = useState(null); const [projects, setProjects] = useState([]); const [toolTypes, setToolTypes] = useState([]); const loadSessions = useCallback(async () => { setStatus("loading"); try { const [sessionsData, config] = await Promise.all([ getUserSessions(), getUserConfig(), ]); setSessions(sessionsData); setLastSessionId(config.last_session_id ?? null); setStatus("ready"); } catch { setStatus("error"); } }, []); useEffect(() => { void loadSessions(); }, [loadSessions]); useEffect(() => { const loadProjects = async () => { try { setProjects(await listProjects()); } catch { /* ignore */ } }; void loadProjects(); }, []); useEffect(() => { const loadToolTypes = async () => { try { setToolTypes(await listToolTypes()); } catch { /* ignore */ } }; void loadToolTypes(); }, []); const activeSessions = useMemo( () => sessions.filter((s) => ["running", "building", "pending"].includes(s.status), ), [sessions], ); const recentSessions = useMemo( () => sessions .filter((s) => ["stopped", "error"].includes(s.status)) .slice(0, 5), [sessions], ); const lastSession = useMemo( () => sessions.find((s) => s.id === lastSessionId) ?? null, [sessions, lastSessionId], ); const handleOpen = useCallback( (session: Session) => { if (session.tool_type_interfaces?.includes("terminal")) { navigate(`/instances/${session.id}/terminal`); } else { navigate(`/projects/${session.project_id}`); } }, [navigate], ); const handleResumeLast = useCallback(() => { if (!lastSession) return; const project = projects.find((p) => p.name === lastSession.project_name); if (project) navigate(`/projects/${project.id}`); }, [lastSession, projects, navigate]); return (

Sessions

{status === "loading" && } {status === "error" && ( void loadSessions()} /> )} {status === "ready" && ( <> {/* Last Session */} {lastSession && (

Last Session

{lastSession.display_name || lastSession.tool_type_name || "Unnamed Session"}

{lastSession.tool_type_name} · {lastSession.project_name} ·{" "} {lastSession.repository_name}

{lastSession.url && (

{lastSession.url}

)} {lastSession.status}
{lastSession.url ? ( Open ) : ( )}
)} {/* Active Sessions */}

Active Sessions {activeSessions.length > 0 && ( {activeSessions.length} )}

{/* Recent Sessions */} {recentSessions.length > 0 && (

Recent Sessions

)} {/* Create Session */} )}
); };