mirror of
https://github.com/jlengrand/Maestro.git
synced 2026-03-10 08:31:19 +00:00
Add support for Factory.ai droid agent.
See: https://factory.ai/product/cli
This commit is contained in:
@@ -612,7 +612,7 @@ describe('buildContextTransferPrompt', () => {
|
||||
});
|
||||
|
||||
it('should work for all agent type combinations', () => {
|
||||
const agents: ToolType[] = ['claude-code', 'opencode', 'codex', 'factory-droid', 'claude', 'terminal'];
|
||||
const agents: ToolType[] = ['claude-code', 'aider', 'opencode', 'codex', 'factory-droid', 'claude', 'terminal'];
|
||||
|
||||
for (const source of agents) {
|
||||
for (const target of agents) {
|
||||
|
||||
@@ -213,6 +213,93 @@ export const AGENT_DEFINITIONS: Omit<AgentConfig, 'available' | 'path' | 'capabi
|
||||
// Default env vars - don't set NO_COLOR as it conflicts with FORCE_COLOR
|
||||
defaultEnvVars: {},
|
||||
|
||||
// UI config options
|
||||
// Model IDs from droid CLI (exact IDs required)
|
||||
// NOTE: autonomyLevel is NOT configurable - Maestro always uses --skip-permissions-unsafe
|
||||
// which conflicts with --auto. This matches Claude Code's behavior.
|
||||
configOptions: [
|
||||
{
|
||||
key: 'model',
|
||||
type: 'select',
|
||||
label: 'Model',
|
||||
description: 'Model to use for Factory Droid',
|
||||
// Model IDs from `droid exec --help` (2026-01-22)
|
||||
options: [
|
||||
'', // Empty = use droid's default (claude-opus-4-5-20251101)
|
||||
// OpenAI models
|
||||
'gpt-5.1',
|
||||
'gpt-5.1-codex',
|
||||
'gpt-5.1-codex-max',
|
||||
'gpt-5.2',
|
||||
// Claude models
|
||||
'claude-sonnet-4-5-20250929',
|
||||
'claude-opus-4-5-20251101',
|
||||
'claude-haiku-4-5-20251001',
|
||||
// Google models
|
||||
'gemini-3-pro-preview',
|
||||
],
|
||||
default: '', // Empty = use droid's default (claude-opus-4-5-20251101)
|
||||
argBuilder: (value: string) => (value && value.trim() ? ['-m', value.trim()] : []),
|
||||
},
|
||||
{
|
||||
key: 'reasoningEffort',
|
||||
type: 'select',
|
||||
label: 'Reasoning Effort',
|
||||
description: 'How much the model should reason before responding',
|
||||
options: ['', 'low', 'medium', 'high'],
|
||||
default: '', // Empty = use droid's default reasoning
|
||||
argBuilder: (value: string) => (value && value.trim() ? ['-r', value.trim()] : []),
|
||||
},
|
||||
{
|
||||
key: 'contextWindow',
|
||||
type: 'number',
|
||||
label: 'Context Window Size',
|
||||
description: 'Maximum context window in tokens (for UI display)',
|
||||
default: 200000,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'factory-droid',
|
||||
name: 'Factory Droid',
|
||||
binaryName: 'droid',
|
||||
command: 'droid',
|
||||
args: [], // Base args for interactive mode (none)
|
||||
requiresPty: false, // Batch mode uses child process
|
||||
|
||||
// Batch mode: droid exec [options] "prompt"
|
||||
batchModePrefix: ['exec'],
|
||||
// Always skip permissions in batch mode (like Claude Code's --dangerously-skip-permissions)
|
||||
// Maestro requires full access to work properly
|
||||
batchModeArgs: ['--skip-permissions-unsafe'],
|
||||
|
||||
// JSON output for parsing
|
||||
jsonOutputArgs: ['-o', 'stream-json'],
|
||||
|
||||
// Session resume: -s <id> (requires a prompt)
|
||||
resumeArgs: (sessionId: string) => ['-s', sessionId],
|
||||
|
||||
// Read-only mode is DEFAULT in droid exec (no flag needed)
|
||||
readOnlyArgs: [],
|
||||
|
||||
// YOLO mode (same as batchModeArgs, kept for explicit yoloMode requests)
|
||||
yoloModeArgs: ['--skip-permissions-unsafe'],
|
||||
|
||||
// Model selection is handled by configOptions.model.argBuilder below
|
||||
// Don't define modelArgs here to avoid duplicate -m flags
|
||||
|
||||
// Working directory
|
||||
workingDirArgs: (dir: string) => ['--cwd', dir],
|
||||
|
||||
// File/image input
|
||||
imageArgs: (imagePath: string) => ['-f', imagePath],
|
||||
|
||||
// Prompt is positional argument (no separator needed)
|
||||
noPromptSeparator: true,
|
||||
|
||||
// Default env vars - don't set NO_COLOR as it conflicts with FORCE_COLOR
|
||||
defaultEnvVars: {},
|
||||
|
||||
// UI config options
|
||||
// Model IDs from droid CLI (exact IDs required)
|
||||
// NOTE: autonomyLevel is NOT configurable - Maestro always uses --skip-permissions-unsafe
|
||||
@@ -627,6 +714,16 @@ export class AgentDetector {
|
||||
path.join(appData, 'npm', 'droid.cmd'),
|
||||
path.join(localAppData, 'npm', 'droid.cmd'),
|
||||
],
|
||||
droid: [
|
||||
// Factory Droid installation paths
|
||||
path.join(home, '.factory', 'bin', 'droid.exe'),
|
||||
path.join(localAppData, 'Factory', 'droid.exe'),
|
||||
path.join(appData, 'Factory', 'droid.exe'),
|
||||
path.join(home, '.local', 'bin', 'droid.exe'),
|
||||
// npm global installation
|
||||
path.join(appData, 'npm', 'droid.cmd'),
|
||||
path.join(localAppData, 'npm', 'droid.cmd'),
|
||||
],
|
||||
};
|
||||
|
||||
const pathsToCheck = knownPaths[binaryName] || [];
|
||||
@@ -715,6 +812,15 @@ export class AgentDetector {
|
||||
// Add paths from Node version managers (in case installed via npm)
|
||||
...versionManagerPaths.map((p) => path.join(p, 'droid')),
|
||||
],
|
||||
droid: [
|
||||
// Factory Droid installation paths
|
||||
path.join(home, '.factory', 'bin', 'droid'),
|
||||
path.join(home, '.local', 'bin', 'droid'),
|
||||
'/opt/homebrew/bin/droid',
|
||||
'/usr/local/bin/droid',
|
||||
// Add paths from Node version managers (in case installed via npm)
|
||||
...versionManagerPaths.map((p) => path.join(p, 'droid')),
|
||||
],
|
||||
};
|
||||
|
||||
const pathsToCheck = knownPaths[binaryName] || [];
|
||||
|
||||
@@ -41,6 +41,7 @@ const VALID_TOOL_TYPES: ToolType[] = [
|
||||
'codex',
|
||||
'terminal',
|
||||
'claude',
|
||||
'aider',
|
||||
'factory-droid',
|
||||
];
|
||||
|
||||
|
||||
@@ -45,6 +45,9 @@ export const AGENT_ICONS: Record<string, string> = {
|
||||
// Enterprise
|
||||
'factory-droid': '🏭',
|
||||
|
||||
// Enterprise
|
||||
'factory-droid': '🏭',
|
||||
|
||||
// Terminal/shell (internal)
|
||||
terminal: '💻',
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@ export const DEFAULT_CONTEXT_WINDOWS: Record<ToolType, number> = {
|
||||
claude: 200000, // Legacy Claude
|
||||
codex: 200000, // OpenAI o3/o4-mini context window
|
||||
opencode: 128000, // OpenCode (depends on model, 128k is conservative default)
|
||||
aider: 128000, // Aider (varies by model, 128k is conservative default)
|
||||
'factory-droid': 200000, // Factory Droid (varies by model, defaults to Claude Opus)
|
||||
terminal: 0, // Terminal has no context window
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Shared type definitions for Maestro CLI and Electron app
|
||||
// These types are used by both the CLI tool and the renderer process
|
||||
|
||||
export type ToolType = 'claude' | 'claude-code' | 'opencode' | 'codex' | 'terminal' | 'factory-droid';
|
||||
export type ToolType = 'claude' | 'claude-code' | 'aider' | 'opencode' | 'codex' | 'terminal' | 'factory-droid';
|
||||
|
||||
/**
|
||||
* ThinkingMode controls how AI reasoning/thinking content is displayed.
|
||||
|
||||
Reference in New Issue
Block a user