feat(multirun): allow selecting the same model multiple times for comparison
Add file attachment support to multi-run launcher Show instance indices for duplicate model selections
This commit is contained in:
@@ -74,7 +74,7 @@ export const useMultiRunStore = create<MultiRunStore>()(
|
||||
createMultiRun: async (params: CreateMultiRunParams) => {
|
||||
const groupName = params.name.trim();
|
||||
const prompt = params.prompt.trim();
|
||||
const { models, agent } = params;
|
||||
const { models, agent, files } = params;
|
||||
|
||||
if (!groupName) {
|
||||
set({ error: 'Group name is required' });
|
||||
@@ -87,20 +87,10 @@ export const useMultiRunStore = create<MultiRunStore>()(
|
||||
}
|
||||
|
||||
if (models.length < 2) {
|
||||
set({ error: 'Select at least 2 unique models' });
|
||||
set({ error: 'Select at least 2 models' });
|
||||
return null;
|
||||
}
|
||||
|
||||
const modelKeys = new Set<string>();
|
||||
for (const model of models) {
|
||||
const key = `${model.providerID}:${model.modelID}`;
|
||||
if (modelKeys.has(key)) {
|
||||
set({ error: `Duplicate model: ${model.providerID}/${model.modelID}` });
|
||||
return null;
|
||||
}
|
||||
modelKeys.add(key);
|
||||
}
|
||||
|
||||
set({ isLoading: true, error: null });
|
||||
|
||||
try {
|
||||
@@ -130,24 +120,34 @@ export const useMultiRunStore = create<MultiRunStore>()(
|
||||
modelID: string;
|
||||
}> = [];
|
||||
|
||||
const usedBranches = new Set<string>();
|
||||
// Count occurrences of each model to handle duplicates
|
||||
const modelCounts = new Map<string, number>();
|
||||
for (const model of models) {
|
||||
const key = `${model.providerID}:${model.modelID}`;
|
||||
modelCounts.set(key, (modelCounts.get(key) || 0) + 1);
|
||||
}
|
||||
|
||||
// Track current index per model during iteration
|
||||
const modelIndexes = new Map<string, number>();
|
||||
|
||||
// 1) Create worktrees + sessions
|
||||
for (const model of models) {
|
||||
const key = `${model.providerID}:${model.modelID}`;
|
||||
const count = modelCounts.get(key) || 1;
|
||||
const index = (modelIndexes.get(key) || 0) + 1;
|
||||
modelIndexes.set(key, index);
|
||||
|
||||
const modelSlug = toModelSlug(model.providerID, model.modelID);
|
||||
const branch = generateBranchName(groupSlug, modelSlug);
|
||||
// Append index only when same model is selected multiple times
|
||||
const branch = count > 1
|
||||
? generateBranchName(groupSlug, `${modelSlug}-${index}`)
|
||||
: generateBranchName(groupSlug, modelSlug);
|
||||
|
||||
if (!branch) {
|
||||
set({ error: 'Branch name is required for worktree creation', isLoading: false });
|
||||
return null;
|
||||
}
|
||||
|
||||
if (usedBranches.has(branch)) {
|
||||
set({ error: `Duplicate branch selected: ${branch}`, isLoading: false });
|
||||
return null;
|
||||
}
|
||||
usedBranches.add(branch);
|
||||
|
||||
const worktreeSlug = sanitizeWorktreeSlug(branch);
|
||||
if (!worktreeSlug) {
|
||||
set({ error: `Invalid branch name: ${branch}`, isLoading: false });
|
||||
@@ -192,6 +192,14 @@ export const useMultiRunStore = create<MultiRunStore>()(
|
||||
|
||||
// 2) Start all runs with the same prompt.
|
||||
// IMPORTANT: do not await model/agent execution here; only worktree + session creation.
|
||||
// Convert files to the format expected by sendMessage
|
||||
const filesForMessage = files?.map((f) => ({
|
||||
type: 'file' as const,
|
||||
mime: f.mime,
|
||||
filename: f.filename,
|
||||
url: f.url,
|
||||
}));
|
||||
|
||||
void (async () => {
|
||||
try {
|
||||
await Promise.allSettled(
|
||||
@@ -204,6 +212,7 @@ export const useMultiRunStore = create<MultiRunStore>()(
|
||||
modelID: run.modelID,
|
||||
text: prompt,
|
||||
agent,
|
||||
files: filesForMessage,
|
||||
})
|
||||
);
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user