Remove the 5-model limit on multi-run groups
The per-group cap of 5 models was enforced in three client-side locations with no server-side constraint and no technical justification; the store iterates models in a plain loop and dispatches each run via Promise.allSettled. Remove the cap entirely from MultiRunLauncher, useMultiRunStore, and AgentManagerEmptyState, and drop the {max} ceiling from the launcher info copy across all locales.
Closes #2847
This commit is contained in:
@@ -32,7 +32,6 @@ import { startDesktopWindowDrag } from '@/lib/desktopNative';
|
||||
import { useI18n } from '@/lib/i18n';
|
||||
|
||||
const MAX_FILE_SIZE = 10 * 1024 * 1024;
|
||||
const MAX_MODELS_PER_GROUP = 5;
|
||||
|
||||
interface MultiRunAttachedFile {
|
||||
id: string;
|
||||
@@ -727,7 +726,6 @@ const RunGroupCard: React.FC<RunGroupCardProps> = ({
|
||||
const snippetRef = React.useRef<SnippetAutocompleteHandle>(null);
|
||||
|
||||
const handleAddModel = React.useCallback((model: ModelSelectionWithId) => {
|
||||
if (group.models.length >= MAX_MODELS_PER_GROUP) return;
|
||||
onUpdate(group.id, { models: [...group.models, model] });
|
||||
}, [group.id, group.models, onUpdate]);
|
||||
|
||||
@@ -987,7 +985,7 @@ const RunGroupCard: React.FC<RunGroupCardProps> = ({
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<FieldLabel
|
||||
required
|
||||
info={<InfoTip>{t('multirun.launcher.models.info', { max: MAX_MODELS_PER_GROUP })}</InfoTip>}
|
||||
info={<InfoTip>{t('multirun.launcher.models.info')}</InfoTip>}
|
||||
>
|
||||
{t('multirun.launcher.models.label')}
|
||||
</FieldLabel>
|
||||
@@ -997,7 +995,6 @@ const RunGroupCard: React.FC<RunGroupCardProps> = ({
|
||||
onRemove={handleRemoveModel}
|
||||
onUpdate={handleUpdateModel}
|
||||
minModels={1}
|
||||
maxModels={MAX_MODELS_PER_GROUP}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -22,8 +22,6 @@ import { useI18n } from '@/lib/i18n';
|
||||
|
||||
/** Max file size in bytes (10MB) */
|
||||
const MAX_FILE_SIZE = 10 * 1024 * 1024;
|
||||
/** Max number of concurrent runs */
|
||||
const MAX_MODELS = 5;
|
||||
|
||||
/** Attached file for agent manager */
|
||||
interface AttachedFile {
|
||||
@@ -132,11 +130,8 @@ export const AgentManagerEmptyState: React.FC<AgentManagerEmptyStateProps> = ({
|
||||
}, [projectRef]);
|
||||
|
||||
const handleAddModel = React.useCallback((model: ModelSelectionWithId) => {
|
||||
if (selectedModels.length >= MAX_MODELS) {
|
||||
return;
|
||||
}
|
||||
setSelectedModels((prev) => [...prev, model]);
|
||||
}, [selectedModels.length]);
|
||||
}, []);
|
||||
|
||||
const handleRemoveModel = React.useCallback((index: number) => {
|
||||
setSelectedModels((prev) => prev.filter((_, i) => i !== index));
|
||||
@@ -529,7 +524,6 @@ export const AgentManagerEmptyState: React.FC<AgentManagerEmptyStateProps> = ({
|
||||
onUpdate={handleUpdateModel}
|
||||
minModels={1}
|
||||
addButtonLabel={t('agentManager.empty.models.addModel')}
|
||||
maxModels={5}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -369,7 +369,7 @@ export const dict = {
|
||||
'multirun.launcher.attachments.attach': 'Attach',
|
||||
'multirun.launcher.attachments.tooltip': 'Same files sent to all runs',
|
||||
'multirun.launcher.models.label': 'Models',
|
||||
'multirun.launcher.models.info': 'Select 2-{max} models. Same model can be added multiple times.',
|
||||
'multirun.launcher.models.info': 'Select 2 or more models. Same model can be added multiple times.',
|
||||
'multirun.launcher.toast.fileTooLarge': 'File "{fileName}" is too large (max 10MB)',
|
||||
'multirun.launcher.toast.attachFailed': 'Failed to attach "{fileName}"',
|
||||
'multirun.launcher.toast.attachedSingle': 'Attached {count} file',
|
||||
|
||||
@@ -370,7 +370,7 @@ export const dict: Record<I18nKey, string> = {
|
||||
"multirun.launcher.attachments.attach": "Adjuntar",
|
||||
"multirun.launcher.attachments.tooltip": "Archivos idénticos enviados a todas las ejecuciones",
|
||||
"multirun.launcher.models.label": "Modelos",
|
||||
"multirun.launcher.models.info": "Selecciona 2-{max} modelos. El mismo modelo puede añadirse varias veces.",
|
||||
"multirun.launcher.models.info": "Selecciona 2 o más modelos. El mismo modelo puede añadirse varias veces.",
|
||||
"multirun.launcher.toast.fileTooLarge": "El archivo \"{fileName}\" es demasiado grande (máximo 10MB)",
|
||||
"multirun.launcher.toast.attachFailed": "No se pudo adjuntar \"{fileName}\"",
|
||||
"multirun.launcher.toast.attachedSingle": "Archivo adjuntado ({count})",
|
||||
|
||||
@@ -201,7 +201,7 @@ export const dict = {
|
||||
'multirun.launcher.attachments.attach': 'Attacher',
|
||||
'multirun.launcher.attachments.tooltip': 'Mêmes fichiers envoyés à toutes les exécutions',
|
||||
'multirun.launcher.models.label': 'Modèles',
|
||||
'multirun.launcher.models.info': 'Sélectionnez les modèles 2-{max}. Le même modèle peut être ajouté plusieurs fois.',
|
||||
'multirun.launcher.models.info': 'Sélectionnez 2 modèles ou plus. Le même modèle peut être ajouté plusieurs fois.',
|
||||
'multirun.launcher.toast.fileTooLarge': 'Le fichier "{fileName}" est trop volumineux (max 10 Mo)',
|
||||
'multirun.launcher.toast.attachFailed': 'Échec de la connexion de "{fileName}"',
|
||||
'multirun.launcher.toast.attachedSingle': 'Fichier {count} joint',
|
||||
|
||||
@@ -370,7 +370,7 @@ export const dict: Record<I18nKey, string> = {
|
||||
'multirun.launcher.attachments.attach': '첨부',
|
||||
'multirun.launcher.attachments.tooltip': '같은 파일을 모든 실행에 보냅니다',
|
||||
'multirun.launcher.models.label': '모델',
|
||||
'multirun.launcher.models.info': '모델을 2~{max}개 선택하세요. 같은 모델을 여러 번 추가할 수 있습니다.',
|
||||
'multirun.launcher.models.info': '모델을 2개 이상 선택하세요. 같은 모델을 여러 번 추가할 수 있습니다.',
|
||||
'multirun.launcher.toast.fileTooLarge': '파일 "{fileName}"이 너무 큽니다(최대 10MB)',
|
||||
'multirun.launcher.toast.attachFailed': '"{fileName}" 첨부 실패',
|
||||
'multirun.launcher.toast.attachedSingle': '파일 {count}개 첨부됨',
|
||||
|
||||
@@ -497,7 +497,7 @@ export const dict: Record<I18nKey, string> = {
|
||||
'multirun.launcher.attachments.attach': 'Dołącz',
|
||||
'multirun.launcher.attachments.tooltip': 'Te same pliki wysłane do wszystkich uruchomień',
|
||||
'multirun.launcher.models.label': 'Modele',
|
||||
'multirun.launcher.models.info': 'Wybierz od 2 do {max} modeli. Ten sam model może być dodany wielokrotnie.',
|
||||
'multirun.launcher.models.info': 'Wybierz 2 lub więcej modeli. Ten sam model może być dodany wielokrotnie.',
|
||||
'multirun.launcher.toast.fileTooLarge': 'Plik "{fileName}" jest zbyt duży (max 10MB)',
|
||||
'multirun.launcher.toast.attachFailed': 'Nie udało się dołączyć "{fileName}"',
|
||||
'multirun.launcher.toast.attachedSingle': 'Dołączono {count} plik',
|
||||
|
||||
@@ -370,7 +370,7 @@ export const dict: Record<I18nKey, string> = {
|
||||
"multirun.launcher.attachments.attach": "Anexar",
|
||||
"multirun.launcher.attachments.tooltip": "Arquivos idênticos enviados a todas as execuções",
|
||||
"multirun.launcher.models.label": "Modelos",
|
||||
"multirun.launcher.models.info": "Selecione 2-{max} modelos. O mesmo modelo pode ser adicionado várias vezes.",
|
||||
"multirun.launcher.models.info": "Selecione 2 ou mais modelos. O mesmo modelo pode ser adicionado várias vezes.",
|
||||
"multirun.launcher.toast.fileTooLarge": "O arquivo \"{fileName}\" é grande demais (máximo 10MB)",
|
||||
"multirun.launcher.toast.attachFailed": "Não foi possível anexar \"{fileName}\"",
|
||||
"multirun.launcher.toast.attachedSingle": "Arquivo anexado ({count})",
|
||||
|
||||
@@ -370,7 +370,7 @@ export const dict: Record<I18nKey, string> = {
|
||||
"multirun.launcher.attachments.attach": "Прикріпити",
|
||||
"multirun.launcher.attachments.tooltip": "Ті самі файли буде надіслано в усі запуски",
|
||||
"multirun.launcher.models.label": "Моделі",
|
||||
"multirun.launcher.models.info": "Вибрати моделі 2-{max}. Ту саму модель можна додавати кілька разів.",
|
||||
"multirun.launcher.models.info": "Вибрати 2 або більше моделей. Ту саму модель можна додавати кілька разів.",
|
||||
"multirun.launcher.toast.fileTooLarge": "Файл \"{fileName}\" завеликий (макс. 10 МБ)",
|
||||
"multirun.launcher.toast.attachFailed": "Не вдалося вкласти \"{fileName}\"",
|
||||
"multirun.launcher.toast.attachedSingle": "Прикріплено файл: {count}",
|
||||
|
||||
@@ -370,7 +370,7 @@ export const dict: Record<I18nKey, string> = {
|
||||
'multirun.launcher.attachments.attach': '附加',
|
||||
'multirun.launcher.attachments.tooltip': '相同文件会发送到所有运行',
|
||||
'multirun.launcher.models.label': '模型',
|
||||
'multirun.launcher.models.info': '选择 2-{max} 个模型。同一模型可重复添加。',
|
||||
'multirun.launcher.models.info': '选择 2 个或更多模型。同一模型可重复添加。',
|
||||
'multirun.launcher.toast.fileTooLarge': '文件“{fileName}”过大(最大 10MB)',
|
||||
'multirun.launcher.toast.attachFailed': '附加“{fileName}”失败',
|
||||
'multirun.launcher.toast.attachedSingle': '已附加 {count} 个文件',
|
||||
|
||||
@@ -383,7 +383,7 @@ export const dict: Record<I18nKey, string> = {
|
||||
'multirun.launcher.attachments.attach': '附加',
|
||||
'multirun.launcher.attachments.tooltip': '相同檔案會傳送到所有執行',
|
||||
'multirun.launcher.models.label': '模型',
|
||||
'multirun.launcher.models.info': '選擇 2-{max} 個模型。同一模型可重複加入。',
|
||||
'multirun.launcher.models.info': '選擇 2 個或更多模型。同一模型可重複加入。',
|
||||
'multirun.launcher.toast.fileTooLarge': '檔案「{fileName}」過大(最大 10MB)',
|
||||
'multirun.launcher.toast.attachFailed': '附加「{fileName}」失敗',
|
||||
'multirun.launcher.toast.attachedSingle': '已附加 {count} 個檔案',
|
||||
|
||||
@@ -226,4 +226,20 @@ describe('useMultiRunStore', () => {
|
||||
'createSession:/repo-worktrees/fix-thing',
|
||||
]);
|
||||
});
|
||||
|
||||
test('accepts more than 5 models per group without a "maximum 5 models" error', async () => {
|
||||
const models = Array.from({ length: 6 }, (_, i) => ({
|
||||
providerID: 'anthropic',
|
||||
modelID: `claude-sonnet-4-5-${i}`,
|
||||
}));
|
||||
|
||||
const result = await useMultiRunStore.getState().createMultiRun({
|
||||
name: 'Many models',
|
||||
isolateRuns: false,
|
||||
groups: [{ prompt: 'Fix it', models }],
|
||||
});
|
||||
|
||||
expect(useMultiRunStore.getState().error).toBeNull();
|
||||
expect(result?.sessionIds).toHaveLength(6);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -138,10 +138,6 @@ export const useMultiRunStore = create<MultiRunStore>()(
|
||||
set({ error: `Group ${gi + 1}: select at least 1 model` });
|
||||
return null;
|
||||
}
|
||||
if (groups[gi].models.length > 5) {
|
||||
set({ error: `Group ${gi + 1}: maximum 5 models allowed` });
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
set({ isLoading: true, error: null });
|
||||
|
||||
Reference in New Issue
Block a user