import { Activity, CheckCircle2, FileCode2, FileText, GitBranch, Loader2, Terminal } from "lucide-react"; import { useMemo } from "react"; import { useAmaSessionEvents } from "../hooks/useAmaSessionEvents"; import { usePersistedSessionEvents } from "../hooks/usePersistedSessionEvents"; import { useSessionRelay } from "../hooks/useSessionRelay"; import { amaRuntimeEventsToRelayEvents, type CodeChangeActivity, extractCodeChangeActivity } from "../lib/codeChangeActivity"; import { FieldLabel, formatRelative } from "./TaskDetailFields"; function taskAnnotations(task: any): Record { const annotations = task?.metadata?.annotations; return annotations && typeof annotations === "object" && !Array.isArray(annotations) ? annotations : {}; } function taskDone(task: any): boolean { return task?.status === "done" || task?.status === "cancelled" || task?.status === "in_review"; } function codeChangeIcon(kind: CodeChangeActivity["kind"]) { switch (kind) { case "edit": case "write": return FileCode2; case "read": return FileText; case "diff": return GitBranch; case "test": case "bash": return Terminal; default: return Activity; } } function CodeChangeRows({ items, phase }: { items: CodeChangeActivity[]; phase: "loading" | "ready" | "error" }) { if (phase === "loading") { return (
Loading runtime activity...
); } if (phase === "error") { return (
Runtime activity unavailable.
); } if (items.length === 0) { return (
No code activity yet.
); } return (
{items.map((item, index) => { const Icon = codeChangeIcon(item.kind); const StatusIcon = item.status === "running" ? Loader2 : CheckCircle2; return (
0 ? "border-t border-border" : ""}`}>
{item.title} {item.subject}
{item.detail &&
{item.detail}
}
{item.status} {formatRelative(item.timestamp)}
); })}
); } function AmaLiveCodeChanges({ task }: { task: any }) { const annotations = taskAnnotations(task); const sessionId = (annotations.sessionId as string) || (annotations.agentSessionId as string) || (annotations["ama.sessionId"] as string); const { events: liveEvents, phase: livePhase } = useAmaSessionEvents({ taskId: task.id, taskDone: taskDone(task), enabled: !taskDone(task), }); const { events: persistedEvents, phase: persistedPhase } = usePersistedSessionEvents({ taskId: task.id, sessionId: sessionId || "", enabled: taskDone(task) || livePhase === "error", }); const events = taskDone(task) || livePhase === "error" ? persistedEvents : amaRuntimeEventsToRelayEvents(liveEvents); const phase = taskDone(task) || livePhase === "error" ? persistedPhase : livePhase; const items = useMemo(() => extractCodeChangeActivity(events, 8), [events]); return ; } function RelayLiveCodeChanges({ sessionId, task }: { sessionId: string; task: any }) { const { events: liveEvents, wsConnected } = useSessionRelay({ sessionId, enabled: !taskDone(task) }); const { events: persistedEvents, phase: persistedPhase } = usePersistedSessionEvents({ taskId: task.id, sessionId, enabled: taskDone(task) || !wsConnected, }); const events = taskDone(task) || !wsConnected ? persistedEvents : liveEvents; const phase = taskDone(task) || !wsConnected ? persistedPhase : "ready"; const items = useMemo(() => extractCodeChangeActivity(events, 8), [events]); return ; } export function LiveCodeChanges({ task }: { task: any }) { const annotations = taskAnnotations(task); const hasAmaSession = typeof annotations["ama.sessionId"] === "string" || typeof annotations.agentSessionId === "string" || typeof annotations["ama.projectId"] === "string" || typeof annotations["ama.runtime"] === "string"; const relaySessionId = typeof task?.active_session_id === "string" ? task.active_session_id : null; if (!hasAmaSession && !relaySessionId) return null; return (
Live Code Changes {hasAmaSession ? : }
); }