From cd219e1727f78e8838aa4b1d00caeb290dceabe9 Mon Sep 17 00:00:00 2001 From: Ayush8923 <80516839+Ayush8923@users.noreply.github.com> Date: Wed, 25 Mar 2026 22:56:29 +0530 Subject: [PATCH 1/5] fix(*): SSR hydration mismatch & improve partial scores UX --- app/(routes)/evaluations/[id]/page.tsx | 51 +++++++++++++++++-- .../icons/evaluations/WarningTriangleIcon.tsx | 23 +++++++++ app/components/icons/index.tsx | 1 + 3 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 app/components/icons/evaluations/WarningTriangleIcon.tsx diff --git a/app/(routes)/evaluations/[id]/page.tsx b/app/(routes)/evaluations/[id]/page.tsx index a073dbf..96f35f4 100644 --- a/app/(routes)/evaluations/[id]/page.tsx +++ b/app/(routes)/evaluations/[id]/page.tsx @@ -27,6 +27,7 @@ import DetailedResultsTable from "@/app/components/DetailedResultsTable"; import { colors } from "@/app/lib/colors"; import { useToast } from "@/app/components/Toast"; import Loader from "@/app/components/Loader"; +import { WarningTriangleIcon } from "@/app/components/icons"; export default function EvaluationReport() { const router = useRouter(); @@ -657,6 +658,24 @@ export default function EvaluationReport() { {/* Metrics */} {hasScore && isNewFormat ? (
+ {summaryScores.some( + (s) => job.total_items && s.total_pairs < job.total_items, + ) && ( +
+ + Some traces are still being scored. Scores shown are + partial and may change — click{" "} + Resync to + get the latest. +
+ )}

(
{summary.std !== undefined && `±${summary.std.toFixed(3)} · `} - {summary.total_pairs} pairs + {job.total_items && + summary.total_pairs < job.total_items ? ( + + {summary.total_pairs}/{job.total_items} pairs + ⚠ + + ) : ( + {summary.total_pairs} pairs + )}

))} @@ -727,7 +758,7 @@ export default function EvaluationReport() { .map((summary) => (
- {summary.total_pairs} pairs + {job.total_items && + summary.total_pairs < job.total_items ? ( + + {summary.total_pairs}/{job.total_items} pairs + ⚠ + + ) : ( + {summary.total_pairs} pairs + )}
))} diff --git a/app/components/icons/evaluations/WarningTriangleIcon.tsx b/app/components/icons/evaluations/WarningTriangleIcon.tsx new file mode 100644 index 0000000..737b9ce --- /dev/null +++ b/app/components/icons/evaluations/WarningTriangleIcon.tsx @@ -0,0 +1,23 @@ +interface IconProps { + className?: string; + style?: React.CSSProperties; +} + +export default function WarningTriangleIcon({ className, style }: IconProps) { + return ( + + + + ); +} diff --git a/app/components/icons/index.tsx b/app/components/icons/index.tsx index 9167c71..c10d348 100644 --- a/app/components/icons/index.tsx +++ b/app/components/icons/index.tsx @@ -4,3 +4,4 @@ export { default as ChevronDownIcon } from "./evaluations/ChevronDownIcon"; export { default as EditIcon } from "./evaluations/EditIcon"; export { default as GearIcon } from "./evaluations/GearIcon"; export { default as CheckIcon } from "./evaluations/CheckIcon"; +export { default as WarningTriangleIcon } from "./evaluations/WarningTriangleIcon"; From 39edb74af835358b1bc389dfa08959c7e0efd1aa Mon Sep 17 00:00:00 2001 From: Ayush8923 <80516839+Ayush8923@users.noreply.github.com> Date: Wed, 25 Mar 2026 23:28:59 +0530 Subject: [PATCH 2/5] fix(*): some of the improvements --- app/(routes)/evaluations/[id]/page.tsx | 137 ++++-------------- .../icons/evaluations/ChevronLeftIcon.tsx | 19 +++ .../icons/evaluations/DatabaseIcon.tsx | 23 +++ .../icons/evaluations/GroupIcon.tsx | 23 +++ app/components/icons/evaluations/MenuIcon.tsx | 23 +++ .../icons/evaluations/RefreshIcon.tsx | 23 +++ app/components/icons/index.tsx | 5 + app/globals.css | 30 ++++ 8 files changed, 172 insertions(+), 111 deletions(-) create mode 100644 app/components/icons/evaluations/ChevronLeftIcon.tsx create mode 100644 app/components/icons/evaluations/DatabaseIcon.tsx create mode 100644 app/components/icons/evaluations/GroupIcon.tsx create mode 100644 app/components/icons/evaluations/MenuIcon.tsx create mode 100644 app/components/icons/evaluations/RefreshIcon.tsx diff --git a/app/(routes)/evaluations/[id]/page.tsx b/app/(routes)/evaluations/[id]/page.tsx index 96f35f4..94159b7 100644 --- a/app/(routes)/evaluations/[id]/page.tsx +++ b/app/(routes)/evaluations/[id]/page.tsx @@ -27,7 +27,14 @@ import DetailedResultsTable from "@/app/components/DetailedResultsTable"; import { colors } from "@/app/lib/colors"; import { useToast } from "@/app/components/Toast"; import Loader from "@/app/components/Loader"; -import { WarningTriangleIcon } from "@/app/components/icons"; +import { + WarningTriangleIcon, + MenuIcon, + ChevronLeftIcon, + DatabaseIcon, + GroupIcon, + RefreshIcon, +} from "@/app/components/icons"; export default function EvaluationReport() { const router = useRouter(); @@ -447,38 +454,14 @@ export default function EvaluationReport() { className="p-1.5 rounded-md flex-shrink-0" style={{ color: colors.text.secondary }} > - - - +

- - - + {job.dataset_name}

@@ -554,19 +525,7 @@ export default function EvaluationReport() { } }} > - - - + Individual Rows @@ -661,14 +608,7 @@ export default function EvaluationReport() { {summaryScores.some( (s) => job.total_items && s.total_pairs < job.total_items, ) && ( -
+
Some traces are still being scored. Scores shown are partial and may change — click{" "} @@ -688,19 +628,9 @@ export default function EvaluationReport() { disabled={isResyncing} className="flex items-center gap-1.5 px-3 py-1.5 rounded-md text-xs font-medium bg-[#171717] text-white disabled:opacity-50" > - - - + {isResyncing ? "Resyncing..." : "Resync"}
@@ -740,12 +670,11 @@ export default function EvaluationReport() { {job.total_items && summary.total_pairs < job.total_items ? ( {summary.total_pairs}/{job.total_items} pairs - ⚠ + ) : ( {summary.total_pairs} pairs @@ -758,16 +687,12 @@ export default function EvaluationReport() { .map((summary) => (
-
+
{summary.name}
@@ -776,15 +701,9 @@ export default function EvaluationReport() { ([key, value]) => (
- + {key} -
+
{job.total_items && summary.total_pairs < job.total_items ? ( {summary.total_pairs}/{job.total_items} pairs - ⚠ + ) : ( {summary.total_pairs} pairs diff --git a/app/components/icons/evaluations/ChevronLeftIcon.tsx b/app/components/icons/evaluations/ChevronLeftIcon.tsx new file mode 100644 index 0000000..64a52ac --- /dev/null +++ b/app/components/icons/evaluations/ChevronLeftIcon.tsx @@ -0,0 +1,19 @@ +interface IconProps { + className?: string; + style?: React.CSSProperties; +} + +export default function ChevronLeftIcon({ className, style }: IconProps) { + return ( + + + + ); +} diff --git a/app/components/icons/evaluations/DatabaseIcon.tsx b/app/components/icons/evaluations/DatabaseIcon.tsx new file mode 100644 index 0000000..360b991 --- /dev/null +++ b/app/components/icons/evaluations/DatabaseIcon.tsx @@ -0,0 +1,23 @@ +interface IconProps { + className?: string; + style?: React.CSSProperties; +} + +export default function DatabaseIcon({ className, style }: IconProps) { + return ( + + + + ); +} diff --git a/app/components/icons/evaluations/GroupIcon.tsx b/app/components/icons/evaluations/GroupIcon.tsx new file mode 100644 index 0000000..8da3de4 --- /dev/null +++ b/app/components/icons/evaluations/GroupIcon.tsx @@ -0,0 +1,23 @@ +interface IconProps { + className?: string; + style?: React.CSSProperties; +} + +export default function GroupIcon({ className, style }: IconProps) { + return ( + + + + ); +} diff --git a/app/components/icons/evaluations/MenuIcon.tsx b/app/components/icons/evaluations/MenuIcon.tsx new file mode 100644 index 0000000..a53975f --- /dev/null +++ b/app/components/icons/evaluations/MenuIcon.tsx @@ -0,0 +1,23 @@ +interface IconProps { + className?: string; + style?: React.CSSProperties; +} + +export default function MenuIcon({ className, style }: IconProps) { + return ( + + + + ); +} diff --git a/app/components/icons/evaluations/RefreshIcon.tsx b/app/components/icons/evaluations/RefreshIcon.tsx new file mode 100644 index 0000000..fedb9e2 --- /dev/null +++ b/app/components/icons/evaluations/RefreshIcon.tsx @@ -0,0 +1,23 @@ +interface IconProps { + className?: string; + style?: React.CSSProperties; +} + +export default function RefreshIcon({ className, style }: IconProps) { + return ( + + + + ); +} diff --git a/app/components/icons/index.tsx b/app/components/icons/index.tsx index c10d348..54feb0f 100644 --- a/app/components/icons/index.tsx +++ b/app/components/icons/index.tsx @@ -1,7 +1,12 @@ // Evaluations Icons export { default as ChevronUpIcon } from "./evaluations/ChevronUpIcon"; export { default as ChevronDownIcon } from "./evaluations/ChevronDownIcon"; +export { default as ChevronLeftIcon } from "./evaluations/ChevronLeftIcon"; export { default as EditIcon } from "./evaluations/EditIcon"; export { default as GearIcon } from "./evaluations/GearIcon"; export { default as CheckIcon } from "./evaluations/CheckIcon"; export { default as WarningTriangleIcon } from "./evaluations/WarningTriangleIcon"; +export { default as MenuIcon } from "./evaluations/MenuIcon"; +export { default as DatabaseIcon } from "./evaluations/DatabaseIcon"; +export { default as GroupIcon } from "./evaluations/GroupIcon"; +export { default as RefreshIcon } from "./evaluations/RefreshIcon"; diff --git a/app/globals.css b/app/globals.css index 7de4e92..a29d7df 100644 --- a/app/globals.css +++ b/app/globals.css @@ -19,6 +19,36 @@ --font-mono: var(--font-geist-mono); } +/* Background colors */ +@theme inline { + --color-bg-primary: #ffffff; + --color-bg-secondary: #fafafa; +} + +/* Text colors */ +@theme inline { + --color-text-primary: #171717; + --color-text-secondary: #737373; +} + +/* Border colors */ +@theme inline { + --color-border: #e5e5e5; +} + +/* Accent colors */ +@theme inline { + --color-accent-primary: #171717; + --color-accent-hover: #404040; +} + +/* Status colors */ +@theme inline { + --color-status-success: #16a34a; + --color-status-error: #dc2626; + --color-status-warning: #f59e0b; +} + @media (prefers-color-scheme: dark) { :root { --background: #000000; From aa742553ebcd2ea3dc4fb3d4d3c083e2abe4e097 Mon Sep 17 00:00:00 2001 From: Ayush8923 <80516839+Ayush8923@users.noreply.github.com> Date: Thu, 26 Mar 2026 22:05:33 +0530 Subject: [PATCH 3/5] fix(*): added the loading in the dataset list --- app/(routes)/evaluations/page.tsx | 5 +++++ app/components/evaluations/DatasetsTab.tsx | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/(routes)/evaluations/page.tsx b/app/(routes)/evaluations/page.tsx index 860ad57..12bcf45 100644 --- a/app/(routes)/evaluations/page.tsx +++ b/app/(routes)/evaluations/page.tsx @@ -53,6 +53,7 @@ function SimplifiedEvalContent() { // Stored datasets const [storedDatasets, setStoredDatasets] = useState([]); + const [isDatasetsLoading, setIsDatasetsLoading] = useState(false); // Evaluation config state const [selectedDatasetId, setSelectedDatasetId] = useState(() => { @@ -86,6 +87,7 @@ function SimplifiedEvalContent() { console.error("No selected API key found for loading datasets"); return; } + setIsDatasetsLoading(true); try { const response = await fetch("/api/evaluations/datasets", { method: "GET", @@ -96,6 +98,8 @@ function SimplifiedEvalContent() { setStoredDatasets(Array.isArray(data) ? data : data.data || []); } catch (e) { console.error("Failed to load datasets:", e); + } finally { + setIsDatasetsLoading(false); } }, [apiKeys, selectedKeyId]); @@ -426,6 +430,7 @@ function SimplifiedEvalContent() { setUploadedFile(null); }} storedDatasets={storedDatasets} + isDatasetsLoading={isDatasetsLoading} apiKeys={apiKeys} selectedKeyId={selectedKeyId} loadStoredDatasets={loadStoredDatasets} diff --git a/app/components/evaluations/DatasetsTab.tsx b/app/components/evaluations/DatasetsTab.tsx index feee141..7e41a1a 100644 --- a/app/components/evaluations/DatasetsTab.tsx +++ b/app/components/evaluations/DatasetsTab.tsx @@ -6,6 +6,7 @@ import { APIKey } from "@/app/lib/types/credentials"; import { Dataset } from "@/app/(routes)/datasets/page"; import { useToast } from "@/app/components/Toast"; import EvalDatasetDescription from "./EvalDatasetDescription"; +import Loader from "@/app/components/Loader"; export interface DatasetsTabProps { leftPanelWidth: number; @@ -22,6 +23,7 @@ export interface DatasetsTabProps { handleCreateDataset: () => void; resetForm: () => void; storedDatasets: Dataset[]; + isDatasetsLoading: boolean; apiKeys: APIKey[]; selectedKeyId: string; loadStoredDatasets: () => void; @@ -43,6 +45,7 @@ export default function DatasetsTab({ handleCreateDataset, resetForm, storedDatasets, + isDatasetsLoading, apiKeys, selectedKeyId, loadStoredDatasets, @@ -559,7 +562,11 @@ export default function DatasetsTab({
- {storedDatasets.length === 0 ? ( + {isDatasetsLoading ? ( +
+ +
+ ) : storedDatasets.length === 0 ? (
Date: Fri, 27 Mar 2026 09:39:01 +0530 Subject: [PATCH 4/5] fix(*): some cleanups and updates --- app/(routes)/evaluations/[id]/page.tsx | 67 +++++++------------------- 1 file changed, 18 insertions(+), 49 deletions(-) diff --git a/app/(routes)/evaluations/[id]/page.tsx b/app/(routes)/evaluations/[id]/page.tsx index 94159b7..09ec47b 100644 --- a/app/(routes)/evaluations/[id]/page.tsx +++ b/app/(routes)/evaluations/[id]/page.tsx @@ -1,6 +1,5 @@ /** - * EvaluationReport.tsx - Detailed evaluation report page - * + * Detailed evaluation report page * Shows metrics overview and per-item scores for a specific evaluation job */ @@ -8,6 +7,7 @@ import { useState, useEffect, useCallback } from "react"; import { useRouter, useParams } from "next/navigation"; +import { apiFetch } from "@/app/lib/apiClient"; import { useAuth } from "@/app/lib/context/AuthContext"; import { useApp } from "@/app/lib/context/AppContext"; import { @@ -73,7 +73,6 @@ export default function EvaluationReport() { return `"${sanitized}"`; }; - // Set initial selected key from context useEffect(() => { if (apiKeys.length > 0 && !selectedKeyId) { setSelectedKeyId(apiKeys[0].id); @@ -91,25 +90,12 @@ export default function EvaluationReport() { setError(null); try { - const response = await fetch( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const data = await apiFetch( `/api/evaluations/${jobId}?export_format=${exportFormat}`, - { - method: "GET", - headers: { "X-API-KEY": selectedKey.key }, - }, + selectedKey.key, ); - if (!response.ok) { - const errorData = await response.json().catch(() => ({})); - throw new Error( - errorData.error || - errorData.message || - `Failed to fetch evaluation: ${response.status}`, - ); - } - - const data = await response.json(); - if (data.success === false && data.error) { toast.error(data.error); setExportFormat("row"); @@ -143,12 +129,11 @@ export default function EvaluationReport() { const fetchAssistantConfig = async (assistantId: string, apiKey: string) => { try { - const response = await fetch(`/api/assistant/${assistantId}`, { - method: "GET", - headers: { "X-API-KEY": apiKey }, - }); - if (!response.ok) return; - const result = await response.json(); + + const result = await apiFetch<{ + success: boolean; + data?: AssistantConfig; + }>(`/api/assistant/${assistantId}`, apiKey); if (result.success && result.data) setAssistantConfig(result.data); } catch (err) { console.error( @@ -164,15 +149,11 @@ export default function EvaluationReport() { apiKey: string, ) => { try { - const configResponse = await fetch(`/api/configs/${configId}`, { - headers: { "X-API-KEY": apiKey }, - }); - if (!configResponse.ok) return; - const versionResponse = await fetch( + await apiFetch(`/api/configs/${configId}`, apiKey); + await apiFetch( `/api/configs/${configId}/versions/${configVersion}`, - { headers: { "X-API-KEY": apiKey } }, + apiKey, ); - if (!versionResponse.ok) return; } catch (error) { console.error("Error fetching config version info:", error); } @@ -329,22 +310,11 @@ export default function EvaluationReport() { setIsResyncing(true); try { - const response = await fetch( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const data = await apiFetch( `/api/evaluations/${jobId}?get_trace_info=true&resync_score=true&export_format=${exportFormat}`, - { - method: "GET", - headers: { "X-API-KEY": selectedKey.key }, - }, + selectedKey.key, ); - if (!response.ok) { - const errorData = await response.json().catch(() => ({})); - throw new Error( - errorData.error || - errorData.message || - `Failed to resync: ${response.status}`, - ); - } - const data = await response.json(); const foundJob = data.data || data; if (!foundJob) throw new Error("Evaluation job not found"); @@ -608,7 +578,7 @@ export default function EvaluationReport() { {summaryScores.some( (s) => job.total_items && s.total_pairs < job.total_items, ) && ( -
+
Some traces are still being scored. Scores shown are partial and may change — click{" "} @@ -834,10 +804,9 @@ export default function EvaluationReport() {