UNPKG

@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

201 lines 7.63 kB
"use strict"; /** * @module TaskUpdater * @description Manages task state transitions with validation * * This module provides functionality for managing task state transitions * with validation to ensure that tasks follow the correct lifecycle. * It enforces a state machine approach to task status changes. */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TaskUpdater = void 0; const a2a_core_1 = require("@dexwox-labs/a2a-core"); /** * Error thrown when an invalid task state transition is attempted * * This error is thrown when a task state transition is attempted that * is not allowed by the state machine rules. * * @example * ```typescript * // This would throw if the transition is invalid * try { * await taskUpdater.transitionTask('task-123', 'completed'); * } catch (error) { * if (error instanceof InvalidTaskStateError) { * console.error('Invalid state transition:', error.message); * } * } * ``` */ class InvalidTaskStateError extends a2a_core_1.A2AError { /** * Creates a new InvalidTaskStateError * * @param message - Error message describing the invalid transition */ constructor(message) { super(message, -32002); // -32002 = Invalid state transition } } /** * Manages task state transitions with validation * * The TaskUpdater enforces a state machine approach to task status changes, * ensuring that tasks can only transition between valid states. It maintains * a history of transitions and provides methods for retrieving this history. * * @example * ```typescript * // Create a task updater with a task manager * const taskManager = new TaskManager(taskStore); * const taskUpdater = new TaskUpdater(taskManager); * * // Transition a task from 'submitted' to 'working' * try { * const updatedTask = await taskUpdater.transitionTask('task-123', 'working'); * console.log(`Task is now ${updatedTask.status}`); * } catch (error) { * console.error('Failed to transition task:', error.message); * } * ``` */ class TaskUpdater { /** * Creates a new TaskUpdater * * @param taskManager - The task manager to use for retrieving and updating tasks */ constructor(taskManager) { this.taskManager = taskManager; this.transitions = this.buildStateTransitionMap(); } /** * Builds the state transition map for the task state machine * * This defines the valid transitions between task states: * - submitted → working, failed * - working → completed, failed, canceled * - input_required → working, failed, canceled * - failed → (terminal state, no transitions) * - completed → (terminal state, no transitions) * - canceled → (terminal state, no transitions) * * @returns A map of valid state transitions * @internal */ buildStateTransitionMap() { const transitions = new Map(); // Define valid state transitions transitions.set('submitted', new Set(['working', 'failed'])); transitions.set('working', new Set(['completed', 'failed', 'canceled'])); transitions.set('input_required', new Set(['working', 'failed', 'canceled'])); transitions.set('failed', new Set([])); transitions.set('completed', new Set([])); transitions.set('canceled', new Set([])); return transitions; } /** * Transitions a task to a new state * * This method validates the state transition against the state machine rules, * creates a transition record, and updates the task with the new state and * transition history. * * @param taskId - ID of the task to transition * @param newState - New state to transition the task to * @returns Promise resolving to the updated task * @throws InvalidTaskStateError if the transition is not allowed * * @example * ```typescript * // Transition a task from 'submitted' to 'working' * try { * const task = await taskUpdater.transitionTask('task-123', 'working'); * console.log('Task transitioned successfully'); * } catch (error) { * if (error instanceof InvalidTaskStateError) { * console.error('Invalid state transition:', error.message); * } else { * console.error('Failed to transition task:', error); * } * } * ``` */ transitionTask(taskId, newState) { return __awaiter(this, void 0, void 0, function* () { const currentTask = yield this.taskManager.getTask(taskId); // Validate state transition if (!this.isValidTransition(currentTask.status, newState)) { throw new InvalidTaskStateError(`Invalid transition from ${currentTask.status} to ${newState}`); } // Create transition record const transition = { from: currentTask.status, to: newState, timestamp: new Date().toISOString() }; // Update task with new state and history return this.taskManager.updateTask(taskId, { status: newState, transitions: [...(currentTask.transitions || []), transition] }); }); } /** * Checks if a state transition is valid * * Validates whether a transition from one state to another is allowed * according to the state machine rules. * * @param from - Current state * @param to - Target state * @returns True if the transition is valid, false otherwise * @internal */ isValidTransition(from, to) { const allowedTransitions = this.transitions.get(from); return allowedTransitions ? allowedTransitions.has(to) : false; } /** * Gets the transition history for a task * * Retrieves the complete history of state transitions for a task, * including the from state, to state, and timestamp for each transition. * * @param taskId - ID of the task * @returns Promise resolving to an array of task transitions * * @example * ```typescript * // Get the transition history for a task * const history = await taskUpdater.getTransitionHistory('task-123'); * console.log(`Task has undergone ${history.length} transitions`); * * // Log each transition * history.forEach(transition => { * console.log( * `${new Date(transition.timestamp).toLocaleString()}: ` + * `${transition.from} → ${transition.to}` * ); * }); * ``` */ getTransitionHistory(taskId) { return __awaiter(this, void 0, void 0, function* () { const task = yield this.taskManager.getTask(taskId); return task.transitions || []; }); } } exports.TaskUpdater = TaskUpdater; //# sourceMappingURL=task-updater.js.map