{"version":3,"file":"media.cjs","names":["#parts","#blobPromise","#transcriptPromise","#fetchImpl","#blobResolve","#blobReject","#transcriptResolve","#transcriptReject","#lastIndex","#urlSourced","#absorbAudio","#absorbImage","#absorbVideo","#absorbFile","#finished","#settled","#totalBytes","#partialSnapshot","#streamController","#transcriptParts","#fetchUrlSourced","#cachedObjectURL","#stream","#buildUrlStream","#buildInlineStream","#startUrlFetch","#urlFetchPromise","#callbacks","#fetch","#active","#activeByNamespaceNode","#flushSlot","#syntheticCounter","#consumeMediaBlock","#emit"],"sources":["../../../src/client/stream/media.ts"],"sourcesContent":["import type {\n  AudioContentBlock,\n  ContentBlock,\n  FileContentBlock,\n  ImageContentBlock,\n  MessagesEvent,\n  VideoContentBlock,\n} from \"@langchain/protocol\";\n\n/**\n * Block types this assembler knows how to reassemble into media handles.\n */\nexport type MediaBlockType = \"audio\" | \"image\" | \"video\" | \"file\";\n\nconst MEDIA_BLOCK_TYPES: ReadonlySet<string> = new Set<MediaBlockType>([\n  \"audio\",\n  \"image\",\n  \"video\",\n  \"file\",\n]);\n\n/**\n * Kinds of failure that can terminate a media handle prematurely.\n *\n * - `\"message-error\"` — the upstream message emitted an `error` event\n *   before completion.\n * - `\"stream-closed\"` — the transport stream closed before\n *   `message-finish` arrived (thread closed, transport dropped, etc.).\n * - `\"fetch-failed\"` — the block was `url`-sourced and the lazy\n *   `fetch()` rejected (CORS, 404, 5xx, network).\n */\nexport type MediaAssemblyErrorKind =\n  | \"message-error\"\n  | \"stream-closed\"\n  | \"fetch-failed\";\n\n/**\n * Typed error thrown through `media.stream` / rejected from\n * `media.blob` / `media.objectURL` when a handle fails before its\n * message completes. Carries the bytes accumulated up to the failure\n * point on `partialBytes` for callers that want to salvage or diagnose.\n */\nexport class MediaAssemblyError extends Error {\n  readonly kind: MediaAssemblyErrorKind;\n  readonly messageId: string;\n  readonly partialBytes: Uint8Array;\n  // oxlint-disable-next-line typescript/no-explicit-any\n  readonly cause?: unknown;\n\n  constructor(\n    kind: MediaAssemblyErrorKind,\n    messageId: string,\n    partialBytes: Uint8Array,\n    message?: string,\n    options?: { cause?: unknown }\n  ) {\n    super(message ?? `media ${kind} for message ${messageId}`);\n    this.name = \"MediaAssemblyError\";\n    this.kind = kind;\n    this.messageId = messageId;\n    this.partialBytes = partialBytes;\n    this.cause = options?.cause;\n  }\n}\n\n/**\n * Shared surface across every media handle returned by\n * {@link MediaAssembler}.\n *\n * The handle is live while its parent message is active:\n *  - `partialBytes` is a snapshot of all bytes received so far.\n *  - `stream` is a lazy, single-consumer byte stream (see\n *    accessor docstring).\n *  - `blob` / `objectURL` settle on `message-finish`.\n *  - `error` becomes set if the handle terminates in any of the\n *    {@link MediaAssemblyErrorKind} failure modes.\n */\nexport interface MediaBase {\n  readonly messageId: string;\n  readonly namespace: string[];\n  readonly node?: string;\n  /** `id` from the originating content block, if the provider sent one. */\n  readonly id?: string;\n  readonly mimeType?: string;\n  /**\n   * Present iff the originating block carried `url` (not `data`).\n   * When set, `blob` / `stream` / `objectURL` lazily fetch from here\n   * on first access.\n   */\n  readonly url?: string;\n\n  /**\n   * Live byte stream.\n   *\n   * Lazy: not materialised unless accessed. On first access the\n   * stream is seeded with every byte already accumulated\n   * (`partialBytes`) and then wired to future chunks. For URL-sourced\n   * blocks, first access triggers `fetch()` and pipes the response\n   * body through.\n   *\n   * Repeated access returns the same {@link ReadableStream} reference\n   * — you can safely read it once, release the lock, and re-acquire a\n   * reader later (e.g. React StrictMode effect re-invokes). The\n   * standard `ReadableStream.locked` semantics prevent concurrent\n   * readers; use `stream.tee()` when you truly need multiple live\n   * consumers.\n   */\n  readonly stream: ReadableStream<Uint8Array>;\n\n  /** Resolves on `message-finish` with the concatenated {@link Blob}. */\n  readonly blob: Promise<Blob>;\n\n  /**\n   * Lazy {@link URL.createObjectURL} over {@link blob}. Cached: first\n   * access creates the URL, subsequent accesses return the same one.\n   * Call {@link revoke} to free the URL slot; the next access creates\n   * a fresh URL. `ThreadStream.close()` auto-revokes as a safety net.\n   */\n  readonly objectURL: Promise<string>;\n\n  /** Live view of accumulated bytes. Settles with final bytes on finish. */\n  readonly partialBytes: Uint8Array;\n\n  /** Set iff the handle settled in an error state. */\n  readonly error?: MediaAssemblyError;\n\n  /** Diagnostic: `false` if block indices arrived out of order. */\n  readonly monotonic: boolean;\n\n  /**\n   * Revoke the currently-cached object URL (if any). Subsequent\n   * accesses to {@link objectURL} create a fresh URL from the Blob.\n   * Idempotent.\n   */\n  revoke(): void;\n}\n\nexport interface AudioMedia extends MediaBase {\n  readonly type: \"audio\";\n  /**\n   * Concatenated transcript across every audio block in this message.\n   * Resolves on `message-finish` with the joined string, or `undefined`\n   * when no block carried a transcript.\n   */\n  readonly transcript: Promise<string | undefined>;\n}\n\nexport interface ImageMedia extends MediaBase {\n  readonly type: \"image\";\n  /** Pixel width, if the provider sent it on the originating block. */\n  readonly width?: number;\n  /** Pixel height, if the provider sent it on the originating block. */\n  readonly height?: number;\n}\n\nexport interface VideoMedia extends MediaBase {\n  readonly type: \"video\";\n}\n\nexport interface FileMedia extends MediaBase {\n  readonly type: \"file\";\n  /** File name hint, if the provider sent it on the originating block. */\n  readonly filename?: string;\n}\n\nexport type AnyMediaHandle = AudioMedia | ImageMedia | VideoMedia | FileMedia;\n\nfunction base64ToBytes(b64: string): Uint8Array {\n  // atob is standard in all modern browsers and Node >= 16. Works on\n  // standard base64 only (no `-`/`_` URL-safe variants; the protocol\n  // uses standard base64).\n  const binary = atob(b64);\n  const bytes = new Uint8Array(binary.length);\n  for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n  return bytes;\n}\n\nfunction concatBytes(parts: Uint8Array[], totalLength: number): Uint8Array {\n  const out = new Uint8Array(totalLength);\n  let offset = 0;\n  for (const part of parts) {\n    out.set(part, offset);\n    offset += part.byteLength;\n  }\n  return out;\n}\n\n/**\n * Concrete handle implementation shared by all four media types.\n *\n * One instance per `(messageId, blockType)` pair created by the\n * assembler on first matching `content-block-start`.\n */\nclass MediaHandleImpl {\n  readonly type: MediaBlockType;\n  readonly messageId: string;\n  readonly namespace: string[];\n  readonly node: string | undefined;\n  readonly id: string | undefined;\n\n  mimeType: string | undefined;\n  url: string | undefined;\n  width?: number;\n  height?: number;\n  filename?: string;\n\n  monotonic = true;\n  error: MediaAssemblyError | undefined;\n\n  // Byte accumulation --------------------------------------------------\n\n  readonly #parts: Uint8Array[] = [];\n  #totalBytes = 0;\n  #partialSnapshot: Uint8Array = new Uint8Array(0);\n\n  // Stream (lazy, idempotent getter) ----------------------------------\n  //\n  // First access creates the `ReadableStream` and wires it to future\n  // chunks; subsequent accesses return the SAME reference. Consumers\n  // that want to fan-out must call `.tee()` explicitly — the native\n  // `ReadableStream.locked` flag prevents two concurrent readers.\n\n  #stream: ReadableStream<Uint8Array> | undefined;\n  #streamController: ReadableStreamDefaultController<Uint8Array> | undefined;\n\n  // Blob / URL settlement ---------------------------------------------\n\n  #blobResolve!: (value: Blob) => void;\n  #blobReject!: (reason: unknown) => void;\n  readonly #blobPromise: Promise<Blob>;\n\n  #transcriptParts: string[] = [];\n  #transcriptResolve!: (value: string | undefined) => void;\n  #transcriptReject!: (reason: unknown) => void;\n  readonly #transcriptPromise: Promise<string | undefined>;\n\n  #cachedObjectURL: string | undefined;\n\n  // URL-sourced mode ---------------------------------------------------\n\n  #urlSourced = false;\n  #urlFetchPromise: Promise<Uint8Array> | undefined;\n\n  // Index tracking -----------------------------------------------------\n\n  #lastIndex = -1;\n\n  // Lifecycle flags ----------------------------------------------------\n\n  #finished = false;\n  #settled = false;\n\n  // Injected dependencies ---------------------------------------------\n\n  readonly #fetchImpl: typeof fetch;\n\n  constructor(options: {\n    type: MediaBlockType;\n    messageId: string;\n    namespace: string[];\n    node: string | undefined;\n    id: string | undefined;\n    mimeType: string | undefined;\n    url: string | undefined;\n    fetch: typeof fetch;\n  }) {\n    this.type = options.type;\n    this.messageId = options.messageId;\n    this.namespace = options.namespace;\n    this.node = options.node;\n    this.id = options.id;\n    this.mimeType = options.mimeType;\n    this.url = options.url;\n    this.#fetchImpl = options.fetch;\n\n    this.#blobPromise = new Promise<Blob>((resolve, reject) => {\n      this.#blobResolve = resolve;\n      this.#blobReject = reject;\n    });\n    // Swallow rejections here so the async promise doesn't surface as\n    // an unhandled rejection when callers never touch `.blob`. Any\n    // consumer that does await it still observes the original reason.\n    this.#blobPromise.catch(() => undefined);\n\n    this.#transcriptPromise = new Promise<string | undefined>(\n      (resolve, reject) => {\n        this.#transcriptResolve = resolve;\n        this.#transcriptReject = reject;\n      }\n    );\n    this.#transcriptPromise.catch(() => undefined);\n  }\n\n  // ---------- Input side (driven by the assembler) ----------\n\n  /** Track a block index for the monotonic-ordering diagnostic. */\n  observeIndex(index: number): void {\n    if (index !== this.#lastIndex + 1 && index !== this.#lastIndex) {\n      this.monotonic = false;\n    }\n    if (index > this.#lastIndex) this.#lastIndex = index;\n  }\n\n  /** Absorb `mime_type` / per-type extras carried on an incoming block. */\n  absorbBlock(block: ContentBlock): void {\n    if (this.#urlSourced) return;\n    // `Extensible` widens `block.type` from a literal to `string` in\n    // the union, defeating TS's discriminated-union narrowing. Cast\n    // after the runtime tag check.\n    if (block.type === \"audio\") this.#absorbAudio(block as AudioContentBlock);\n    else if (block.type === \"image\")\n      this.#absorbImage(block as ImageContentBlock);\n    else if (block.type === \"video\")\n      this.#absorbVideo(block as VideoContentBlock);\n    else if (block.type === \"file\") this.#absorbFile(block as FileContentBlock);\n  }\n\n  /** Record that the originating block arrived with `url` not `data`. */\n  enterUrlMode(url: string): void {\n    this.#urlSourced = true;\n    this.url = url;\n  }\n\n  /** Push a fresh chunk of bytes into the handle. */\n  pushBytes(bytes: Uint8Array): void {\n    if (this.#finished || this.#settled) return;\n    if (bytes.byteLength === 0) return;\n    this.#parts.push(bytes);\n    this.#totalBytes += bytes.byteLength;\n    this.#partialSnapshot = concatBytes(this.#parts, this.#totalBytes);\n    if (this.#streamController != null) {\n      try {\n        this.#streamController.enqueue(bytes);\n      } catch {\n        // Reader detached; ignore — `partialBytes`/`blob` still work.\n      }\n    }\n  }\n\n  /** Append a transcript fragment from an audio block. */\n  pushTranscript(fragment: string): void {\n    if (this.type !== \"audio\") return;\n    if (this.#finished || this.#settled) return;\n    if (fragment.length === 0) return;\n    this.#transcriptParts.push(fragment);\n  }\n\n  /** Called on `message-finish`. Settles blob/transcript/stream. */\n  finish(): void {\n    if (this.#finished || this.#settled) return;\n    this.#finished = true;\n    this.#settled = true;\n    // Cast: the lib types reject `Uint8Array<ArrayBufferLike>` because\n    // `BlobPart` requires `Uint8Array<ArrayBuffer>` specifically. Our\n    // accumulator is allocated with `new Uint8Array(len)`, so it is\n    // backed by an `ArrayBuffer` (not `SharedArrayBuffer`).\n    const blob = new Blob([this.#partialSnapshot as unknown as BlobPart], {\n      type: this.mimeType ?? \"\",\n    });\n    this.#blobResolve(blob);\n    this.#transcriptResolve(\n      this.#transcriptParts.length === 0\n        ? undefined\n        : this.#transcriptParts.join(\"\")\n    );\n    try {\n      this.#streamController?.close();\n    } catch {\n      // Reader may have detached already.\n    }\n  }\n\n  /** Propagate an error through blob/transcript/stream. */\n  fail(\n    kind: MediaAssemblyErrorKind,\n    reason?: string,\n    cause?: unknown\n  ): MediaAssemblyError {\n    if (this.#settled) {\n      return (\n        this.error ??\n        new MediaAssemblyError(\n          kind,\n          this.messageId,\n          this.#partialSnapshot,\n          reason,\n          { cause }\n        )\n      );\n    }\n    this.#settled = true;\n    const err = new MediaAssemblyError(\n      kind,\n      this.messageId,\n      this.#partialSnapshot,\n      reason,\n      { cause }\n    );\n    this.error = err;\n    this.#blobReject(err);\n    this.#transcriptReject(err);\n    try {\n      this.#streamController?.error(err);\n    } catch {\n      // Reader may have detached already.\n    }\n    return err;\n  }\n\n  // ---------- Public surface read by consumers ----------\n\n  get partialBytes(): Uint8Array {\n    return this.#partialSnapshot;\n  }\n\n  get blob(): Promise<Blob> {\n    if (this.#urlSourced)\n      return this.#fetchUrlSourced().then(\n        (bytes) =>\n          new Blob([bytes as unknown as BlobPart], {\n            type: this.mimeType ?? \"\",\n          })\n      );\n    return this.#blobPromise;\n  }\n\n  get transcript(): Promise<string | undefined> {\n    return this.#transcriptPromise;\n  }\n\n  get objectURL(): Promise<string> {\n    if (this.#cachedObjectURL != null) {\n      const cached = this.#cachedObjectURL;\n      return Promise.resolve(cached);\n    }\n    return this.blob.then((blob) => {\n      // Race-safe: if revoke() fired before we got here, we cache the\n      // freshly-created URL for the next reader.\n      if (this.#cachedObjectURL != null) return this.#cachedObjectURL;\n      const url = URL.createObjectURL(blob);\n      this.#cachedObjectURL = url;\n      return url;\n    });\n  }\n\n  revoke(): void {\n    const url = this.#cachedObjectURL;\n    if (url == null) return;\n    this.#cachedObjectURL = undefined;\n    try {\n      URL.revokeObjectURL(url);\n    } catch {\n      // URL.revokeObjectURL is side-effect-only; very unlikely to throw\n      // but keep the handle usable if a polyfill misbehaves.\n    }\n  }\n\n  get stream(): ReadableStream<Uint8Array> {\n    if (this.#stream != null) return this.#stream;\n    if (this.#urlSourced) return this.#buildUrlStream();\n    return this.#buildInlineStream();\n  }\n\n  // ---------- Internals ----------\n\n  #absorbAudio(block: AudioContentBlock): void {\n    const mimeType =\n      block.mime_type ?? (block as { mimeType?: string }).mimeType;\n    if (this.mimeType == null && mimeType != null) this.mimeType = mimeType;\n    if (block.transcript != null && block.transcript.length > 0) {\n      this.pushTranscript(block.transcript);\n    }\n  }\n\n  #absorbImage(block: ImageContentBlock): void {\n    const mimeType =\n      block.mime_type ?? (block as { mimeType?: string }).mimeType;\n    if (this.mimeType == null && mimeType != null) this.mimeType = mimeType;\n    if (this.width == null && block.width != null) this.width = block.width;\n    if (this.height == null && block.height != null) this.height = block.height;\n  }\n\n  #absorbVideo(block: VideoContentBlock): void {\n    const mimeType =\n      block.mime_type ?? (block as { mimeType?: string }).mimeType;\n    if (this.mimeType == null && mimeType != null) this.mimeType = mimeType;\n  }\n\n  #absorbFile(block: FileContentBlock): void {\n    const mimeType =\n      block.mime_type ?? (block as { mimeType?: string }).mimeType;\n    if (this.mimeType == null && mimeType != null) this.mimeType = mimeType;\n    if (this.filename == null && block.filename != null)\n      this.filename = block.filename;\n  }\n\n  #buildInlineStream(): ReadableStream<Uint8Array> {\n    const seed = this.#partialSnapshot;\n    const alreadyFinished = this.#finished;\n    const alreadyErrored = this.error;\n\n    this.#stream = new ReadableStream<Uint8Array>({\n      start: (controller) => {\n        this.#streamController = controller;\n        if (seed.byteLength > 0) controller.enqueue(seed);\n        if (alreadyErrored != null) {\n          controller.error(alreadyErrored);\n          return;\n        }\n        if (alreadyFinished) {\n          controller.close();\n        }\n      },\n      cancel: () => {\n        this.#streamController = undefined;\n      },\n    });\n    return this.#stream;\n  }\n\n  #buildUrlStream(): ReadableStream<Uint8Array> {\n    // For URL-sourced blocks, we pipe the fetch response body directly\n    // through. `partialBytes` / `blob` share the same buffered bytes via\n    // #fetchUrlSourced().\n    const urlSourceFetch = this.#startUrlFetch();\n    this.#stream = new ReadableStream<Uint8Array>({\n      start: async (controller) => {\n        try {\n          const response = await urlSourceFetch;\n          if (response.body == null) {\n            const bytes = new Uint8Array(await response.arrayBuffer());\n            if (bytes.byteLength > 0) controller.enqueue(bytes);\n            controller.close();\n            return;\n          }\n          const reader = response.body.getReader();\n          // oxlint-disable-next-line no-constant-condition\n          while (true) {\n            const { done, value } = await reader.read();\n            if (done) break;\n            if (value != null) controller.enqueue(value);\n          }\n          controller.close();\n        } catch (err) {\n          controller.error(\n            this.fail(\"fetch-failed\", (err as Error)?.message, err)\n          );\n        }\n      },\n      cancel: () => {\n        this.#streamController = undefined;\n      },\n    });\n    return this.#stream;\n  }\n\n  /** Memoised fetch for URL-sourced blocks — returns one `Response`. */\n  #startUrlFetch(): Promise<Response> {\n    const url = this.url!;\n    return this.#fetchImpl(url).then((response) => {\n      if (!response.ok) {\n        throw new Error(\n          `fetch(${url}) failed: ${response.status} ${response.statusText}`\n        );\n      }\n      return response;\n    });\n  }\n\n  /** Fetch + buffer for URL-sourced `blob` access. Memoised. */\n  #fetchUrlSourced(): Promise<Uint8Array> {\n    if (this.#urlFetchPromise != null) return this.#urlFetchPromise;\n    this.#urlFetchPromise = (async () => {\n      try {\n        const response = await this.#startUrlFetch();\n        const bytes = new Uint8Array(await response.arrayBuffer());\n        this.#parts.length = 0;\n        this.#parts.push(bytes);\n        this.#totalBytes = bytes.byteLength;\n        this.#partialSnapshot = bytes;\n        this.#finished = true;\n        this.#settled = true;\n        return bytes;\n      } catch (err) {\n        throw this.fail(\"fetch-failed\", (err as Error)?.message, err);\n      }\n    })();\n    return this.#urlFetchPromise;\n  }\n}\n\n/**\n * Dispatch callbacks receive a freshly-started handle on its first\n * matching `content-block-start`. Exactly one callback fires per\n * `(messageId, blockType)` pair.\n */\nexport interface MediaAssemblerCallbacks {\n  onAudio?: (media: AudioMedia) => void;\n  onImage?: (media: ImageMedia) => void;\n  onVideo?: (media: VideoMedia) => void;\n  onFile?: (media: FileMedia) => void;\n  /**\n   * Invoked for every type; receives the same handle as the typed\n   * callback. Useful for writing one \"all media\" consumer without\n   * registering four type-specific callbacks.\n   */\n  onMedia?: (media: AnyMediaHandle) => void;\n}\n\nexport interface MediaAssemblerOptions extends MediaAssemblerCallbacks {\n  /**\n   * Injected `fetch` used for URL-sourced blocks. Defaults to the\n   * global `fetch`. Throws on first URL access if neither is present.\n   */\n  fetch?: typeof fetch;\n}\n\n/**\n * Incrementally folds `messages` events into typed media handles\n * (audio / image / video / file) that buffer bytes, expose a\n * {@link Blob}, and lazily mint an object URL for direct use in\n * `<audio>` / `<img>` / `<video>` tags.\n *\n * Semantics pinned during design:\n *  - One handle per `(messageId, blockType)` pair. Mixed-type messages\n *    surface on multiple iterables with the same `messageId`.\n *  - Handle yielded on the **first matching `content-block-start`** —\n *    messages with no matching blocks never yield an item (filters\n *    `lc_run--` LangChain terminator noise automatically).\n *  - Byte extraction: every `content-block-start` /\n *    `content-block-delta` with a `data` field decodes base64 and\n *    pushes into the accumulator. `content-block-finish` is a sync\n *    point.\n *  - URL-sourced blocks: if the initial block carries `url`, the\n *    handle enters URL mode — `blob`/`stream`/`objectURL` lazy-fetch\n *    on first access, subsequent data/url deltas are ignored.\n *  - Fail loud: `message-error`, stream closure before finish, and\n *    fetch failures all populate `handle.error`, reject `blob` /\n *    `transcript` / `objectURL`, and error the stream.\n *  - Diagnostic only: `handle.monotonic` flips false if block indices\n *    arrive out of order (protocol guarantees in-order within a\n *    subscription, so `false` indicates an upstream bug).\n */\n/**\n * Per-`(namespace, node)` bookkeeping for the active message the\n * assembler is currently folding.\n *\n * Protocol v2 only carries `id` on `message-start`; all\n * subsequent `content-block-*` / `message-finish` / `error` events\n * address the active message by position (same namespace + node). The\n * assembler therefore pins a message entry when `message-start`\n * arrives and resolves follow-ups by looking up `(namespace, node)`.\n */\ninterface ActiveMessage {\n  /** `id` from `message-start`, or empty string when synthesized. */\n  messageId: string;\n  /** `${messageId}::${mediaType}::${index}` keys currently active under this message. */\n  keys: Set<string>;\n  /** Content-block index → active media key. */\n  indexKeys: Map<number, string>;\n}\n\nexport class MediaAssembler {\n  readonly #callbacks: MediaAssemblerCallbacks;\n  readonly #fetch: typeof fetch;\n  // Keyed by `${messageId}::${type}::${blockIndex}`.\n  readonly #active = new Map<string, MediaHandleImpl>();\n  // Maps `${namespace.join(\"/\")}::${node ?? \"\"}` → active message. One\n  // entry per in-flight logical message; replaced on each\n  // `message-start`, removed on `message-finish` / `error`.\n  readonly #activeByNamespaceNode = new Map<string, ActiveMessage>();\n  // Monotonically increasing counter used to mint stable synthetic\n  // ids when a `content-block-*` arrives before any `message-start`\n  // (e.g. late-attaching subscribers that missed the message-start).\n  #syntheticCounter = 0;\n\n  constructor(options: MediaAssemblerOptions = {}) {\n    this.#callbacks = options;\n    if (options.fetch != null) {\n      this.#fetch = options.fetch;\n    } else if (typeof fetch === \"function\") {\n      this.#fetch = fetch;\n    } else {\n      // Throw lazily on URL access rather than construction, so\n      // inline-only flows in Node without a global fetch still work.\n      this.#fetch = () => {\n        throw new Error(\n          \"MediaAssembler: no fetch implementation available. Pass `fetch` in options.\"\n        );\n      };\n    }\n  }\n\n  /**\n   * Fold a single `messages` event. Non-media blocks and\n   * informational events (e.g. `content-block-finish`) are no-ops.\n   */\n  consume(event: MessagesEvent): void {\n    const data = event.params.data;\n    const namespace = event.params.namespace;\n    const node = event.params.node;\n    const nsNodeKey = `${namespace.join(\"/\")}::${node ?? \"\"}`;\n\n    if (data.event === \"message-start\") {\n      // A new `message-start` may arrive before a prior message on\n      // the same `(namespace, node)` emitted `message-finish` (the\n      // protocol permits trimmed replays on late subscribers). Flush\n      // any in-flight handles under that slot before rebinding.\n      this.#flushSlot(nsNodeKey, \"finish\");\n      this.#activeByNamespaceNode.set(nsNodeKey, {\n        messageId: data.id ?? \"\",\n        keys: new Set(),\n        indexKeys: new Map(),\n      });\n      return;\n    }\n\n    if (data.event === \"message-finish\") {\n      this.#flushSlot(nsNodeKey, \"finish\");\n      this.#activeByNamespaceNode.delete(nsNodeKey);\n      return;\n    }\n\n    if (data.event === \"error\") {\n      this.#flushSlot(\n        nsNodeKey,\n        \"error\",\n        (data as { message?: string }).message\n      );\n      this.#activeByNamespaceNode.delete(nsNodeKey);\n      return;\n    }\n\n    if (\n      data.event !== \"content-block-start\" &&\n      data.event !== \"content-block-delta\" &&\n      data.event !== \"content-block-finish\"\n    ) {\n      return;\n    }\n\n    const block = (data as { content?: ContentBlock; index?: number }).content;\n    const blockIndex = (data as { index?: number }).index ?? 0;\n\n    // Resolve the active message for this `(namespace, node)`. If the\n    // subscriber attached mid-message and missed `message-start`,\n    // synthesize one so downstream blocks still produce a handle.\n    let active = this.#activeByNamespaceNode.get(nsNodeKey);\n    if (active == null) {\n      active = {\n        messageId: `__synthetic_${++this.#syntheticCounter}`,\n        keys: new Set(),\n        indexKeys: new Map(),\n      };\n      this.#activeByNamespaceNode.set(nsNodeKey, active);\n    }\n\n    if (block == null && data.event === \"content-block-delta\") {\n      const delta = (data as { delta?: unknown }).delta;\n      const deltaKey = active.indexKeys.get(blockIndex);\n      const deltaHandle =\n        deltaKey != null ? this.#active.get(deltaKey) : undefined;\n      if (delta == null || typeof delta !== \"object\") {\n        return;\n      }\n\n      const record = delta as Record<string, unknown>;\n\n      if (deltaHandle == null) {\n        if (\n          record.type !== \"block-delta\" ||\n          record.fields == null ||\n          typeof record.fields !== \"object\"\n        ) {\n          return;\n        }\n\n        const fields = record.fields as ContentBlock;\n        if (!MEDIA_BLOCK_TYPES.has(fields.type)) {\n          return;\n        }\n\n        this.#consumeMediaBlock({\n          active,\n          block: fields,\n          blockIndex,\n          dataEvent: data.event,\n          namespace,\n          node,\n          terminal: false,\n          createIfMissing: true,\n        });\n        return;\n      }\n\n      deltaHandle.observeIndex(blockIndex);\n      if (record.type === \"data-delta\" && typeof record.data === \"string\") {\n        try {\n          deltaHandle.pushBytes(base64ToBytes(record.data));\n        } catch (err) {\n          deltaHandle.fail(\"message-error\", \"invalid base64 on delta\", err);\n        }\n        return;\n      }\n\n      if (\n        record.type === \"block-delta\" &&\n        record.fields != null &&\n        typeof record.fields === \"object\"\n      ) {\n        const fields = record.fields as\n          | AudioContentBlock\n          | ImageContentBlock\n          | VideoContentBlock\n          | FileContentBlock;\n        deltaHandle.absorbBlock(fields);\n        if (!deltaHandle.error && fields.data != null) {\n          try {\n            deltaHandle.pushBytes(base64ToBytes(fields.data));\n          } catch (err) {\n            deltaHandle.fail(\"message-error\", \"invalid base64 on delta\", err);\n          }\n        }\n      }\n      return;\n    }\n\n    if (block == null) return;\n    const blockType = block.type;\n    if (!MEDIA_BLOCK_TYPES.has(blockType)) return;\n\n    this.#consumeMediaBlock({\n      active,\n      block: block as ContentBlock,\n      blockIndex,\n      dataEvent: data.event,\n      namespace,\n      node,\n      terminal: data.event === \"content-block-finish\",\n      createIfMissing:\n        data.event === \"content-block-start\" ||\n        data.event === \"content-block-finish\",\n    });\n  }\n\n  #consumeMediaBlock({\n    active,\n    block,\n    blockIndex,\n    dataEvent,\n    namespace,\n    node,\n    terminal,\n    createIfMissing,\n  }: {\n    active: ActiveMessage;\n    block: ContentBlock;\n    blockIndex: number;\n    dataEvent: string;\n    namespace: string[];\n    node: string | undefined;\n    terminal: boolean;\n    createIfMissing: boolean;\n  }): void {\n    const blockType = block.type;\n    if (!MEDIA_BLOCK_TYPES.has(blockType)) return;\n\n    const mediaType = blockType as MediaBlockType;\n    const key = `${active.messageId}::${mediaType}::${blockIndex}`;\n    let handle = this.#active.get(key);\n    const isStart = dataEvent === \"content-block-start\";\n\n    if (handle == null) {\n      const isTerminalBlock = terminal;\n      if (!isStart && !isTerminalBlock && !createIfMissing) {\n        return;\n      }\n      const mediaBlock = block as\n        | AudioContentBlock\n        | ImageContentBlock\n        | VideoContentBlock\n        | FileContentBlock;\n      handle = new MediaHandleImpl({\n        type: mediaType,\n        messageId: active.messageId,\n        namespace: [...namespace],\n        node,\n        id: (mediaBlock as { id?: string }).id,\n        mimeType:\n          mediaBlock.mime_type ??\n          (mediaBlock as { mimeType?: string }).mimeType,\n        url:\n          mediaBlock.url != null && mediaBlock.data == null\n            ? mediaBlock.url\n            : undefined,\n        fetch: this.#fetch,\n      });\n      if (mediaBlock.url != null && mediaBlock.data == null) {\n        handle.enterUrlMode(mediaBlock.url);\n      }\n      handle.observeIndex(blockIndex);\n      handle.absorbBlock(block);\n      if (mediaBlock.data != null) {\n        try {\n          handle.pushBytes(base64ToBytes(mediaBlock.data));\n        } catch (err) {\n          handle.fail(\"message-error\", \"invalid base64 on initial block\", err);\n        }\n      }\n      this.#active.set(key, handle);\n      active.keys.add(key);\n      active.indexKeys.set(blockIndex, key);\n      this.#emit(handle);\n      if (isTerminalBlock) {\n        handle.finish();\n        this.#active.delete(key);\n        active.keys.delete(key);\n        active.indexKeys.delete(blockIndex);\n      }\n      return;\n    }\n\n    // Subsequent event on an existing handle.\n    // - `content-block-finish` is a sync point: skip to avoid\n    //   double-counting bytes when the server echoes the full block\n    //   on both start and finish (typical for atomic, non-delta\n    //   blocks such as whole audio frames or single-shot images).\n    // A late subscriber may miss `content-block-start`; in that case a\n    // terminal block with full content is handled above by creating and\n    // immediately settling a one-block handle.\n    if (terminal) return;\n\n    const mediaBlock = block as\n      | AudioContentBlock\n      | ImageContentBlock\n      | VideoContentBlock\n      | FileContentBlock;\n    handle.observeIndex(blockIndex);\n    handle.absorbBlock(block);\n    if (!handle.error && mediaBlock.data != null) {\n      try {\n        handle.pushBytes(base64ToBytes(mediaBlock.data));\n      } catch (err) {\n        handle.fail(\"message-error\", \"invalid base64 on delta\", err);\n      }\n    }\n  }\n\n  /**\n   * Finish or fail every media handle currently active under the\n   * given `(namespace, node)` slot and clear its bookkeeping. Called\n   * on `message-finish`, `error`, and when a new `message-start`\n   * rebinds a still-open slot.\n   */\n  #flushSlot(\n    nsNodeKey: string,\n    mode: \"finish\" | \"error\",\n    errorMessage?: string\n  ): void {\n    const active = this.#activeByNamespaceNode.get(nsNodeKey);\n    if (active == null) return;\n    for (const key of active.keys) {\n      const handle = this.#active.get(key);\n      if (handle != null) {\n        if (mode === \"finish\") handle.finish();\n        else handle.fail(\"message-error\", errorMessage);\n      }\n      this.#active.delete(key);\n    }\n    active.keys.clear();\n    active.indexKeys.clear();\n  }\n\n  /**\n   * Abort all outstanding handles with a `stream-closed` error.\n   * Called when the upstream event source terminates before the\n   * messages it was assembling had a chance to finish.\n   */\n  close(): void {\n    for (const handle of this.#active.values()) {\n      handle.fail(\"stream-closed\", \"upstream event stream closed\");\n    }\n    this.#active.clear();\n    this.#activeByNamespaceNode.clear();\n  }\n\n  #emit(handle: MediaHandleImpl): void {\n    switch (handle.type) {\n      case \"audio\":\n        this.#callbacks.onAudio?.(handle as unknown as AudioMedia);\n        break;\n      case \"image\":\n        this.#callbacks.onImage?.(handle as unknown as ImageMedia);\n        break;\n      case \"video\":\n        this.#callbacks.onVideo?.(handle as unknown as VideoMedia);\n        break;\n      case \"file\":\n        this.#callbacks.onFile?.(handle as unknown as FileMedia);\n        break;\n    }\n    this.#callbacks.onMedia?.(handle as unknown as AnyMediaHandle);\n  }\n}\n"],"mappings":"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"}