Skip to content

Commit 716dddf

Browse files
committed
feat(evals): Refactor settings UI and display run configuration
1 parent 0e70240 commit 716dddf

File tree

4 files changed

+1038
-372
lines changed

4 files changed

+1038
-372
lines changed

evals/apps/web/src/app/runs/[id]/run.tsx

Lines changed: 171 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,99 @@
11
"use client"
22

3-
import { useMemo } from "react"
3+
import { useMemo, useState } from "react" // Added useState
44
import { useRouter } from "next/navigation"
5-
import { LoaderCircle, Download, ArrowLeft } from "lucide-react"
5+
import { LoaderCircle, Download, ArrowLeft, ChevronDown, ChevronUp } from "lucide-react" // Added Chevrons
66

77
import * as db from "@evals/db"
8-
8+
import { rooCodeDefaults } from "@evals/types" // Added rooCodeDefaults
9+
import { CONCURRENCY_DEFAULT } from "@/lib/schemas" // Added CONCURRENCY_DEFAULT
910
import { formatCurrency, formatDuration, formatTokens } from "@/lib/formatters"
1011
import { useRunStatus } from "@/hooks/use-run-status"
11-
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Button } from "@/components/ui"
12+
import {
13+
Table,
14+
TableBody,
15+
TableCell,
16+
TableHead,
17+
TableHeader,
18+
TableRow,
19+
Button,
20+
Collapsible, // Added Collapsible components
21+
CollapsibleContent,
22+
CollapsibleTrigger,
23+
// ScrollArea, // Removed ScrollArea
24+
} from "@/components/ui"
25+
// import { SettingsDiff } from "../new/settings-diff" // Removed SettingsDiff
1226

1327
import { TaskStatus } from "./task-status"
1428
import { ConnectionStatus } from "./connection-status"
1529
import { EventSourceStatus } from "@/hooks/use-event-source"
30+
import { RooCodeSettings } from "@evals/types" // Added RooCodeSettings type
1631

1732
type TaskMetrics = Pick<db.TaskMetrics, "tokensIn" | "tokensOut" | "tokensContext" | "duration" | "cost">
1833

1934
interface Task extends db.Task {
2035
taskMetrics?: TaskMetrics | null
2136
}
2237

