hataraku
Version:
An autonomous coding agent for building AI-powered development tools. The name "Hataraku" (働く) means "to work" in Japanese.
137 lines • 5.03 kB
JavaScript
import { z } from 'zod';
class WorkflowBuilderImpl {
config;
input;
tasks = [];
conditionalTasks = [];
constructor(config, input) {
this.config = config;
this.input = input;
}
async task(name, executor, input) {
// Emit task start event
this.config.onTaskStart?.(name);
try {
// Execute task
const result = await executor(input);
// Store result for later use in workflow
this.tasks.push({
name,
executor: async () => result,
input
});
// Emit task complete event
this.config.onTaskComplete?.(name, result);
return result;
}
catch (error) {
console.error('Task failed', name, error);
const taskError = error instanceof Error ? error : new Error(String(error));
throw new Error(`Workflow '${this.config.name}' failed: Task '${name}' failed: ${taskError.message}`);
}
}
when(condition, builder) {
this.conditionalTasks.push({
condition: (results) => {
try {
return condition(results);
}
catch (error) {
return false;
}
},
builder: (b) => builder(b)
});
return this;
}
parallel(tasks) {
const promises = tasks.map(async ({ name, task, input }) => {
this.config.onTaskStart?.(name);
try {
const result = await task(input);
this.config.onTaskComplete?.(name, result);
return result;
}
catch (error) {
const taskError = error instanceof Error ? error : new Error(String(error));
throw new Error(`Task '${name}' failed: ${taskError.message}`);
}
});
return Promise.all(promises);
}
success(result) {
return result;
}
fail(message) {
throw new Error(message);
}
async run() {
const results = {};
for (const task of this.tasks) {
// Emit task start event
this.config.onTaskStart?.(task.name);
// Execute task
const result = await task.executor(task.input);
results[task.name] = result;
// Emit task complete event
this.config.onTaskComplete?.(task.name, result);
// Check conditional tasks after each task execution
for (const conditional of this.conditionalTasks) {
if (conditional.condition(results)) {
const conditionalBuilder = new WorkflowBuilderImpl(this.config, this.input);
const builtConditional = conditional.builder(conditionalBuilder);
const conditionalResults = await builtConditional.run();
Object.assign(results, conditionalResults);
}
}
}
return results;
}
}
export function createWorkflow(config, builder) {
if (!config.name) {
throw new Error('name is required');
}
return {
name: config.name,
description: config.description,
run: async (input, options) => {
try {
// Notify workflow start
config.onWorkflowStart?.(config.name, input);
if (!builder) {
throw new Error('Builder function is required');
}
// Create workflow builder with input
const workflowBuilder = new WorkflowBuilderImpl(config, input);
// Execute builder function
const builderResult = await builder(workflowBuilder);
// Get output
const output = builderResult instanceof WorkflowBuilderImpl
? await builderResult.run()
: builderResult;
// Validate output if schema provided
if (options?.outputSchema) {
return options.outputSchema.parse(output);
}
// Notify workflow completion
config.onWorkflowComplete?.(config.name, output);
return output;
}
catch (error) {
// Create workflow error
const workflowError = error instanceof Error
? new Error(`Workflow '${config.name}' failed: ${error.message}`)
: new Error(`Workflow '${config.name}' failed: ${String(error)}`);
// Notify error
config.onError?.(workflowError);
// Special handling for validation errors
if (error instanceof z.ZodError) {
throw new Error('Validation error');
}
throw workflowError;
}
}
};
}
//# sourceMappingURL=workflow.js.map