- Added Claude Code integration with full context compaction support - Added OpenClaw integration with deterministic pipeline support - Implemented parallel agent execution (4 projects x 3 roles pattern) - Added workspace isolation with permissions and quotas - Implemented Lobster-compatible YAML workflow parser - Added persistent memory store for cross-session context - Created comprehensive README with hero section This project was 100% autonomously built by Z.AI GLM-5
233 lines
5.7 KiB
TypeScript
233 lines
5.7 KiB
TypeScript
/**
|
|
* Task Agent Module
|
|
*
|
|
* Specialized agent for executing structured tasks with
|
|
* planning, execution, and verification phases.
|
|
*/
|
|
|
|
import { BaseAgent, AgentConfig, AgentResponse, AgentTool } from './base-agent';
|
|
|
|
export interface TaskStep {
|
|
id: string;
|
|
description: string;
|
|
status: 'pending' | 'running' | 'completed' | 'failed';
|
|
result?: unknown;
|
|
error?: string;
|
|
}
|
|
|
|
export interface TaskPlan {
|
|
steps: TaskStep[];
|
|
estimatedComplexity: 'low' | 'medium' | 'high';
|
|
dependencies: Map<string, string[]>;
|
|
}
|
|
|
|
export interface TaskResult {
|
|
success: boolean;
|
|
steps: TaskStep[];
|
|
output: unknown;
|
|
errors: string[];
|
|
}
|
|
|
|
/**
|
|
* TaskAgent - Agent specialized for structured task execution
|
|
*/
|
|
export class TaskAgent extends BaseAgent {
|
|
private currentPlan: TaskPlan | null = null;
|
|
private taskHistory: TaskResult[] = [];
|
|
|
|
constructor(config: AgentConfig) {
|
|
super(config);
|
|
|
|
// Add default tools for task agents
|
|
this.addTool({
|
|
name: 'plan',
|
|
description: 'Create a plan for a complex task',
|
|
execute: async (params) => {
|
|
const task = params as { description: string };
|
|
return this.createPlan(task.description);
|
|
}
|
|
});
|
|
|
|
this.addTool({
|
|
name: 'execute_step',
|
|
description: 'Execute a single step of the plan',
|
|
execute: async (params) => {
|
|
const step = params as { stepId: string };
|
|
return this.executeStep(step.stepId);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Execute a task with planning
|
|
*/
|
|
async act(input: string, context?: string): Promise<AgentResponse> {
|
|
// First, create a plan
|
|
this.currentPlan = await this.createPlan(input);
|
|
|
|
// Execute the plan
|
|
const result = await this.executePlan();
|
|
|
|
this.taskHistory.push(result);
|
|
|
|
return {
|
|
content: result.success
|
|
? `Task completed successfully.\n${JSON.stringify(result.output, null, 2)}`
|
|
: `Task failed. Errors: ${result.errors.join(', ')}`,
|
|
tokens: { prompt: 0, completion: 0, total: 0 },
|
|
metadata: {
|
|
plan: this.currentPlan,
|
|
result
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Create a plan for a task
|
|
*/
|
|
private async createPlan(taskDescription: string): Promise<TaskPlan> {
|
|
const planningPrompt = `Break down the following task into steps. For each step, provide a brief description.
|
|
|
|
Task: ${taskDescription}
|
|
|
|
Respond in JSON format:
|
|
{
|
|
"steps": [
|
|
{ "id": "step1", "description": "First step description" },
|
|
{ "id": "step2", "description": "Second step description" }
|
|
],
|
|
"complexity": "low|medium|high",
|
|
"dependencies": {
|
|
"step2": ["step1"]
|
|
}
|
|
}`;
|
|
|
|
const response = await this.process(planningPrompt);
|
|
|
|
try {
|
|
// Extract JSON from response
|
|
const jsonMatch = response.content.match(/\{[\s\S]*\}/);
|
|
if (jsonMatch) {
|
|
const plan = JSON.parse(jsonMatch[0]);
|
|
return {
|
|
steps: plan.steps.map((s: TaskStep) => ({ ...s, status: 'pending' as const })),
|
|
estimatedComplexity: plan.complexity || 'medium',
|
|
dependencies: new Map(Object.entries(plan.dependencies || {}))
|
|
};
|
|
}
|
|
} catch {
|
|
// Fall back to simple plan
|
|
}
|
|
|
|
// Default simple plan
|
|
return {
|
|
steps: [{ id: 'step1', description: taskDescription, status: 'pending' }],
|
|
estimatedComplexity: 'low',
|
|
dependencies: new Map()
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Execute the current plan
|
|
*/
|
|
private async executePlan(): Promise<TaskResult> {
|
|
if (!this.currentPlan) {
|
|
return {
|
|
success: false,
|
|
steps: [],
|
|
output: null,
|
|
errors: ['No plan available']
|
|
};
|
|
}
|
|
|
|
const errors: string[] = [];
|
|
const completedSteps = new Set<string>();
|
|
|
|
// Execute steps in order, respecting dependencies
|
|
for (const step of this.currentPlan.steps) {
|
|
// Check dependencies
|
|
const deps = this.currentPlan.dependencies.get(step.id) || [];
|
|
const depsMet = deps.every(depId => completedSteps.has(depId));
|
|
|
|
if (!depsMet) {
|
|
step.status = 'failed';
|
|
step.error = 'Dependencies not met';
|
|
errors.push(`Step ${step.id}: Dependencies not met`);
|
|
continue;
|
|
}
|
|
|
|
// Execute step
|
|
step.status = 'running';
|
|
try {
|
|
const result = await this.executeStep(step.id);
|
|
step.status = 'completed';
|
|
step.result = result;
|
|
completedSteps.add(step.id);
|
|
} catch (error) {
|
|
step.status = 'failed';
|
|
step.error = String(error);
|
|
errors.push(`Step ${step.id}: ${error}`);
|
|
}
|
|
}
|
|
|
|
const success = errors.length === 0;
|
|
const finalStep = this.currentPlan.steps[this.currentPlan.steps.length - 1];
|
|
|
|
return {
|
|
success,
|
|
steps: this.currentPlan.steps,
|
|
output: finalStep.result,
|
|
errors
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Execute a single step
|
|
*/
|
|
private async executeStep(stepId: string): Promise<unknown> {
|
|
if (!this.currentPlan) throw new Error('No plan available');
|
|
|
|
const step = this.currentPlan.steps.find(s => s.id === stepId);
|
|
if (!step) throw new Error(`Step ${stepId} not found`);
|
|
|
|
const response = await this.process(
|
|
`Execute the following step and provide the result:\n\n${step.description}`
|
|
);
|
|
|
|
return response.content;
|
|
}
|
|
|
|
/**
|
|
* Get task history
|
|
*/
|
|
getTaskHistory(): TaskResult[] {
|
|
return [...this.taskHistory];
|
|
}
|
|
|
|
/**
|
|
* Get current plan
|
|
*/
|
|
getCurrentPlan(): TaskPlan | null {
|
|
return this.currentPlan;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a task agent
|
|
*/
|
|
export function createTaskAgent(
|
|
name: string,
|
|
systemPrompt: string,
|
|
options?: {
|
|
description?: string;
|
|
tools?: AgentTool[];
|
|
}
|
|
): TaskAgent {
|
|
return new TaskAgent({
|
|
name,
|
|
systemPrompt,
|
|
description: options?.description || `Task Agent: ${name}`,
|
|
tools: options?.tools
|
|
});
|
|
}
|