mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-10-09 03:17:58 +00:00
fix(web-evals): refine recommendation objective and profile snapshot layout
This commit is contained in:
parent
a91054f8a6
commit
6c5b7addc4
2 changed files with 94 additions and 77 deletions
|
|
@ -62,7 +62,7 @@ function pickCandidate(rec: RoleRecommendation | undefined, mode: EvalOptimizati
|
|||
return rec.best[0] ?? null
|
||||
}
|
||||
|
||||
function shortProvider(provider: string) {
|
||||
function shortProvider(provider: string): string {
|
||||
switch (provider) {
|
||||
case "openai":
|
||||
return "OpenAI"
|
||||
|
|
@ -81,12 +81,12 @@ function shortProvider(provider: string) {
|
|||
}
|
||||
}
|
||||
|
||||
function formatDollars(value: number) {
|
||||
function formatDollars(value: number): string {
|
||||
if (!Number.isFinite(value)) return "—"
|
||||
return `$${Math.round(value)}`
|
||||
}
|
||||
|
||||
function formatSeconds(value: number) {
|
||||
function formatSeconds(value: number): string {
|
||||
if (!Number.isFinite(value)) return "—"
|
||||
return `${value.toFixed(1)}s`
|
||||
}
|
||||
|
|
@ -95,7 +95,7 @@ function buildObjectiveQueryString(
|
|||
searchParams: { get(name: string): string | null },
|
||||
objectiveSlug: string,
|
||||
mode: EvalOptimizationMode,
|
||||
) {
|
||||
): string {
|
||||
const params = new URLSearchParams()
|
||||
params.set("objective", objectiveSlug)
|
||||
params.set("mode", mode)
|
||||
|
|
@ -107,9 +107,85 @@ function buildObjectiveQueryString(
|
|||
return `?${params.toString()}`
|
||||
}
|
||||
|
||||
type PrimaryScatterPoint = {
|
||||
name: string
|
||||
provider: string
|
||||
score: number
|
||||
successRate: number
|
||||
dailyCost: number
|
||||
dotSize: number
|
||||
isSelected: boolean
|
||||
}
|
||||
|
||||
type ObjectiveDataPreviewProps = {
|
||||
points: PrimaryScatterPoint[]
|
||||
compareHref: string
|
||||
}
|
||||
|
||||
function ObjectiveDataPreview({ points, compareHref }: ObjectiveDataPreviewProps): JSX.Element {
|
||||
return (
|
||||
<div className="mt-6 rounded-2xl border border-border/50 bg-background/15 p-6 backdrop-blur-sm">
|
||||
<p className="text-xs font-semibold uppercase tracking-[0.24em] text-muted-foreground/70">Data preview</p>
|
||||
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">
|
||||
Composite score vs estimated daily cost for the primary agent, with dot size mapped to success rate.
|
||||
</p>
|
||||
|
||||
<div className="mt-4 h-[320px] w-full overflow-hidden rounded-2xl border border-border/50 bg-background/10 p-3">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<ScatterChart margin={{ top: 10, right: 10, bottom: 10, left: 0 }}>
|
||||
<XAxis
|
||||
type="number"
|
||||
dataKey="dailyCost"
|
||||
name="Daily Cost"
|
||||
tick={{ fill: "currentColor", fontSize: 12 }}
|
||||
axisLine={{ stroke: "rgba(255,255,255,0.08)" }}
|
||||
tickLine={{ stroke: "rgba(255,255,255,0.08)" }}
|
||||
/>
|
||||
<YAxis
|
||||
type="number"
|
||||
dataKey="score"
|
||||
name="Score"
|
||||
domain={[40, 100]}
|
||||
tick={{ fill: "currentColor", fontSize: 12 }}
|
||||
axisLine={{ stroke: "rgba(255,255,255,0.08)" }}
|
||||
tickLine={{ stroke: "rgba(255,255,255,0.08)" }}
|
||||
/>
|
||||
<ZAxis type="number" dataKey="dotSize" range={[60, 360]} />
|
||||
<Tooltip content={<ObjectiveTooltip />} />
|
||||
<Scatter data={points} fill="#3b82f6">
|
||||
{points.map((point, i) => {
|
||||
const pointColor = point.isSelected ? "#22c55e" : "#3b82f6"
|
||||
const strokeColor = point.isSelected ? "rgba(34,197,94,0.65)" : "rgba(59,130,246,0.35)"
|
||||
const strokeWidth = point.isSelected ? 2 : 1
|
||||
|
||||
return <Cell key={i} fill={pointColor} stroke={strokeColor} strokeWidth={strokeWidth} />
|
||||
})}
|
||||
</Scatter>
|
||||
</ScatterChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
|
||||
<div className="mt-4">
|
||||
<Link
|
||||
href={compareHref}
|
||||
className="inline-flex items-center gap-2 rounded-full border border-border/60 bg-background/10 px-5 py-2.5 text-sm font-semibold text-muted-foreground transition-colors hover:bg-background/20 hover:text-foreground">
|
||||
Compare the full set
|
||||
<ArrowRight className="size-4" />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
type ObjectiveTooltipPayloadEntry = { payload?: unknown }
|
||||
|
||||
function ObjectiveTooltip({ active, payload }: { active?: boolean; payload?: ObjectiveTooltipPayloadEntry[] }) {
|
||||
function ObjectiveTooltip({
|
||||
active,
|
||||
payload,
|
||||
}: {
|
||||
active?: boolean
|
||||
payload?: ObjectiveTooltipPayloadEntry[]
|
||||
}): JSX.Element | null {
|
||||
if (!active || !payload?.length) return null
|
||||
const entryPayload = payload[0]?.payload
|
||||
const p = entryPayload as
|
||||
|
|
@ -204,7 +280,7 @@ export function ObjectiveContent({ objective, initialMode, recs }: Props) {
|
|||
[mode, objective.slug, searchParams],
|
||||
)
|
||||
|
||||
const primaryScatter = useMemo(() => {
|
||||
const primaryScatter = useMemo<PrimaryScatterPoint[]>(() => {
|
||||
if (!primaryRoleId) return []
|
||||
const rec = recByRole.get(primaryRoleId)
|
||||
if (!rec) return []
|
||||
|
|
@ -219,6 +295,10 @@ export function ObjectiveContent({ objective, initialMode, recs }: Props) {
|
|||
}))
|
||||
}, [primaryCandidate?.modelId, primaryRoleId, recByRole])
|
||||
|
||||
const comparePrimaryHref = primaryRoleId
|
||||
? `/evals/recommendations/roles/${primaryRoleId}/compare${roleQuery}`
|
||||
: "/evals/recommendations"
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
{/* Atmosphere */}
|
||||
|
|
@ -529,6 +609,8 @@ export function ObjectiveContent({ objective, initialMode, recs }: Props) {
|
|||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
<ObjectiveDataPreview points={primaryScatter} compareHref={comparePrimaryHref} />
|
||||
</div>
|
||||
|
||||
<div className="lg:col-span-5">
|
||||
|
|
@ -571,69 +653,6 @@ export function ObjectiveContent({ objective, initialMode, recs }: Props) {
|
|||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="mt-6 rounded-2xl border border-border/50 bg-background/15 p-6 backdrop-blur-sm">
|
||||
<p className="text-xs font-semibold uppercase tracking-[0.24em] text-muted-foreground/70">
|
||||
Data preview
|
||||
</p>
|
||||
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">
|
||||
Composite score vs estimated daily cost for the primary agent, with dot size mapped
|
||||
to success rate.
|
||||
</p>
|
||||
|
||||
<div className="mt-4 h-[320px] w-full overflow-hidden rounded-2xl border border-border/50 bg-background/10 p-3">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<ScatterChart margin={{ top: 10, right: 10, bottom: 10, left: 0 }}>
|
||||
<XAxis
|
||||
type="number"
|
||||
dataKey="dailyCost"
|
||||
name="Daily Cost"
|
||||
tick={{ fill: "currentColor", fontSize: 12 }}
|
||||
axisLine={{ stroke: "rgba(255,255,255,0.08)" }}
|
||||
tickLine={{ stroke: "rgba(255,255,255,0.08)" }}
|
||||
/>
|
||||
<YAxis
|
||||
type="number"
|
||||
dataKey="score"
|
||||
name="Score"
|
||||
domain={[40, 100]}
|
||||
tick={{ fill: "currentColor", fontSize: 12 }}
|
||||
axisLine={{ stroke: "rgba(255,255,255,0.08)" }}
|
||||
tickLine={{ stroke: "rgba(255,255,255,0.08)" }}
|
||||
/>
|
||||
<ZAxis type="number" dataKey="dotSize" range={[60, 360]} />
|
||||
<Tooltip content={<ObjectiveTooltip />} />
|
||||
<Scatter data={primaryScatter} fill="#3b82f6">
|
||||
{primaryScatter.map((d, i) => (
|
||||
<Cell
|
||||
key={i}
|
||||
fill={d.isSelected ? "#22c55e" : "#3b82f6"}
|
||||
stroke={
|
||||
d.isSelected
|
||||
? "rgba(34,197,94,0.65)"
|
||||
: "rgba(59,130,246,0.35)"
|
||||
}
|
||||
strokeWidth={d.isSelected ? 2 : 1}
|
||||
/>
|
||||
))}
|
||||
</Scatter>
|
||||
</ScatterChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
|
||||
<div className="mt-4">
|
||||
<Link
|
||||
href={
|
||||
primaryRoleId
|
||||
? `/evals/recommendations/roles/${primaryRoleId}/compare${roleQuery}`
|
||||
: "/evals/recommendations"
|
||||
}
|
||||
className="inline-flex items-center gap-2 rounded-full border border-border/60 bg-background/10 px-5 py-2.5 text-sm font-semibold text-muted-foreground transition-colors hover:bg-background/20 hover:text-foreground">
|
||||
Compare the full set
|
||||
<ArrowRight className="size-4" />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -294,6 +294,7 @@ export function WorkersContent({
|
|||
if (!objectiveDefaultModel?.modelId) return "—"
|
||||
return formatModelIdForUi(objectiveDefaultModel.modelId)
|
||||
}, [objectiveDefaultModel])
|
||||
const selectedModeLabel = getModeLabel(selectedMode)
|
||||
const examplePrompt = selectedOutcome?.builderProfile?.examplePrompt ?? ""
|
||||
const cloudSetupHref = useMemo(() => {
|
||||
if (!effectiveOutcomeId) return "/cloud-agents/setup"
|
||||
|
|
@ -515,7 +516,7 @@ export function WorkersContent({
|
|||
Optimized for
|
||||
</p>
|
||||
<p className="mt-1 text-sm font-semibold text-foreground">
|
||||
{getModeLabel(selectedMode)}
|
||||
{selectedModeLabel}
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-3">
|
||||
|
|
@ -780,9 +781,6 @@ export function WorkersContent({
|
|||
{outcome.description}
|
||||
</p>
|
||||
</div>
|
||||
<span className="shrink-0 inline-flex items-center rounded-full border border-border/50 bg-background/20 px-2.5 py-1 text-[10px] font-semibold text-foreground/70">
|
||||
Optimized for: {getModeLabel(selectedMode)}
|
||||
</span>
|
||||
</div>
|
||||
</motion.button>
|
||||
)
|
||||
|
|
@ -811,8 +809,8 @@ export function WorkersContent({
|
|||
|
||||
<div className="relative">
|
||||
<div className="border-b border-border/40 px-6 pb-5 pt-6">
|
||||
<div className="flex flex-wrap items-start justify-between gap-4">
|
||||
<div className="min-w-0">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="min-w-0 flex-1">
|
||||
<p className="text-xs font-semibold uppercase tracking-[0.24em] text-muted-foreground/70">
|
||||
Profile snapshot
|
||||
</p>
|
||||
|
|
@ -830,7 +828,7 @@ export function WorkersContent({
|
|||
|
||||
<div className="shrink-0">
|
||||
<span className="inline-flex items-center rounded-full border border-border/50 bg-background/20 px-3 py-1 text-xs font-semibold text-foreground/80">
|
||||
Optimized for: {getModeLabel(selectedMode)}
|
||||
Optimized for: {selectedModeLabel}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -963,7 +961,7 @@ export function WorkersContent({
|
|||
<Link
|
||||
href={`/evals/recommendations/${selectedOutcome.slug}?mode=${selectedMode}`}
|
||||
className="inline-flex flex-1 items-center justify-center gap-2 rounded-2xl border border-border/60 bg-background/10 px-4 py-3 text-sm font-semibold text-muted-foreground transition-colors hover:border-border hover:bg-background/15 hover:text-foreground">
|
||||
Learn more / customize
|
||||
Learn more about this profile
|
||||
<ArrowRight className="size-4" />
|
||||
</Link>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue