"use client"; import type { ToolCallMessagePartProps } from "@assistant-ui/react"; import { useAtomValue, useSetAtom } from "jotai"; import { useParams, usePathname } from "next/navigation"; import * as pdfjsLib from "pdfjs-dist"; import { useCallback, useEffect, useRef, useState } from "react"; import { z } from "zod"; import { openReportPanelAtom, reportPanelAtom } from "@/atoms/chat/report-panel.atom"; import { TextShimmerLoader } from "@/components/prompt-kit/loader"; import { useMediaQuery } from "@/hooks/use-media-query"; import { getAuthHeaders } from "@/lib/auth-utils"; pdfjsLib.GlobalWorkerOptions.workerSrc = new URL( "pdfjs-dist/build/pdf.worker.min.mjs", import.meta.url ).toString(); const GenerateResumeArgsSchema = z.object({ user_info: z.string(), user_instructions: z.string().nullish(), parent_report_id: z.number().nullish(), }); const GenerateResumeResultSchema = z.object({ status: z.enum(["ready", "failed"]), report_id: z.number().nullish(), title: z.string().nullish(), content_type: z.string().nullish(), message: z.string().nullish(), error: z.string().nullish(), }); type GenerateResumeArgs = z.infer; type GenerateResumeResult = z.infer; function ResumeGeneratingState() { return (

Resume

); } function ResumeErrorState({ title, error }: { title: string; error: string }) { return (

Resume Generation Failed

{title && title !== "Resume" && (

{title}

)}

{error}

); } function ResumeCancelledState() { return (

Resume Cancelled

Resume generation was cancelled

); } function ThumbnailSkeleton() { return (
); } function PdfThumbnail({ pdfUrl, onLoad, onError, }: { pdfUrl: string; onLoad: () => void; onError: () => void; }) { const wrapperRef = useRef(null); const canvasRef = useRef(null); const [ready, setReady] = useState(false); useEffect(() => { let cancelled = false; const renderThumbnail = async () => { try { const loadingTask = pdfjsLib.getDocument({ url: pdfUrl, httpHeaders: getAuthHeaders(), }); const pdf = await loadingTask.promise; if (cancelled) { pdf.destroy(); return; } const page = await pdf.getPage(1); if (cancelled) { pdf.destroy(); return; } const canvas = canvasRef.current; if (!canvas) { pdf.destroy(); return; } const containerWidth = wrapperRef.current?.clientWidth || 400; const unscaledViewport = page.getViewport({ scale: 1 }); const fitScale = containerWidth / unscaledViewport.width; const viewport = page.getViewport({ scale: fitScale }); const dpr = window.devicePixelRatio || 1; canvas.width = Math.ceil(viewport.width * dpr); canvas.height = Math.ceil(viewport.height * dpr); await page.render({ canvas, viewport, transform: dpr !== 1 ? [dpr, 0, 0, dpr, 0, 0] : undefined, }).promise; if (!cancelled) { setReady(true); onLoad(); } pdf.destroy(); } catch { if (!cancelled) onError(); } }; renderThumbnail(); return () => { cancelled = true; }; }, [pdfUrl, onLoad, onError]); return (
); } function ResumeCard({ reportId, title, shareToken, autoOpen = false, }: { reportId: number; title: string; shareToken?: string | null; autoOpen?: boolean; }) { const openPanel = useSetAtom(openReportPanelAtom); const panelState = useAtomValue(reportPanelAtom); const isDesktop = useMediaQuery("(min-width: 768px)"); const autoOpenedRef = useRef(false); const [pdfUrl, setPdfUrl] = useState(null); const [thumbState, setThumbState] = useState<"loading" | "ready" | "error">("loading"); useEffect(() => { const previewPath = shareToken ? `/api/v1/public/${shareToken}/reports/${reportId}/preview` : `/api/v1/reports/${reportId}/preview`; setPdfUrl(`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}${previewPath}`); if (autoOpen && isDesktop && !autoOpenedRef.current) { autoOpenedRef.current = true; openPanel({ reportId, title, shareToken, contentType: "typst", }); } }, [reportId, title, shareToken, autoOpen, isDesktop, openPanel]); const onThumbLoad = useCallback(() => setThumbState("ready"), []); const onThumbError = useCallback(() => setThumbState("error"), []); const isActive = panelState.isOpen && panelState.reportId === reportId; const handleOpen = () => { openPanel({ reportId, title, shareToken, contentType: "typst", }); }; return (
); } export const GenerateResumeToolUI = ({ result, status, }: ToolCallMessagePartProps) => { const params = useParams(); const pathname = usePathname(); const isPublicRoute = pathname?.startsWith("/public/"); const shareToken = isPublicRoute && typeof params?.token === "string" ? params.token : null; const sawRunningRef = useRef(false); if (status.type === "running" || status.type === "requires-action") { sawRunningRef.current = true; } if (status.type === "running" || status.type === "requires-action") { return ; } if (status.type === "incomplete") { if (status.reason === "cancelled") { return ; } if (status.reason === "error") { return ( ); } } if (!result) { return ; } if (result.status === "failed") { return ( ); } if (result.status === "ready" && result.report_id) { return ( ); } return ; };