Merge pull request #304 from pedramamini/conductor-profile

Add Conductor Profile
This commit is contained in:
Pedram Amini
2026-02-05 02:05:43 -06:00
committed by GitHub
21 changed files with 294 additions and 37 deletions

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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({

View File

@@ -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.

View File

@@ -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:
@@ -27,8 +31,11 @@ Your session history is stored at `{{AGENT_HISTORY_PATH}}`. When you need contex
- `timestamp`: When the task was completed (Unix ms)
- `type`: `AUTO` (automated) or `USER` (interactive)
- `success`: Whether the task succeeded
- `fullResponse`: Complete AI response text (for detailed context)
- `elapsedTimeMs`: How long the task took
- `contextUsage`: Context window usage percentage at completion
To recall recent work, read the file and scan the most recent entries by timestamp.
To recall recent work, read the file and scan the most recent entries by timestamp. Use `summary` for quick scanning and `fullResponse` when you need detailed context about what was done.
## Auto-run Documents

View File

@@ -1,9 +1,25 @@
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.
## Task Recall
Your session history is stored at `{{AGENT_HISTORY_PATH}}`. When you need context about previously completed work in this project, read this JSON file and parse the `entries` array. Each entry contains:
- `summary`: Brief description of the task
- `timestamp`: When the task was completed (Unix ms)
- `type`: `AUTO` (automated) or `USER` (interactive)
- `success`: Whether the task succeeded
- `fullResponse`: Complete AI response text (for detailed context)
- `elapsedTimeMs`: How long the task took
To recall recent work, read the file and scan the most recent entries by timestamp. Use `summary` for quick scanning and `fullResponse` when you need detailed context about what has already been accomplished.
## File Access Restrictions
**WRITE ACCESS (Limited):**

View File

@@ -1,9 +1,25 @@
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.
## Task Recall
Your session history is stored at `{{AGENT_HISTORY_PATH}}`. When you need context about previously completed work in this project, read this JSON file and parse the `entries` array. Each entry contains:
- `summary`: Brief description of the task
- `timestamp`: When the task was completed (Unix ms)
- `type`: `AUTO` (automated) or `USER` (interactive)
- `success`: Whether the task succeeded
- `fullResponse`: Complete AI response text (for detailed context)
- `elapsedTimeMs`: How long the task took
To recall recent work, read the file and scan the most recent entries by timestamp. Use `summary` for quick scanning and `fullResponse` when you need detailed context about what has already been accomplished.
## File Access Restrictions
**WRITE ACCESS (Limited):**

View File

@@ -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)

View File

@@ -977,7 +977,7 @@ export const MainPanel = React.memo(
<GitBranch className="w-3 h-3 shrink-0" />
{/* Hide branch name text at narrow widths, show on hover via title */}
{!useIconOnlyGitBranch && (
<span className="truncate max-w-[120px]">
<span className="truncate">
{gitInfo?.branch || 'GIT'}
</span>
)}

View File

@@ -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
<div className="flex-1 p-6 overflow-y-auto scrollbar-thin">
{activeTab === 'general' && (
<div className="space-y-5">
{/* About Me (Conductor Profile) */}
<div>
<label className="block text-xs font-bold opacity-70 uppercase mb-1 flex items-center gap-2">
<User className="w-3 h-3" />
About Me
</label>
<p className="text-xs opacity-50 mb-2">
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)
</p>
<div className="relative">
<textarea
value={conductorProfile}
onChange={(e) => setConductorProfile(e.target.value)}
placeholder="e.g., I'm a senior developer working on a React/TypeScript project. I prefer concise explanations and clean code patterns..."
className="w-full p-3 rounded border bg-transparent outline-none text-sm resize-none"
style={{
borderColor: theme.colors.border,
color: theme.colors.textMain,
minHeight: '100px',
}}
maxLength={1000}
/>
<div
className="absolute bottom-2 right-2 text-xs"
style={{
color:
conductorProfile.length > 900
? theme.colors.warning
: theme.colors.textDim,
}}
>
{conductorProfile.length}/1000
</div>
</div>
</div>
{/* Default Shell */}
<div>
<label className="block text-xs font-bold opacity-70 uppercase mb-1 flex items-center gap-2">

View File

@@ -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<SshRemoteConfig[]>([]);
@@ -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,7 +1137,8 @@ export function AgentSelectionScreen({ theme }: AgentSelectionScreenProps): JSX.
</div>
{/* Section 2: Note box - centered in available space */}
{/* Section 2: Note box - only shown if user has existing agents */}
{hasExistingAgents && (
<div className="flex justify-center">
<div
className="flex items-start gap-2.5 px-4 py-3 rounded-lg max-w-lg text-xs"
@@ -1141,6 +1166,7 @@ export function AgentSelectionScreen({ theme }: AgentSelectionScreenProps): JSX.
</span>
</div>
</div>
)}
{/* Section 3: Agent Grid or Connection Error */}
{sshConnectionError ? (

View File

@@ -60,6 +60,10 @@ export interface SystemPromptConfig {
existingDocs?: ExistingDocument[];
/** Auto Run folder path (defaults to agentPath/Auto Run Docs if not provided) */
autoRunFolderPath?: string;
/** History file path for task recall (optional, enables AI to recall recent work) */
historyFilePath?: string;
/** Conductor profile (user's About Me from settings) */
conductorProfile?: string;
}
/**
@@ -112,7 +116,7 @@ export const READY_CONFIDENCE_THRESHOLD = 80;
* @returns The complete system prompt for the agent
*/
export function generateSystemPrompt(config: SystemPromptConfig): string {
const { agentName, agentPath, existingDocs, autoRunFolderPath } = config;
const { agentName, agentPath, existingDocs, autoRunFolderPath, historyFilePath, conductorProfile } = config;
const projectName = agentName || 'this project';
// Default Auto Run folder to standard location under working directory
@@ -140,6 +144,7 @@ export function generateSystemPrompt(config: SystemPromptConfig): string {
// Build template context for remaining variables (date/time, etc.)
// Include autoRunFolderPath so {{AUTORUN_FOLDER}} is properly substituted
// Include historyFilePath for {{AGENT_HISTORY_PATH}} task recall
const templateContext: TemplateContext = {
session: {
id: 'wizard',
@@ -150,6 +155,8 @@ export function generateSystemPrompt(config: SystemPromptConfig): string {
autoRunFolderPath: effectiveAutoRunFolder,
},
autoRunFolder: effectiveAutoRunFolder,
historyFilePath: historyFilePath,
conductorProfile: conductorProfile,
};
// Substitute any remaining template variables using the central function

View File

@@ -72,6 +72,8 @@ export interface UseInputProcessingDeps {
onSkillsCommand?: () => Promise<void>;
/** Whether automatic tab naming is enabled */
automaticTabNamingEnabled?: boolean;
/** Conductor profile (user's About Me from settings) */
conductorProfile?: string;
}
/**
@@ -128,6 +130,7 @@ export function useInputProcessing(deps: UseInputProcessingDeps): UseInputProces
isWizardActive,
onSkillsCommand,
automaticTabNamingEnabled,
conductorProfile,
} = deps;
// Ref for the processInput function so external code can access the latest version
@@ -239,6 +242,7 @@ export function useInputProcessing(deps: UseInputProcessingDeps): UseInputProces
substituteTemplateVariables(matchingCustomCommand.prompt, {
session: activeSession,
gitBranch,
conductorProfile,
});
// ALWAYS queue slash commands - they execute in order like write messages
@@ -903,6 +907,7 @@ export function useInputProcessing(deps: UseInputProcessingDeps): UseInputProces
session: freshSession,
gitBranch,
historyFilePath,
conductorProfile,
});
// Prepend system prompt to user's message

View File

@@ -126,6 +126,10 @@ export interface UseSettingsReturn {
// Loading state
settingsLoaded: boolean;
// Conductor Profile (About Me)
conductorProfile: string;
setConductorProfile: (value: string) => void;
// LLM settings
llmProvider: LLMProvider;
modelSlug: string;
@@ -360,6 +364,9 @@ export function useSettings(): UseSettingsReturn {
// Loading state
const [settingsLoaded, setSettingsLoaded] = useState(false);
// Conductor Profile (About Me) - optional, up to 1000 characters
const [conductorProfile, setConductorProfileState] = useState('');
// LLM Config
const [llmProvider, setLlmProviderState] = useState<LLMProvider>('openrouter');
const [modelSlug, setModelSlugState] = useState('anthropic/claude-3.5-sonnet');
@@ -517,6 +524,15 @@ export function useSettings(): UseSettingsReturn {
// Wrapper functions that persist to electron-store
// PERF: All wrapped in useCallback to prevent re-renders
// Conductor Profile (About Me)
const setConductorProfile = useCallback((value: string) => {
// Enforce 1000 character limit
const trimmed = value.slice(0, 1000);
setConductorProfileState(trimmed);
window.maestro.settings.set('conductorProfile', trimmed);
}, []);
const setLlmProvider = useCallback((value: LLMProvider) => {
setLlmProviderState(value);
window.maestro.settings.set('llmProvider', value);
@@ -1344,6 +1360,7 @@ export function useSettings(): UseSettingsReturn {
const allSettings = (await window.maestro.settings.getAll()) as Record<string, unknown>;
// Extract settings from the batch response
const savedConductorProfile = allSettings['conductorProfile'];
const savedEnterToSendAI = allSettings['enterToSendAI'];
const savedEnterToSendTerminal = allSettings['enterToSendTerminal'];
const savedDefaultSaveToHistory = allSettings['defaultSaveToHistory'];
@@ -1411,6 +1428,9 @@ export function useSettings(): UseSettingsReturn {
const savedFileTabAutoRefreshEnabled = allSettings['fileTabAutoRefreshEnabled'];
const savedSuppressWindowsWarning = allSettings['suppressWindowsWarning'];
// Conductor Profile (About Me)
if (savedConductorProfile !== undefined) setConductorProfileState(savedConductorProfile as string);
if (savedEnterToSendAI !== undefined) setEnterToSendAIState(savedEnterToSendAI as boolean);
if (savedEnterToSendTerminal !== undefined)
setEnterToSendTerminalState(savedEnterToSendTerminal as boolean);
@@ -1814,6 +1834,8 @@ export function useSettings(): UseSettingsReturn {
return useMemo(
() => ({
settingsLoaded,
conductorProfile,
setConductorProfile,
llmProvider,
modelSlug,
apiKey,
@@ -1963,6 +1985,7 @@ export function useSettings(): UseSettingsReturn {
[
// State values
settingsLoaded,
conductorProfile,
llmProvider,
modelSlug,
apiKey,
@@ -2008,6 +2031,7 @@ export function useSettings(): UseSettingsReturn {
firstAutoRunCompleted,
onboardingStats,
// Setter functions (stable via useCallback)
setConductorProfile,
setLlmProvider,
setModelSlug,
setApiKey,

View File

@@ -149,6 +149,10 @@ export interface InlineWizardState {
remoteId: string | null;
workingDirOverride?: string;
};
/** Conductor profile (user's About Me from settings) */
conductorProfile?: string;
/** History file path for task recall (fetched once during startWizard) */
historyFilePath?: string;
}
/**
@@ -206,6 +210,7 @@ export interface UseInlineWizardReturn {
* @param sessionId - The session ID for playbook creation
* @param autoRunFolderPath - User-configured Auto Run folder path (if set, overrides default projectPath/Auto Run Docs)
* @param sessionSshRemoteConfig - SSH remote configuration (for remote execution)
* @param conductorProfile - Conductor profile (user's About Me from settings)
*/
startWizard: (
naturalLanguageInput?: string,
@@ -220,7 +225,8 @@ export interface UseInlineWizardReturn {
enabled: boolean;
remoteId: string | null;
workingDirOverride?: string;
}
},
conductorProfile?: string
) => Promise<void>;
/** End the wizard and restore previous UI state */
endWizard: () => Promise<PreviousUIState | null>;
@@ -467,7 +473,8 @@ export function useInlineWizard(): UseInlineWizardReturn {
enabled: boolean;
remoteId: string | null;
workingDirOverride?: string;
}
},
conductorProfile?: string
): Promise<void> => {
// Tab ID is required for per-tab wizard management
const effectiveTabId = tabId || 'default';
@@ -524,9 +531,23 @@ export function useInlineWizard(): UseInlineWizardReturn {
subfolderPath: null,
autoRunFolderPath: effectiveAutoRunFolderPath,
sessionSshRemoteConfig,
conductorProfile,
}));
try {
// Step 0: Fetch history file path for task recall (if session ID is available)
// This is done early so it's available for both conversation session and state
let historyFilePath: string | undefined;
if (sessionId) {
try {
const fetchedPath = await window.maestro.history.getFilePath(sessionId);
historyFilePath = fetchedPath ?? undefined; // Convert null to undefined
} catch {
// History file path not available - continue without it
logger.debug('Could not fetch history file path', '[InlineWizard]', { sessionId });
}
}
// Step 1: Check for existing Auto Run documents in the configured folder
// Use the effective Auto Run folder path (user-configured or default)
let hasExistingDocs = false;
@@ -591,6 +612,7 @@ export function useInlineWizard(): UseInlineWizardReturn {
supportedWizardAgents.includes(agentType) &&
effectiveAutoRunFolderPath
) {
// historyFilePath was fetched in Step 0 above
const session = startInlineWizardConversation({
mode,
agentType,
@@ -600,6 +622,8 @@ export function useInlineWizard(): UseInlineWizardReturn {
existingDocs: docsWithContent.length > 0 ? docsWithContent : undefined,
autoRunFolderPath: effectiveAutoRunFolderPath,
sessionSshRemoteConfig,
conductorProfile,
historyFilePath,
});
// Store conversation session per-tab
@@ -629,12 +653,14 @@ export function useInlineWizard(): UseInlineWizardReturn {
}
// Update state with parsed results
// Store historyFilePath so it's available for setMode if user is in 'ask' mode
setTabState(effectiveTabId, (prev) => ({
...prev,
isInitializing: false,
mode,
goal,
existingDocuments: existingDocs,
historyFilePath,
}));
} catch (error) {
// Handle any errors during initialization
@@ -747,6 +773,7 @@ export function useInlineWizard(): UseInlineWizardReturn {
effectiveAutoRunFolderPath
) {
console.log('[useInlineWizard] Auto-creating session for direct message in ask mode');
// Use historyFilePath from state (fetched during startWizard)
session = startInlineWizardConversation({
mode: 'new',
agentType: currentState.agentType,
@@ -756,6 +783,8 @@ export function useInlineWizard(): UseInlineWizardReturn {
existingDocs: undefined,
autoRunFolderPath: effectiveAutoRunFolderPath,
sessionSshRemoteConfig: currentState.sessionSshRemoteConfig,
conductorProfile: currentState.conductorProfile,
historyFilePath: currentState.historyFilePath,
});
conversationSessionsMap.current.set(tabId, session);
// Update mode to 'new' since we're proceeding with a new plan
@@ -928,6 +957,7 @@ export function useInlineWizard(): UseInlineWizardReturn {
(currentState.projectPath ? getAutoRunFolderPath(currentState.projectPath) : null);
if (currentState.agentType && effectiveAutoRunFolderPath) {
// Use historyFilePath from state (fetched during startWizard)
const session = startInlineWizardConversation({
mode: newMode,
agentType: currentState.agentType,
@@ -937,6 +967,8 @@ export function useInlineWizard(): UseInlineWizardReturn {
existingDocs: undefined, // Will be loaded separately if needed
autoRunFolderPath: effectiveAutoRunFolderPath,
sessionSshRemoteConfig: currentState.sessionSshRemoteConfig,
conductorProfile: currentState.conductorProfile,
historyFilePath: currentState.historyFilePath,
});
conversationSessionsMap.current.set(tabId, session);
@@ -1191,6 +1223,7 @@ export function useInlineWizard(): UseInlineWizardReturn {
autoRunFolderPath: effectiveAutoRunFolderPath,
sessionId: currentState.sessionId || undefined,
sessionSshRemoteConfig: currentState.sessionSshRemoteConfig,
conductorProfile: currentState.conductorProfile,
callbacks: {
onStart: () => {
console.log('[useInlineWizard] Document generation started');

View File

@@ -96,6 +96,10 @@ export interface InlineWizardConversationConfig {
remoteId: string | null;
workingDirOverride?: string;
};
/** Conductor profile (user's About Me from settings) */
conductorProfile?: string;
/** History file path for task recall (optional, enables AI to recall recent work) */
historyFilePath?: string;
}
/**
@@ -213,6 +217,7 @@ export function generateInlineWizardPrompt(config: InlineWizardConversationConfi
}
// Build template context for remaining variables
// Include historyFilePath for {{AGENT_HISTORY_PATH}} task recall
const templateContext: TemplateContext = {
session: {
id: 'inline-wizard',
@@ -223,6 +228,8 @@ export function generateInlineWizardPrompt(config: InlineWizardConversationConfi
autoRunFolderPath: autoRunFolderPath,
},
autoRunFolder: autoRunFolderPath,
conductorProfile: config.conductorProfile,
historyFilePath: config.historyFilePath,
};
// Substitute any remaining template variables

View File

@@ -134,6 +134,8 @@ export interface DocumentGenerationConfig {
remoteId: string | null;
workingDirOverride?: string;
};
/** Conductor profile (user's About Me from settings) */
conductorProfile?: string;
/** Optional callbacks */
callbacks?: DocumentGenerationCallbacks;
}
@@ -358,6 +360,7 @@ export function generateDocumentPrompt(
cwd: directoryPath,
fullPath: directoryPath,
},
conductorProfile: config.conductorProfile,
};
// Substitute any remaining template variables

View File

@@ -3,6 +3,9 @@
*
* Available variables (case-insensitive):
*
* Conductor Variables (the Maestro user):
* {{CONDUCTOR_PROFILE}} - User's About Me profile (from Settings → General)
*
* Agent Variables:
* {{AGENT_NAME}} - Agent name
* {{AGENT_PATH}} - Agent home directory path (full path to project)
@@ -68,12 +71,15 @@ export interface TemplateContext {
documentPath?: string;
// History file path for task recall
historyFilePath?: string;
// Conductor profile (user's About Me from settings)
conductorProfile?: string;
}
// List of all available template variables for documentation (alphabetically sorted)
// Variables marked as autoRunOnly are only shown in Auto Run contexts, not in AI Commands settings
export const TEMPLATE_VARIABLES = [
{ variable: '{{AGENT_GROUP}}', description: 'Agent group name' },
{ variable: '{{CONDUCTOR_PROFILE}}', description: 'Conductor\'s About Me profile' },
{ variable: '{{AGENT_HISTORY_PATH}}', description: 'History file path (task recall)' },
{ variable: '{{AGENT_NAME}}', description: 'Agent name' },
{ variable: '{{AGENT_PATH}}', description: 'Agent home directory path' },
@@ -120,11 +126,15 @@ export function substituteTemplateVariables(template: string, context: TemplateC
documentName,
documentPath,
historyFilePath,
conductorProfile,
} = context;
const now = new Date();
// Build replacements map
const replacements: Record<string, string> = {
// Conductor variables (the Maestro user)
CONDUCTOR_PROFILE: conductorProfile || '',
// Agent variables
AGENT_NAME: session.name,
AGENT_PATH: session.fullPath || session.projectRoot || session.cwd,