{"version":3,"file":"stream.cjs","names":[],"sources":["../../src/utils/stream.ts"],"sourcesContent":["import { GenerationChunk } from \"@langchain/core/outputs\";\n\nexport interface AbstractStream {\n  /**\n   * Add more text to the buffer\n   * @param data\n   */\n  appendBuffer(data: string): void;\n\n  /**\n   * Indicate that there is no more text to be added to the buffer\n   * (ie - our source material is done)\n   */\n  closeBuffer(): void;\n  /**\n   * Get the next chunk that is coming from the stream.\n   * This chunk may be null, usually indicating the last chunk in the stream.\n   */\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  nextChunk(): Promise<any>;\n\n  /**\n   * Is the stream done?\n   * A stream is only done if all of the following are true:\n   * - There is no more data to be added to the text buffer\n   * - There is no more data in the text buffer\n   * - There are no chunks that are waiting to be consumed\n   */\n  get streamDone(): boolean;\n}\n\n/**\n * Parse an SSE event line into key-value pair.\n * Format: \"field: value\" or \"field:value\" (with optional whitespace after colon)\n *\n * Uses string operations instead of regex to avoid ReDoS vulnerabilities.\n * This is safer and more performant than regex-based parsing.\n */\nfunction parseEventLine(line: string): { key: string; value: string } | null {\n  const colonIndex = line.indexOf(\":\");\n  if (colonIndex === -1 || colonIndex === 0) {\n    return null;\n  }\n\n  const key = line.substring(0, colonIndex).trim();\n  if (key.length === 0) {\n    return null;\n  }\n\n  // Skip colon and any whitespace after it\n  let valueStart = colonIndex + 1;\n  while (\n    valueStart < line.length &&\n    (line[valueStart] === \" \" ||\n      line[valueStart] === \"\\t\" ||\n      line[valueStart] === \"\\r\" ||\n      line[valueStart] === \"\\n\")\n  ) {\n    valueStart++;\n  }\n\n  const value = line.substring(valueStart);\n  return { key, value };\n}\n\nexport function complexValue(value: unknown): unknown {\n  if (value === null || typeof value === \"undefined\") {\n    // I dunno what to put here. An error, probably\n    return undefined;\n  } else if (typeof value === \"object\") {\n    if (Array.isArray(value)) {\n      return {\n        list_val: value.map((avalue) => complexValue(avalue)),\n      };\n    } else {\n      const ret: Record<string, unknown> = {};\n      // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n      const v: Record<string, any> = value;\n      Object.keys(v).forEach((key) => {\n        ret[key] = complexValue(v[key]);\n      });\n      return { struct_val: ret };\n    }\n  } else if (typeof value === \"number\") {\n    if (Number.isInteger(value)) {\n      return { int_val: value };\n    } else {\n      return { float_val: value };\n    }\n  } else {\n    return {\n      string_val: [value],\n    };\n  }\n}\n\nexport function simpleValue(val: unknown): unknown {\n  if (val && typeof val === \"object\" && !Array.isArray(val)) {\n    // oxlint-disable-next-line no-prototype-builtins\n    if (val.hasOwnProperty(\"stringVal\")) {\n      return (val as { stringVal: string[] }).stringVal[0];\n\n      // oxlint-disable-next-line no-prototype-builtins\n    } else if (val.hasOwnProperty(\"boolVal\")) {\n      return (val as { boolVal: boolean[] }).boolVal[0];\n\n      // oxlint-disable-next-line no-prototype-builtins\n    } else if (val.hasOwnProperty(\"listVal\")) {\n      const { listVal } = val as { listVal: unknown[] };\n      return listVal.map((aval) => simpleValue(aval));\n\n      // oxlint-disable-next-line no-prototype-builtins\n    } else if (val.hasOwnProperty(\"structVal\")) {\n      const ret: Record<string, unknown> = {};\n      const struct = (val as { structVal: Record<string, unknown> }).structVal;\n      Object.keys(struct).forEach((key) => {\n        ret[key] = simpleValue(struct[key]);\n      });\n      return ret;\n    } else {\n      const ret: Record<string, unknown> = {};\n      const struct = val as Record<string, unknown>;\n      Object.keys(struct).forEach((key) => {\n        ret[key] = simpleValue(struct[key]);\n      });\n      return ret;\n    }\n  } else if (Array.isArray(val)) {\n    return val.map((aval) => simpleValue(aval));\n  } else {\n    return val;\n  }\n}\nexport class JsonStream implements AbstractStream {\n  _buffer = \"\";\n\n  _bufferOpen = true;\n\n  _firstRun = true;\n\n  /**\n   * Add data to the buffer. This may cause chunks to be generated, if available.\n   * @param data\n   */\n  appendBuffer(data: string): void {\n    this._buffer += data;\n    // Our first time, skip to the opening of the array\n    if (this._firstRun) {\n      this._skipTo(\"[\");\n      this._firstRun = false;\n    }\n\n    this._parseBuffer();\n  }\n\n  /**\n   * Indicate there is no more data that will be added to the text buffer.\n   * This should be called when all the data has been read and added to indicate\n   * that we should process everything remaining in the buffer.\n   */\n  closeBuffer(): void {\n    this._bufferOpen = false;\n    this._parseBuffer();\n  }\n\n  /**\n   * Skip characters in the buffer till we get to the start of an object.\n   * Then attempt to read a full object.\n   * If we do read a full object, turn it into a chunk and send it to the chunk handler.\n   * Repeat this for as much as we can.\n   */\n  _parseBuffer(): void {\n    let obj = null;\n    do {\n      this._skipTo(\"{\");\n      obj = this._getFullObject();\n      if (obj !== null) {\n        const chunk = this._simplifyObject(obj);\n        this._handleChunk(chunk);\n      }\n    } while (obj !== null);\n\n    if (!this._bufferOpen) {\n      // No more data will be added, and we have parsed everything we could,\n      // so everything else is garbage.\n      this._handleChunk(null);\n      this._buffer = \"\";\n    }\n  }\n\n  /**\n   * If the string is present, move the start of the buffer to the first occurrence\n   * of that string. This is useful for skipping over elements or parts that we're not\n   * really interested in parsing. (ie - the opening characters, comma separators, etc.)\n   * @param start The string to start the buffer with\n   */\n  _skipTo(start: string): void {\n    const index = this._buffer.indexOf(start);\n    if (index > 0) {\n      this._buffer = this._buffer.slice(index);\n    }\n  }\n\n  /**\n   * Given what is in the buffer, parse a single object out of it.\n   * If a complete object isn't available, return null.\n   * Assumes that we are at the start of an object to parse.\n   */\n  _getFullObject(): object | null {\n    let ret: object | null = null;\n\n    // Loop while we don't have something to return AND we have something in the buffer\n    let index = 0;\n    while (ret === null && this._buffer.length > index) {\n      // Advance to the next close bracket after our current index\n      index = this._buffer.indexOf(\"}\", index + 1);\n\n      // If we don't find one, exit with null\n      if (index === -1) {\n        return null;\n      }\n\n      // If we have one, try to turn it into an object to return\n      try {\n        const objStr = this._buffer.substring(0, index + 1);\n        ret = JSON.parse(objStr);\n\n        // We only get here if it parsed it ok\n        // If we did turn it into an object, remove it from the buffer\n        this._buffer = this._buffer.slice(index + 1);\n      } catch {\n        // It didn't parse it correctly, so we swallow the exception and continue\n      }\n    }\n\n    return ret;\n  }\n\n  _simplifyObject(obj: unknown): object {\n    return obj as object;\n  }\n\n  // Set up a potential Promise that the handler can resolve.\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  _chunkResolution: (chunk: any) => void;\n\n  // If there is no Promise (it is null), the handler must add it to the queue\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  _chunkPending: Promise<any> | null = null;\n\n  // A queue that will collect chunks while there is no Promise\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  _chunkQueue: any[] = [];\n\n  /**\n   * Register that we have another chunk available for consumption.\n   * If we are waiting for a chunk, resolve the promise waiting for it immediately.\n   * If not, then add it to the queue.\n   * @param chunk\n   */\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  _handleChunk(chunk: any): void {\n    if (this._chunkPending) {\n      this._chunkResolution(chunk);\n      this._chunkPending = null;\n    } else {\n      this._chunkQueue.push(chunk);\n    }\n  }\n\n  /**\n   * Get the next chunk that is coming from the stream.\n   * This chunk may be null, usually indicating the last chunk in the stream.\n   */\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  async nextChunk(): Promise<any> {\n    if (this._chunkQueue.length > 0) {\n      // If there is data in the queue, return the next queue chunk\n      return this._chunkQueue.shift() as GenerationChunk;\n    } else {\n      // Otherwise, set up a promise that handleChunk will cause to be resolved\n      this._chunkPending = new Promise((resolve) => {\n        this._chunkResolution = resolve;\n      });\n      return this._chunkPending;\n    }\n  }\n\n  /**\n   * Is the stream done?\n   * A stream is only done if all of the following are true:\n   * - There is no more data to be added to the text buffer\n   * - There is no more data in the text buffer\n   * - There are no chunks that are waiting to be consumed\n   */\n  get streamDone(): boolean {\n    return (\n      !this._bufferOpen &&\n      this._buffer.length === 0 &&\n      this._chunkQueue.length === 0 &&\n      this._chunkPending === null\n    );\n  }\n}\n\nexport class ComplexJsonStream extends JsonStream {\n  _simplifyObject(obj: unknown): object {\n    return simpleValue(obj) as object;\n  }\n}\n\nexport class ReadableAbstractStream implements AbstractStream {\n  private baseStream: AbstractStream;\n\n  decoder: TextDecoder;\n\n  constructor(baseStream: AbstractStream, body: ReadableStream | null) {\n    this.baseStream = baseStream;\n    this.decoder = new TextDecoder(\"utf-8\");\n    if (body) {\n      // oxlint-disable-next-line no-void\n      void this.run(body);\n    } else {\n      console.error(\"Unexpected empty body while streaming\");\n    }\n  }\n\n  appendBuffer(data: string): void {\n    return this.baseStream.appendBuffer(data);\n  }\n\n  closeBuffer(): void {\n    return this.baseStream.closeBuffer();\n  }\n\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  nextChunk(): Promise<any> {\n    return this.baseStream.nextChunk();\n  }\n\n  get streamDone(): boolean {\n    return this.baseStream.streamDone;\n  }\n\n  // Should be a ReadableStream, but the Gaxios Readable stream isn't.\n  // But both should support async iterators, so make sure of that.\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  async run(body: any) {\n    if (typeof body[Symbol.asyncIterator] === \"function\") {\n      for await (const value of body) {\n        const svalue = this.decoder.decode(value, { stream: true });\n        this.appendBuffer(svalue);\n      }\n      this.closeBuffer();\n    } else {\n      throw Error(\"Stream must implement async iterator.\");\n    }\n  }\n}\n\nexport class ReadableJsonStream extends ReadableAbstractStream {\n  constructor(body: ReadableStream | null) {\n    super(new JsonStream(), body);\n  }\n}\n\nexport class SseStream implements AbstractStream {\n  _buffer = \"\";\n\n  _bufferOpen = true;\n\n  appendBuffer(data: string): void {\n    this._buffer += data;\n    this._parseBuffer();\n  }\n\n  closeBuffer(): void {\n    this._bufferOpen = false;\n    this._parseBuffer();\n  }\n\n  /**\n   * Attempt to load an entire event.\n   * For each entire event we load,\n   * send them to be handled.\n   */\n  _parseBuffer(): void {\n    const events = this._buffer.split(/\\n\\n/);\n    this._buffer = events.pop() ?? \"\";\n    events.forEach((event) => this._handleEvent(event.trim()));\n\n    if (!this._bufferOpen) {\n      // No more data will be added, and we have parsed\n      // everything. So dump the rest.\n      this._handleEvent(null);\n      this._buffer = \"\";\n    }\n  }\n\n  /**\n   * Given an event string, get all the fields\n   * in the event. It is assumed there is one field\n   * per line, but that field names can be duplicated,\n   * indicating to append the new value to the previous value\n   * @param event\n   */\n  _parseEvent(event: string | null): Record<string, string> | null {\n    if (!event || event.trim() === \"\") {\n      return null;\n    }\n    const ret: Record<string, string> = {};\n    const lines = event.split(/\\n/);\n    lines.forEach((line) => {\n      const parsed = parseEventLine(line);\n      if (parsed) {\n        const { key, value } = parsed;\n        const cur = ret[key] ?? \"\";\n        ret[key] = `${cur}${value}`;\n      }\n    });\n\n    return ret;\n  }\n\n  // Set up a potential Promise that the handler can resolve.\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  _chunkResolution: (chunk: any) => void;\n\n  // If there is no Promise (it is null), the handler must add it to the queue\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  _chunkPending: Promise<any> | null = null;\n\n  // A queue that will collect chunks while there is no Promise\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  _chunkQueue: any[] = [];\n\n  _handleEvent(event: string | null): void {\n    const chunk = this._parseEvent(event);\n    if (this._chunkPending) {\n      this._chunkResolution(chunk);\n      this._chunkPending = null;\n    } else {\n      this._chunkQueue.push(chunk);\n    }\n  }\n\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  async nextChunk(): Promise<any> {\n    if (this._chunkQueue.length > 0) {\n      // If there is data in the queue, return the next queue chunk\n      return this._chunkQueue.shift() as Record<string, string>;\n    } else {\n      // Otherwise, set up a promise that handleChunk will cause to be resolved\n      this._chunkPending = new Promise((resolve) => {\n        this._chunkResolution = resolve;\n      });\n      return this._chunkPending;\n    }\n  }\n\n  get streamDone(): boolean {\n    return (\n      !this._bufferOpen &&\n      this._buffer.length === 0 &&\n      this._chunkQueue.length === 0 &&\n      this._chunkPending === null\n    );\n  }\n}\n\nexport class ReadableSseStream extends ReadableAbstractStream {\n  constructor(body: ReadableStream | null) {\n    super(new SseStream(), body);\n  }\n}\n\nexport class SseJsonStream extends SseStream {\n  _jsonAttribute: string = \"data\";\n\n  constructor(jsonAttribute?: string) {\n    super();\n    this._jsonAttribute = jsonAttribute ?? this._jsonAttribute;\n  }\n\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  async nextChunk(): Promise<any> {\n    const eventRecord = (await super.nextChunk()) as Record<string, string>;\n    const json = eventRecord?.[this._jsonAttribute];\n    if (!json) {\n      return null;\n    } else {\n      return JSON.parse(json);\n    }\n  }\n}\n\nexport class ReadableSseJsonStream extends ReadableAbstractStream {\n  constructor(body: ReadableStream | null) {\n    super(new SseJsonStream(), body);\n  }\n}\n"],"mappings":"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"}