@dexwox-labs/a2a-core
Version:
Core types, validation and telemetry for Google's Agent-to-Agent (A2A) protocol - shared foundation for client and server implementations
177 lines • 5.88 kB
JavaScript
;
/**
* @module TaskUtils
* @description Utilities for working with tasks in the A2A protocol
*
* This module provides utility functions for validating and managing tasks
* in the A2A protocol. Tasks are the primary unit of work in the protocol and
* follow a specific state machine with defined transitions.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.TaskErrorCode = void 0;
exports.validateTransition = validateTransition;
exports.validateTask = validateTask;
exports.createTransition = createTransition;
const errors_1 = require("../errors");
/**
* Error codes specific to task operations
*
* These error codes are used to identify specific issues that can occur
* when working with tasks, such as invalid state transitions or missing
* required properties.
*/
var TaskErrorCode;
(function (TaskErrorCode) {
/** Error code when a task state transition is invalid (-32070) */
TaskErrorCode[TaskErrorCode["InvalidTransition"] = -32070] = "InvalidTransition";
/** Error code when a task is missing a required ID (-32071) */
TaskErrorCode[TaskErrorCode["MissingTaskId"] = -32071] = "MissingTaskId";
/** Error code when a task state is invalid (-32072) */
TaskErrorCode[TaskErrorCode["InvalidState"] = -32072] = "InvalidState";
})(TaskErrorCode || (exports.TaskErrorCode = TaskErrorCode = {}));
/**
* Map of valid task state transitions
*
* This constant defines the valid state transitions for tasks in the A2A protocol.
* Each key represents a current state, and the array value contains all valid
* next states. Empty arrays indicate terminal states with no valid transitions.
*
* The state machine follows these rules:
* - submitted → working, failed, canceled
* - working → input_required, completed, failed, canceled
* - input_required → working, failed, canceled
* - completed → (terminal state, no transitions)
* - failed → (terminal state, no transitions)
* - canceled → (terminal state, no transitions)
*
* @internal
*/
const VALID_TRANSITIONS = {
submitted: ['working', 'failed', 'canceled'],
working: ['input_required', 'completed', 'failed', 'canceled'],
input_required: ['working', 'failed', 'canceled'],
completed: [],
failed: [],
canceled: []
};
/**
* Validates that a task state transition is allowed
*
* This function checks if a proposed state transition follows the rules of the
* task state machine. It throws an error if the transition is not allowed.
*
* @param current - Current task state
* @param next - Proposed next state
* @throws {A2AError} If the transition is invalid
*
* @example
* ```typescript
* try {
* // Valid transition
* validateTransition('submitted', 'working');
* console.log('Transition is valid');
*
* // Invalid transition
* validateTransition('completed', 'working');
* } catch (error) {
* console.error('Invalid transition:', error.message);
* // Output: Invalid transition: Invalid transition from completed to working
* }
* ```
*/
function validateTransition(current, next) {
if (!VALID_TRANSITIONS[current].includes(next)) {
throw new errors_1.A2AError(`Invalid transition from ${current} to ${next}`, TaskErrorCode.InvalidTransition);
}
}
/**
* Validates that a task has all required properties and a valid state
*
* This function checks that a task has a valid ID and state. It throws
* appropriate errors if validation fails, which can be caught and handled
* by the caller.
*
* @param task - Task object to validate
* @throws {A2AError} If validation fails, with specific error codes
*
* @example
* ```typescript
* try {
* // Valid task
* validateTask({
* id: 'task-123',
* name: 'Example Task',
* status: 'working',
* createdAt: new Date().toISOString(),
* updatedAt: new Date().toISOString()
* });
* console.log('Task is valid');
*
* // This would throw an error
* validateTask({
* name: 'Invalid Task', // Missing ID
* status: 'working',
* createdAt: new Date().toISOString(),
* updatedAt: new Date().toISOString()
* });
* } catch (error) {
* console.error('Validation failed:', error.message);
* }
* ```
*/
function validateTask(task) {
if (!task.id) {
throw new errors_1.A2AError('Task missing required id', TaskErrorCode.MissingTaskId);
}
if (!Object.keys(VALID_TRANSITIONS).includes(task.status)) {
throw new errors_1.A2AError(`Invalid task state: ${task.status}`, TaskErrorCode.InvalidState);
}
}
/**
* Creates a new task transition record
*
* This function creates a transition record that documents a change in task state.
* Transition records include the starting state, ending state, timestamp, and an
* optional reason for the transition.
*
* @param from - Starting task state
* @param to - Ending task state
* @param reason - Optional reason for the transition
* @returns A new transition object with timestamp
*
* @example
* ```typescript
* // Create a transition record when a task is completed
* const transition = createTransition('working', 'completed');
* console.log(transition);
* // Output: {
* // from: 'working',
* // to: 'completed',
* // timestamp: '2023-05-26T12:34:56.789Z'
* // }
*
* // Create a transition record with a reason
* const failedTransition = createTransition(
* 'working',
* 'failed',
* 'API request timeout'
* );
* console.log(failedTransition);
* // Output: {
* // from: 'working',
* // to: 'failed',
* // timestamp: '2023-05-26T12:35:12.345Z',
* // reason: 'API request timeout'
* // }
* ```
*/
function createTransition(from, to, reason) {
validateTransition(from, to);
return {
from,
to,
timestamp: new Date().toISOString(),
reason
};
}
//# sourceMappingURL=task.js.map