From 5cb53ac37b8294a46acd267f8ca6eaf5de5ebf9b Mon Sep 17 00:00:00 2001 From: Pedram Amini Date: Thu, 5 Feb 2026 01:36:45 -0600 Subject: [PATCH 1/3] Improve new agent wizard UX with tip box and header rename - Rename wizard header from "Create a Maestro Agent" to "New Agent Wizard" - Add info tip box explaining in-tab wizard alternative (/wizard command, wand button) - Only show tip box when user has existing agents (first-time users won't see it) - Update note copy: "The new agent wizard captures application inputs until complete" - Add final sentence: "The in-tab wizard runs alongside your other work" - Move "Select the provider" text directly above agent tiles - Center note box vertically with equal spacing - Update test mocks with sessions.getAll and sshRemote.getConfigs --- .../Wizard/WizardKeyboardNavigation.test.tsx | 6 ++ .../Wizard/WizardThemeStyles.test.tsx | 6 ++ .../Wizard/screens/AgentSelectionScreen.tsx | 80 ++++++++++++------- 3 files changed, 65 insertions(+), 27 deletions(-) diff --git a/src/__tests__/renderer/components/Wizard/WizardKeyboardNavigation.test.tsx b/src/__tests__/renderer/components/Wizard/WizardKeyboardNavigation.test.tsx index 421a025c..dcfcce96 100644 --- a/src/__tests__/renderer/components/Wizard/WizardKeyboardNavigation.test.tsx +++ b/src/__tests__/renderer/components/Wizard/WizardKeyboardNavigation.test.tsx @@ -154,6 +154,12 @@ const mockMaestro = { shell: { openExternal: vi.fn(), }, + sshRemote: { + getConfigs: vi.fn().mockResolvedValue({ success: true, configs: [] }), + }, + sessions: { + getAll: vi.fn().mockResolvedValue([]), + }, }; // Mock theme diff --git a/src/__tests__/renderer/components/Wizard/WizardThemeStyles.test.tsx b/src/__tests__/renderer/components/Wizard/WizardThemeStyles.test.tsx index 74043a24..e9cbfb41 100644 --- a/src/__tests__/renderer/components/Wizard/WizardThemeStyles.test.tsx +++ b/src/__tests__/renderer/components/Wizard/WizardThemeStyles.test.tsx @@ -159,6 +159,12 @@ const mockMaestro = { fs: { readFile: vi.fn(), }, + sshRemote: { + getConfigs: vi.fn().mockResolvedValue({ success: true, configs: [] }), + }, + sessions: { + getAll: vi.fn().mockResolvedValue([]), + }, }; // Helper to render with required providers diff --git a/src/renderer/components/Wizard/screens/AgentSelectionScreen.tsx b/src/renderer/components/Wizard/screens/AgentSelectionScreen.tsx index 37c5d5a2..a8a4a89f 100644 --- a/src/renderer/components/Wizard/screens/AgentSelectionScreen.tsx +++ b/src/renderer/components/Wizard/screens/AgentSelectionScreen.tsx @@ -326,6 +326,9 @@ export function AgentSelectionScreen({ theme }: AgentSelectionScreenProps): JSX. const [loadingModels, setLoadingModels] = useState(false); const [refreshingAgent, setRefreshingAgent] = useState(false); + // Track if user has existing agents (to show/hide the note about in-tab wizard) + const [hasExistingAgents, setHasExistingAgents] = useState(false); + // SSH Remote configuration state // Initialize from wizard context if already set (e.g., when SSH was configured before opening wizard) const [sshRemotes, setSshRemotes] = useState([]); @@ -492,6 +495,27 @@ export function AgentSelectionScreen({ theme }: AgentSelectionScreenProps): JSX. }; }, []); + // Check if user has existing agents on mount + useEffect(() => { + let mounted = true; + + async function checkExistingAgents() { + try { + const sessions = await window.maestro.sessions.getAll(); + if (mounted) { + setHasExistingAgents(sessions.length > 0); + } + } catch (error) { + console.error('Failed to check existing agents:', error); + } + } + checkExistingAgents(); + + return () => { + mounted = false; + }; + }, []); + // Focus on mount - currently focus name field since only Claude is supported // TODO: When multiple agents are supported, focus the tiles instead useEffect(() => { @@ -1113,34 +1137,36 @@ export function AgentSelectionScreen({ theme }: AgentSelectionScreenProps): JSX. - {/* Section 2: Note box - centered in available space */} -
-
- - - Note: The new agent wizard captures - application inputs until complete. For a lighter touch, create a new agent then run{' '} - - /wizard - - {' '}or click the{' '} - - {' '}button in the Auto Run panel. The in-tab wizard runs alongside your other work. - + {/* Section 2: Note box - only shown if user has existing agents */} + {hasExistingAgents && ( +
+
+ + + Note: The new agent wizard captures + application inputs until complete. For a lighter touch, create a new agent then run{' '} + + /wizard + + {' '}or click the{' '} + + {' '}button in the Auto Run panel. The in-tab wizard runs alongside your other work. + +
-
+ )} {/* Section 3: Agent Grid or Connection Error */} {sshConnectionError ? ( From 58eeeefb8b163ffc8fc8c80853eb2f34ed387cb2 Mon Sep 17 00:00:00 2001 From: Pedram Amini Date: Thu, 5 Feb 2026 01:47:56 -0600 Subject: [PATCH 2/3] Add Conductor Profile feature for personalized AI interactions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduces an "About Me" field in Settings → General that allows users to describe their background, preferences, and communication style. This profile is exposed as {{CONDUCTOR_PROFILE}} template variable and included in AI chat, group chat, and wizard prompts so agents can tailor their responses to the user. --- docs/configuration.md | 2 +- docs/slash-commands.md | 6 +++ .../components/SettingsModal.test.tsx | 4 ++ .../shared/templateVariables.test.ts | 23 ++++++++++ src/prompts/group-chat-moderator-system.md | 8 +++- src/prompts/maestro-system-prompt.md | 4 ++ src/prompts/wizard-inline-system.md | 4 ++ src/prompts/wizard-system.md | 4 ++ src/renderer/App.tsx | 16 +++++-- src/renderer/components/MainPanel.tsx | 2 +- src/renderer/components/SettingsModal.tsx | 42 +++++++++++++++++++ .../hooks/input/useInputProcessing.ts | 5 +++ src/renderer/hooks/settings/useSettings.ts | 24 +++++++++++ src/renderer/hooks/useInlineWizard.ts | 14 ++++++- .../services/inlineWizardConversation.ts | 3 ++ .../inlineWizardDocumentGeneration.ts | 3 ++ src/shared/templateVariables.ts | 10 +++++ 17 files changed, 166 insertions(+), 8 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 1ee65512..78f6a6f4 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -12,7 +12,7 @@ Settings are organized into tabs: | Tab | Contents | |-----|----------| -| **General** | Shell configuration, input send behavior, default toggles (history, thinking), automatic tab naming, power management, updates, privacy, usage stats, storage location | +| **General** | About Me (conductor profile), shell configuration, input send behavior, default toggles (history, thinking), automatic tab naming, power management, updates, privacy, usage stats, storage location | | **Display** | Font family and size, terminal width, log level and buffer, max output lines per response, document graph settings, context window warnings | | **Shortcuts** | Customize keyboard shortcuts (see [Keyboard Shortcuts](./keyboard-shortcuts)) | | **Themes** | Dark, light, and vibe mode themes, custom theme builder with import/export | diff --git a/docs/slash-commands.md b/docs/slash-commands.md index 4aaafae0..dc283706 100644 --- a/docs/slash-commands.md +++ b/docs/slash-commands.md @@ -44,6 +44,12 @@ Create your own slash commands in **Settings → AI Commands**. Each command has Commands support **template variables** that are automatically substituted at runtime: +### Conductor Variables + +| Variable | Description | +|----------|-------------| +| `{{CONDUCTOR_PROFILE}}` | Your "About Me" profile from Settings → General. Tells agents about your background, preferences, and communication style. | + ### Agent Variables | Variable | Description | diff --git a/src/__tests__/renderer/components/SettingsModal.test.tsx b/src/__tests__/renderer/components/SettingsModal.test.tsx index 3192a233..d858f297 100644 --- a/src/__tests__/renderer/components/SettingsModal.test.tsx +++ b/src/__tests__/renderer/components/SettingsModal.test.tsx @@ -68,6 +68,10 @@ vi.mock('../../../renderer/components/CustomThemeBuilder', () => ({ // Mock useSettings hook (used for context management settings and SSH remote ignore settings) vi.mock('../../../renderer/hooks/settings/useSettings', () => ({ useSettings: () => ({ + // Conductor profile settings + conductorProfile: '', + setConductorProfile: vi.fn(), + // Context management settings contextManagementSettings: { autoGroomContexts: true, maxContextTokens: 100000, diff --git a/src/__tests__/shared/templateVariables.test.ts b/src/__tests__/shared/templateVariables.test.ts index 7d27a9d6..6d1d8c3e 100644 --- a/src/__tests__/shared/templateVariables.test.ts +++ b/src/__tests__/shared/templateVariables.test.ts @@ -58,6 +58,11 @@ describe('TEMPLATE_VARIABLES constant', () => { }); }); + it('should include conductor variables', () => { + const variables = TEMPLATE_VARIABLES.map((v) => v.variable); + expect(variables).toContain('{{CONDUCTOR_PROFILE}}'); + }); + it('should include key agent variables', () => { const variables = TEMPLATE_VARIABLES.map((v) => v.variable); expect(variables).toContain('{{AGENT_NAME}}'); @@ -138,6 +143,24 @@ describe('substituteTemplateVariables', () => { vi.useRealTimers(); }); + describe('Conductor Variables', () => { + it('should replace {{CONDUCTOR_PROFILE}} with conductorProfile', () => { + const context = createTestContext({ + conductorProfile: 'Senior developer specializing in TypeScript and React', + }); + const result = substituteTemplateVariables('Profile: {{CONDUCTOR_PROFILE}}', context); + expect(result).toBe('Profile: Senior developer specializing in TypeScript and React'); + }); + + it('should replace {{CONDUCTOR_PROFILE}} with empty string when conductorProfile is undefined', () => { + const context = createTestContext({ + conductorProfile: undefined, + }); + const result = substituteTemplateVariables('Profile: {{CONDUCTOR_PROFILE}}', context); + expect(result).toBe('Profile: '); + }); + }); + describe('Agent Variables', () => { it('should replace {{AGENT_NAME}} with session.name', () => { const context = createTestContext({ diff --git a/src/prompts/group-chat-moderator-system.md b/src/prompts/group-chat-moderator-system.md index 8f692a36..16b0d403 100644 --- a/src/prompts/group-chat-moderator-system.md +++ b/src/prompts/group-chat-moderator-system.md @@ -1,4 +1,10 @@ -You are a Group Chat Moderator in Maestro, a multi-agent orchestration tool. Your role is to: +You are a Group Chat Moderator in Maestro, a multi-agent orchestration tool. + +## Conductor Profile + +{{CONDUCTOR_PROFILE}} + +Your role is to: 1. **Assist the user directly** - You are a capable AI assistant. For simple questions or tasks, respond directly without delegating to other agents. diff --git a/src/prompts/maestro-system-prompt.md b/src/prompts/maestro-system-prompt.md index 93555f5c..c121f1ac 100644 --- a/src/prompts/maestro-system-prompt.md +++ b/src/prompts/maestro-system-prompt.md @@ -2,6 +2,10 @@ You are **{{AGENT_NAME}}**, powered by **{{TOOL_TYPE}}**, operating as a Maestro-managed AI coding agent. +## Conductor Profile + +{{CONDUCTOR_PROFILE}} + ## About Maestro Maestro is an Electron desktop application for managing multiple AI coding assistants simultaneously with a keyboard-first interface. For more information: diff --git a/src/prompts/wizard-inline-system.md b/src/prompts/wizard-inline-system.md index cb9314c5..6a9b047a 100644 --- a/src/prompts/wizard-inline-system.md +++ b/src/prompts/wizard-inline-system.md @@ -1,5 +1,9 @@ You are a planning assistant helping in an existing Maestro session for "{{PROJECT_NAME}}". +## Conductor Profile + +{{CONDUCTOR_PROFILE}} + ## Your Role You are helping plan work in an active session. The user has an established project context and wants to create or extend a Playbook. diff --git a/src/prompts/wizard-system.md b/src/prompts/wizard-system.md index af3e2e67..cd8d63e5 100644 --- a/src/prompts/wizard-system.md +++ b/src/prompts/wizard-system.md @@ -1,5 +1,9 @@ You are a friendly project discovery assistant helping to set up "{{PROJECT_NAME}}". +## Conductor Profile + +{{CONDUCTOR_PROFILE}} + ## Your Role You are 🎼 Maestro's onboarding assistant, helping the user define their project so we can create an actionable plan. diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index 1ae69f95..a54fa61f 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -453,6 +453,7 @@ function MaestroConsoleInner() { const settings = useSettings(); const { settingsLoaded, + conductorProfile, llmProvider, setLlmProvider, modelSlug, @@ -4551,6 +4552,7 @@ You are taking over this conversation. Based on the context above, provide a bri const substitutedSystemPrompt = substituteTemplateVariables(maestroSystemPrompt, { session: targetSession, gitBranch, + conductorProfile, }); effectivePrompt = `${substitutedSystemPrompt}\n\n---\n\n# User Request\n\n${effectivePrompt}`; } @@ -7497,7 +7499,8 @@ You are taking over this conversation. Based on the context above, provide a bri activeTab.id, // Tab ID for per-tab isolation activeSession.id, // Session ID for playbook creation activeSession.autoRunFolderPath, // User-configured Auto Run folder path (if set) - activeSession.sessionSshRemoteConfig // SSH remote config for remote execution + activeSession.sessionSshRemoteConfig, // SSH remote config for remote execution + conductorProfile // Conductor profile (user's About Me from settings) ); // Rename the tab to "Wizard" immediately when wizard starts @@ -7526,7 +7529,7 @@ You are taking over this conversation. Based on the context above, provide a bri }; addLogToActiveTab(activeSession.id, wizardLog); }, - [activeSession, startInlineWizard, addLogToActiveTab] + [activeSession, startInlineWizard, addLogToActiveTab, conductorProfile] ); // Launch wizard in a new tab - triggered from Auto Run panel button @@ -7580,7 +7583,8 @@ You are taking over this conversation. Based on the context above, provide a bri newTab.id, activeSession.id, activeSession.autoRunFolderPath, // User-configured Auto Run folder path (if set) - activeSession.sessionSshRemoteConfig // SSH remote config for remote execution + activeSession.sessionSshRemoteConfig, // SSH remote config for remote execution + conductorProfile // Conductor profile (user's About Me from settings) ); // Show a system log entry @@ -7597,6 +7601,7 @@ You are taking over this conversation. Based on the context above, provide a bri defaultShowThinking, startInlineWizard, addLogToTab, + conductorProfile, ]); // Determine if wizard is active for the current tab @@ -7634,6 +7639,7 @@ You are taking over this conversation. Based on the context above, provide a bri isWizardActive: isWizardActiveForCurrentTab, onSkillsCommand: handleSkillsCommand, automaticTabNamingEnabled, + conductorProfile, }); // Auto-send context when a tab with autoSendOnActivate becomes active @@ -10113,6 +10119,7 @@ You are taking over this conversation. Based on the context above, provide a bri promptToSend = substituteTemplateVariables(matchingCommand.prompt, { session, gitBranch, + conductorProfile, }); commandMetadata = { command: matchingCommand.command, @@ -10411,6 +10418,7 @@ You are taking over this conversation. Based on the context above, provide a bri const substitutedSystemPrompt = substituteTemplateVariables(maestroSystemPrompt, { session, gitBranch, + conductorProfile, }); // Prepend system prompt to user's message @@ -10482,6 +10490,7 @@ You are taking over this conversation. Based on the context above, provide a bri const substitutedPrompt = substituteTemplateVariables(promptWithArgs, { session, gitBranch, + conductorProfile, }); // For NEW sessions (no agentSessionId), prepend Maestro system prompt @@ -10494,6 +10503,7 @@ You are taking over this conversation. Based on the context above, provide a bri const substitutedSystemPrompt = substituteTemplateVariables(maestroSystemPrompt, { session, gitBranch, + conductorProfile, }); // Prepend system prompt to command's prompt (for agent only) diff --git a/src/renderer/components/MainPanel.tsx b/src/renderer/components/MainPanel.tsx index a00d8e9b..d34daf4a 100644 --- a/src/renderer/components/MainPanel.tsx +++ b/src/renderer/components/MainPanel.tsx @@ -977,7 +977,7 @@ export const MainPanel = React.memo( {/* Hide branch name text at narrow widths, show on hover via title */} {!useIconOnlyGitBranch && ( - + {gitInfo?.branch || 'GIT'} )} diff --git a/src/renderer/components/SettingsModal.tsx b/src/renderer/components/SettingsModal.tsx index 63032f50..89d79f8d 100644 --- a/src/renderer/components/SettingsModal.tsx +++ b/src/renderer/components/SettingsModal.tsx @@ -31,6 +31,7 @@ import { Monitor, PartyPopper, Tag, + User, } from 'lucide-react'; import { useSettings } from '../hooks'; import type { @@ -283,6 +284,9 @@ export const SettingsModal = memo(function SettingsModal(props: SettingsModalPro // Context management settings from useSettings hook const { + // Conductor Profile (About Me) + conductorProfile, + setConductorProfile, contextManagementSettings, updateContextManagementSettings, // Document Graph settings @@ -951,6 +955,44 @@ export const SettingsModal = memo(function SettingsModal(props: SettingsModalPro
{activeTab === 'general' && (
+ {/* About Me (Conductor Profile) */} +
+ +

+ Tell us a little about yourself so that agents created under Maestro know how to + work and communicate with you. As the conductor, you orchestrate the symphony of AI + agents. (Optional, max 1000 characters) +

+
+