mirror of
https://github.com/jlengrand/Maestro.git
synced 2026-03-10 08:31:19 +00:00
Add Conductor Profile feature for personalized AI interactions
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.
This commit is contained in:
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
)}
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -149,6 +149,8 @@ export interface InlineWizardState {
|
||||
remoteId: string | null;
|
||||
workingDirOverride?: string;
|
||||
};
|
||||
/** Conductor profile (user's About Me from settings) */
|
||||
conductorProfile?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,6 +208,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 +223,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 +471,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,6 +529,7 @@ export function useInlineWizard(): UseInlineWizardReturn {
|
||||
subfolderPath: null,
|
||||
autoRunFolderPath: effectiveAutoRunFolderPath,
|
||||
sessionSshRemoteConfig,
|
||||
conductorProfile,
|
||||
}));
|
||||
|
||||
try {
|
||||
@@ -600,6 +606,7 @@ export function useInlineWizard(): UseInlineWizardReturn {
|
||||
existingDocs: docsWithContent.length > 0 ? docsWithContent : undefined,
|
||||
autoRunFolderPath: effectiveAutoRunFolderPath,
|
||||
sessionSshRemoteConfig,
|
||||
conductorProfile,
|
||||
});
|
||||
|
||||
// Store conversation session per-tab
|
||||
@@ -756,6 +763,7 @@ export function useInlineWizard(): UseInlineWizardReturn {
|
||||
existingDocs: undefined,
|
||||
autoRunFolderPath: effectiveAutoRunFolderPath,
|
||||
sessionSshRemoteConfig: currentState.sessionSshRemoteConfig,
|
||||
conductorProfile: currentState.conductorProfile,
|
||||
});
|
||||
conversationSessionsMap.current.set(tabId, session);
|
||||
// Update mode to 'new' since we're proceeding with a new plan
|
||||
@@ -937,6 +945,7 @@ export function useInlineWizard(): UseInlineWizardReturn {
|
||||
existingDocs: undefined, // Will be loaded separately if needed
|
||||
autoRunFolderPath: effectiveAutoRunFolderPath,
|
||||
sessionSshRemoteConfig: currentState.sessionSshRemoteConfig,
|
||||
conductorProfile: currentState.conductorProfile,
|
||||
});
|
||||
|
||||
conversationSessionsMap.current.set(tabId, session);
|
||||
@@ -1191,6 +1200,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');
|
||||
|
||||
@@ -96,6 +96,8 @@ export interface InlineWizardConversationConfig {
|
||||
remoteId: string | null;
|
||||
workingDirOverride?: string;
|
||||
};
|
||||
/** Conductor profile (user's About Me from settings) */
|
||||
conductorProfile?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -223,6 +225,7 @@ export function generateInlineWizardPrompt(config: InlineWizardConversationConfi
|
||||
autoRunFolderPath: autoRunFolderPath,
|
||||
},
|
||||
autoRunFolder: autoRunFolderPath,
|
||||
conductorProfile: config.conductorProfile,
|
||||
};
|
||||
|
||||
// Substitute any remaining template variables
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user