hataraku
Version:
An autonomous coding agent for building AI-powered development tools. The name "Hataraku" (働く) means "to work" in Japanese.
217 lines • 10.2 kB
JavaScript
import chalk from 'chalk';
import { input, select } from '@inquirer/prompts';
import { TaskManager } from '../../config/TaskManager';
import { ProfileManager } from '../../config/ProfileManager';
import { AgentManager } from '../../config/agent-manager';
import { ConfigLoader } from '../../config/config-loader';
import { executeWithConfig } from '../execution';
export function registerTaskCommands(program) {
const taskCommand = program
.command('task')
.description('Manage tasks');
taskCommand
.command('list')
.description('List all tasks')
.action(async () => {
try {
const taskManager = new TaskManager();
const tasks = await taskManager.listTasks();
console.log(chalk.bold('\nAvailable Tasks:'));
if (tasks.length === 0) {
console.log(chalk.gray(' No tasks found.'));
}
else {
for (const task of tasks) {
console.log(` ${chalk.blue('•')} ${task}`);
}
}
console.log('');
}
catch (error) {
console.error(chalk.red('Error listing tasks:'), error);
process.exit(1);
}
});
taskCommand
.command('show <n>')
.description('Show task details')
.action(async (name) => {
try {
const taskManager = new TaskManager();
const task = await taskManager.getTask(name);
console.log(chalk.bold(`\nTask: ${task.name}`));
console.log(chalk.gray('─'.repeat(30)));
console.log(`${chalk.blue('Description:')} ${task.description}`);
console.log(`${chalk.blue('Agent:')} ${task.agent}`);
if (task.schema) {
console.log(chalk.blue('\nInput Schema:'));
console.log(` ${JSON.stringify(task.schema, null, 2).replace(/\n/g, '\n ')}`);
}
console.log(chalk.blue('\nTask Definition:'));
if (typeof task.task === 'string') {
console.log(` ${task.task.substring(0, 100)}${task.task.length > 100 ? '...' : ''}`);
}
else {
console.log(` Template with parameters: ${task.task.parameters.join(', ')}`);
}
console.log('');
}
catch (error) {
console.error(chalk.red('Error showing task:'), error);
process.exit(1);
}
});
taskCommand
.command('run <n>')
.description('Run a task')
.option('--agent <agent>', 'Use a specific agent for this task')
.option('--provider <provider>', 'Use a specific provider for this task')
.option('--model <model>', 'Use a specific model for this task')
.option('-p, --param <params...>', 'Specify task parameters in key=value format (e.g., --param fileName=main.js language=JavaScript)')
.option('--no-interactive', 'Skip interactive prompts for parameters')
.action(async (name, options) => {
try {
const taskManager = new TaskManager();
const task = await taskManager.getTask(name);
console.log(chalk.blue(`\nPreparing to run task: ${task.name}`));
// Get input for task
const inputData = {};
// First, parse any parameters passed via command line
if (options.param && options.param.length > 0) {
for (const paramPair of options.param) {
const [key, ...valueParts] = paramPair.split('=');
const value = valueParts.join('='); // Rejoin in case value contains "="
if (key && value !== undefined) {
// Convert value based on the schema type if available
if (task.schema && task.schema.properties && task.schema.properties[key]) {
const propType = task.schema.properties[key].type;
if (propType === 'array') {
inputData[key] = value.split(',').map(item => item.trim());
}
else if (propType === 'boolean') {
inputData[key] = value.toLowerCase() === 'true';
}
else if (propType === 'number') {
inputData[key] = Number(value);
}
else {
inputData[key] = value;
}
}
else {
inputData[key] = value;
}
console.log(chalk.green(`Parameter: ${key}=${JSON.stringify(inputData[key])}`));
}
else {
console.error(chalk.yellow(`Warning: Skipping invalid parameter format: ${paramPair}. Use key=value format.`));
}
}
}
// If interactive mode is enabled and we have a schema, prompt for missing values
if (options.interactive !== false && task.schema) {
const schema = task.schema;
if (schema.properties) {
for (const [key, prop] of Object.entries(schema.properties)) {
// Skip if already provided via command line
if (inputData[key] !== undefined)
continue;
const isRequired = schema.required && schema.required.includes(key);
const promptMessage = `${prop.description || key}${isRequired ? ' (required)' : ''}:`;
if (prop.type === 'array') {
const items = await input({
message: promptMessage,
validate: value => {
if (isRequired && !value)
return 'This field is required';
return true;
}
});
inputData[key] = items.split(',').map(item => item.trim());
}
else if (prop.type === 'boolean') {
inputData[key] = await select({
message: promptMessage,
choices: [
{ name: 'Yes', value: true },
{ name: 'No', value: false }
]
});
}
else {
inputData[key] = await input({
message: promptMessage,
validate: value => {
if (isRequired && !value)
return 'This field is required';
return true;
}
});
}
}
}
}
// Validate if all required parameters are provided
if (task.schema && task.schema.required) {
const required = task.schema.required;
const missingParams = required.filter((param) => inputData[param] === undefined);
if (missingParams.length > 0) {
console.error(chalk.red(`Error: Missing required parameters: ${missingParams.join(', ')}`));
process.exit(1);
}
}
// Process task template
const prompt = taskManager.processTaskTemplate(task, inputData);
console.log(chalk.blue('\nExecuting task...'));
// Get agent (from option, task config, or default)
const configLoader = new ConfigLoader();
const profile = await (new ProfileManager()).getActiveProfile();
let agent;
if (options.agent) {
try {
agent = await (new AgentManager()).getAgent(options.agent);
}
catch (error) {
console.error(chalk.yellow(`Warning: Agent '${options.agent}' not found. Using task agent.`));
}
}
if (!agent) {
try {
agent = await (new AgentManager()).getAgent(task.agent);
}
catch (error) {
console.error(chalk.yellow(`Warning: Task agent '${task.agent}' not found. Using default configuration.`));
}
}
// Execute task with agent or directly with model
const cliOptions = {
provider: options.provider || profile.provider,
model: options.model || profile.model,
agent: agent?.name,
stream: profile.options?.stream,
sound: profile.options?.sound
};
console.log(chalk.blue('\nExecuting task with prompt:'));
console.log(chalk.green(prompt));
try {
// Use the executeWithConfig function to actually run the task
const code = await executeWithConfig(prompt, cliOptions, false);
if (code !== 0) {
console.error(chalk.red(`Task execution failed with code ${code}`));
process.exit(code);
}
process.exit(0);
}
catch (execError) {
console.error(chalk.red('Error executing task:'), execError);
process.exit(1);
}
}
catch (error) {
console.error(chalk.red('Error running task:'), error);
process.exit(1);
}
});
return program;
}
//# sourceMappingURL=task.js.map