Implements Phase 1 of the FlowPilot-First pivot — the core AI session experience where engineers describe a problem and FlowPilot guides them through structured diagnosis with selectable options, free-text escape hatches, and auto-generated documentation on resolution. Backend: AISession + AISessionStep models, FlowPilot Engine (LLM orchestration with structured JSON output), Flow Matching Engine v1 (semantic + keyword + recency scoring), 8 API endpoints with auth, rate limiting, and AI quota enforcement. Frontend: Intake screen, conversational session view with sidebar, step cards with options/actions/resolution suggestions, resolve/escalate modals, documentation view with rating, session history integration, and /pilot route with sidebar navigation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
61 lines
2.3 KiB
TypeScript
61 lines
2.3 KiB
TypeScript
import { Link } from 'react-router-dom'
|
|
import { Clock, CheckCircle2, ArrowUpRight, AlertCircle, Pause } from 'lucide-react'
|
|
import { cn } from '@/lib/utils'
|
|
import type { AISessionSummary } from '@/types/ai-session'
|
|
|
|
interface AISessionListItemProps {
|
|
session: AISessionSummary
|
|
}
|
|
|
|
const STATUS_CONFIG = {
|
|
active: { icon: Clock, color: 'text-primary', label: 'Active' },
|
|
paused: { icon: Pause, color: 'text-amber-400', label: 'Paused' },
|
|
resolved: { icon: CheckCircle2, color: 'text-emerald-400', label: 'Resolved' },
|
|
escalated: { icon: ArrowUpRight, color: 'text-amber-400', label: 'Escalated' },
|
|
abandoned: { icon: AlertCircle, color: 'text-[#5a6170]', label: 'Abandoned' },
|
|
} as const
|
|
|
|
export function AISessionListItem({ session }: AISessionListItemProps) {
|
|
const config = STATUS_CONFIG[session.status as keyof typeof STATUS_CONFIG] ?? STATUS_CONFIG.active
|
|
const StatusIcon = config.icon
|
|
|
|
return (
|
|
<Link
|
|
to={`/pilot/${session.id}`}
|
|
className="glass-card block p-4 transition-all"
|
|
>
|
|
<div className="flex items-start justify-between gap-3">
|
|
<div className="flex-1 min-w-0">
|
|
<p className="text-sm font-medium text-foreground truncate">
|
|
{session.problem_summary || 'Untitled session'}
|
|
</p>
|
|
<div className="mt-1.5 flex items-center gap-3 flex-wrap">
|
|
{session.problem_domain && (
|
|
<span className="font-label rounded-md bg-primary/10 px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-primary">
|
|
{session.problem_domain}
|
|
</span>
|
|
)}
|
|
<span className={cn('flex items-center gap-1 text-xs', config.color)}>
|
|
<StatusIcon size={12} />
|
|
{config.label}
|
|
</span>
|
|
<span className="text-xs text-muted-foreground">
|
|
{session.step_count} steps
|
|
</span>
|
|
<span className="text-xs text-[#5a6170]">
|
|
{new Date(session.created_at).toLocaleDateString(undefined, {
|
|
month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit',
|
|
})}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
{session.session_rating && (
|
|
<span className="font-label text-xs text-amber-400">
|
|
{'★'.repeat(session.session_rating)}
|
|
</span>
|
|
)}
|
|
</div>
|
|
</Link>
|
|
)
|
|
}
|