"use client"; import Link from "@/components/routing/app-link"; import { IconAlertTriangle, IconRefresh } from "@tabler/icons-react"; import { Alert, AlertDescription, AlertTitle } from "@kandev/ui/alert"; import { Button } from "@kandev/ui/button"; // EnsureSessionErrorInfo wraps a parsed ensure error so UI can offer a targeted action for the missing-agent-profile case. export type EnsureSessionErrorInfo = { title: string; detail: string; isAgentProfileMissing: boolean; action: { label: string; href: string } | null; }; // Matches the backend's exact validation message in task_http_handlers.go / task_ws_handlers.go. const AGENT_PROFILE_MISSING_HINT = "agent_profile_id is required"; export function describeEnsureError( error: Error | null, workspaceId?: string | null, ): EnsureSessionErrorInfo | null { if (!error) return null; const message = error.message ?? ""; const isAgentProfileMissing = message.toLowerCase().includes(AGENT_PROFILE_MISSING_HINT); if (isAgentProfileMissing) { return { title: "No agent profile configured", detail: "This task has no agent profile, and the workspace, workflow, and workflow step have no default set. Pick a default agent profile so new tasks can start a session.", isAgentProfileMissing: true, action: workspaceId ? { label: "Open workspace settings", href: `/settings/workspace/${workspaceId}` } : null, }; } return { title: "Couldn't start a session", detail: message || "The backend rejected the session request.", isAgentProfileMissing: false, action: null, }; } type BannerProps = { error: Error | null; onRetry: () => void; workspaceId?: string | null; }; /** Slim banner for the task page, rendered above the layout. */ export function EnsureSessionErrorBanner({ error, onRetry, workspaceId }: BannerProps) { const info = describeEnsureError(error, workspaceId); if (!info) return null; return (
{info.title} {info.detail} {info.action ? ( {info.action.label} ) : null}
); } /** Full-panel centered state for the kanban preview's empty-sessions slot. */ export function EnsureSessionErrorEmptyState({ error, onRetry, workspaceId }: BannerProps) { const info = describeEnsureError(error, workspaceId); if (!info) return null; return (
{info.title} {info.detail} {info.action ? ( {info.action.label} ) : null}
); }