{"version":3,"sources":["../../src/common/utils.ts"],"sourcesContent":["/**\n * Copyright 2025 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 {\n  EmbedderReference,\n  GenkitError,\n  Part as GenkitPart,\n  JSONSchema,\n  MediaPart,\n  ModelReference,\n  StatusName,\n  StatusNameSchema,\n  getClientHeader as defaultGetClientHeader,\n  z,\n} from 'genkit';\nimport { logger } from 'genkit/logging';\nimport { GenerateRequest } from 'genkit/model';\nimport { applyGeminiPartialArgs } from './converters.mjs';\nimport {\n  GeminiInteraction,\n  InteractionSseEvent,\n  InteractionStreamResult,\n  TextContent,\n} from './interaction-types.mjs';\nimport {\n  GenerateContentCandidate,\n  GenerateContentResponse,\n  GenerateContentStreamResult,\n  PART_KEYS,\n  Part,\n  isObject,\n} from './types.mjs';\n\n/**\n * `Api-Revision` header value for Interactions API requests. It selects the\n * steps-based schema (`steps` in responses, step list input) that the\n * Interactions converters read and write; without it the server uses the\n * older `outputs` / turn list schema.\n */\nexport const INTERACTIONS_API_REVISION = '2026-05-20';\n\nexport function buildTraceMetadataInput(\n  url: string,\n  fetchOptions: RequestInit,\n  traceOptions: {\n    request?: unknown;\n    model?: string;\n    clientOptions?: { timeout?: number };\n  }\n): Record<string, unknown> {\n  const safeHeaders = { ...(fetchOptions.headers as Record<string, string>) };\n\n  const redactString = (str: string | undefined): string | undefined => {\n    if (!str) return str;\n    return `<REDACTED> (${str.length} characters)`;\n  };\n\n  if (safeHeaders['x-goog-api-key']) {\n    safeHeaders['x-goog-api-key'] = redactString(\n      safeHeaders['x-goog-api-key']\n    )!;\n  }\n  if (safeHeaders['Authorization']) {\n    safeHeaders['Authorization'] = redactString(safeHeaders['Authorization'])!;\n  }\n\n  const safeOptions: any = {};\n  if (traceOptions.clientOptions?.timeout) {\n    safeOptions.timeout = traceOptions.clientOptions.timeout;\n  }\n\n  return {\n    apiEndpoint: url,\n    request: traceOptions.request,\n    headers: safeHeaders,\n    ...(Object.keys(safeOptions).length > 0 ? { options: safeOptions } : {}),\n    ...(traceOptions.model ? { model: traceOptions.model } : {}),\n  };\n}\n\n/**\n * Safely extracts the error message from the error.\n * @param e The error\n * @returns The error message\n */\nexport function extractErrMsg(e: unknown): string {\n  let errorMessage = 'An unknown error occurred';\n  if (e instanceof Error) {\n    errorMessage = e.message;\n  } else if (typeof e === 'string') {\n    errorMessage = e;\n  } else {\n    // Fallback for other types\n    try {\n      errorMessage = JSON.stringify(e);\n    } catch (stringifyError) {\n      errorMessage = 'Failed to stringify error object';\n    }\n  }\n  return errorMessage;\n}\n\n/**\n * Custom replacer function for JSON.stringify to truncate long string fields.\n * Truncates strings to the first 100 and last 10 characters\n * if the original string is longer than 110 characters.\n *\n * @param key The key of the property being stringified.\n * @param value The value of the property being stringified.\n * @return The transformed value, or the original value if no transformation is needed.\n */\nexport function stringTruncator(key: string, value: unknown): unknown {\n  const beginLength = 100;\n  const endLength = 10;\n  const totalLength = beginLength + endLength;\n  if (typeof value === 'string' && value.length > totalLength) {\n    const start = value.substring(0, 100);\n    const end = value.substring(value.length - 10);\n    return `${start}...[TRUNCATED]...${end}`;\n  }\n  return value; // Return the original value for other keys or non-string values\n}\n\n/**\n * Gets the un-prefixed model name from a modelReference\n */\nexport function extractVersion(\n  model: ModelReference<z.ZodTypeAny> | EmbedderReference<z.ZodTypeAny>\n): string {\n  return model.version ? model.version : checkModelName(model.name);\n}\n\n/**\n * Gets the model name without certain prefixes..\n * e.g. for \"models/googleai/gemini-2.5-pro\" it returns just 'gemini-2.5-pro'\n * @param name A string containing the model string with possible prefixes\n * @returns the model string stripped of certain prefixes\n */\nexport function modelName(name?: string): string | undefined {\n  if (!name) return name;\n\n  // Remove any of these prefixes:\n  const prefixesToRemove =\n    /background-model\\/|model\\/|models\\/|embedders\\/|googleai\\/|vertexai\\//g;\n  return name.replace(prefixesToRemove, '');\n}\n\n/**\n * Gets the suffix of a model string.\n * Throws if the string is empty.\n * @param name A string containing the model string\n * @returns the model string stripped of prefixes and guaranteed not empty.\n */\nexport function checkModelName(name?: string): string {\n  const version = modelName(name);\n  if (!version) {\n    throw new GenkitError({\n      status: 'INVALID_ARGUMENT',\n      message: 'Model name is required.',\n    });\n  }\n  return version;\n}\n\nexport function extractText(request: GenerateRequest) {\n  return (\n    request.messages\n      .at(-1)\n      ?.content.map((c) => c.text || '')\n      .join('') ?? ''\n  );\n}\n\nconst KNOWN_MIME_TYPES = {\n  jpg: 'image/jpeg',\n  jpeg: 'image/jpeg',\n  png: 'image/png',\n  mp4: 'video/mp4',\n  pdf: 'application/pdf',\n};\n\nexport function extractMimeType(url?: string): string {\n  if (!url) {\n    return '';\n  }\n\n  const dataPrefix = 'data:';\n  if (!url.startsWith(dataPrefix)) {\n    // Not a data url, try suffix\n    url.lastIndexOf('.');\n    const key = url.substring(url.lastIndexOf('.') + 1);\n    if (Object.keys(KNOWN_MIME_TYPES).includes(key)) {\n      return KNOWN_MIME_TYPES[key];\n    }\n    return '';\n  }\n\n  const commaIndex = url.indexOf(',');\n  if (commaIndex == -1) {\n    // Invalid - missing separator\n    return '';\n  }\n\n  // The part between 'data:' and the comma\n  let mimeType = url.substring(dataPrefix.length, commaIndex);\n  const base64Marker = ';base64';\n  if (mimeType.endsWith(base64Marker)) {\n    mimeType = mimeType.substring(0, mimeType.length - base64Marker.length);\n  }\n\n  return mimeType.trim();\n}\n\nexport function checkSupportedMimeType(\n  media: MediaPart['media'],\n  supportedTypes: string[]\n) {\n  if (!supportedTypes.includes(media.contentType ?? '')) {\n    throw new GenkitError({\n      status: 'INVALID_ARGUMENT',\n      message: `Invalid mimeType for ${displayUrl(media.url)}: \"${media.contentType}\". Supported mimeTypes: ${supportedTypes.join(', ')}`,\n    });\n  }\n}\n\n/**\n *\n * @param url The url to show (e.g. in an error message)\n * @returns The appropriately  sized url\n */\nexport function displayUrl(url: string): string {\n  if (url.length <= 50) {\n    return url;\n  }\n\n  return url.substring(0, 25) + '...' + url.substring(url.length - 25);\n}\n\nfunction isMediaPart(part: GenkitPart): part is MediaPart {\n  return (part as MediaPart).media !== undefined;\n}\n\n/**\n *\n * @param request A generate request to extract from\n * @param metadataType The media must have metadata matching this type if isDefault is false\n * @param isDefault 'true' allows missing metadata type to match as well.\n * @returns\n */\nexport function extractMedia(\n  request: GenerateRequest,\n  params: {\n    metadataType?: string;\n    /* Is there is no metadata type, it will match if isDefault is true */\n    isDefault?: boolean;\n  }\n): MediaPart['media'] | undefined {\n  const mediaArray = extractMediaArray(request, params);\n  if (mediaArray?.length) {\n    return mediaArray[0].media;\n  }\n\n  return undefined;\n}\n\n/**\n *\n * @param request A generate request to extract from\n * @param metadataType The media must have metadata matching this type if isDefault is false\n * @param isDefault 'true' allows missing metadata type to match as well.\n * @returns\n */\nexport function extractMediaArray(\n  request: GenerateRequest,\n  params: {\n    metadataType?: string;\n    /* If there is no metadata type, it will match if isDefault is true */\n    isDefault?: boolean;\n  }\n): MediaPart[] | undefined {\n  // MediaPart filter:  Keeps parts matching `params.metadataType`,\n  // or parts with no metadata type if `params.isDefault` is true.\n  // Keeps everything if no params are specified.\n  const matchesMediaParams = (part: MediaPart) => {\n    if (params.metadataType || params.isDefault) {\n      // We need to check the metadata type\n      const metadata = part.metadata;\n      if (!metadata?.type) {\n        return !!params.isDefault;\n      } else {\n        return metadata.type == params.metadataType;\n      }\n    }\n    return true;\n  };\n\n  const mediaArray = request.messages\n    .at(-1)\n    ?.content.filter(isMediaPart)\n    .filter(matchesMediaParams)\n    ?.map((mediaPart) => {\n      let media = mediaPart.media;\n      if (media && !media?.contentType) {\n        // Add the mimeType\n        media = {\n          url: media.url,\n          contentType: extractMimeType(media.url),\n        };\n      }\n\n      return {\n        media,\n        metadata: {\n          referenceType: mediaPart.metadata?.referenceType ?? 'asset',\n        },\n      };\n    });\n\n  if (mediaArray?.length) {\n    return mediaArray;\n  }\n\n  return undefined;\n}\n\n/**\n * Cleans a JSON schema by removing specific keys and standardizing types.\n *\n * @param {JSONSchema} schema The JSON schema to clean.\n * @returns {JSONSchema} The cleaned JSON schema.\n */\nexport function cleanSchema(schema: JSONSchema): JSONSchema {\n  const out = structuredClone(schema);\n  for (const key in out) {\n    if (key === '$schema' || key === 'additionalProperties') {\n      delete out[key];\n      continue;\n    }\n    if (typeof out[key] === 'object' && out[key] !== null) {\n      out[key] = cleanSchema(out[key]);\n    }\n    // Zod nullish() and picoschema optional fields will produce type `[\"string\", \"null\"]`\n    // which is not supported by the model API. Convert them to just `\"string\"`.\n    if (key === 'type' && Array.isArray(out[key])) {\n      // find the first that's not `null`.\n      out[key] = out[key].find((t) => t !== 'null');\n    }\n  }\n  return out;\n}\n\n// ---------------------------------------------------------------------------\n// Interactions API stream processing (Interactions-only).\n//\n// Kept separate from the generateContent stream processing below so that the\n// generateContent path can be removed cleanly once those models are retired.\n// ---------------------------------------------------------------------------\n\n/**\n * Interactions API content-policy codes. These are reported in two ways:\n *  - prompt blocked before execution: HTTP 400 with `error.code` set;\n *  - response blocked after execution: HTTP 200, `status: 'failed'`, with the\n *    code in `interaction.errors[]`.\n *\n * In the second case the plugin returns `finishReason: 'blocked'` (matching\n * the generateContent path) rather than throwing. When thrown (first case) they\n * map to `FAILED_PRECONDITION`, which is not retryable: the same input will be\n * blocked again.\n */\nconst INTERACTION_CONTENT_BLOCK_CODES = new Set([\n  'safety',\n  'recitation',\n  'language',\n  'prohibited_content',\n  'spii',\n  'blocklist',\n  'image_safety',\n  'image_prohibited_content',\n  'image_recitation',\n  'image_other',\n  'content_blocked',\n  'jailbreak',\n  'model_armor',\n]);\n\n/**\n * Reports whether an Interactions API error code is a content-policy block\n * (safety, recitation, blocklist, etc.).\n *\n * @param code The `code` field from an Interactions API error.\n */\nexport function isInteractionContentBlockCode(code: unknown): boolean {\n  return (\n    typeof code === 'string' &&\n    INTERACTION_CONTENT_BLOCK_CODES.has(code.trim().toLowerCase())\n  );\n}\n\n/**\n * Interactions API error codes mapped to Genkit statuses.\n *\n * The Interactions API reports errors as `{ code: string, message: string }`.\n * The public spec documents `code` only as \"a URI that identifies the error\n * type\" and does not enumerate values; this table is the full set of codes the\n * API returns (with the HTTP status the API pairs each one with).\n */\nconst INTERACTION_ERROR_CODE_TO_STATUS: Record<string, StatusName> = {\n  // Generation failures reported via `status: 'failed'` + `errors[]` after the\n  // server's own internal retries are exhausted. The server message advises\n  // retrying, so these map to ABORTED (\"retry at a higher level\"), which the\n  // retry middleware retries by default.\n  malformed_function_call: 'ABORTED',\n  unexpected_tool_call: 'ABORTED',\n  no_image: 'ABORTED',\n  // Content-policy blocks; see INTERACTION_CONTENT_BLOCK_CODES.\n  ...Object.fromEntries(\n    [...INTERACTION_CONTENT_BLOCK_CODES].map((code): [string, StatusName] => [\n      code,\n      'FAILED_PRECONDITION',\n    ])\n  ),\n  service_unavailable: 'UNAVAILABLE', // 503: server or model overloaded\n  rate_limit_exceeded: 'RESOURCE_EXHAUSTED', // 429: RPM/TPM limits\n  quota_exceeded: 'RESOURCE_EXHAUSTED', // 429: RPD/daily limits\n  invalid_request: 'INVALID_ARGUMENT', // 400: general bad request\n  parameter_unknown: 'INVALID_ARGUMENT', // 400: unrecognized field\n  failed_precondition: 'FAILED_PRECONDITION', // 400\n  out_of_range: 'OUT_OF_RANGE', // 400\n  // 400: exceeded the agent's max token limit. Deterministic for a given\n  // request, so deliberately not RESOURCE_EXHAUSTED (which is retryable).\n  agent_max_token_limit: 'INVALID_ARGUMENT',\n  model_not_found: 'NOT_FOUND', // 404\n  not_found: 'NOT_FOUND', // 404\n  authentication: 'UNAUTHENTICATED', // 401\n  permission_denied: 'PERMISSION_DENIED', // 403\n  already_exists: 'ALREADY_EXISTS', // 409\n  aborted: 'ABORTED', // 409\n  cancelled: 'CANCELLED', // 499\n  deadline_exceeded: 'DEADLINE_EXCEEDED', // 504\n  api_error: 'INTERNAL', // 500\n  unimplemented: 'UNIMPLEMENTED', // 501\n};\n\n/**\n * Maps an Interactions API error `code` to a Genkit `StatusName`.\n *\n * Looks the code up (case-insensitively) in the known Interactions error codes.\n * Also accepts numeric HTTP codes (e.g. `503` or `\"503\"`), in case the front\n * end returns a Google-style error body instead.\n *\n * @param code The `code` field from an Interactions API error.\n * @returns The matching `StatusName`, or `undefined` if it cannot be mapped.\n */\nexport function interactionErrorCodeToGenkitStatus(\n  code: unknown\n): StatusName | undefined {\n  if (typeof code === 'number') {\n    const status = httpStatusToGenkitStatus(code);\n    return status === 'UNKNOWN' ? undefined : status;\n  }\n  if (typeof code !== 'string' || !code.trim()) {\n    return undefined;\n  }\n  const normalized = code.trim().toLowerCase();\n  if (/^\\d+$/.test(normalized)) {\n    return interactionErrorCodeToGenkitStatus(Number(normalized));\n  }\n  return Object.prototype.hasOwnProperty.call(\n    INTERACTION_ERROR_CODE_TO_STATUS,\n    normalized\n  )\n    ? INTERACTION_ERROR_CODE_TO_STATUS[normalized]\n    : undefined;\n}\n\n/**\n * Builds an error for leftover, unparsed Interactions stream text. When the\n * model is overloaded (or otherwise fails), the API may return a plain JSON\n * error body (e.g. `{\"error\":{\"code\":\"service_unavailable\",\"message\":\"...\"}}`)\n * instead of SSE `data:` frames. Surfacing a `GenkitError` with the correct\n * status lets downstream middleware (e.g. retry) react appropriately.\n *\n * @param text The leftover text that could not be parsed as an SSE event.\n * @returns A `GenkitError` if the text is a recognizable API error body,\n *  otherwise a generic `Error`.\n */\nexport function parseInteractionStreamErrorText(text: string): Error {\n  try {\n    const json = JSON.parse(text);\n    const apiError = json?.error;\n    if (\n      apiError &&\n      typeof apiError === 'object' &&\n      (apiError.code || apiError.status)\n    ) {\n      // Prefer an explicit Google-style `status` if present, otherwise map the\n      // Interactions `code`.\n      const parsedStatus = StatusNameSchema.safeParse(apiError.status);\n      const status: StatusName = parsedStatus.success\n        ? parsedStatus.data\n        : (interactionErrorCodeToGenkitStatus(apiError.code) ?? 'UNKNOWN');\n      const message =\n        typeof apiError.message === 'string'\n          ? apiError.message\n          : 'Error streaming from the model';\n      return new GenkitError({\n        status,\n        message,\n        detail: json,\n      });\n    }\n  } catch (e) {\n    // Not JSON or not a recognizable error body, fall through to generic error.\n  }\n  // Truncate to avoid memory/log bloat from large non-JSON payloads.\n  const truncatedText =\n    text.length > 500 ? text.substring(0, 500) + '...' : text;\n  return new Error('Failed to parse stream: ' + truncatedText);\n}\n\nexport function interactionProcessStream(\n  response: Response\n): InteractionStreamResult {\n  if (!response.body) {\n    throw new Error('Error processing stream because response.body not found');\n  }\n  const inputStream = response.body.pipeThrough(\n    new TextDecoderStream('utf8', { fatal: true })\n  );\n  const responseStream = getInteractionResponseStream(inputStream);\n  const [stream1, stream2] = responseStream.tee();\n  const responsePromise = getInteractionResponsePromise(stream2);\n  // See processStream: avoid an unhandled rejection if the caller only\n  // consumes `stream` and it errors before `response` is ever awaited.\n  responsePromise.catch(() => {});\n  return {\n    stream: generateInteractionResponseSequence(stream1),\n    response: responsePromise,\n  };\n}\n\n/**\n * Reports whether a parsed SSE payload is an Interactions stream event, i.e.\n * an object with a string `event_type`. Event payloads are not otherwise\n * validated; their fields are read defensively where they are used.\n */\nfunction isInteractionSseEvent(value: unknown): value is InteractionSseEvent {\n  return isObject(value) && typeof value.event_type === 'string';\n}\n\nfunction getInteractionResponseStream(\n  inputStream: ReadableStream<string>\n): ReadableStream<InteractionSseEvent> {\n  const reader = inputStream.getReader();\n  const stream = new ReadableStream<InteractionSseEvent>({\n    start(controller) {\n      let currentText = '';\n      return pump();\n      function pump(): Promise<(() => Promise<void>) | undefined> {\n        return reader\n          .read()\n          .then(({ value, done }) => {\n            if (done) {\n              reader.releaseLock();\n              if (currentText.trim()) {\n                controller.error(parseInteractionStreamErrorText(currentText));\n                return;\n              }\n              controller.close();\n              return;\n            }\n\n            currentText += value;\n\n            while (true) {\n              const doubleNewline = currentText.indexOf('\\n\\n');\n              const doubleReturn = currentText.indexOf('\\r\\r');\n              const doubleReturnNewline = currentText.indexOf('\\r\\n\\r\\n');\n\n              let endIndex = -1;\n              let skip = 2;\n              if (\n                doubleReturnNewline !== -1 &&\n                (endIndex === -1 || doubleReturnNewline < endIndex)\n              ) {\n                endIndex = doubleReturnNewline;\n                skip = 4;\n              }\n              if (\n                doubleNewline !== -1 &&\n                (endIndex === -1 || doubleNewline < endIndex)\n              ) {\n                endIndex = doubleNewline;\n                skip = 2;\n              }\n              if (\n                doubleReturn !== -1 &&\n                (endIndex === -1 || doubleReturn < endIndex)\n              ) {\n                endIndex = doubleReturn;\n                skip = 2;\n              }\n\n              if (endIndex === -1) {\n                break; // Need more data\n              }\n\n              const block = currentText.substring(0, endIndex);\n              currentText = currentText.substring(endIndex + skip);\n\n              const lines = block.split(/\\r\\n|\\r|\\n/);\n              let dataText = '';\n\n              for (const line of lines) {\n                if (line.startsWith('data: ')) {\n                  dataText += line.substring(6);\n                } else if (line.startsWith('data:')) {\n                  dataText += line.substring(5);\n                }\n              }\n\n              if (dataText === '[DONE]') {\n                continue;\n              }\n\n              if (dataText) {\n                let parsed: unknown;\n                try {\n                  parsed = JSON.parse(dataText);\n                } catch {\n                  reader.releaseLock();\n                  controller.error(\n                    new Error(`Error parsing JSON response: \"${dataText}\"`)\n                  );\n                  return;\n                }\n                if (isInteractionSseEvent(parsed)) {\n                  controller.enqueue(parsed);\n                }\n                // Unknown payloads (no `event_type`) are skipped, as the API\n                // docs recommend for unrecognized events.\n              }\n            }\n            return pump();\n          })\n          .catch((e: unknown) => {\n            reader.releaseLock();\n            if (e instanceof Error && e.name === 'AbortError') {\n              throw new GenkitError({\n                status: 'ABORTED',\n                message: 'Request aborted when reading from the stream',\n              });\n            }\n            // Keep the original error (e.g. a dropped connection) so the\n            // failure can be diagnosed.\n            const detail = e instanceof Error ? e.message : String(e);\n            throw new Error(`Error reading from the stream: ${detail}`, {\n              cause: e,\n            });\n          });\n      }\n    },\n    cancel() {\n      reader.cancel().catch(() => {});\n    },\n  });\n  return stream;\n}\n\nasync function* generateInteractionResponseSequence(\n  stream: ReadableStream<InteractionSseEvent>\n): AsyncGenerator<InteractionSseEvent> {\n  const reader = stream.getReader();\n  try {\n    while (true) {\n      const { value, done } = await reader.read();\n      if (done) {\n        break;\n      }\n      yield value;\n    }\n  } finally {\n    reader.releaseLock();\n  }\n}\n\nasync function getInteractionResponsePromise(\n  stream: ReadableStream<InteractionSseEvent>\n): Promise<GeminiInteraction> {\n  let interaction: GeminiInteraction = {};\n  const partialArgumentsMap = new Map<number, string>();\n  const reader = stream.getReader();\n  try {\n    while (true) {\n      const { done, value } = await reader.read();\n      if (done) {\n        return interaction;\n      }\n\n      if (value.event_type === 'error') {\n        throw new GenkitError({\n          // Map the error code so e.g. quota/overload errors get a retryable\n          // status; fall back to INTERNAL for unrecognized codes.\n          status:\n            interactionErrorCodeToGenkitStatus(value.error?.code) ?? 'INTERNAL',\n          message: `Interaction API returned an error: [${value.error?.code}] ${value.error?.message}`,\n          detail: value,\n        });\n      }\n\n      if (\n        value.event_type === 'interaction.created' ||\n        value.event_type === 'interaction.completed'\n      ) {\n        // Merge metadata (id, status, usage, errors, ...) only. Steps are\n        // assembled from step.* events, and these events may carry partial or\n        // no steps, which must not overwrite them. Use their steps only if\n        // none were streamed.\n        const { steps, ...rest } = value.interaction;\n        Object.assign(interaction, rest);\n        if (steps?.length && !interaction.steps?.length) {\n          interaction.steps = steps;\n        }\n      } else if (value.event_type === 'interaction.status_update') {\n        interaction.status = value.status;\n      } else if (value.event_type === 'step.start') {\n        if (!interaction.steps) interaction.steps = [];\n        interaction.steps[value.index] = value.step;\n      } else if (value.event_type === 'step.delta') {\n        if (!interaction.steps) interaction.steps = [];\n        const step = interaction.steps[value.index];\n        if (step) {\n          if (\n            step.type === 'model_output' ||\n            step.type === 'user_input' ||\n            step.type === 'thought'\n          ) {\n            const contentArray =\n              step.type === 'thought' ? step.summary : step.content;\n            if (!contentArray) {\n              if (step.type === 'thought') step.summary = [];\n              else step.content = [];\n            }\n            const arr = (\n              step.type === 'thought' ? step.summary : step.content\n            )!;\n\n            if (value.delta.type === 'text') {\n              // Append to the previous text block so a streamed answer becomes\n              // a single block, matching the non-streamed response. This also\n              // keeps annotation start/end indices meaningful.\n              const last = arr[arr.length - 1];\n              if (last?.type === 'text') {\n                last.text = (last.text ?? '') + value.delta.text;\n              } else {\n                arr.push({ type: 'text', text: value.delta.text });\n              }\n            } else if (\n              value.delta.type === 'image' ||\n              value.delta.type === 'audio' ||\n              value.delta.type === 'video' ||\n              value.delta.type === 'document'\n            ) {\n              // Media deltas have the same shape as the matching content block.\n              arr.push({ ...value.delta });\n            } else if (value.delta.type === 'text_annotation_delta') {\n              if (value.delta.annotations?.length) {\n                let target = [...arr]\n                  .reverse()\n                  .find((c): c is TextContent => c.type === 'text');\n                if (!target) {\n                  target = { type: 'text', text: '' };\n                  arr.push(target);\n                }\n                target.annotations = [\n                  ...(target.annotations ?? []),\n                  ...value.delta.annotations,\n                ];\n              }\n            } else if (\n              value.delta.type === 'thought_summary' &&\n              value.delta.content\n            ) {\n              arr.push(value.delta.content);\n            } else if (value.delta.type === 'thought_signature') {\n              if (step.type === 'thought') {\n                step.signature = value.delta.signature;\n              }\n            } else if (value.delta.type === 'function_call') {\n              // A function call that is part of the content array\n              arr.push({\n                type: 'function_call',\n                name: value.delta.name,\n                id: value.delta.id,\n                arguments: value.delta.arguments,\n              });\n            }\n          } else if (\n            step.type === 'function_call' &&\n            value.delta.type === 'arguments_delta'\n          ) {\n            const existing = partialArgumentsMap.get(value.index) || '';\n            partialArgumentsMap.set(\n              value.index,\n              existing + (value.delta.arguments || '')\n            );\n          } else if (value.delta.type === step.type) {\n            // Built-in tool steps (google_search_call/result,\n            // code_execution_call/result, url_context_*, file_search_*,\n            // google_maps_*, mcp_server_tool_*, function_result, ...): step.start\n            // carries only ids and an empty signature; the arguments, result\n            // and real signature arrive in a delta of the same type. Copy those\n            // fields onto the step.\n            const { type: _type, ...fields } = value.delta;\n            Object.assign(\n              step,\n              Object.fromEntries(\n                Object.entries(fields).filter(([, v]) => v !== undefined)\n              )\n            );\n          }\n        }\n      } else if (value.event_type === 'step.stop') {\n        // If we had partial arguments for this step, parse them and update the function call arguments\n        if (partialArgumentsMap.has(value.index)) {\n          const step = interaction.steps?.[value.index];\n          if (step && step.type === 'function_call') {\n            try {\n              const argStr = partialArgumentsMap.get(value.index);\n              if (argStr) {\n                step.arguments = JSON.parse(argStr);\n              }\n            } catch (e) {\n              logger.warn(\n                'Failed to parse partial arguments JSON for function call:',\n                e\n              );\n            }\n          }\n          partialArgumentsMap.delete(value.index);\n        }\n      }\n    }\n  } finally {\n    reader.releaseLock();\n  }\n}\n\n/**\n * Maps an HTTP status code to the corresponding Genkit `StatusName`.\n *\n * @param code The HTTP status code.\n * @returns The matching `StatusName`, or `'UNKNOWN'` if there is no mapping.\n */\nexport function httpStatusToGenkitStatus(code?: number): StatusName {\n  switch (code) {\n    case 400:\n      return 'INVALID_ARGUMENT';\n    case 401:\n      return 'UNAUTHENTICATED';\n    case 403:\n      return 'PERMISSION_DENIED';\n    case 404:\n      return 'NOT_FOUND';\n    case 429:\n      return 'RESOURCE_EXHAUSTED';\n    case 499:\n      return 'CANCELLED';\n    case 500:\n      return 'INTERNAL';\n    case 503:\n      return 'UNAVAILABLE';\n    case 504:\n      return 'DEADLINE_EXCEEDED';\n    default:\n      return 'UNKNOWN';\n  }\n}\n\n/** Reports whether every element of an array is a string. */\nexport function isStringArray(values: unknown[]): values is string[] {\n  return values.every((v) => typeof v === 'string');\n}\n\n/** Hints for config fields the Interactions API doesn't support. */\nconst DROPPED_CONFIG_FIELD_HINTS: Record<string, string> = {\n  'thinkingConfig.thinkingBudget':\n    \" Use thinkingConfig.thinkingLevel ('LOW' | 'MEDIUM' | 'HIGH') instead.\",\n};\n\n/** `model:field` pairs that have already been warned about. */\nconst warnedDroppedConfigFields = new Set<string>();\n\n/**\n * Warns (once per model and field) that a config field isn't supported by the\n * model and was ignored.\n */\nexport function warnDroppedConfigField(model: string, field: string) {\n  const key = `${model}:${field}`;\n  if (warnedDroppedConfigFields.has(key)) return;\n  warnedDroppedConfigFields.add(key);\n  logger.warn(\n    `${field} is not supported by '${model}' and was ignored.` +\n      (DROPPED_CONFIG_FIELD_HINTS[field] ?? '')\n  );\n}\n\n/**\n * Reports whether a URL targets the Interactions API, i.e. its path contains\n * an `interactions` segment.\n */\nexport function isInteractionUrl(url: string): boolean {\n  let pathname: string;\n  try {\n    pathname = new URL(url).pathname;\n  } catch {\n    pathname = url.split('?')[0];\n  }\n  return pathname.split('/').includes('interactions');\n}\n\n/**\n * Builds an error for leftover, unparsed stream text. When the model API is\n * overloaded (or otherwise fails), it may return HTTP 200 with a plain JSON\n * error body instead of SSE `data:` frames. In that case we surface a proper\n * `GenkitError` with the correct status so downstream middleware (e.g. retry)\n * can react appropriately, rather than a generic parse error.\n *\n * @param text The leftover text that could not be parsed as a stream chunk.\n * @returns A `GenkitError` if the text is a recognizable API error body,\n *  otherwise a generic `Error`.\n */\nexport function parseStreamErrorText(text: string): Error {\n  try {\n    const json = JSON.parse(text);\n    const apiError = json?.error;\n    if (\n      apiError &&\n      typeof apiError === 'object' &&\n      (apiError.code || apiError.status)\n    ) {\n      // Coerce `code` to a number so a stringified code (e.g. \"503\") still maps.\n      const rawCode = Number(apiError.code);\n      const status: StatusName = StatusNameSchema.safeParse(apiError.status)\n        .success\n        ? (apiError.status as StatusName)\n        : httpStatusToGenkitStatus(isNaN(rawCode) ? undefined : rawCode);\n      const message =\n        typeof apiError.message === 'string'\n          ? apiError.message\n          : 'Error streaming from the model';\n      return new GenkitError({\n        status,\n        message,\n        detail: json,\n      });\n    }\n  } catch (e) {\n    // Not JSON or not a recognizable error body, fall through to generic error.\n  }\n  // Truncate to avoid memory/log bloat from large non-JSON payloads (e.g. an\n  // HTML error page from an upstream proxy).\n  const truncatedText =\n    text.length > 500 ? text.substring(0, 500) + '...' : text;\n  return new Error('Failed to parse stream: ' + truncatedText);\n}\n\n/**\n * Processes the streaming body of a Response object. It decodes the stream as\n * UTF-8 text, parses JSON objects from specially formatted lines (e.g., \"data: {}\"),\n * and returns both an async generator for individual responses and a promise\n * that resolves to the aggregated final response.\n *\n * @param response The Response object with a streaming body.\n * @returns An object containing:\n *  - stream: An AsyncGenerator yielding each GenerateContentResponse.\n *  - response: A Promise resolving to the aggregated GenerateContentResponse.\n */\nexport function processStream(response: Response): GenerateContentStreamResult {\n  if (!response.body) {\n    throw new Error('Error processing stream because response.body not found');\n  }\n  const inputStream = response.body.pipeThrough(\n    new TextDecoderStream('utf8', { fatal: true })\n  );\n  const responseStream = getResponseStream(inputStream);\n  const [stream1, stream2] = responseStream.tee();\n  const responsePromise = getResponsePromise(stream2);\n  // Attach a no-op catch so that if the caller only consumes `stream` and it\n  // errors before `response` is ever awaited, the teed response promise does\n  // not become an unhandled rejection (which would crash the process). This\n  // does not swallow the rejection for a real awaiter of `response`.\n  responsePromise.catch(() => {});\n  return {\n    stream: generateResponseSequence(stream1),\n    response: responsePromise,\n  };\n}\n\nfunction getResponseStream(\n  inputStream: ReadableStream<string>\n): ReadableStream<GenerateContentResponse> {\n  const responseLineRE = /^data: (.*)(?:\\n\\n|\\r\\r|\\r\\n\\r\\n)/;\n  const reader = inputStream.getReader();\n  const stream = new ReadableStream<GenerateContentResponse>({\n    start(controller) {\n      let currentText = '';\n      return pump();\n      function pump(): Promise<(() => Promise<void>) | undefined> {\n        return reader\n          .read()\n          .then(({ value, done }) => {\n            if (done) {\n              reader.releaseLock();\n              if (currentText.trim()) {\n                controller.error(parseStreamErrorText(currentText));\n                return;\n              }\n              controller.close();\n              return;\n            }\n\n            currentText += value;\n            let match = currentText.match(responseLineRE);\n            let parsedResponse: GenerateContentResponse;\n            while (match) {\n              try {\n                parsedResponse = JSON.parse(match[1]);\n              } catch (e) {\n                reader.releaseLock();\n                controller.error(\n                  new Error(`Error parsing JSON response: \"${match[1]}\"`)\n                );\n                return;\n              }\n              controller.enqueue(parsedResponse);\n              currentText = currentText.substring(match[0].length);\n              match = currentText.match(responseLineRE);\n            }\n            return pump();\n          })\n          .catch((e: Error) => {\n            reader.releaseLock();\n            let err = e;\n            err.stack = e.stack;\n            if (err.name === 'AbortError') {\n              err = new GenkitError({\n                status: 'ABORTED',\n                message: 'Request aborted when reading from the stream',\n              });\n            } else {\n              err = new Error('Error reading from the stream');\n            }\n            throw err;\n          });\n      }\n    },\n    cancel() {\n      // Catch prevents unhandled promise rejection if the stream was already cleanly finalized\n      reader.cancel().catch(() => {});\n    },\n  });\n  return stream;\n}\n\nasync function* generateResponseSequence(\n  stream: ReadableStream<GenerateContentResponse>\n): AsyncGenerator<GenerateContentResponse> {\n  const reader = stream.getReader();\n  try {\n    while (true) {\n      const { value, done } = await reader.read();\n      if (done) {\n        break;\n      }\n      yield value;\n    }\n  } finally {\n    reader.releaseLock();\n  }\n}\n\nasync function getResponsePromise(\n  stream: ReadableStream<GenerateContentResponse>\n): Promise<GenerateContentResponse> {\n  const allResponses: GenerateContentResponse[] = [];\n  const reader = stream.getReader();\n  try {\n    while (true) {\n      const { done, value } = await reader.read();\n      if (done) {\n        return aggregateResponses(allResponses);\n      }\n      allResponses.push(value);\n    }\n  } finally {\n    reader.releaseLock();\n  }\n}\n\nfunction handleFunctionCall(\n  part: Part,\n  newPart: Partial<Part>,\n  activePartialToolRequest: Part | null\n): {\n  shouldContinue: boolean;\n  newActivePartialToolRequest: Part | null;\n} {\n  // If there's an active partial tool request, we're in the middle of a stream.\n  if (activePartialToolRequest) {\n    if (part.functionCall?.partialArgs) {\n      applyGeminiPartialArgs(\n        activePartialToolRequest.functionCall!.args!,\n        part.functionCall.partialArgs\n      );\n    }\n    // If `willContinue` is false, this is the end of the stream.\n    if (!part.functionCall!.willContinue) {\n      newPart.thoughtSignature = activePartialToolRequest.thoughtSignature;\n      part.functionCall = activePartialToolRequest.functionCall;\n      delete part.functionCall!.willContinue;\n      activePartialToolRequest = null;\n    } else {\n      // If `willContinue` is true, we're still in the middle of a stream.\n      // This is a partial result, so we skip adding it to the parts list.\n      return {\n        shouldContinue: true,\n        newActivePartialToolRequest: activePartialToolRequest,\n      };\n    }\n    // If `willContinue` is true on a part and there's no active partial request,\n    // this is the start of a new streaming tool call.\n  } else if (part.functionCall!.willContinue) {\n    activePartialToolRequest = {\n      ...part,\n      functionCall: {\n        ...part.functionCall,\n        args: part.functionCall!.args || {},\n      },\n    };\n    if (part.functionCall?.partialArgs) {\n      applyGeminiPartialArgs(\n        activePartialToolRequest.functionCall!.args!,\n        part.functionCall.partialArgs\n      );\n    }\n    // This is the start of a partial, so we skip adding it to the parts list.\n    return {\n      shouldContinue: true,\n      newActivePartialToolRequest: activePartialToolRequest,\n    };\n  }\n\n  // If we're here, it's a regular, non-streaming tool call.\n  newPart.functionCall = part.functionCall;\n  return {\n    shouldContinue: false,\n    newActivePartialToolRequest: activePartialToolRequest,\n  };\n}\n\nfunction aggregateResponses(\n  responses: GenerateContentResponse[]\n): GenerateContentResponse {\n  const lastResponse = responses.at(-1);\n  if (lastResponse === undefined) {\n    throw new Error(\n      'Error aggregating stream chunks because the final response in stream chunk is undefined'\n    );\n  }\n  const aggregatedResponse: GenerateContentResponse = {};\n  if (lastResponse.promptFeedback) {\n    aggregatedResponse.promptFeedback = lastResponse.promptFeedback;\n  }\n  let activePartialToolRequest: Part | null = null;\n  for (const response of responses) {\n    for (const candidate of response.candidates ?? []) {\n      const index = candidate.index ?? 0;\n      if (!aggregatedResponse.candidates) {\n        aggregatedResponse.candidates = [];\n      }\n      if (!aggregatedResponse.candidates[index]) {\n        aggregatedResponse.candidates[index] = {\n          index,\n        } as GenerateContentCandidate;\n      }\n      const aggregatedCandidate = aggregatedResponse.candidates[index];\n      aggregateMetadata(aggregatedCandidate, candidate, 'citationMetadata');\n      aggregateMetadata(aggregatedCandidate, candidate, 'groundingMetadata');\n      if (candidate.safetyRatings?.length) {\n        aggregatedCandidate.safetyRatings = (\n          aggregatedCandidate.safetyRatings ?? []\n        ).concat(candidate.safetyRatings);\n      }\n      if (candidate.finishReason !== undefined) {\n        aggregatedCandidate.finishReason = candidate.finishReason;\n      }\n      if (candidate.finishMessage !== undefined) {\n        aggregatedCandidate.finishMessage = candidate.finishMessage;\n      }\n\n      if (candidate.avgLogprobs !== undefined) {\n        aggregatedCandidate.avgLogprobs = candidate.avgLogprobs;\n      }\n      if (candidate.logprobsResult !== undefined) {\n        aggregatedCandidate.logprobsResult = candidate.logprobsResult;\n      }\n\n      /**\n       * Candidates should always have content and parts, but this handles\n       * possible malformed responses.\n       */\n      if (candidate.content && candidate.content.parts) {\n        if (!aggregatedCandidate.content) {\n          aggregatedCandidate.content = {\n            role: candidate.content.role || 'user',\n            parts: [],\n          };\n        }\n\n        for (const part of candidate.content.parts) {\n          const newPart: Partial<Part> = {};\n\n          // Instead of iterating over the keys in the Object, which might\n          // Contain new, unsupported things, we iterate over the PART_KEYS\n          // which is the list of Part keys we know about.\n          // This keeps us in sync\n          for (const key of PART_KEYS) {\n            if (key === 'functionCall') {\n              // shouldContinue in the functionCall logic below applies to the\n              // top level for loop, not this nested one.\n              continue;\n            } else if (key === 'text') {\n              if (typeof part.text === 'string') {\n                newPart.text = part.text;\n              }\n            } else if (part[key]) {\n              // Essentially newPart[key] = part[key] with type safety.\n              Object.assign(newPart, { [key]: part[key] });\n            }\n          }\n\n          if (part.functionCall) {\n            // function calls are special, there can be partials, so we need aggregate\n            // the partials into final functionCall.\n            const { shouldContinue, newActivePartialToolRequest } =\n              handleFunctionCall(part, newPart, activePartialToolRequest);\n            if (shouldContinue) {\n              activePartialToolRequest = newActivePartialToolRequest;\n              continue;\n            }\n            activePartialToolRequest = newActivePartialToolRequest;\n          }\n\n          if (Object.keys(newPart).length === 0) {\n            newPart.text = '';\n          }\n          aggregatedCandidate.content.parts.push(newPart as Part);\n        }\n      }\n    }\n    if (response.usageMetadata) {\n      aggregatedResponse.usageMetadata = response.usageMetadata;\n    }\n  }\n  return aggregatedResponse;\n}\n\nfunction aggregateMetadata<K extends keyof GenerateContentCandidate>(\n  aggCandidate: GenerateContentCandidate,\n  chunkCandidate: GenerateContentCandidate,\n  fieldName: K\n) {\n  const chunkObj = chunkCandidate[fieldName];\n  const aggObj = aggCandidate[fieldName];\n  if (chunkObj === undefined) return; // Nothing to do\n\n  if (aggObj === undefined) {\n    aggCandidate[fieldName] = chunkObj;\n    return;\n  }\n\n  if (isObject(chunkObj)) {\n    for (const k of Object.keys(chunkObj)) {\n      if (Array.isArray(aggObj[k]) && Array.isArray(chunkObj[k])) {\n        aggObj[k] = aggObj[k].concat(chunkObj[k]);\n      } else {\n        // last one wins, also handles only one being an array.\n        aggObj[k] = chunkObj[k] ?? aggObj[k];\n      }\n    }\n  }\n}\n\nexport function getGenkitClientHeader() {\n  if (process.env.MONOSPACE_ENV == 'true') {\n    return defaultGetClientHeader() + ' firebase-studio-vm';\n  }\n  return defaultGetClientHeader();\n}\n\n/**\n * Copies headers into a plain object, leaving out the named headers in any\n * letter case. Header names are case-insensitive, but object keys aren't:\n * without this, a custom `api-revision` would sit next to the plugin's\n * `Api-Revision` and fetch would send both values.\n *\n * @param headers The headers to copy (e.g. user-provided custom headers).\n * @param names The header names to leave out.\n */\nexport function withoutHeaders(\n  headers: Record<string, string> | Headers | undefined,\n  names: string[]\n): Record<string, string> {\n  const excluded = new Set(names.map((n) => n.toLowerCase()));\n  const result: Record<string, string> = {};\n  const add = (value: string, key: string) => {\n    if (!excluded.has(key.toLowerCase())) {\n      result[key] = value;\n    }\n  };\n  if (headers instanceof Headers) {\n    headers.forEach(add);\n  } else if (headers) {\n    for (const [key, value] of Object.entries(headers)) {\n      add(value, key);\n    }\n  }\n  return result;\n}\n\nexport function isKnownKey<T extends object>(\n  key: string | number | symbol,\n  obj: T\n): key is keyof T {\n  return key in obj;\n}\n\n/**\n * Parses the value of a `Retry-After` HTTP header into milliseconds.\n * Supports both delay-seconds (e.g. \"60\") and HTTP-date formats\n * (e.g. \"Mon, 19 May 2026 12:00:00 GMT\") per RFC 7231 §7.1.3.\n *\n * @param value The raw Retry-After header value.\n * @returns The delay in milliseconds, or undefined if the value cannot be parsed.\n */\nexport function parseRetryAfterMs(value: string): number | undefined {\n  if (!value || !value.trim()) {\n    return undefined;\n  }\n  // Try as delay-seconds (e.g., \"60\")\n  const seconds = Number(value);\n  if (!isNaN(seconds) && seconds >= 0) {\n    return seconds * 1000;\n  }\n  // Try as HTTP-date (e.g., \"Mon, 19 May 2026 12:00:00 GMT\")\n  const date = new Date(value);\n  if (!isNaN(date.getTime())) {\n    return Math.max(0, date.getTime() - Date.now());\n  }\n  return undefined;\n}\n\n/**\n * Converts a string in camelCase to lowercase snake_case.\n */\nexport function camelToSnakeCase(str: string): string {\n  return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\nexport function convertObjectKeysToSnakeCase(obj: Array<unknown>): unknown[];\nexport function convertObjectKeysToSnakeCase(\n  obj: Record<string, unknown>\n): Record<string, unknown>;\nexport function convertObjectKeysToSnakeCase(obj: unknown): unknown;\n\nexport function convertObjectKeysToSnakeCase(obj: unknown): unknown {\n  if (typeof obj !== 'object' || obj === null) {\n    return obj;\n  }\n\n  if (Array.isArray(obj)) {\n    return obj.map((item) => convertObjectKeysToSnakeCase(item));\n  }\n\n  const newObj: Record<string, unknown> = {};\n  for (const key in obj) {\n    if (Object.prototype.hasOwnProperty.call(obj, key)) {\n      const snakeCaseKey = camelToSnakeCase(key);\n      newObj[snakeCaseKey] = convertObjectKeysToSnakeCase(obj[key]);\n    }\n  }\n  return newObj;\n}\n\nexport function toSnakeCaseObj(val: unknown): Record<string, unknown> {\n  const snakeVal = convertObjectKeysToSnakeCase(val);\n  return isObject(snakeVal) ? snakeVal : {};\n}\n\n/**\n * Inserts raw audio bytes at the end of a WAV file's `data` chunk and updates\n * the RIFF and `data` sizes. Chunks after `data` (the server sends one) stay\n * after the audio. Returns `undefined` if `wav` isn't a WAV file with a\n * `data` chunk.\n */\nexport function appendToWavData(\n  wav: Buffer,\n  audio: Buffer\n): Buffer | undefined {\n  if (\n    wav.length < 12 ||\n    wav.toString('ascii', 0, 4) !== 'RIFF' ||\n    wav.toString('ascii', 8, 12) !== 'WAVE'\n  ) {\n    return undefined;\n  }\n  // Walk the chunks: each is a 4-byte id, a 4-byte little-endian size, then\n  // the data, padded to an even length.\n  let offset = 12;\n  while (offset + 8 <= wav.length) {\n    const id = wav.toString('ascii', offset, offset + 4);\n    const size = wav.readUInt32LE(offset + 4);\n    const dataStart = offset + 8;\n    if (id === 'data') {\n      const dataEnd = Math.min(dataStart + size, wav.length);\n      const result = Buffer.concat([\n        wav.subarray(0, dataEnd),\n        audio,\n        wav.subarray(dataEnd),\n      ]);\n      result.writeUInt32LE(size + audio.length, offset + 4);\n      result.writeUInt32LE(result.length - 8, 4);\n      return result;\n    }\n    offset = dataStart + size + (size % 2);\n  }\n  return undefined;\n}\n\n/**\n * Returns `bytes` without any ID3v2 tags at the start. A tag is only removed\n * if its header is valid (\"ID3\", version 2-4, size bytes below 0x80) and the\n * whole tag fits in `bytes`; otherwise `bytes` is returned unchanged.\n */\nexport function stripLeadingId3Tags(bytes: Buffer): Buffer {\n  let start = 0;\n  while (start + 10 <= bytes.length) {\n    const b = bytes.subarray(start);\n    const isTag =\n      b[0] === 0x49 && // I\n      b[1] === 0x44 && // D\n      b[2] === 0x33 && // 3\n      b[3] >= 2 &&\n      b[3] <= 4 &&\n      b[4] !== 0xff &&\n      b[6] < 0x80 &&\n      b[7] < 0x80 &&\n      b[8] < 0x80 &&\n      b[9] < 0x80;\n    if (!isTag) break;\n    // The size is \"syncsafe\" (7 bits per byte) and excludes the 10-byte\n    // header and the optional 10-byte footer (flag 0x10).\n    const size = (b[6] << 21) | (b[7] << 14) | (b[8] << 7) | b[9];\n    const tagLength = 10 + size + (b[5] & 0x10 ? 10 : 0);\n    if (tagLength > b.length) break;\n    start += tagLength;\n  }\n  return start === 0 ? bytes : bytes.subarray(start);\n}\n\nexport const TEST_ONLY = { aggregateResponses };\n"],"mappings":"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","names":[]}