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

235 lines 7.97 kB
"use strict"; /** * @module EventQueue * @description Event queue system for task events in the A2A protocol * * This module provides an event queue implementation for managing and distributing * task-related events in the A2A protocol server. It supports event publishing, * subscription, history tracking, and hierarchical event propagation. */ 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.EventQueue = void 0; const node_events_1 = require("node:events"); /** * Event queue for task-related events * * The EventQueue provides a publish-subscribe system for task-related events * in the A2A protocol server. It maintains a history of recent events, supports * hierarchical event propagation through child queues, and provides methods for * publishing and subscribing to events. * * @example * ```typescript * // Create an event queue * const eventQueue = new EventQueue(); * * // Subscribe to events * const unsubscribe = eventQueue.subscribe(event => { * console.log(`Event: ${event.type} for task ${event.task.id}`); * * if (event.type === 'taskCompleted') { * console.log('Task completed successfully!'); * } * }); * * // Publish an event * eventQueue.publish({ * type: 'taskCreated', * task: someTask, * timestamp: Date.now() * }); * * // Later, unsubscribe * unsubscribe(); * * // Create a child queue that receives all events from the parent * const childQueue = eventQueue.tap(); * ``` */ class EventQueue { constructor() { /** Event emitter for handling event subscriptions */ this.emitter = new node_events_1.EventEmitter(); /** History of recent events */ this.history = []; /** Maximum number of events to keep in history */ this.maxHistory = 1000; /** Child queues that receive events from this queue */ this.children = []; /** Whether this queue has been shut down */ this.isShutdown = false; } /** * Publishes an event to the queue * * This method adds an event to the queue's history, emits it to all subscribers, * and propagates it to any child queues. If the queue has been shut down, * an error is thrown. * * @param event - The event to publish * @throws Error if the queue has been shut down * * @example * ```typescript * eventQueue.publish({ * type: 'taskUpdated', * task: updatedTask, * timestamp: Date.now(), * previousState: 'submitted' * }); * ``` */ publish(event) { if (this.isShutdown) { throw new Error('EventQueue has been shutdown'); } // Add to history and enforce size limit this.history.push(event); if (this.history.length > this.maxHistory) { this.history.shift(); } this.emitter.emit('event', event); // Propagate to child queues this.children.forEach(child => child.publish(event)); } /** * Subscribes to events from the queue * * This method registers a callback to be called for each event in the queue. * It immediately calls the callback with all historical events, then registers * it for future events. It returns a function that can be called to unsubscribe. * * @param callback - Function to call for each event * @returns Function to call to unsubscribe * * @example * ```typescript * const unsubscribe = eventQueue.subscribe(event => { * if (event.type === 'taskCompleted') { * console.log(`Task ${event.task.id} completed`); * } * }); * * // Later, when no longer interested in events * unsubscribe(); * ``` */ subscribe(callback) { // Send historical events first this.history.forEach(event => callback(event)); // Subscribe to new events this.emitter.on('event', callback); return () => this.emitter.off('event', callback); } /** * Creates a child queue that receives all events from this queue * * This method creates a new EventQueue and registers it as a child of this queue. * All events published to this queue will also be published to the child queue. * This is useful for creating specialized event handlers or for filtering events. * * @returns A new EventQueue that receives all events from this queue * * @example * ```typescript * // Create a main event queue * const mainQueue = new EventQueue(); * * // Create a specialized queue for completed tasks * const completedTasksQueue = mainQueue.tap(); * completedTasksQueue.subscribe(event => { * if (event.type === 'taskCompleted') { * // Handle completed tasks * } * }); * ``` */ tap() { const child = new EventQueue(); this.children.push(child); return child; } /** * Shuts down the event queue * * This method marks the queue as shut down, closes all child queues, * and removes all event listeners. After calling this method, no more * events can be published to the queue. * * @example * ```typescript * // When done with the event queue * eventQueue.close(); * ``` */ close() { this.isShutdown = true; this.children.forEach(child => child.close()); this.emitter.removeAllListeners(); } /** * Gets a copy of the event history * * This method returns a copy of the queue's event history. The returned array * is a new instance, so modifications to it will not affect the queue's history. * * @returns A copy of the event history * * @example * ```typescript * const history = eventQueue.getHistory(); * console.log(`Queue has ${history.length} events in history`); * ``` */ getHistory() { return [...this.history]; } /** * Waits for and returns the next event from the queue * * This method returns a promise that resolves with the next event published * to the queue. If the queue is shut down, it resolves with undefined. * This is useful for implementing event-driven workflows. * * @returns Promise that resolves with the next event, or undefined if the queue is shut down * * @example * ```typescript * // Process events one at a time * async function processEvents() { * while (true) { * const event = await eventQueue.dequeue(); * if (!event) { * console.log('Queue has been shut down'); * break; * } * console.log(`Processing event: ${event.type}`); * } * } * ``` */ dequeue() { return __awaiter(this, void 0, void 0, function* () { if (this.isShutdown) { return undefined; } return new Promise(resolve => { const unsubscribe = this.subscribe(event => { unsubscribe(); resolve(event); }); }); }); } } exports.EventQueue = EventQueue; //# sourceMappingURL=event-queue.js.map