"use client";
import Link from "@/components/routing/app-link";
import { IconAlertTriangle, IconInfoCircle, IconRefresh } from "@tabler/icons-react";
import { Alert, AlertDescription, AlertTitle } from "@kandev/ui/alert";
import { Button } from "@kandev/ui/button";
import { useTranslation } from "react-i18next";
import { t } from "@/lib/i18n";
import { cn } from "@/lib/utils";
import type { SessionRecoveryFailure } from "@/hooks/domains/session/use-session-resumption";
// 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.
// i18n-exempt: matches the backend's exact validation message. See the comment above.
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: t("task:noAgentProfileConfigured"),
detail: t("task:noAgentProfileConfiguredDetail"),
isAgentProfileMissing: true,
action: workspaceId
? {
label: t("task:openWorkspaceSettings"),
href: `/settings/workspaces/${workspaceId}`,
}
: null,
};
}
return {
title: t("task:couldnTStartASession"),
detail: message || t("task:backendRejectedSessionRequest"),
isAgentProfileMissing: false,
action: null,
};
}
type RecoveryAction = {
label: string;
onClick: () => void;
testId: string;
disabled?: boolean;
};
type BannerProps = {
error: Error | null;
onRetry: () => void;
workspaceId?: string | null;
action?: RecoveryAction;
secondaryAction?: RecoveryAction;
retryDisabled?: boolean;
recoveryFailure?: SessionRecoveryFailure | null;
testId?: string;
compact?: boolean;
};
function RecoveryFailureDetails({ failure }: { failure: SessionRecoveryFailure }) {
const { t } = useTranslation();
return (
{t("task:sessionRecoveryDetails")}