UNPKG

@kddd/artinet-sdk

Version:

TypeScript SDK for the Agent2Agent (A2A) Protocol

134 lines 5.06 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.setupSseStream = setupSseStream; exports.sendSSEEvent = sendSSEEvent; exports.sendSSEError = sendSSEError; exports.processTaskStream = processTaskStream; const state_js_1 = require("../../server/lib/state.js"); const errors_js_1 = require("../../utils/common/errors.js"); const utils_js_1 = require("../../utils/common/utils.js"); const log_js_1 = require("../../utils/logging/log.js"); const constants_js_1 = require("../../utils/common/constants.js"); /** * Sets up a Server-Sent Events stream with appropriate headers * and initializes tracking for the stream. * * @param res The Express Response object * @param taskId The task ID to associate with this stream * @param reqId The request ID for acknowledgment * @param initialStatus Optional initial status to send * @param addStreamMethod Function to add stream to tracking * @param sendSseMethod Function to send SSE events */ function setupSseStream(res, taskId, initialStatus, addStreamMethod) { // Set up SSE stream headers res.setHeader("Content-Type", "text/event-stream"); res.setHeader("Cache-Control", "no-cache"); res.setHeader("Connection", "keep-alive"); // Track this stream for potential cancellation if tracking method provided if (addStreamMethod) { addStreamMethod(taskId, res); } // Send initial status if provided if (initialStatus) { sendSSEEvent(res, initialStatus); } } /** * Sends a Server-Sent Event with task data. * @param res The Express Response object * @param reqId The request ID * @param eventData The event data to send */ function sendSSEEvent(res, update) { if (!res.writable) { return; } const response = { jsonrpc: "2.0", id: update.id, result: update, }; res.write(`data: ${JSON.stringify(response)}\n\n`); } /** * Sends a Server-Sent Event with error data. * @param res The Express Response object * @param reqId The request ID * @param error The error to send */ function sendSSEError(res, error) { if (!res.writable) { return; } const response = { jsonrpc: "2.0", error: error, }; res.write(`data: ${JSON.stringify(response)}\n\n`); } /** * Processes a task stream, handling generator yields and sending SSE events. * @param req The request object * @param res The response object * @param taskId The task ID * @param context The task context * @param initialData The initial task data */ async function processTaskStream(taskStore, taskHandler, res, taskId, context, initialData, onCancel, onEnd) { let currentData = initialData; const generator = taskHandler(context); try { for await (const yieldValue of generator) { if (context.isCancelled()) { await onCancel(currentData, res); return; } currentData = await (0, state_js_1.updateState)(taskStore, currentData, yieldValue); context.task = currentData.task; if ((0, utils_js_1.isTaskStatusUpdate)(yieldValue)) { sendSSEEvent(res, { id: taskId, status: currentData.task.status, final: constants_js_1.FINAL_STATES.includes(currentData.task.status.state), }); } else if ((0, utils_js_1.isArtifactUpdate)(yieldValue)) { const artifactIndex = currentData.task.artifacts?.findIndex((a) => a.name && a.name === yieldValue.name) ?? yieldValue.index ?? -1; if (artifactIndex >= 0 && currentData.task.artifacts && artifactIndex < currentData.task.artifacts.length) { sendSSEEvent(res, { id: taskId, artifact: currentData.task.artifacts[artifactIndex], final: constants_js_1.FINAL_STATES.includes(currentData.task.status.state), }); } } } } catch (error) { try { const failedUpdate = (0, errors_js_1.FAILED_UPDATE)(error instanceof Error ? error.message : String(error)); currentData = await (0, state_js_1.updateState)(taskStore, currentData, failedUpdate); sendSSEEvent(res, { id: taskId, status: currentData.task.status, }); } catch (saveError) { (0, log_js_1.logError)("A2AServer", "Failed to save error state for streaming task", saveError, { taskId, originalError: error }); } sendSSEError(res, (0, errors_js_1.INTERNAL_ERROR)(`Task execution error: ${error instanceof Error ? error.message : String(error)}`)); } finally { onEnd(taskId, res); if (!res.writableEnded) { res.write("event: close\ndata: {}\n\n"); res.end(); } } } //# sourceMappingURL=stream.js.map