From c260cc824eb87694db78732c9a3f641fae98542e Mon Sep 17 00:00:00 2001 From: chr1syy Date: Thu, 5 Feb 2026 07:45:02 +0100 Subject: [PATCH 1/6] 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. --- src/main/group-chat/group-chat-router.ts | 6 +++++- src/renderer/App.tsx | 1 + src/renderer/components/NewGroupChatModal.tsx | 11 ++++++----- src/shared/group-chat-types.ts | 2 ++ 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main/group-chat/group-chat-router.ts b/src/main/group-chat/group-chat-router.ts index 032a5062..406a22ab 100644 --- a/src/main/group-chat/group-chat-router.ts +++ b/src/main/group-chat/group-chat-router.ts @@ -452,6 +452,7 @@ ${message}`; }); const configResolution = applyAgentConfigOverrides(agent, baseArgs, { agentConfigValues, + sessionCustomModel: chat.moderatorConfig?.customModel, sessionCustomArgs: chat.moderatorConfig?.customArgs, sessionCustomEnvVars: chat.moderatorConfig?.customEnvVars, }); @@ -849,7 +850,9 @@ export async function routeModeratorResponse( // Apply SSH wrapping if configured for this session 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( { command: spawnCommand, @@ -1149,6 +1152,7 @@ Review the agent responses above. Either: }); const configResolution = applyAgentConfigOverrides(agent, baseArgs, { agentConfigValues, + sessionCustomModel: chat.moderatorConfig?.customModel, sessionCustomArgs: chat.moderatorConfig?.customArgs, sessionCustomEnvVars: chat.moderatorConfig?.customEnvVars, }); diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index a57d9bd7..0c56cc9b 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -8394,6 +8394,7 @@ You are taking over this conversation. Based on the context above, provide a bri customPath?: string; customArgs?: string; customEnvVars?: Record; + customModel?: string; } ) => { const chat = await window.maestro.groupChat.create(name, moderatorAgentId, moderatorConfig); diff --git a/src/renderer/components/NewGroupChatModal.tsx b/src/renderer/components/NewGroupChatModal.tsx index c04d7c07..458f357d 100644 --- a/src/renderer/components/NewGroupChatModal.tsx +++ b/src/renderer/components/NewGroupChatModal.tsx @@ -163,15 +163,18 @@ export function NewGroupChatModal({ // Build moderator config from state 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; return { customPath: customPath || undefined, customArgs: customArgs || undefined, customEnvVars: Object.keys(customEnvVars).length > 0 ? customEnvVars : undefined, + customModel: customModelValue || undefined, }; - }, [customPath, customArgs, customEnvVars]); + }, [customPath, customArgs, customEnvVars, agentConfig]); const handleCreate = useCallback(() => { if (name.trim() && selectedAgent) { @@ -351,9 +354,7 @@ export function NewGroupChatModal({ > {availableTiles.map((tile) => { const isBeta = - tile.id === 'codex' || - tile.id === 'opencode' || - tile.id === 'factory-droid'; + tile.id === 'codex' || tile.id === 'opencode' || tile.id === 'factory-droid'; return (