mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-25 00:36:31 +02:00
chore: ran linting
This commit is contained in:
parent
aef4c90107
commit
0fa32c3a10
6 changed files with 140 additions and 73 deletions
|
|
@ -204,8 +204,19 @@ def _get_template(template_id: str | None = None) -> dict[str, str]:
|
|||
|
||||
|
||||
_MONTH_NAMES = [
|
||||
"", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
|
||||
"",
|
||||
"Jan",
|
||||
"Feb",
|
||||
"Mar",
|
||||
"Apr",
|
||||
"May",
|
||||
"Jun",
|
||||
"Jul",
|
||||
"Aug",
|
||||
"Sep",
|
||||
"Oct",
|
||||
"Nov",
|
||||
"Dec",
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -452,7 +463,9 @@ def create_generate_resume_tool(
|
|||
)
|
||||
return failed.id
|
||||
except Exception:
|
||||
logger.exception("[generate_resume] Could not persist failed report row")
|
||||
logger.exception(
|
||||
"[generate_resume] Could not persist failed report row"
|
||||
)
|
||||
return None
|
||||
|
||||
try:
|
||||
|
|
@ -471,7 +484,9 @@ def create_generate_resume_tool(
|
|||
llm = await get_document_summary_llm(read_session, search_space_id)
|
||||
|
||||
if not llm:
|
||||
error_msg = "No LLM configured. Please configure a language model in Settings."
|
||||
error_msg = (
|
||||
"No LLM configured. Please configure a language model in Settings."
|
||||
)
|
||||
report_id = await _save_failed_report(error_msg)
|
||||
return {
|
||||
"status": "failed",
|
||||
|
|
@ -497,7 +512,8 @@ def create_generate_resume_tool(
|
|||
parent_body = _strip_header(parent_content)
|
||||
prompt = _REVISION_PROMPT.format(
|
||||
llm_reference=llm_reference,
|
||||
user_instructions=user_instructions or "Improve and refine the resume.",
|
||||
user_instructions=user_instructions
|
||||
or "Improve and refine the resume.",
|
||||
previous_content=parent_body,
|
||||
)
|
||||
else:
|
||||
|
|
@ -553,7 +569,10 @@ def create_generate_resume_tool(
|
|||
if attempt == 0:
|
||||
dispatch_custom_event(
|
||||
"report_progress",
|
||||
{"phase": "fixing", "message": "Fixing compilation issue..."},
|
||||
{
|
||||
"phase": "fixing",
|
||||
"message": "Fixing compilation issue...",
|
||||
},
|
||||
)
|
||||
fix_prompt = _FIX_COMPILE_PROMPT.format(
|
||||
llm_reference=llm_reference,
|
||||
|
|
@ -563,7 +582,9 @@ def create_generate_resume_tool(
|
|||
fix_response = await llm.ainvoke(
|
||||
[HumanMessage(content=fix_prompt)]
|
||||
)
|
||||
if fix_response.content and isinstance(fix_response.content, str):
|
||||
if fix_response.content and isinstance(
|
||||
fix_response.content, str
|
||||
):
|
||||
body = _strip_typst_fences(fix_response.content)
|
||||
body = _strip_imports(body)
|
||||
name = _extract_name(body) or name
|
||||
|
|
@ -571,7 +592,9 @@ def create_generate_resume_tool(
|
|||
typst_source = header + body
|
||||
|
||||
if compile_error:
|
||||
error_msg = f"Typst compilation failed after 2 attempts: {compile_error}"
|
||||
error_msg = (
|
||||
f"Typst compilation failed after 2 attempts: {compile_error}"
|
||||
)
|
||||
report_id = await _save_failed_report(error_msg)
|
||||
return {
|
||||
"status": "failed",
|
||||
|
|
|
|||
|
|
@ -42,7 +42,13 @@ export const openReportPanelAtom = atom(
|
|||
wordCount,
|
||||
shareToken,
|
||||
contentType,
|
||||
}: { reportId: number; title: string; wordCount?: number; shareToken?: string | null; contentType?: string }
|
||||
}: {
|
||||
reportId: number;
|
||||
title: string;
|
||||
wordCount?: number;
|
||||
shareToken?: string | null;
|
||||
contentType?: string;
|
||||
}
|
||||
) => {
|
||||
if (!get(reportPanelAtom).isOpen) {
|
||||
set(preReportCollapsedAtom, get(rightPanelCollapsedAtom));
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import { ZoomInIcon, ZoomOutIcon } from "lucide-react";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import * as pdfjsLib from "pdfjs-dist";
|
||||
import type { PDFDocumentProxy, RenderTask } from "pdfjs-dist";
|
||||
import * as pdfjsLib from "pdfjs-dist";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { getAuthHeaders } from "@/lib/auth-utils";
|
||||
|
|
@ -50,7 +50,7 @@ export function PdfViewer({ pdfUrl, isPublic = false }: PdfViewerProps) {
|
|||
const dims = pageDimsRef.current[pageIndex];
|
||||
return dims ? Math.floor(dims.height * scale) : 0;
|
||||
},
|
||||
[scale],
|
||||
[scale]
|
||||
);
|
||||
|
||||
const getVisibleRange = useCallback(() => {
|
||||
|
|
@ -285,14 +285,28 @@ export function PdfViewer({ pdfUrl, isPublic = false }: PdfViewerProps) {
|
|||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
{numPages > 0 && (
|
||||
<div className={`flex items-center justify-center gap-2 px-4 py-2 border-b shrink-0 select-none ${isPublic ? "bg-main-panel" : "bg-sidebar"}`}>
|
||||
<Button variant="ghost" size="icon" onClick={zoomOut} disabled={scale <= MIN_ZOOM} className="size-7">
|
||||
<div
|
||||
className={`flex items-center justify-center gap-2 px-4 py-2 border-b shrink-0 select-none ${isPublic ? "bg-main-panel" : "bg-sidebar"}`}
|
||||
>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={zoomOut}
|
||||
disabled={scale <= MIN_ZOOM}
|
||||
className="size-7"
|
||||
>
|
||||
<ZoomOutIcon className="size-4" />
|
||||
</Button>
|
||||
<span className="text-xs text-muted-foreground tabular-nums min-w-[40px] text-center">
|
||||
{Math.round(scale * 100)}%
|
||||
</span>
|
||||
<Button variant="ghost" size="icon" onClick={zoomIn} disabled={scale >= MAX_ZOOM} className="size-7">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={zoomIn}
|
||||
disabled={scale >= MAX_ZOOM}
|
||||
className="size-7"
|
||||
>
|
||||
<ZoomInIcon className="size-4" />
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -303,7 +317,9 @@ export function PdfViewer({ pdfUrl, isPublic = false }: PdfViewerProps) {
|
|||
className={`relative flex-1 overflow-auto ${isPublic ? "bg-main-panel" : "bg-sidebar"}`}
|
||||
>
|
||||
{loading ? (
|
||||
<div className={`absolute inset-0 flex items-center justify-center ${isPublic ? "text-foreground" : "text-sidebar-foreground"}`}>
|
||||
<div
|
||||
className={`absolute inset-0 flex items-center justify-center ${isPublic ? "text-foreground" : "text-sidebar-foreground"}`}
|
||||
>
|
||||
<Spinner size="md" />
|
||||
</div>
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -308,42 +308,42 @@ export function ReportPanelContent({
|
|||
</Button>
|
||||
)}
|
||||
|
||||
{/* Export — plain button for resume (typst), dropdown for others */}
|
||||
{reportContent?.content_type === "typst" ? (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => handleExport("pdf")}
|
||||
disabled={isLoading || !reportContent?.content || exporting !== null}
|
||||
className={`h-8 min-w-[100px] px-3.5 py-4 text-[15px] ${btnBg} select-none`}
|
||||
>
|
||||
{exporting === "pdf" ? <Spinner size="xs" /> : "Download"}
|
||||
</Button>
|
||||
) : (
|
||||
<DropdownMenu modal={insideDrawer ? false : undefined}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
disabled={isLoading || !reportContent?.content}
|
||||
className={`h-8 px-3.5 py-4 text-[15px] gap-1.5 ${btnBg} select-none`}
|
||||
>
|
||||
Export
|
||||
<ChevronDownIcon className="size-3" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
align="start"
|
||||
className={`min-w-[200px] select-none${insideDrawer ? " z-[100]" : ""}`}
|
||||
{/* Export — plain button for resume (typst), dropdown for others */}
|
||||
{reportContent?.content_type === "typst" ? (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => handleExport("pdf")}
|
||||
disabled={isLoading || !reportContent?.content || exporting !== null}
|
||||
className={`h-8 min-w-[100px] px-3.5 py-4 text-[15px] ${btnBg} select-none`}
|
||||
>
|
||||
<ExportDropdownItems
|
||||
onExport={handleExport}
|
||||
exporting={exporting}
|
||||
showAllFormats={!shareToken}
|
||||
/>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)}
|
||||
{exporting === "pdf" ? <Spinner size="xs" /> : "Download"}
|
||||
</Button>
|
||||
) : (
|
||||
<DropdownMenu modal={insideDrawer ? false : undefined}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
disabled={isLoading || !reportContent?.content}
|
||||
className={`h-8 px-3.5 py-4 text-[15px] gap-1.5 ${btnBg} select-none`}
|
||||
>
|
||||
Export
|
||||
<ChevronDownIcon className="size-3" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
align="start"
|
||||
className={`min-w-[200px] select-none${insideDrawer ? " z-[100]" : ""}`}
|
||||
>
|
||||
<ExportDropdownItems
|
||||
onExport={handleExport}
|
||||
exporting={exporting}
|
||||
showAllFormats={!shareToken}
|
||||
/>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)}
|
||||
|
||||
{/* Version switcher — only shown when multiple versions exist */}
|
||||
{versions.length > 1 && (
|
||||
|
|
@ -395,10 +395,10 @@ export function ReportPanelContent({
|
|||
</div>
|
||||
</div>
|
||||
) : reportContent.content_type === "typst" ? (
|
||||
<PdfViewer
|
||||
pdfUrl={`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}${shareToken ? `/api/v1/public/${shareToken}/reports/${activeReportId}/preview` : `/api/v1/reports/${activeReportId}/preview`}`}
|
||||
isPublic={isPublic}
|
||||
/>
|
||||
<PdfViewer
|
||||
pdfUrl={`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}${shareToken ? `/api/v1/public/${shareToken}/reports/${activeReportId}/preview` : `/api/v1/reports/${activeReportId}/preview`}`}
|
||||
isPublic={isPublic}
|
||||
/>
|
||||
) : reportContent.content ? (
|
||||
isReadOnly ? (
|
||||
<div className="h-full overflow-y-auto px-5 py-4">
|
||||
|
|
|
|||
|
|
@ -99,7 +99,9 @@ function ReportErrorState({ title, error }: { title: string; error: string }) {
|
|||
{title && title !== "Report" && (
|
||||
<p className="text-sm font-medium text-foreground line-clamp-2">{title}</p>
|
||||
)}
|
||||
<p className={`text-sm text-muted-foreground${title && title !== "Report" ? " mt-1" : ""}`}>{error}</p>
|
||||
<p className={`text-sm text-muted-foreground${title && title !== "Report" ? " mt-1" : ""}`}>
|
||||
{error}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -217,11 +219,11 @@ function ReportCard({
|
|||
<div
|
||||
className={`my-4 max-w-lg overflow-hidden rounded-2xl border bg-muted/30 transition-[box-shadow] duration-300 ${isActive ? "ring-1 ring-primary/50" : ""}`}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleOpen}
|
||||
className="w-full text-left transition-colors hover:bg-muted/50 focus:outline-none focus-visible:outline-none cursor-pointer"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleOpen}
|
||||
className="w-full text-left transition-colors hover:bg-muted/50 focus:outline-none focus-visible:outline-none cursor-pointer"
|
||||
>
|
||||
<div className="px-5 pt-5 pb-4 select-none">
|
||||
<p className="text-sm font-semibold text-foreground line-clamp-2">
|
||||
{isLoading ? title : metadata.title}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
import type { ToolCallMessagePartProps } from "@assistant-ui/react";
|
||||
import { useAtomValue, useSetAtom } from "jotai";
|
||||
import { useParams, usePathname } from "next/navigation";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
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";
|
||||
|
|
@ -70,7 +70,9 @@ function ResumeErrorState({ title, error }: { title: string; error: string }) {
|
|||
{title && title !== "Resume" && (
|
||||
<p className="text-sm font-medium text-foreground line-clamp-2">{title}</p>
|
||||
)}
|
||||
<p className={`text-sm text-muted-foreground${title && title !== "Resume" ? " mt-1" : ""}`}>{error}</p>
|
||||
<p className={`text-sm text-muted-foreground${title && title !== "Resume" ? " mt-1" : ""}`}>
|
||||
{error}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -101,7 +103,15 @@ function ThumbnailSkeleton() {
|
|||
);
|
||||
}
|
||||
|
||||
function PdfThumbnail({ pdfUrl, onLoad, onError }: { pdfUrl: string; onLoad: () => void; onError: () => void }) {
|
||||
function PdfThumbnail({
|
||||
pdfUrl,
|
||||
onLoad,
|
||||
onError,
|
||||
}: {
|
||||
pdfUrl: string;
|
||||
onLoad: () => void;
|
||||
onError: () => void;
|
||||
}) {
|
||||
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
const [ready, setReady] = useState(false);
|
||||
|
|
@ -117,13 +127,22 @@ function PdfThumbnail({ pdfUrl, onLoad, onError }: { pdfUrl: string; onLoad: ()
|
|||
});
|
||||
|
||||
const pdf = await loadingTask.promise;
|
||||
if (cancelled) { pdf.destroy(); return; }
|
||||
if (cancelled) {
|
||||
pdf.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
const page = await pdf.getPage(1);
|
||||
if (cancelled) { pdf.destroy(); return; }
|
||||
if (cancelled) {
|
||||
pdf.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) { pdf.destroy(); return; }
|
||||
if (!canvas) {
|
||||
pdf.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
const containerWidth = wrapperRef.current?.clientWidth || 400;
|
||||
const unscaledViewport = page.getViewport({ scale: 1 });
|
||||
|
|
@ -152,15 +171,14 @@ function PdfThumbnail({ pdfUrl, onLoad, onError }: { pdfUrl: string; onLoad: ()
|
|||
};
|
||||
|
||||
renderThumbnail();
|
||||
return () => { cancelled = true; };
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [pdfUrl, onLoad, onError]);
|
||||
|
||||
return (
|
||||
<div ref={wrapperRef}>
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className={ready ? "w-full h-auto" : "hidden"}
|
||||
/>
|
||||
<canvas ref={canvasRef} className={ready ? "w-full h-auto" : "hidden"} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -294,7 +312,9 @@ export const GenerateResumeToolUI = ({
|
|||
return (
|
||||
<ResumeErrorState
|
||||
title={result.title || "Resume"}
|
||||
error={result.error || "Resume generation failed. Please try again or rephrase your request."}
|
||||
error={
|
||||
result.error || "Resume generation failed. Please try again or rephrase your request."
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue