autoagent-cli
Version:
Run autonomous AI agents using Claude or Gemini for task execution
247 lines (246 loc) • 10.2 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.AutonomousAgent = void 0;
const events_1 = require("events");
const path = __importStar(require("path"));
const config_manager_1 = require("./config-manager");
const stm_manager_1 = require("../utils/stm-manager");
const providers_1 = require("../providers");
const hook_manager_1 = require("./hook-manager");
const session_manager_1 = require("./session-manager");
class AutonomousAgent extends events_1.EventEmitter {
constructor(config) {
super();
this.isExecuting = false;
this.abortController = null;
this.hookManager = null;
this.currentSession = null;
this.config = {
workspace: process.cwd(),
provider: undefined,
includeCoAuthoredBy: true,
autoUpdateContext: true,
debug: false,
dryRun: false,
enableRollback: false,
...config
};
this.configManager = new config_manager_1.ConfigManager(this.config.workspace);
const stmTasksDir = path.join(this.config.workspace ?? process.cwd(), '.autoagent', 'stm-tasks');
this.stmManager = new stm_manager_1.STMManager({ tasksDir: stmTasksDir });
this.sessionManager = new session_manager_1.SessionManager();
if (!this.config.signal) {
process.on('SIGINT', () => void this.handleInterrupt());
process.on('SIGTERM', () => void this.handleInterrupt());
}
}
async initialize() {
await this.configManager.loadConfig();
const userConfig = this.configManager.getConfig();
if (userConfig.hooks) {
this.currentSession = this.sessionManager.createSession(this.config.workspace ?? process.cwd());
await this.sessionManager.saveSession(this.currentSession);
await this.sessionManager.setCurrentSession(this.currentSession.id);
this.hookManager = new hook_manager_1.HookManager(userConfig.hooks, this.currentSession.id, this.config.workspace ?? process.cwd());
}
}
async executeTask(taskId) {
if (this.isExecuting) {
throw new Error('Agent is already executing a task');
}
this.isExecuting = true;
this.emit('execution-start', taskId);
const startTime = Date.now();
try {
const task = await this.stmManager.getTask(taskId);
if (!task) {
throw new Error(`Task ${taskId} not found`);
}
if (this.currentSession) {
const taskIdParts = taskId.split('-');
const issueNumberStr = taskIdParts[0] !== undefined && taskIdParts[0] !== '' ? taskIdParts[0] : '0';
this.currentSession.issueNumber = parseInt(issueNumberStr, 10);
this.currentSession.issueTitle = task.title;
this.currentSession.status = 'active';
await this.sessionManager.saveSession(this.currentSession);
}
if (this.hookManager) {
const hookResult = await this.hookManager.executeHooks('PreExecutionStart', {
taskId,
taskTitle: task.title,
taskStatus: task.status
});
if (hookResult.blocked) {
throw new Error(`Execution blocked by hook: ${hookResult.reason ?? 'Unknown reason'}`);
}
}
const provider = await this.getProvider();
if (!provider) {
throw new Error('No available providers');
}
const context = await this.buildTaskContext(task);
const output = await provider.execute(context, this.config.workspace ?? process.cwd(), this.config.additionalDirectories ?? [], this.config.signal);
await this.stmManager.updateTaskStatus(taskId, 'completed');
const result = {
success: true,
taskId,
taskTitle: task.title,
duration: Date.now() - startTime,
output,
provider: provider.getName()
};
if (this.hookManager) {
await this.hookManager.executeHooks('PostExecutionEnd', {
taskId,
taskTitle: task.title,
success: true,
duration: result.duration
});
}
this.emit('execution-end', result);
return result;
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
const result = {
success: false,
taskId,
duration: Date.now() - startTime,
error: errorMessage
};
try {
await this.stmManager.updateTaskStatus(taskId, 'pending');
}
catch (updateError) {
}
if (this.hookManager) {
await this.hookManager.executeHooks('PostExecutionEnd', {
taskId,
success: false,
error: errorMessage,
duration: result.duration
});
}
this.emit('error', error);
return result;
}
finally {
this.isExecuting = false;
this.abortController = null;
if (this.currentSession) {
this.currentSession.status = 'completed';
await this.sessionManager.saveSession(this.currentSession);
}
}
}
async createTask(title, content) {
return this.stmManager.createTask(title, content);
}
async listTasks(status) {
const filters = status !== undefined && status !== '' ? { status: status } : undefined;
const tasks = await this.stmManager.listTasks(filters);
return tasks.map(task => ({
id: task.id.toString(),
title: task.title,
status: task.status === 'done' ? 'completed' : task.status
}));
}
async getTask(taskId) {
return this.stmManager.getTask(taskId);
}
async updateTaskStatus(taskId, status) {
await this.stmManager.updateTaskStatus(taskId, status);
}
async searchTasks(query) {
const tasks = await this.stmManager.searchTasks(query);
return tasks.map(task => ({
id: task.id.toString(),
title: task.title,
status: task.status === 'done' ? 'completed' : task.status
}));
}
async getStatus() {
const allTasks = await this.stmManager.listTasks();
const completedTasks = allTasks.filter(task => task.status === 'done');
const pendingTasks = allTasks.filter(task => task.status === 'pending' || task.status === 'in-progress');
return {
totalTasks: allTasks.length,
completedTasks: completedTasks.length,
pendingTasks: pendingTasks.length,
currentTaskId: this.isExecuting ? this.currentSession?.issueNumber?.toString() : undefined
};
}
async buildTaskContext(task) {
const sections = await this.stmManager.getTaskSections(task.id.toString());
let context = `# Task: ${task.title}\n\n`;
if (sections.description !== undefined && sections.description !== '') {
context += `## Description\n${sections.description}\n\n`;
}
if (sections.details !== undefined && sections.details !== '') {
context += `## Technical Details\n${sections.details}\n\n`;
}
if (sections.validation !== undefined && sections.validation !== '') {
context += `## Validation Criteria\n${sections.validation}\n\n`;
}
context += 'Please complete this task. Make all necessary changes to implement the requirements.';
return context;
}
async getProvider() {
const userConfig = this.configManager.getConfig();
if (this.config.provider) {
const provider = (0, providers_1.createProvider)(this.config.provider);
const isAvailable = await provider.checkAvailability();
if (isAvailable) {
return provider;
}
}
return (0, providers_1.getFirstAvailableProvider)(userConfig.providers);
}
async handleInterrupt() {
if (this.abortController) {
this.abortController.abort();
}
if (this.currentSession) {
this.currentSession.status = 'interrupted';
await this.sessionManager.saveSession(this.currentSession);
}
process.exit(0);
}
getSTMManager() {
return this.stmManager;
}
}
exports.AutonomousAgent = AutonomousAgent;