MAESTRO: Implement model selection for OpenCode moderator - Task 3.1

- Add customModel field to ModeratorConfig type for storing selected model
- Update NewGroupChatModal to pass agentConfig.model through moderatorConfig
- Update App.tsx handleCreateGroupChat to accept customModel parameter
- Update spawnModeratorSynthesis to pass sessionCustomModel from moderatorConfig
- Update initial moderator spawn to pass sessionCustomModel for both spawns
- Verify modelArgs config produces correct --model flag in arguments

This enables users to select a custom model when creating a group chat,
and ensures the selected model is applied when spawning the OpenCode moderator.
This commit is contained in:
chr1syy
2026-02-05 07:45:02 +01:00
parent 811e592076
commit c260cc824e
4 changed files with 14 additions and 6 deletions

View File

@@ -452,6 +452,7 @@ ${message}`;
}); });
const configResolution = applyAgentConfigOverrides(agent, baseArgs, { const configResolution = applyAgentConfigOverrides(agent, baseArgs, {
agentConfigValues, agentConfigValues,
sessionCustomModel: chat.moderatorConfig?.customModel,
sessionCustomArgs: chat.moderatorConfig?.customArgs, sessionCustomArgs: chat.moderatorConfig?.customArgs,
sessionCustomEnvVars: chat.moderatorConfig?.customEnvVars, sessionCustomEnvVars: chat.moderatorConfig?.customEnvVars,
}); });
@@ -849,7 +850,9 @@ export async function routeModeratorResponse(
// Apply SSH wrapping if configured for this session // Apply SSH wrapping if configured for this session
if (sshStore && matchingSession?.sshRemoteConfig) { if (sshStore && matchingSession?.sshRemoteConfig) {
console.log(`[GroupChat:Debug] Applying SSH wrapping for participant ${participantName}...`); console.log(
`[GroupChat:Debug] Applying SSH wrapping for participant ${participantName}...`
);
const sshWrapped = await wrapSpawnWithSsh( const sshWrapped = await wrapSpawnWithSsh(
{ {
command: spawnCommand, command: spawnCommand,
@@ -1149,6 +1152,7 @@ Review the agent responses above. Either:
}); });
const configResolution = applyAgentConfigOverrides(agent, baseArgs, { const configResolution = applyAgentConfigOverrides(agent, baseArgs, {
agentConfigValues, agentConfigValues,
sessionCustomModel: chat.moderatorConfig?.customModel,
sessionCustomArgs: chat.moderatorConfig?.customArgs, sessionCustomArgs: chat.moderatorConfig?.customArgs,
sessionCustomEnvVars: chat.moderatorConfig?.customEnvVars, sessionCustomEnvVars: chat.moderatorConfig?.customEnvVars,
}); });

View File

@@ -8394,6 +8394,7 @@ You are taking over this conversation. Based on the context above, provide a bri
customPath?: string; customPath?: string;
customArgs?: string; customArgs?: string;
customEnvVars?: Record<string, string>; customEnvVars?: Record<string, string>;
customModel?: string;
} }
) => { ) => {
const chat = await window.maestro.groupChat.create(name, moderatorAgentId, moderatorConfig); const chat = await window.maestro.groupChat.create(name, moderatorAgentId, moderatorConfig);

View File

@@ -163,15 +163,18 @@ export function NewGroupChatModal({
// Build moderator config from state // Build moderator config from state
const buildModeratorConfig = useCallback((): ModeratorConfig | undefined => { const buildModeratorConfig = useCallback((): ModeratorConfig | undefined => {
const hasConfig = customPath || customArgs || Object.keys(customEnvVars).length > 0; const customModelValue = agentConfig.model;
const hasConfig =
customPath || customArgs || Object.keys(customEnvVars).length > 0 || customModelValue;
if (!hasConfig) return undefined; if (!hasConfig) return undefined;
return { return {
customPath: customPath || undefined, customPath: customPath || undefined,
customArgs: customArgs || undefined, customArgs: customArgs || undefined,
customEnvVars: Object.keys(customEnvVars).length > 0 ? customEnvVars : undefined, customEnvVars: Object.keys(customEnvVars).length > 0 ? customEnvVars : undefined,
customModel: customModelValue || undefined,
}; };
}, [customPath, customArgs, customEnvVars]); }, [customPath, customArgs, customEnvVars, agentConfig]);
const handleCreate = useCallback(() => { const handleCreate = useCallback(() => {
if (name.trim() && selectedAgent) { if (name.trim() && selectedAgent) {
@@ -351,9 +354,7 @@ export function NewGroupChatModal({
> >
{availableTiles.map((tile) => { {availableTiles.map((tile) => {
const isBeta = const isBeta =
tile.id === 'codex' || tile.id === 'codex' || tile.id === 'opencode' || tile.id === 'factory-droid';
tile.id === 'opencode' ||
tile.id === 'factory-droid';
return ( return (
<option key={tile.id} value={tile.id}> <option key={tile.id} value={tile.id}>
{tile.name} {tile.name}

View File

@@ -73,6 +73,8 @@ export interface ModeratorConfig {
customArgs?: string; customArgs?: string;
/** Custom environment variables */ /** Custom environment variables */
customEnvVars?: Record<string, string>; customEnvVars?: Record<string, string>;
/** Custom model selection (e.g., 'ollama/qwen3:8b') */
customModel?: string;
/** SSH remote config for remote execution */ /** SSH remote config for remote execution */
sshRemoteConfig?: { sshRemoteConfig?: {
enabled: boolean; enabled: boolean;