@dexwox-labs/a2a-server
Version:
TypeScript server implementation for Google's Agent-to-Agent (A2A) protocol - includes Express/WebSocket handlers, request validation and queue management
156 lines (141 loc) • 5.33 kB
text/typescript
/**
* @module AgentExecutor
* @description Interfaces and implementations for executing agent tasks
*
* This module provides the interfaces and implementations for executing tasks
* on behalf of agents in the A2A protocol. It handles task lifecycle management,
* status updates, and event publishing.
*/
import { EventQueue } from './event-queue';
import { RequestContext } from './request-context';
/**
* Interface for executing agent tasks
*
* This interface defines the contract for executing tasks on behalf of agents.
* Implementations are responsible for handling task execution, cancellation,
* and lifecycle management.
*
* @example
* ```typescript
* class CustomAgentExecutor implements AgentExecutor {
* async execute(context: RequestContext, eventQueue: EventQueue): Promise<void> {
* // Custom execution logic
* console.log(`Executing task ${context.task.id}`);
*
* // Publish events
* eventQueue.publish({
* type: 'task.updated',
* payload: { taskId: context.task.id, status: 'working' }
* });
* }
*
* async cancel(context: RequestContext, eventQueue: EventQueue): Promise<void> {
* // Custom cancellation logic
* console.log(`Canceling task ${context.task.id}`);
* }
* }
* ```
*/
export interface AgentExecutor {
/**
* Execute a task with the given context
* @param context Request context including task details
* @param eventQueue Event queue for publishing task events
*/
execute(context: RequestContext, eventQueue: EventQueue): Promise<void>;
/**
* Cancel an ongoing task execution
* @param context Request context including task details
* @param eventQueue Event queue for publishing cancellation events
*/
cancel(context: RequestContext, eventQueue: EventQueue): Promise<void>;
}
import { TaskManager } from '../tasks/task-manager';
import { TaskEventManager } from './task-event-manager';
import {
Task,
InvalidTaskStateError,
TaskNotFoundError,
TaskAlreadyCompletedError,
TaskCanceledError,
TaskFailedError
} from '@dexwox-labs/a2a-core';
/**
* Default implementation of the AgentExecutor interface
*
* This class provides a basic implementation of the AgentExecutor interface
* that manages task lifecycle, publishes events, and handles errors. It uses
* a TaskManager for task persistence and a TaskEventManager for event publishing.
*
* @example
* ```typescript
* // Create dependencies
* const taskStore = new InMemoryTaskStore();
* const taskManager = new TaskManager(taskStore);
* const taskEventManager = new TaskEventManager();
*
* // Create the executor
* const executor = new DefaultAgentExecutor(taskManager, taskEventManager);
*
* // Execute a task
* await executor.execute(
* createRequestContext(task, 'agent-123'),
* new EventQueue()
* );
* ```
*/
export class DefaultAgentExecutor implements AgentExecutor {
/**
* Creates a new DefaultAgentExecutor
*
* @param taskManager - The task manager for task persistence
* @param taskEventManager - The task event manager for event publishing
*/
constructor(
private taskManager: TaskManager,
private taskEventManager: TaskEventManager
) {}
/**
* Executes a task on behalf of an agent
*
* This method handles the execution of a task, including updating its status,
* publishing events, and handling errors. It transitions the task from its
* current state to 'working' and then to 'completed' if successful.
*
* @param context - The request context containing task and agent information
* @param eventQueue - The event queue for publishing events
* @returns Promise that resolves when execution is complete
* @throws Various task-related errors if execution fails
*/
async execute(context: RequestContext, eventQueue: EventQueue): Promise<void> {
const task = await this.taskManager.getTask(context.task.id);
// Update task status to working
const workingTask = await this.taskManager.updateTaskStatus(task.id, 'working');
// Publish task update event
this.taskEventManager.taskUpdated(workingTask, task.status);
try {
// TODO: Implement actual agent execution logic
// For now we'll simulate successful completion
await new Promise(resolve => setTimeout(resolve, 1000));
const completedTask = await this.taskManager.updateTaskStatus(task.id, 'completed');
this.taskEventManager.taskCompleted(completedTask);
} catch (error) {
const failedTask = await this.taskManager.updateTaskStatus(task.id, 'failed');
const normalizedError = error instanceof Error
? error
: new Error(error instanceof Object ? JSON.stringify(error) : String(error));
this.taskEventManager.taskFailed(failedTask, normalizedError);
throw normalizedError;
}
}
async cancel(context: RequestContext, eventQueue: EventQueue): Promise<void> {
const task = await this.taskManager.getTask(context.task.id);
if (['completed', 'failed', 'canceled'].includes(task.status)) {
throw new InvalidTaskStateError(
`Task ${task.id} is already in terminal state: ${task.status}`
);
}
await this.taskManager.cancelTask(task.id);
this.taskEventManager.taskCanceled(task);
}
}