UNPKG

hataraku

Version:

An autonomous coding agent for building AI-powered development tools. The name "Hataraku" (働く) means "to work" in Japanese.

250 lines 9.92 kB
"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.TaskManager = void 0; const fs = __importStar(require("fs/promises")); const path = __importStar(require("path")); const config_paths_1 = require("./config-paths"); const taskConfig_1 = require("./taskConfig"); const agent_manager_1 = require("./agent-manager"); /** * Manager for task configurations * Handles CRUD operations for task configurations stored in the tasks directory */ class TaskManager { tasksDir; agentManager; constructor() { // Ensure config directories exist (0, config_paths_1.createConfigDirectories)(); const paths = (0, config_paths_1.getConfigPaths)(); this.tasksDir = paths.tasksDir; this.agentManager = new agent_manager_1.AgentManager(); } /** * List all available task configurations * @returns Array of task configuration names */ async listTasks() { try { const files = await fs.readdir(this.tasksDir); return files .filter(file => file.endsWith('.json')) .map(file => path.basename(file, '.json')); } catch (error) { // If directory doesn't exist or can't be read, return empty array return []; } } /** * Get a specific task configuration * @param name Task configuration name * @returns Task configuration object * @throws Error if task configuration not found or invalid */ async getTask(name) { const filePath = path.join(this.tasksDir, `${name}.json`); try { const data = await fs.readFile(filePath, 'utf-8'); const config = JSON.parse(data); return taskConfig_1.TaskConfigSchema.parse(config); } catch (error) { throw new Error(`Task configuration '${name}' not found or invalid: ${error.message}`); } } /** * Create a new task configuration * @param name Task configuration name * @param config Task configuration object * @throws Error if task configuration already exists or is invalid */ async createTask(name, config) { const filePath = path.join(this.tasksDir, `${name}.json`); try { // Check if file already exists await fs.access(filePath); // If we get here, the file exists, so throw an error throw new Error(`Task configuration '${name}' already exists`); } catch (error) { // Only proceed if error is that file doesn't exist (ENOENT) if (error.code !== 'ENOENT') { // If this is our own error about the file already existing, rethrow it if (error instanceof Error && error.message.includes('already exists')) { throw error; } // Otherwise throw an unexpected error throw error; } // Validate configuration taskConfig_1.TaskConfigSchema.parse(config); // Validate agent reference await this.validateAgentReference(config.agent); // Write configuration to file await fs.writeFile(filePath, JSON.stringify(config, null, 2)); } } /** * Update an existing task configuration * @param name Task configuration name * @param updates Task configuration updates * @throws Error if task configuration not found or is invalid */ async updateTask(name, updates) { const filePath = path.join(this.tasksDir, `${name}.json`); try { // Check if file exists and get current config const currentConfig = await this.getTask(name); // Update config with new values const updatedConfig = { ...currentConfig, ...updates }; // Validate the updated configuration taskConfig_1.TaskConfigSchema.parse(updatedConfig); // Validate agent reference if it was updated if (updates.agent) { await this.validateAgentReference(updatedConfig.agent); } // Write updated configuration to file await fs.writeFile(filePath, JSON.stringify(updatedConfig, null, 2)); } catch (error) { if (error instanceof Error && error.message.includes('not found')) { throw error; } throw new Error(`Failed to update task '${name}': ${error.message}`); } } /** * Delete a task configuration * @param name Task configuration name * @throws Error if task configuration not found */ async deleteTask(name) { const filePath = path.join(this.tasksDir, `${name}.json`); try { await fs.unlink(filePath); } catch (error) { if (error.code === 'ENOENT') { throw new Error(`Task configuration '${name}' not found`); } // Only re-throw known errors, convert unknown errors to a standard message throw error instanceof Error ? error : new Error(`Unknown error occurred: ${error}`); } } /** * Validate agent reference in a task configuration * @param agentName Agent name reference * @throws Error if the referenced agent doesn't exist */ async validateAgentReference(agentName) { try { await this.agentManager.getAgent(agentName); } catch (error) { throw new Error(`Referenced agent '${agentName}' not found`); } } /** * Process a task template with given input * @param task Task configuration * @param input Task input * @returns Processed task prompt */ processTaskTemplate(task, input) { // Handle both old and new format let template; let parameters = []; // Check if task.task is an object (old format) or string (new format) if (typeof task.task === 'object' && task.task.template) { // Old format: task.task is an object with template and parameters template = task.task.template; parameters = task.task.parameters || []; } else { // New format: task.task is a string and parameters is a comma-separated string template = task.task; parameters = task.parameters ? task.parameters.split(',').map(p => p.trim()) : []; } // Simple template substitution using a function that evaluates expressions in template string return template.replace(/\${([^}]*)}/g, (_, expr) => { try { // Use Function constructor to safely evaluate the expression with input parameters const evalFn = new Function(...parameters, `return ${expr}`); return String(evalFn(...parameters.map(param => input[param]))); } catch (error) { return `[Error: ${error instanceof Error ? error.message : 'Invalid expression'}]`; } }); } /** * Initialize default task configurations * Creates default task configurations if they don't exist */ async initializeDefaults() { const tasks = await this.listTasks(); // Create default code review task if not exists if (!tasks.includes('code-review')) { try { await this.createTask('code-review', taskConfig_1.DEFAULT_CODE_REVIEW_TASK); } catch (error) { // Ignore error if agent doesn't exist yet, will be created later if (!(error instanceof Error && error.message.includes('agent') && error.message.includes('not found'))) { throw error; } } } // Create default code explanation task if not exists if (!tasks.includes('explain-code')) { try { await this.createTask('explain-code', taskConfig_1.DEFAULT_CODE_EXPLANATION_TASK); } catch (error) { // Ignore error if agent doesn't exist yet, will be created later if (!(error instanceof Error && error.message.includes('agent') && error.message.includes('not found'))) { throw error; } } } } } exports.TaskManager = TaskManager; //# sourceMappingURL=TaskManager.js.map