Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ export async function GET(
comment_count: evalVersion.comments.length,
comments: evalVersion.comments.map((comment) => ({
header: comment.header,
level: comment.level,
variant: comment.variant,
source: comment.source,
metadata: comment.metadata,
description: comment.description,
Expand Down
5 changes: 3 additions & 2 deletions apps/web/src/app/docs/[docId]/export/ExportClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useEffect, useState } from "react";

import yaml from "js-yaml";
import { RefreshCw } from "lucide-react";
import type { CommentVariant } from "@roast/ai";

import CodeBlock from "@/components/CodeBlock";
import { Button } from "@/components/ui/button";
Expand All @@ -13,7 +14,7 @@ interface Comment {
description: string;
importance?: number | null;
grade?: number | null;
level?: string | null;
variant?: CommentVariant | null;
source?: string | null;
metadata?: any;
highlight?: {
Expand Down Expand Up @@ -181,7 +182,7 @@ export function ExportClient({ document, evaluations }: ExportClientProps) {

// Add expanded data only if mode is 'expanded'
if (commentsMode === 'expanded') {
if (comment.level) commentData.level = comment.level;
if (comment.variant) commentData.variant = comment.variant;
if (comment.source) commentData.source = comment.source;
if (comment.metadata) commentData.metadata = comment.metadata;

Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/app/docs/[docId]/export/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export default async function DocumentExportPage({
description: comment.description,
importance: comment.importance,
grade: comment.grade,
level: comment.level,
variant: comment.variant,
source: comment.source,
metadata: comment.metadata,
highlight: comment.highlight
Expand Down
6 changes: 3 additions & 3 deletions apps/web/src/app/monitor/evals/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from "@heroicons/react/24/outline";
import { GradeBadge } from "@/components/GradeBadge";
import { EvaluationContent } from "@/components/evaluation";

import type { CommentVariant } from "@roast/ai";
interface Evaluation {
id: string;
createdAt: string;
Expand Down Expand Up @@ -45,7 +45,7 @@ interface Evaluation {
importance: number | null;
grade: number | null;
header: string | null;
level: string | null;
variant: string | null;
source: string | null;
metadata: Record<string, any> | null;
}>;
Expand Down Expand Up @@ -277,7 +277,7 @@ export default function EvaluationsMonitorPage() {
evaluationVersionId: selectedVersion.id,
highlightId: comment.id,
header: comment.header ?? null,
level: comment.level ?? null,
variant: comment.variant as CommentVariant | null,
source: comment.source ?? null,
metadata: comment.metadata ?? null,
highlight: {
Expand Down
18 changes: 9 additions & 9 deletions apps/web/src/app/tools/utils/toolExamples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,31 +362,31 @@ export const toolExamples: Record<string, ToolExample[]> = {
index: 0,
header: 'Cherry-picked timeframe',
description: 'Selecting only the best-performing time period to make an investment look better than it actually is.',
level: 'warning',
variant: 'warning',
importance: 85,
quotedText: 'grown 1000% in the last year'
},
{
index: 1,
header: 'Survivorship bias',
description: 'Only considering successful cases while ignoring all the people who lost money.',
level: 'warning',
variant: 'warning',
importance: 80,
quotedText: 'Everyone who invested got rich'
},
{
index: 2,
header: 'Survivorship bias again',
description: 'Another instance of only showing winners, not losers.',
level: 'warning',
variant: 'warning',
importance: 75,
quotedText: 'My friend made millions'
},
{
index: 3,
header: 'Hasty generalization',
description: 'Drawing broad conclusions from a single example.',
level: 'warning',
variant: 'warning',
importance: 70,
quotedText: 'My friend made millions, so you will too'
}
Expand All @@ -403,23 +403,23 @@ export const toolExamples: Record<string, ToolExample[]> = {
index: 0,
header: 'Vague reference',
description: 'Which studies? What did they find? This needs specific citations.',
level: 'warning',
variant: 'warning',
importance: 90,
quotedText: 'Studies show'
},
{
index: 1,
header: 'Weasel words',
description: 'Some research is very vague - how much? What quality?',
level: 'nitpick',
variant: 'nitpick',
importance: 40,
quotedText: 'Some research'
},
{
index: 2,
header: 'Statement is factual',
description: 'This is actually accurate and verifiable.',
level: 'info',
variant: 'info',
importance: 20,
quotedText: 'contains antioxidants'
}
Expand All @@ -436,15 +436,15 @@ export const toolExamples: Record<string, ToolExample[]> = {
index: 0,
header: 'Impossible claim',
description: 'No medical treatment has 100% efficacy. This is a red flag for misinformation.',
level: 'error',
variant: 'error',
importance: 95,
quotedText: 'works 100% of the time'
},
{
index: 1,
header: 'Appeal to conspiracy',
description: 'Doctors hate it suggests a conspiracy theory framing that undermines credibility.',
level: 'warning',
variant: 'warning',
importance: 85,
quotedText: 'Doctors hate it'
}
Expand Down
7 changes: 4 additions & 3 deletions apps/web/src/application/workflows/evaluation/exportXml.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { logger } from "@/infrastructure/logging/logger";
import type { CommentVariant } from "@roast/ai";

interface ExportEvaluationData {
evaluation: {
Expand All @@ -22,7 +23,7 @@ interface ExportEvaluationData {
importance?: number | null;
grade?: number | null;
header?: string | null;
level?: string | null;
variant?: CommentVariant | null;
source?: string | null;
metadata?: Record<string, any> | null;
}>;
Expand Down Expand Up @@ -122,8 +123,8 @@ export function exportEvaluationToXml(data: ExportEvaluationData): string {
if (comment.header) {
xml += ` <header><![CDATA[${comment.header}]]></header>\n`;
}
if (comment.level) {
xml += ` <level>${comment.level}</level>\n`;
if (comment.variant) {
xml += ` <variant>${comment.variant}</variant>\n`;
}
if (comment.source) {
xml += ` <source>${comment.source}</source>\n`;
Expand Down
6 changes: 4 additions & 2 deletions apps/web/src/application/workflows/evaluation/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { CommentVariant } from "@roast/ai";

/**
* Standardized evaluation display data structure
*/
Expand All @@ -15,7 +17,7 @@ export interface EvaluationDisplayData {
evaluationVersionId: string;
highlightId: string;
header?: string | null;
level?: string | null;
variant?: CommentVariant | null;
source?: string | null;
metadata?: Record<string, any> | null;
highlight: {
Expand Down Expand Up @@ -73,7 +75,7 @@ export interface EvaluationContentProps {
evaluationVersionId: string;
highlightId: string;
header?: string | null;
level?: string | null;
variant?: CommentVariant | null;
source?: string | null;
metadata?: Record<string, any> | null;
highlight: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ export function EvaluationsTab({
evaluationVersionId: selectedEvaluation.evaluationId,
highlightId: comment.id,
header: comment.header ?? null,
level: comment.level ?? null,
variant: comment.variant ?? null,
source: comment.source ?? null,
metadata: comment.metadata ?? null,
highlight: {
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/components/AgentDetail/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Agent } from "@roast/ai";
import type { Agent, CommentVariant } from "@roast/ai";

export interface AgentDetailProps {
agent: Agent;
Expand Down Expand Up @@ -48,7 +48,7 @@ export interface AgentEvaluation {
importance?: number | null;
grade?: number | null;
header?: string | null;
level?: string | null;
variant?: CommentVariant | null;
source?: string | null;
metadata?: any | null;
}>;
Expand Down
147 changes: 147 additions & 0 deletions apps/web/src/components/CommentVariantIndicator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import type { CommentVariant } from "@roast/ai";
import { CheckCircleIcon, CheckIcon, XMarkIcon } from "@heroicons/react/24/solid";

interface CommentVariantIndicatorProps {
variant: CommentVariant | null | undefined;
size?: "sm" | "md" | "lg";
isHovered?: boolean;
className?: string;
}

/**
* Displays a visual indicator (icon with colored background) for a comment variant
*
* Sizes:
* - sm: 5x5 (h-5 w-5) - used in comment lists
* - md: 6x6 (h-6 w-6) - used in modals
* - lg: custom - can be styled with className
*/
export function CommentVariantIndicator({
variant,
size = "md",
isHovered = false,
className,
}: CommentVariantIndicatorProps) {
const variantType = variant || "info"; // Default to info if not set

let bgColor = "bg-blue-500";
let iconContent: React.ReactNode;

// Determine background color based on variant and hover state
switch (variantType) {
case "error":
bgColor = isHovered ? "bg-red-500" : "bg-red-400";
iconContent = <XMarkIcon className="text-white" />;
break;
case "warning":
bgColor = isHovered ? "bg-orange-500" : "bg-orange-400";
iconContent = <span className="text-white font-bold leading-none">!</span>;
break;
case "nitpick":
bgColor = isHovered ? "bg-fuchsia-500" : "bg-fuchsia-300";
iconContent = <span className="text-white font-bold leading-none">·</span>;
break;
case "success":
bgColor = isHovered ? "bg-green-500" : "bg-green-300";
iconContent = <CheckIcon className="text-white" />;
break;
case "debug":
bgColor = isHovered ? "bg-gray-500" : "bg-gray-400";
iconContent = <span className="text-white font-bold leading-none text-xs">d</span>;
break;
case "info":
default:
bgColor = isHovered ? "bg-blue-500" : "bg-blue-400";
iconContent = <span className="text-white font-bold leading-none">i</span>;
break;
}

// Determine size classes
let sizeClasses = "";
let iconSizeClass = "";
let textSizeClass = "";

switch (size) {
case "sm":
sizeClasses = "h-5 w-5";
iconSizeClass = "h-3.5 w-3.5";
textSizeClass = "text-xs";
break;
case "md":
sizeClasses = "h-6 w-6";
iconSizeClass = "h-5 w-5";
textSizeClass = "text-base";
break;
case "lg":
sizeClasses = "h-8 w-8";
iconSizeClass = "h-6 w-6";
textSizeClass = "text-lg";
break;
}

// Clone icon element with size class if it's an icon component
let content = iconContent;
if (typeof iconContent === 'object' && iconContent && 'type' in iconContent) {
const IconComponent = iconContent.type as any;
if (IconComponent === XMarkIcon || IconComponent === CheckIcon || IconComponent === CheckCircleIcon) {
content = <IconComponent className={`${iconSizeClass} text-white`} />;
} else if (iconContent.type === 'span') {
// For text content, add text size
content = <span className={`text-white font-bold leading-none ${textSizeClass}`}>{(iconContent as any).props.children}</span>;
}
}

return (
<div
className={`${sizeClasses} ${bgColor} rounded-sm flex flex-shrink-0 items-center justify-center ${className || ""}`}
aria-label={`${variantType} indicator`}
>
{content}
</div>
);
}

/**
* Variant for EvaluationComments - uses CheckCircleIcon for success
*/
export function CommentVariantIndicatorCompact({
variant,
className,
}: Omit<CommentVariantIndicatorProps, "size" | "isHovered">) {
const variantType = variant || "info";

let bgColor = "bg-blue-400";
let content: React.ReactNode;

switch (variantType) {
case "error":
bgColor = "bg-red-500";
content = <XMarkIcon className="h-3.5 w-3.5 text-white" />;
break;
case "warning":
bgColor = "bg-amber-500";
content = <span className="text-white font-bold text-xs leading-none">!</span>;
break;
case "nitpick":
bgColor = "bg-fuchsia-500";
content = <span className="text-white font-bold text-xs leading-none">·</span>;
break;
case "success":
bgColor = "bg-green-500";
content = <CheckCircleIcon className="h-3.5 w-3.5 text-white" />;
break;
case "info":
case "debug":
default:
bgColor = "bg-blue-500";
content = <span className="text-white font-bold text-xs leading-none">i</span>;
break;
}

return (
<div className={`h-5 w-5 rounded-sm ${bgColor} flex flex-shrink-0 items-center justify-center ${className || ""}`}>
{content}
</div>
);
}

Loading