claude-flow
Version:
Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration
231 lines • 12.3 kB
JavaScript
/**
* Autopilot MCP Tools
*
* 10 MCP tools for persistent swarm completion management.
* Allows programmatic control of the autopilot loop via MCP.
*
* ADR-072: Autopilot Integration
* @module @claude-flow/cli/mcp-tools/autopilot
*/
import { validateText } from './validate-input.js';
import { loadState, saveState, appendLog, loadLog, discoverTasks, isTerminal, tryLoadLearning, validateNumber, validateTaskSources, VALID_TASK_SOURCES, } from '../autopilot-state.js';
function ok(data) {
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
}
// ── MCP Tool Definitions ──────────────────────────────────────
const autopilotStatus = {
name: 'autopilot_status',
description: 'Get autopilot state including enabled status, iteration count, task progress, and learning metrics. Use when running long-horizon goals that should resume automatically across sessions — Claude Code has no native autonomous-loop scheduler. Pair with autopilot_enable + a goal description, then let cron fires advance the work. For interactive single-task sessions, native Task is fine.',
category: 'autopilot',
inputSchema: { type: 'object', properties: {} },
handler: async () => {
const state = loadState();
const tasks = discoverTasks(state.taskSources);
const completed = tasks.filter(t => isTerminal(t.status)).length;
return ok({
enabled: state.enabled,
sessionId: state.sessionId,
iterations: state.iterations,
maxIterations: state.maxIterations,
timeoutMinutes: state.timeoutMinutes,
elapsedMs: state.enabled ? Date.now() - state.startTime : 0,
tasks: { completed, total: tasks.length, percent: tasks.length === 0 ? 100 : Math.round((completed / tasks.length) * 100) },
taskSources: state.taskSources,
});
},
};
const autopilotEnable = {
name: 'autopilot_enable',
description: 'Enable autopilot persistent completion. Agents will be re-engaged when tasks remain incomplete. Use when running long-horizon goals that should resume automatically across sessions — Claude Code has no native autonomous-loop scheduler. Pair with autopilot_enable + a goal description, then let cron fires advance the work. For interactive single-task sessions, native Task is fine.',
category: 'autopilot',
inputSchema: { type: 'object', properties: {} },
handler: async () => {
const state = loadState();
state.enabled = true;
state.startTime = Date.now();
state.iterations = 0;
saveState(state);
appendLog({ ts: Date.now(), event: 'enabled', sessionId: state.sessionId });
return ok({ enabled: true, maxIterations: state.maxIterations, timeoutMinutes: state.timeoutMinutes });
},
};
const autopilotDisable = {
name: 'autopilot_disable',
description: 'Disable autopilot. Agents will be allowed to stop even if tasks remain. Use when running long-horizon goals that should resume automatically across sessions — Claude Code has no native autonomous-loop scheduler. Pair with autopilot_enable + a goal description, then let cron fires advance the work. For interactive single-task sessions, native Task is fine.',
category: 'autopilot',
inputSchema: { type: 'object', properties: {} },
handler: async () => {
const state = loadState();
state.enabled = false;
saveState(state);
appendLog({ ts: Date.now(), event: 'disabled', iterations: state.iterations });
return ok({ enabled: false });
},
};
const autopilotConfig = {
name: 'autopilot_config',
description: 'Configure autopilot limits: max iterations (1-1000), timeout in minutes (1-1440), and task sources. Use when running long-horizon goals that should resume automatically across sessions — Claude Code has no native autonomous-loop scheduler. Pair with autopilot_enable + a goal description, then let cron fires advance the work. For interactive single-task sessions, native Task is fine.',
category: 'autopilot',
inputSchema: {
type: 'object',
properties: {
maxIterations: { type: 'number', description: 'Max re-engagement iterations (1-1000)' },
timeoutMinutes: { type: 'number', description: 'Timeout in minutes (1-1440)' },
taskSources: { type: 'array', items: { type: 'string' }, description: `Task sources: ${[...VALID_TASK_SOURCES].join(', ')}` },
},
},
handler: async (params) => {
const state = loadState();
if (params.maxIterations !== undefined) {
state.maxIterations = validateNumber(params.maxIterations, 1, 1000, state.maxIterations);
}
if (params.timeoutMinutes !== undefined) {
state.timeoutMinutes = validateNumber(params.timeoutMinutes, 1, 1440, state.timeoutMinutes);
}
if (params.taskSources !== undefined) {
state.taskSources = validateTaskSources(params.taskSources);
}
saveState(state);
return ok({ maxIterations: state.maxIterations, timeoutMinutes: state.timeoutMinutes, taskSources: state.taskSources });
},
};
const autopilotReset = {
name: 'autopilot_reset',
description: 'Reset autopilot iteration counter and restart the timer. Use when running long-horizon goals that should resume automatically across sessions — Claude Code has no native autonomous-loop scheduler. Pair with autopilot_enable + a goal description, then let cron fires advance the work. For interactive single-task sessions, native Task is fine.',
category: 'autopilot',
inputSchema: { type: 'object', properties: {} },
handler: async () => {
const state = loadState();
state.iterations = 0;
state.startTime = Date.now();
state.history = [];
state.lastCheck = null;
saveState(state);
appendLog({ ts: Date.now(), event: 'reset' });
return ok({ reset: true, iterations: 0 });
},
};
const autopilotLog = {
name: 'autopilot_log',
description: 'Retrieve the autopilot event log. Shows enable/disable events, re-engagements, completions. Use when running long-horizon goals that should resume automatically across sessions — Claude Code has no native autonomous-loop scheduler. Pair with autopilot_enable + a goal description, then let cron fires advance the work. For interactive single-task sessions, native Task is fine.',
category: 'autopilot',
inputSchema: {
type: 'object',
properties: {
last: { type: 'number', description: 'Return only the last N entries' },
},
},
handler: async (params) => {
const log = loadLog();
const last = validateNumber(params.last, 1, 10000, 0);
return ok(last > 0 ? log.slice(-last) : log);
},
};
const autopilotProgress = {
name: 'autopilot_progress',
description: 'Detailed task progress broken down by source (team-tasks, swarm-tasks, file-checklist). Use when running long-horizon goals that should resume automatically across sessions — Claude Code has no native autonomous-loop scheduler. Pair with autopilot_enable + a goal description, then let cron fires advance the work. For interactive single-task sessions, native Task is fine.',
category: 'autopilot',
inputSchema: { type: 'object', properties: {} },
handler: async () => {
const state = loadState();
const tasks = discoverTasks(state.taskSources);
const bySource = {};
for (const t of tasks) {
if (!bySource[t.source])
bySource[t.source] = { completed: 0, total: 0, tasks: [] };
bySource[t.source].total++;
if (isTerminal(t.status)) {
bySource[t.source].completed++;
}
bySource[t.source].tasks.push(t);
}
const completed = tasks.filter(t => isTerminal(t.status)).length;
return ok({
overall: { completed, total: tasks.length, percent: tasks.length === 0 ? 100 : Math.round((completed / tasks.length) * 100) },
bySource,
});
},
};
const autopilotLearn = {
name: 'autopilot_learn',
description: 'Discover success patterns from past task completions. Requires AgentDB for full functionality. Use when running long-horizon goals that should resume automatically across sessions — Claude Code has no native autonomous-loop scheduler. Pair with autopilot_enable + a goal description, then let cron fires advance the work. For interactive single-task sessions, native Task is fine.',
category: 'autopilot',
inputSchema: { type: 'object', properties: {} },
handler: async () => {
const learning = await tryLoadLearning();
if (learning) {
const [metrics, patterns] = await Promise.all([
learning.getMetrics(),
learning.discoverSuccessPatterns(),
]);
return ok({ metrics, patterns });
}
return ok({ available: false, reason: 'AgentDB/AutopilotLearning not initialized', patterns: [] });
},
};
const autopilotHistory = {
name: 'autopilot_history',
description: 'Search past completion episodes by keyword. Requires AgentDB. Use when running long-horizon goals that should resume automatically across sessions — Claude Code has no native autonomous-loop scheduler. Pair with autopilot_enable + a goal description, then let cron fires advance the work. For interactive single-task sessions, native Task is fine.',
category: 'autopilot',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', description: 'Search query' },
limit: { type: 'number', description: 'Max results (default 10)' },
},
required: ['query'],
},
handler: async (params) => {
const vQuery = validateText(params.query, 'query');
if (!vQuery.valid)
return ok({ query: '', results: [], error: vQuery.error });
const query = String(params.query || '');
const limit = validateNumber(params.limit, 1, 100, 10);
const learning = await tryLoadLearning();
if (learning) {
const results = await learning.recallSimilarTasks(query, limit);
return ok({ query, results });
}
return ok({ query, results: [], available: false });
},
};
const autopilotPredict = {
name: 'autopilot_predict',
description: 'Predict the optimal next action based on current state and learned patterns. Use when running long-horizon goals that should resume automatically across sessions — Claude Code has no native autonomous-loop scheduler. Pair with autopilot_enable + a goal description, then let cron fires advance the work. For interactive single-task sessions, native Task is fine.',
category: 'autopilot',
inputSchema: { type: 'object', properties: {} },
handler: async () => {
const state = loadState();
const learning = await tryLoadLearning();
if (learning) {
const prediction = await learning.predictNextAction(state);
return ok(prediction);
}
// Heuristic fallback
const tasks = discoverTasks(state.taskSources);
const incomplete = tasks.filter(t => !isTerminal(t.status));
if (incomplete.length === 0) {
return ok({ action: 'none', confidence: 1.0, reason: 'All tasks complete' });
}
return ok({
action: `Work on: ${incomplete[0].subject}`,
confidence: 0.5,
reason: 'Heuristic (learning not available)',
remaining: incomplete.length,
});
},
};
// ── Export ─────────────────────────────────────────────────────
export const autopilotTools = [
autopilotStatus,
autopilotEnable,
autopilotDisable,
autopilotConfig,
autopilotReset,
autopilotLog,
autopilotProgress,
autopilotLearn,
autopilotHistory,
autopilotPredict,
];
//# sourceMappingURL=autopilot-tools.js.map