File size: 5,688 Bytes
80d8c84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import { FileText, FlaskConical, Target, Microscope, Copy, Check, ArrowRight } from 'lucide-react';
import { useState } from 'react';
import type { PaperSummary } from '@/types';
import { cn } from '@/lib/utils';

interface PaperPanelProps {
  paper: PaperSummary;
  seed: number;
  template: string;
  difficulty: string;
  round: number;
  maxRounds: number;
  episodeId?: string;
  className?: string;
}

export default function PaperPanel({
  paper,
  seed,
  template,
  difficulty,
  round,
  maxRounds,
  episodeId,
  className,
}: PaperPanelProps) {
  const [copied, setCopied] = useState(false);
  const templateLabel = template.replace(/_/g, ' ');

  function copyEpisodeId() {
    if (!episodeId) return;
    navigator.clipboard.writeText(episodeId);
    setCopied(true);
    setTimeout(() => setCopied(false), 1500);
  }
  return (
    <div className={cn('flex flex-col gap-4 overflow-y-auto', className)}>
      <div className="rounded-lg border border-border bg-card p-4">
        <div className="mb-3 flex items-center justify-between gap-2">
          <div className="flex items-center gap-2">
            <FileText className="h-4 w-4 text-primary" />
            <h2 className="text-sm font-semibold">Source Paper</h2>
          </div>
          <span className="rounded-full bg-primary/10 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-[0.18em] text-primary">
            PDF to task
          </span>
        </div>
        <div className="rounded-lg border border-border/60 bg-muted/30 p-3">
          <div className="mb-2 flex items-center gap-2 text-[11px] uppercase tracking-[0.18em] text-muted-foreground">
            <span className="rounded bg-destructive/10 px-1.5 py-0.5 font-semibold text-destructive">PDF</span>
            <span>Seeded replication brief</span>
          </div>
          <h3 className="mb-2 text-base font-medium leading-snug">{paper.title}</h3>
          <p className="text-sm text-muted-foreground">
            ReplicaLab freezes this paper into a reproducible benchmark so the agents must preserve the
            claim while adapting to budget, compute, reagent, and scheduling constraints.
          </p>
        </div>
      </div>
      <div className="rounded-lg border border-border bg-card p-4">
        <div className="mb-3 flex items-center gap-2">
          <ArrowRight className="h-4 w-4 text-primary" />
          <h3 className="text-sm font-semibold">Parsed Replication Brief</h3>
        </div>
        <div className="space-y-3 text-sm text-muted-foreground">
          <div className="flex items-start gap-2">
            <Target className="mt-0.5 h-3.5 w-3.5 shrink-0 text-primary" />
            <div><span className="font-medium text-foreground">Objective: </span>{paper.hypothesis}</div>
          </div>
          <div className="flex items-start gap-2">
            <Microscope className="mt-0.5 h-3.5 w-3.5 shrink-0 text-primary" />
            <div><span className="font-medium text-foreground">Original Method: </span>{paper.method}</div>
          </div>
          <div className="flex items-start gap-2">
            <FlaskConical className="mt-0.5 h-3.5 w-3.5 shrink-0 text-primary" />
            <div><span className="font-medium text-foreground">Result To Preserve: </span>{paper.key_finding}</div>
          </div>
        </div>
      </div>
      <div className="rounded-lg border border-border bg-card p-4">
        <h3 className="mb-3 text-sm font-semibold">Original Experiment</h3>
        <div className="grid grid-cols-2 gap-2 text-xs">
          <Stat label="Sample Size" value={paper.original_sample_size.toString()} />
          <Stat label="Technique" value={paper.original_technique} />
          <Stat label="Duration" value={`${paper.original_duration_days}d`} />
          <Stat label="Controls" value={paper.original_controls.length.toString()} />
        </div>
        <div className="mt-2 flex flex-wrap gap-1">
          {paper.original_controls.map((c) => (
            <span key={c} className="rounded-full bg-muted px-2 py-0.5 text-xs text-muted-foreground">{c.replace(/_/g, ' ')}</span>
          ))}
        </div>
      </div>
      <div className="rounded-lg border border-border bg-card p-4">
        <h3 className="mb-3 text-sm font-semibold">Benchmark Context</h3>
        {episodeId && (
          <button
            onClick={copyEpisodeId}
            className="mb-2 flex w-full items-center gap-1.5 rounded-md bg-muted/50 px-2 py-1.5 text-xs text-muted-foreground transition-colors hover:bg-muted"
          >
            {copied ? <Check className="h-3 w-3 text-lab-manager" /> : <Copy className="h-3 w-3" />}
            <span className="font-mono truncate">{episodeId}</span>
          </button>
        )}
        <div className="grid grid-cols-2 gap-2 text-xs">
          <Stat label="Seed" value={seed.toString()} />
          <Stat label="Family" value={templateLabel} />
          <Stat label="Difficulty" value={difficulty} />
          <Stat label="Round" value={`${round} / ${maxRounds}`} highlight={round >= maxRounds} />
        </div>
        <p className="mt-3 text-xs text-muted-foreground">
          Training and evaluation reuse this exact seed and scenario family so baseline and trained policies can
          be compared on the same task.
        </p>
      </div>
    </div>
  );
}

function Stat({ label, value, highlight }: { label: string; value: string; highlight?: boolean }) {
  return (
    <div className="rounded-md bg-muted/50 px-2 py-1.5">
      <div className="text-muted-foreground">{label}</div>
      <div className={cn('font-medium', highlight ? 'text-destructive' : 'text-foreground')}>{value}</div>
    </div>
  );
}