import type { StatusPartStatus, StreamOperation, StreamWireEvent, StructuredStreamEvent, } from "../../types"; import { chatUnavailableMessage } from "../../constants"; import type { StreamProtocolAdapter } from "../protocol"; export function isStructuredEvent( event: StreamWireEvent, ): event is StructuredStreamEvent { switch (event.type) { case "start": case "finish": case "step-start": case "step-end": case "text-start": case "text-delta": case "text-end": case "data-status": case "data-products": case "source-url": case "source-document": return true; case "error": return "message" in event; default: return false; } } function normalizeStepEndStatus( raw: string | undefined, ): "completed" | "error" { if (raw === "completed" || raw === "error") return raw; return "completed"; } function normalizeStatusPartStatus(raw: string | undefined): StatusPartStatus { if (raw === "running" || raw === "completed" || raw === "error") return raw; return "running"; } export class StructuredStreamAdapter implements StreamProtocolAdapter { canHandle(event: StreamWireEvent): boolean { return isStructuredEvent(event); } adapt(raw: StreamWireEvent): StreamOperation[] { const event = raw as StructuredStreamEvent; switch (event.type) { case "start": return [{ type: "messageStart", id: event.id }]; case "finish": return [{ type: "messageFinish", id: event.id }]; case "error": return [{ type: "messageError", message: chatUnavailableMessage }]; case "step-start": return [{ type: "stepStart", id: event.id, label: event.label }]; case "step-end": return [ { type: "stepEnd", id: event.id, status: normalizeStepEndStatus(event.status), message: event.message, }, ]; case "text-start": return [{ type: "textStart", id: event.id }]; case "text-delta": return [{ type: "textDelta", id: event.id, delta: event.delta }]; case "text-end": return [{ type: "textEnd", id: event.id }]; case "data-status": return [ { type: "statusUpsert", id: event.id, message: event.message, status: normalizeStatusPartStatus(event.status), }, ]; case "data-products": return [ { type: "productsUpsert", id: event.id, products: event.products, }, ]; case "source-url": return [ { type: "sourceUpsert", sourceType: "source-url" as const, id: event.id, title: event.title, url: event.url, }, ]; case "source-document": return [ { type: "sourceUpsert", sourceType: "source-document" as const, id: event.id, title: event.title, excerpt: event.excerpt, url: event.url, }, ]; default: return []; } } finish(): StreamOperation[] { return []; } }