{"version":3,"sources":["../../src/generate/chunk.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { GenkitError } from '@genkit-ai/core';\nimport { extractJson } from '../extract.js';\nimport type {\n  GenerateResponseChunkData,\n  Part,\n  Role,\n  ToolRequestPart,\n} from '../model.js';\n\nexport type ChunkParser<T = unknown> = (chunk: GenerateResponseChunk<T>) => T;\n\nexport class GenerateResponseChunk<T = unknown>\n  implements GenerateResponseChunkData\n{\n  /** The index of the message this chunk corresponds to, starting with `0` for the first model response of the generation. */\n  index: number;\n  /** The role of the message this chunk corresponds to. Will always be `model` or `tool`. */\n  role: Role;\n  /** The content generated in this chunk. */\n  content: Part[];\n  /** Custom model-specific data for this chunk. */\n  custom?: unknown;\n  /** Accumulated chunks for partial output extraction. */\n  previousChunks?: GenerateResponseChunkData[];\n  /** The parser to be used to parse `output` from this chunk. */\n  parser?: ChunkParser<T>;\n\n  constructor(\n    data: GenerateResponseChunkData,\n    options: {\n      previousChunks?: GenerateResponseChunkData[];\n      role: Role;\n      index: number;\n      parser?: ChunkParser<T>;\n    }\n  ) {\n    this.content = data.content || [];\n    this.custom = data.custom;\n    this.previousChunks = options.previousChunks\n      ? [...options.previousChunks]\n      : undefined;\n    this.index = options.index;\n    this.role = options.role;\n    this.parser = options.parser;\n  }\n\n  /**\n   * Concatenates all `text` parts present in the chunk with no delimiter.\n   * @returns A string of all concatenated text parts.\n   */\n  get text(): string {\n    return this.content.map((part) => part.text || '').join('');\n  }\n\n  /**\n   * Concatenates all `reasoning` parts present in the chunk with no delimiter.\n   * @returns A string of all concatenated reasoning parts.\n   */\n  get reasoning(): string {\n    return this.content.map((part) => part.reasoning || '').join('');\n  }\n\n  /**\n   * Concatenates all `text` parts of all chunks from the response thus far.\n   * @returns A string of all concatenated chunk text content.\n   */\n  get accumulatedText(): string {\n    return this.previousText + this.text;\n  }\n\n  /**\n   * Concatenates all `text` parts of all preceding chunks.\n   */\n  get previousText(): string {\n    if (!this.previousChunks)\n      throw new GenkitError({\n        status: 'FAILED_PRECONDITION',\n        message: 'Cannot compose accumulated text without previous chunks.',\n      });\n\n    return this.previousChunks\n      ?.map((c) => c.content.map((p) => p.text || '').join(''))\n      .join('');\n  }\n\n  /**\n   * Returns the first media part detected in the chunk. Useful for extracting\n   * (for example) an image from a generation expected to create one.\n   * @returns The first detected `media` part in the chunk.\n   */\n  get media(): { url: string; contentType?: string } | null {\n    return this.content.find((part) => part.media)?.media || null;\n  }\n\n  /**\n   * Returns the first detected `data` part of a chunk.\n   * @returns The first `data` part detected in the chunk (if any).\n   */\n  get data(): T | null {\n    return this.content.find((part) => part.data)?.data as T | null;\n  }\n\n  /**\n   * Returns all tool request found in this chunk.\n   * @returns Array of all tool request found in this chunk.\n   */\n  get toolRequests(): ToolRequestPart[] {\n    return this.content.filter(\n      (part) => !!part.toolRequest\n    ) as ToolRequestPart[];\n  }\n\n  /**\n   * Parses the chunk into the desired output format using the parser associated\n   * with the generate request, or falls back to naive JSON parsing otherwise.\n   */\n  get output(): T | null {\n    if (this.parser) return this.parser(this);\n    return this.data || extractJson(this.accumulatedText);\n  }\n\n  toJSON(): GenerateResponseChunkData {\n    const data = {\n      role: this.role,\n      index: this.index,\n      content: this.content,\n    } as GenerateResponseChunkData;\n    if (this.custom) {\n      data.custom = this.custom;\n    }\n    return data;\n  }\n}\n"],"mappings":"AAgBA,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB;AAUrB,MAAM,sBAEb;AAAA;AAAA,EAEE;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA,EAEA,YACE,MACA,SAMA;AACA,SAAK,UAAU,KAAK,WAAW,CAAC;AAChC,SAAK,SAAS,KAAK;AACnB,SAAK,iBAAiB,QAAQ,iBAC1B,CAAC,GAAG,QAAQ,cAAc,IAC1B;AACJ,SAAK,QAAQ,QAAQ;AACrB,SAAK,OAAO,QAAQ;AACpB,SAAK,SAAS,QAAQ;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,OAAe;AACjB,WAAO,KAAK,QAAQ,IAAI,CAAC,SAAS,KAAK,QAAQ,EAAE,EAAE,KAAK,EAAE;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,YAAoB;AACtB,WAAO,KAAK,QAAQ,IAAI,CAAC,SAAS,KAAK,aAAa,EAAE,EAAE,KAAK,EAAE;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,kBAA0B;AAC5B,WAAO,KAAK,eAAe,KAAK;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,eAAuB;AACzB,QAAI,CAAC,KAAK;AACR,YAAM,IAAI,YAAY;AAAA,QACpB,QAAQ;AAAA,QACR,SAAS;AAAA,MACX,CAAC;AAEH,WAAO,KAAK,gBACR,IAAI,CAAC,MAAM,EAAE,QAAQ,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EACvD,KAAK,EAAE;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,QAAsD;AACxD,WAAO,KAAK,QAAQ,KAAK,CAAC,SAAS,KAAK,KAAK,GAAG,SAAS;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,OAAiB;AACnB,WAAO,KAAK,QAAQ,KAAK,CAAC,SAAS,KAAK,IAAI,GAAG;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,eAAkC;AACpC,WAAO,KAAK,QAAQ;AAAA,MAClB,CAAC,SAAS,CAAC,CAAC,KAAK;AAAA,IACnB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,SAAmB;AACrB,QAAI,KAAK,OAAQ,QAAO,KAAK,OAAO,IAAI;AACxC,WAAO,KAAK,QAAQ,YAAY,KAAK,eAAe;AAAA,EACtD;AAAA,EAEA,SAAoC;AAClC,UAAM,OAAO;AAAA,MACX,MAAM,KAAK;AAAA,MACX,OAAO,KAAK;AAAA,MACZ,SAAS,KAAK;AAAA,IAChB;AACA,QAAI,KAAK,QAAQ;AACf,WAAK,SAAS,KAAK;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AACF;","names":[]}