38+
// Mapping from setting keys to human-readable labels
39+
const settingLabels: Partial<Record<keyof RooCodeSettings, string>> = {
40+
modelTemperature: "Model Temperature",
41+
reasoningEffort: "Reasoning Effort",
42+
includeMaxTokens: "Include Max Tokens",
43+
terminalOutputLineLimit: "Terminal Output Limit",
44+
terminalShellIntegrationTimeout: "Terminal Integration Timeout",
45+
// terminalShellIntegrationDisabled: "Terminal Integration Disabled", // Removed incorrect key
46+
terminalCommandDelay: "Terminal Command Delay",
47+
terminalPowershellCounter: "Terminal PowerShell Counter",
48+
terminalZshClearEolMark: "Terminal Zsh Clear EOL Mark",
49+
terminalZshOhMy: "Terminal Zsh Oh My",
50+
terminalZshP10k: "Terminal Zsh P10k",
51+
terminalZdotdir: "Terminal Zdotdir",
52+
// terminalCompressProgressBar: "Compress Terminal Progress", // Removed incorrect key
53+
allowedCommands: "Allowed Commands",
54+
maxReadFileLine: "Max Read File Line",
55+
maxOpenTabsContext: "Max Open Tabs Context",
56+
maxWorkspaceFiles: "Max Workspace Files",
57+
rateLimitSeconds: "Rate Limit (s)",
58+
requestDelaySeconds: "Request Delay (s)",
59+
writeDelayMs: "Write Delay (ms)",
60+
fuzzyMatchThreshold: "Fuzzy Match Threshold",
61+
autoApprovalEnabled: "Auto-Approval",
62+
alwaysAllowReadOnly: "Always Allow ReadOnly (Workspace)",
63+
alwaysAllowReadOnlyOutsideWorkspace: "Always Allow ReadOnly (Outside)",
64+
alwaysAllowWrite: "Always Allow Write (Workspace)",
65+
alwaysAllowWriteOutsideWorkspace: "Always Allow Write (Outside)",
66+
alwaysAllowBrowser: "Always Allow Browser",
67+
alwaysApproveResubmit: "Always Approve Resubmit",
68+
alwaysAllowMcp: "Always Allow MCP",
69+
alwaysAllowModeSwitch: "Always Allow Mode Switch",
70+
alwaysAllowSubtasks: "Always Allow Subtasks",
71+
alwaysAllowExecute: "Always Allow Execute",
72+
diffEnabled: "Diff View Enabled",
73+
// Add more labels as needed
74+
}
75+
76+
// Function to format setting values for display
77+
const formatSettingValue = (value: any): string => {
78+
if (typeof value === "boolean") {
79+
return value ? "Enabled" : "Disabled"
80+
}
81+
if (Array.isArray(value)) {
82+
// Handle '*' specifically for allowedCommands
83+
if (value.length === 1 && value[0] === "*") {
84+
return "All (*)"
85+
}
86+
return value.join(", ") || "(empty)"
87+
}
88+
if (value === null || value === undefined) {
89+
return "(default)"
90+
}
91+
return String(value)
92+
}
93+
2394
export function Run({ run }: { run: db.Run }) {
2495
const router = useRouter()
96+
const [isSettingsOpen, setIsSettingsOpen] = useState(false) // State for settings collapsible
2597
const { tasks, status, tokenUsage, usageUpdatedAt } = useRunStatus(run) as {
2698
tasks: Task[]
2799
status: EventSourceStatus
@@ -95,38 +167,126 @@ export function Run({ run }: { run: db.Run }) {
95167
document.body.removeChild(link)
96168
}
97169

170+
// Filter and format settings that differ from defaults
171+
const nonDefaultSettings = useMemo(() => {
172+
const settings = (run.settings || {}) as Partial<RooCodeSettings> // Cast to partial for easier comparison
173+
const defaults = rooCodeDefaults as RooCodeSettings
174+
const diff: { label: string; value: string }[] = []
175+
176+
// Iterate over known setting keys with labels
177+
for (const key in settingLabels) {
178+
const typedKey = key as keyof RooCodeSettings
179+
const runValue = settings[typedKey]
180+
const defaultValue = defaults[typedKey]
181+
182+
// Check if the key exists in run settings and differs from default
183+
if (
184+
runValue !== undefined &&
185+
runValue !== null && // Explicitly check for null
186+
JSON.stringify(runValue) !== JSON.stringify(defaultValue) // Compare values robustly
187+
) {
188+
diff.push({
189+
label: settingLabels[typedKey]!,
190+
value: formatSettingValue(runValue),
191+
})
192+
}
193+
}
194+
// Add concurrency separately if it differs from the imported default
195+
if (run.concurrency !== CONCURRENCY_DEFAULT) {
196+
diff.push({
197+
label: "Concurrency",
198+
value: formatSettingValue(run.concurrency),
199+
})
200+
}
201+
202+
// Sort alphabetically by label
203+
diff.sort((a, b) => a.label.localeCompare(b.label))
204+
205+
return diff
206+
}, [run.settings, run.concurrency])
207+
208+
const hasNonDefaultSettings = nonDefaultSettings.length > 0
209+
98210
return (
99211
<>
100212
<div>
101213
<div className="mb-6">
102-
<div className="flex justify-between items-center">
214+
<div className="flex justify-between items-start">
215+
{" "}
216+
{/* Changed items-center to items-start */}
103217
<div>
104218
<h1 className="text-3xl font-bold">Run #{run.id}</h1>
105-
<div className="grid grid-cols-2 gap-x-8 gap-y-2 mt-4">
219+
<div className="grid grid-cols-2 md:grid-cols-4 gap-x-8 gap-y-2 mt-4">
220+
{" "}
221+
{/* Use 4 columns */}
222+
{/* API Provider */}
106223
<div>
107-
<div className="text-sm font-medium text-muted-foreground">Provider</div>
108-
<div>{run.model.split("/")[0] || "Unknown"}</div>
224+
<div className="text-sm font-medium text-muted-foreground">API Provider</div>
225+
<div>{run.settings?.apiProvider || "Unknown"}</div>
109226
</div>
227+
{/* Model */}
110228
<div>
111229
<div className="text-sm font-medium text-muted-foreground">Model</div>
112230
<div>{run.model.includes("/") ? run.model.split("/")[1] : run.model}</div>
113231
</div>
232+
{/* Temperature */}
114233
<div>
115234
<div className="text-sm font-medium text-muted-foreground">Temperature</div>
116235
<div>
117236
{run.settings?.modelTemperature !== undefined &&
118-
run.settings?.modelTemperature !== null
237+
run.settings?.modelTemperature !== null &&
238+
run.settings?.modelTemperature !== rooCodeDefaults.modelTemperature
119239
? run.settings.modelTemperature
120-
: "Default"}
240+
: "(default)"}
121241
</div>
122242
</div>
243+
{/* Concurrency */}
244+
<div>
245+
<div className="text-sm font-medium text-muted-foreground">Concurrency</div>
246+
<div>{run.concurrency !== CONCURRENCY_DEFAULT ? run.concurrency : "(default)"}</div>
247+
</div>
248+
{/* Notes */}
123249
{run.description && (
124-
<div className="col-span-2">
250+
<div className="col-span-full md:col-span-4">
251+
{" "}
252+
{/* Span full width */}
125253
<div className="text-sm font-medium text-muted-foreground">Notes</div>
126254
<div className="max-w-[500px]">{run.description}</div>
127255
</div>
128256
)}
129257
</div>
258+
{/* Settings Collapsible Section */}
259+
{hasNonDefaultSettings && ( // Only show if there are non-default settings
260+
<Collapsible
261+
open={isSettingsOpen}
262+
onOpenChange={setIsSettingsOpen}
263+
className="mt-4 border rounded-md max-w-xl">
264+
{" "}
265+
{/* Added max-width */}
266+
<CollapsibleTrigger asChild>
267+
<Button variant="ghost" className="flex w-full justify-between p-2">
268+
<span className="font-medium">
269+
Other Configuration ({nonDefaultSettings.length} non-default)
270+
</span>
271+
{isSettingsOpen ? (
272+
<ChevronUp className="h-4 w-4" />
273+
) : (
274+
<ChevronDown className="h-4 w-4" />
275+
)}
276+
</Button>
277+
</CollapsibleTrigger>
278+
<CollapsibleContent className="p-4">
279+
<div className="space-y-2">
280+
{nonDefaultSettings.map(({ label, value }) => (
281+
<div key={label} className="flex justify-between text-sm">
282+
<span className="text-muted-foreground">{label}:</span>
283+
<span className="font-mono text-right">{value}</span>
284+
</div>
285+
))}
286+
</div>
287+
</CollapsibleContent>
288+
</Collapsible>
289+
)}
130290
</div>
131291
<div className="flex items-center gap-4">
132292
<Button variant="outline" size="sm" onClick={() => router.push("/")} title="Back to runs">

0 commit comments

Comments
 (0)