UNPKG

@artinet/sdk

Version:
111 lines 3.87 kB
import { processUpdate } from "../../server/lib/state.js"; import { FAILED_UPDATE, INTERNAL_ERROR } from "../../utils/common/errors.js"; import { logError } from "../../utils/logging/log.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 */ export 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, taskId, 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 */ export function sendSSEEvent(res, id, update) { if (!res.writable) { return; } const response = { jsonrpc: "2.0", id: 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 */ export 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 */ export async function processTaskStream(context, taskStore, engine, res, taskId, initialData, onCancel, onEnd, executionContext) { let currentData = initialData; const generator = engine(executionContext); try { for await (const yieldValue of generator) { if (context.isCancelled()) { await onCancel(context, currentData, res); return; } currentData = await processUpdate(taskStore, { context: context, current: currentData, update: yieldValue, }); context.task = currentData.task; sendSSEEvent(res, taskId, yieldValue); } } catch (error) { try { const failedUpdate = FAILED_UPDATE(taskId, context.contextId, "failed-update", error instanceof Error ? error.message : String(error)); currentData = await processUpdate(taskStore, { context: context, current: currentData, update: failedUpdate, }); sendSSEEvent(res, taskId, failedUpdate); } catch (saveError) { logError("A2AServer", "Failed to save error state for streaming task", saveError, { taskId, originalError: error }); } sendSSEError(res, 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