Skip to content

Commit 08a67c7

Browse files
authored
feat: add model name config in Benchmark Jobs (#118)
## Description Adding model name to be shown in cloning; this means we can 1-1 clone and expect running jobs from clones on runloop. Names still must be unique
1 parent 253dfb3 commit 08a67c7

3 files changed

Lines changed: 67 additions & 12 deletions

File tree

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"build:mcp": "pnpm run build && node scripts/build-mcp.js",
1212
"dev": "tsc --watch",
1313
"start": "node dist/cli.js",
14+
"start:debug": "node dist/cli.js 2> debug.log",
1415
"prepublishOnly": "pnpm run build",
1516
"version:patch": "pnpm version patch",
1617
"version:minor": "pnpm version minor",

src/router/Router.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,10 @@ export function Router() {
328328
<BenchmarkJobDetailScreen key={currentScreen} {...params} />
329329
)}
330330
{currentScreen === "benchmark-job-create" && (
331-
<BenchmarkJobCreateScreen key={currentScreen} {...params} />
331+
<BenchmarkJobCreateScreen
332+
key={`benchmark-job-create-${params.cloneFromJobId ?? "new"}`}
333+
{...params}
334+
/>
332335
)}
333336
{!KNOWN_SCREENS.has(currentScreen) && (
334337
<UnknownScreen key={currentScreen} screenName={currentScreen} />

src/screens/BenchmarkJobCreateScreen.tsx

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ type FormField =
3535
| "benchmark"
3636
| "scenarios"
3737
| "agents"
38+
| "model_names"
3839
| "name"
3940
| "agent_timeout"
4041
| "concurrent_trials"
@@ -48,6 +49,8 @@ interface FormData {
4849
scenarioNames: string[];
4950
agentIds: string[];
5051
agentNames: string[];
52+
/** Comma-separated model names (one per agent, or one value applied to all) */
53+
modelNamesInput: string;
5154
name: string;
5255
agentTimeout: string;
5356
concurrentTrials: string;
@@ -169,17 +172,35 @@ export function BenchmarkJobCreateScreen({
169172
const [currentField, setCurrentField] =
170173
React.useState<FormField>(initialField);
171174

172-
const [formData, setFormData] = React.useState<FormData>({
173-
sourceType: initialSourceType,
174-
benchmarkId: initialBenchmarkIds || "",
175-
benchmarkName: "",
176-
scenarioIds: initialScenarioIds ? initialScenarioIds.split(",") : [],
177-
scenarioNames: [],
178-
agentIds: cloneAgentIds ? cloneAgentIds.split(",") : [],
179-
agentNames: cloneAgentNames ? cloneAgentNames.split(",") : [],
180-
name: cloneJobName ? `${cloneJobName} (clone)` : "",
181-
agentTimeout: cloneAgentTimeout || "",
182-
concurrentTrials: cloneConcurrentTrials || "1",
175+
const [formData, setFormData] = React.useState<FormData>(() => {
176+
let modelNamesInput = "";
177+
try {
178+
if (cloneAgentConfigs) {
179+
const arr = JSON.parse(cloneAgentConfigs) as Array<{
180+
modelName?: string | null;
181+
model_name?: string | null;
182+
}>;
183+
modelNamesInput = arr
184+
.map((a) => a.modelName ?? a.model_name ?? "")
185+
.filter(Boolean)
186+
.join(", ");
187+
}
188+
} catch {
189+
// ignore invalid JSON
190+
}
191+
return {
192+
sourceType: initialSourceType,
193+
benchmarkId: initialBenchmarkIds || "",
194+
benchmarkName: "",
195+
scenarioIds: initialScenarioIds ? initialScenarioIds.split(",") : [],
196+
scenarioNames: [],
197+
agentIds: cloneAgentIds ? cloneAgentIds.split(",") : [],
198+
agentNames: cloneAgentNames ? cloneAgentNames.split(",") : [],
199+
modelNamesInput,
200+
name: cloneJobName ? `${cloneJobName} (clone)` : "",
201+
agentTimeout: cloneAgentTimeout || "",
202+
concurrentTrials: cloneConcurrentTrials || "1",
203+
};
183204
});
184205

185206
const [createdJob, setCreatedJob] = React.useState<BenchmarkJob | null>(null);
@@ -267,6 +288,13 @@ export function BenchmarkJobCreateScreen({
267288
required: true,
268289
description: "Select one or more agents to run",
269290
},
291+
{
292+
key: "model_names",
293+
label: "Model names (comma-separated, optional)",
294+
type: "text",
295+
placeholder: "e.g. claude-3-5-sonnet, gpt-4o",
296+
description: "One per agent, or one value applied to all",
297+
},
270298
{
271299
key: "name",
272300
label: "Job Name",
@@ -483,13 +511,29 @@ export function BenchmarkJobCreateScreen({
483511
// Use the full cloned configs
484512
agentConfigs = JSON.parse(cloneAgentConfigs);
485513
} else {
514+
// Parse comma-separated model names: one per agent, or single value applied to all
515+
const modelNamesParsed = formData.modelNamesInput
516+
? formData.modelNamesInput
517+
.split(",")
518+
.map((s) => s.trim())
519+
.filter(Boolean)
520+
: [];
521+
const applyModelName = (index: number): string | undefined => {
522+
if (modelNamesParsed.length === 0) return undefined;
523+
if (modelNamesParsed.length === 1) return modelNamesParsed[0];
524+
return modelNamesParsed[index] ?? undefined;
525+
};
526+
486527
// Build agent configs from form data (backward compatibility)
487528
agentConfigs = formData.agentIds.map((agentId, index) => {
488529
const config: AgentConfig = {
489530
name: formData.agentNames[index],
490531
agentId: agentId,
491532
};
492533

534+
const modelName = applyModelName(index);
535+
if (modelName) config.modelName = modelName;
536+
493537
if (formData.agentTimeout) {
494538
const timeout = parseInt(formData.agentTimeout, 10);
495539
if (!isNaN(timeout) && timeout > 0) {
@@ -706,6 +750,8 @@ export function BenchmarkJobCreateScreen({
706750
if (formData.agentNames.length === 0) return "";
707751
if (formData.agentNames.length === 1) return formData.agentNames[0];
708752
return `${formData.agentNames.length} agents selected`;
753+
case "model_names":
754+
return formData.modelNamesInput;
709755
case "name":
710756
return formData.name;
711757
case "agent_timeout":
@@ -837,6 +883,11 @@ export function BenchmarkJobCreateScreen({
837883
onChange={(val) => {
838884
if (field.key === "name") {
839885
setFormData((prev) => ({ ...prev, name: val }));
886+
} else if (field.key === "model_names") {
887+
setFormData((prev) => ({
888+
...prev,
889+
modelNamesInput: val,
890+
}));
840891
} else if (field.key === "agent_timeout") {
841892
setFormData((prev) => ({
842893
...prev,

0 commit comments

Comments
 (0)