diff --git a/CHANGELOG.md b/CHANGELOG.md index bc3fba37..f514c53c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- Multi Run / Agent Manager: Select the Agent you want to run for the Worktree sessions +- Agent Manager now submits the promt, if valid similar to the Chat interfaces + ## [1.4.3] - 2026-01-04 - VS Code extension: added Agent Manager panel to run the same prompt across up to 5 models in parallel (thanks to @wienans). diff --git a/packages/ui/src/components/multirun/AgentSelector.tsx b/packages/ui/src/components/multirun/AgentSelector.tsx new file mode 100644 index 00000000..674c1370 --- /dev/null +++ b/packages/ui/src/components/multirun/AgentSelector.tsx @@ -0,0 +1,92 @@ +import React from 'react'; +import { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectLabel, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; +import { useConfigStore } from '@/stores/useConfigStore'; + +export interface AgentSelectorProps { + /** Currently selected agent name (empty string for no agent) */ + value: string; + /** Called when agent selection changes */ + onChange: (agentName: string) => void; + /** Optional className for the trigger */ + className?: string; + /** Whether the selector is disabled */ + disabled?: boolean; + /** ID for accessibility */ + id?: string; +} + +/** + * Agent selector dropdown for selecting an agent for multi-run sessions. + * Uses getVisibleAgents from useConfigStore to show available agents. + */ +export const AgentSelector: React.FC = ({ + value, + onChange, + className, + disabled, + id, +}) => { + const getVisibleAgents = useConfigStore((state) => state.getVisibleAgents); + const loadAgents = useConfigStore((state) => state.loadAgents); + const agents = getVisibleAgents(); + + // Load agents on mount + React.useEffect(() => { + loadAgents(); + }, [loadAgents]); + + // Use empty string to represent "no agent" selection + const handleValueChange = (newValue: string) => { + onChange(newValue === '__none__' ? '' : newValue); + }; + + // Convert empty value to __none__ for the Select component (which doesn't handle empty strings well) + const selectValue = value || '__none__'; + + return ( + + ); +}; diff --git a/packages/ui/src/components/multirun/MultiRunLauncher.tsx b/packages/ui/src/components/multirun/MultiRunLauncher.tsx index d08a88a9..3a5c303a 100644 --- a/packages/ui/src/components/multirun/MultiRunLauncher.tsx +++ b/packages/ui/src/components/multirun/MultiRunLauncher.tsx @@ -13,6 +13,7 @@ import { useUIStore } from '@/stores/useUIStore'; import type { CreateMultiRunParams, MultiRunModelSelection } from '@/types/multirun'; import { ModelMultiSelect, generateInstanceId, type ModelSelectionWithId } from './ModelMultiSelect'; import { BranchSelector, useBranchOptions } from './BranchSelector'; +import { AgentSelector } from './AgentSelector'; /** Max file size in bytes (10MB) */ const MAX_FILE_SIZE = 10 * 1024 * 1024; @@ -50,6 +51,7 @@ export const MultiRunLauncher: React.FC = ({ const [name, setName] = React.useState(''); const [prompt, setPrompt] = React.useState(() => initialPrompt ?? ''); const [selectedModels, setSelectedModels] = React.useState([]); + const [selectedAgent, setSelectedAgent] = React.useState(''); const [attachedFiles, setAttachedFiles] = React.useState([]); const [isSubmitting, setIsSubmitting] = React.useState(false); const fileInputRef = React.useRef(null); @@ -191,6 +193,7 @@ export const MultiRunLauncher: React.FC = ({ name: name.trim(), prompt: prompt.trim(), models: modelsForStore, + agent: selectedAgent || undefined, worktreeBaseBranch, files: filesForStore.length > 0 ? filesForStore : undefined, }; @@ -303,6 +306,24 @@ export const MultiRunLauncher: React.FC = ({ + {/* Agent selection */} +
+ + +

+ Optional agent to use for all runs. +

+
+ {/* Prompt */}