{"version":3,"sources":["../../src/llm/utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { VideoBufferType, VideoFrame } from '@livekit/rtc-node';\nimport type { JSONSchema7 } from 'json-schema';\nimport { jsonrepair } from 'jsonrepair';\nimport sharp from 'sharp';\nimport { log } from '../log.js';\nimport type { UnknownUserData } from '../voice/run_context.js';\nimport type { ChatContext } from './chat_context.js';\nimport {\n  type ChatContent,\n  type ChatItem,\n  FunctionCall,\n  FunctionCallOutput,\n  type ImageContent,\n} from './chat_context.js';\nimport {\n  type ToolContext,\n  type ToolInputSchema,\n  type ToolOptions,\n  sortedToolNames,\n} from './tool_context.js';\nimport {\n  isZodSchema,\n  jsonSchemaAllowsNull,\n  parseZodSchema,\n  zodSchemaToJsonSchema,\n} from './zod-utils.js';\n\nexport const THINK_TAG_START = '<think>';\nexport const THINK_TAG_END = '</think>';\n\nexport class ThinkingTokenFilter {\n  startTag: string;\n  endTag: string;\n  buffer = '';\n  endMarker?: string;\n\n  constructor(startTag: string = THINK_TAG_START, endTag: string = THINK_TAG_END) {\n    this.startTag = startTag;\n    this.endTag = endTag;\n  }\n}\n\nfunction partialMarkerLength(content: string, markers: string[]): number {\n  let longest = 0;\n\n  for (const marker of markers) {\n    for (let length = 1; length <= Math.min(content.length, marker.length - 1); length += 1) {\n      if (content.endsWith(marker.slice(0, length))) {\n        longest = Math.max(longest, length);\n      }\n    }\n  }\n\n  return longest;\n}\n\nfunction flattenDeltaContent(content: string | unknown[] | null | undefined) {\n  if (content === null || content === undefined || typeof content === 'string') {\n    return content;\n  }\n\n  if (Array.isArray(content)) {\n    const parts: string[] = [];\n    for (const part of content) {\n      if (typeof part === 'string') {\n        parts.push(part);\n        continue;\n      }\n\n      const text =\n        typeof part === 'object' && part !== null && 'text' in part ? part.text : undefined;\n      if (typeof text === 'string') {\n        parts.push(text);\n      }\n    }\n\n    // No text part carries no content, unlike a part containing an empty string.\n    return parts.length > 0 ? parts.join('') : undefined;\n  }\n\n  log().warn(\n    { contentType: typeof content },\n    'unexpected streaming delta content type; dropping the chunk',\n  );\n  return undefined;\n}\n\nexport function stripThinkingTokens(\n  content: string | unknown[] | null | undefined,\n  state: ThinkingTokenFilter,\n  { final = false }: { final?: boolean } = {},\n): string | undefined {\n  content = flattenDeltaContent(content);\n  if (content !== null && content !== undefined) {\n    state.buffer += content;\n  }\n\n  const visible: string[] = [];\n  while (state.buffer) {\n    if (state.endMarker !== undefined) {\n      const idx = state.buffer.indexOf(state.endMarker);\n      if (idx < 0) {\n        const keep = partialMarkerLength(state.buffer, [state.endMarker]);\n        state.buffer = keep ? state.buffer.slice(-keep) : '';\n        break;\n      }\n\n      state.buffer = state.buffer.slice(idx + state.endMarker.length);\n      state.endMarker = undefined;\n      continue;\n    }\n\n    const idx = state.buffer.indexOf(state.startTag);\n    if (idx >= 0) {\n      visible.push(state.buffer.slice(0, idx));\n      state.buffer = state.buffer.slice(idx + state.startTag.length);\n      state.endMarker = state.endTag;\n      continue;\n    }\n\n    const keep = partialMarkerLength(state.buffer, [state.startTag]);\n    visible.push(keep ? state.buffer.slice(0, -keep) : state.buffer);\n    state.buffer = keep ? state.buffer.slice(-keep) : '';\n    break;\n  }\n\n  if (final) {\n    if (state.endMarker === undefined) {\n      visible.push(state.buffer);\n    }\n    state.buffer = '';\n    state.endMarker = undefined;\n  }\n\n  const result = visible.join('');\n  return result || (content === '' ? '' : undefined);\n}\n\nexport interface SerializedImage {\n  inferenceDetail: 'auto' | 'high' | 'low';\n  mimeType?: string;\n  base64Data?: string;\n  externalUrl?: string;\n}\n\nfunction getChannelsFromVideoBufferType(type: VideoBufferType): 3 | 4 {\n  switch (type) {\n    case VideoBufferType.RGBA:\n    case VideoBufferType.ABGR:\n    case VideoBufferType.ARGB:\n    case VideoBufferType.BGRA:\n      return 4;\n    case VideoBufferType.RGB24:\n      return 3;\n    default:\n      // YUV formats (I420, I420A, I422, I444, I010, NV12) need conversion\n      throw new Error(`Unsupported VideoBufferType: ${type}. Only RGB/RGBA formats are supported.`);\n  }\n}\n\nfunction ensureRGBCompatible(frame: VideoFrame): VideoFrame {\n  // If the frame is already in an RGB/RGBA-compatible format, return it directly\n  if (\n    frame.type === VideoBufferType.RGBA ||\n    frame.type === VideoBufferType.BGRA ||\n    frame.type === VideoBufferType.ARGB ||\n    frame.type === VideoBufferType.ABGR ||\n    frame.type === VideoBufferType.RGB24\n  ) {\n    return frame;\n  }\n\n  // Otherwise, attempt conversion for other formats (like YUV)\n  try {\n    return frame.convert(VideoBufferType.RGBA);\n  } catch (error) {\n    throw new Error(\n      `Failed to convert format ${frame.type} to RGB: ${error}. ` +\n        `Consider using RGB/RGBA formats or converting on the client side.`,\n    );\n  }\n}\n\nexport async function serializeImage(image: ImageContent): Promise<SerializedImage> {\n  if (typeof image.image === 'string') {\n    if (image.image.startsWith('data:')) {\n      const [header, base64Data] = image.image.split(',', 2) as [string, string];\n      const headerParts = header.split(';');\n      const mimeParts = headerParts[0]?.split(':');\n      const headerMime = mimeParts?.[1];\n\n      if (!headerMime) {\n        throw new Error('Invalid data URL format');\n      }\n\n      let mimeType: string;\n      if (image.mimeType && image.mimeType !== headerMime) {\n        console.warn(\n          `Provided mimeType '${image.mimeType}' does not match data URL mime type '${headerMime}'. Using provided mimeType.`,\n        );\n        mimeType = image.mimeType;\n      } else {\n        mimeType = headerMime;\n      }\n\n      const supportedTypes = new Set(['image/jpeg', 'image/png', 'image/webp', 'image/gif']);\n      if (!supportedTypes.has(mimeType)) {\n        throw new Error(`Unsupported mimeType ${mimeType}. Must be jpeg, png, webp, or gif`);\n      }\n\n      return {\n        base64Data,\n        mimeType: mimeType,\n        inferenceDetail: image.inferenceDetail,\n      };\n    }\n\n    // External URL\n    return {\n      mimeType: image.mimeType,\n      inferenceDetail: image.inferenceDetail,\n      externalUrl: image.image,\n    };\n  } else if (image.image instanceof VideoFrame) {\n    const frame = ensureRGBCompatible(image.image);\n    const channels = getChannelsFromVideoBufferType(frame.type);\n\n    // Sharp needs to know the format of raw pixel data\n    let encoded = sharp(frame.data, {\n      raw: {\n        width: frame.width,\n        height: frame.height,\n        channels,\n      },\n    });\n\n    if (image.inferenceWidth && image.inferenceHeight) {\n      encoded = encoded.resize(image.inferenceWidth, image.inferenceHeight);\n    }\n\n    const base64Data = await encoded\n      .png()\n      .toBuffer()\n      .then((buffer) => buffer.toString('base64'));\n\n    return {\n      base64Data,\n      mimeType: 'image/png',\n      inferenceDetail: image.inferenceDetail,\n    };\n  } else {\n    throw new Error('Unsupported image type');\n  }\n}\n\n/** Raw OpenAI-adherent function parameters. */\nexport type OpenAIFunctionParameters = {\n  type: 'object';\n  properties: { [id: string]: any }; // eslint-disable-line @typescript-eslint/no-explicit-any\n  required: string[];\n  additionalProperties?: boolean;\n};\n\n// TODO(brian): remove this helper once we have the real RunContext user data\nexport const createToolOptions = <UserData extends UnknownUserData>(\n  toolCallId: string,\n  userData: UserData = {} as UserData,\n): ToolOptions<UserData> => {\n  return {\n    ctx: { userData },\n    toolCallId,\n    abortSignal: new AbortController().signal,\n  } as unknown as ToolOptions<UserData>;\n};\n\n/** @internal */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const oaiParams = (schema: any, isOpenai: boolean = true): OpenAIFunctionParameters => {\n  // Adapted from https://github.com/vercel/ai/blob/56eb0ee9/packages/provider-utils/src/zod-schema.ts\n  const jsonSchema = zodSchemaToJsonSchema(schema, isOpenai);\n  const { properties, required, additionalProperties } = jsonSchema as OpenAIFunctionParameters;\n\n  return {\n    type: 'object',\n    properties,\n    required,\n    additionalProperties,\n  };\n};\n\n/** @internal */\nexport const oaiBuildFunctionInfo = (\n  toolCtx: ToolContext,\n  toolCallId: string,\n  toolName: string,\n  rawArgs: string,\n): FunctionCall => {\n  const tool = toolCtx.getFunctionTool(toolName);\n  if (!tool) {\n    throw new Error(`AI tool ${toolName} not found`);\n  }\n\n  return FunctionCall.create({\n    callId: toolCallId,\n    name: toolName,\n    args: rawArgs,\n  });\n};\n\nconst templateTokenPatterns = [\n  /<\\|[^<>|]{0,40}\\|>/g,\n  /<\\|[^<>a-zA-Z0-9_]{0,10}/g,\n  /[^<>a-zA-Z0-9_]{0,10}\\|>/g,\n  /<(?:start|end)_of_turn>/g,\n];\n\nfunction stripTemplateTokens(value: unknown): unknown {\n  if (typeof value === 'string') {\n    return templateTokenPatterns.reduce((out, pattern) => out.replace(pattern, ''), value).trim();\n  }\n\n  if (Array.isArray(value)) {\n    return value.map(stripTemplateTokens).filter((item) => item !== '' && item !== null);\n  }\n\n  if (value && typeof value === 'object') {\n    return Object.fromEntries(\n      Object.entries(value).map(([key, nestedValue]) => [key, stripTemplateTokens(nestedValue)]),\n    );\n  }\n\n  return value;\n}\n\nexport function parseFunctionArguments(\n  rawArgs: string | Record<string, unknown>,\n): Record<string, unknown> {\n  let args: unknown;\n  const rawForError = typeof rawArgs === 'string' ? rawArgs : JSON.stringify(rawArgs);\n\n  if (typeof rawArgs === 'string') {\n    try {\n      args = JSON.parse(rawArgs);\n    } catch (strictError) {\n      let repaired: unknown;\n      try {\n        repaired = JSON.parse(jsonrepair(rawArgs));\n      } catch {\n        throw new Error(\n          `could not parse function arguments as JSON: ${strictError}: ${rawForError.slice(0, 200)}`,\n        );\n      }\n\n      args = stripTemplateTokens(repaired);\n    }\n  } else {\n    args = rawArgs;\n  }\n\n  while (typeof args === 'string') {\n    const stringArgs = args;\n    try {\n      args = JSON.parse(stringArgs);\n    } catch {\n      throw new Error(\n        `function arguments decoded to a non-JSON string: ${stringArgs.slice(0, 200)}`,\n      );\n    }\n  }\n\n  if (args === null) {\n    return {};\n  }\n  if (typeof args !== 'object' || Array.isArray(args)) {\n    throw new Error(`expected object from function arguments: ${rawForError.slice(0, 200)}`);\n  }\n\n  return args as Record<string, unknown>;\n}\n\nfunction isJsonObject(value: unknown): value is Record<string, unknown> {\n  return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction resolveJsonSchemaRef(root: Record<string, unknown>, ref: string): unknown {\n  if (!ref.startsWith('#/')) {\n    throw new Error(`Unexpected $ref format ${ref}; does not start with #/`);\n  }\n\n  return ref\n    .slice(2)\n    .split('/')\n    .reduce<unknown>((current, part) => {\n      if (!isJsonObject(current)) {\n        throw new Error(`Encountered non-object while resolving ${ref}`);\n      }\n      const key = part.replace(/~1/g, '/').replace(/~0/g, '~');\n      return current[key];\n    }, root);\n}\n\nfunction jsonTypeMatches(value: unknown, typ: string): boolean {\n  switch (typ) {\n    case 'null':\n      return value === null;\n    case 'object':\n      return isJsonObject(value);\n    case 'array':\n      return Array.isArray(value);\n    case 'boolean':\n      return typeof value === 'boolean';\n    case 'integer':\n      return typeof value === 'number' && Number.isInteger(value);\n    case 'number':\n      return typeof value === 'number';\n    case 'string':\n      return typeof value === 'string';\n    default:\n      return true;\n  }\n}\n\nfunction jsonSchemaMatches(\n  value: unknown,\n  schema: Record<string, unknown>,\n  root: Record<string, unknown>,\n): boolean {\n  const ref = schema.$ref;\n  if (typeof ref === 'string') {\n    const resolved = resolveJsonSchemaRef(root, ref);\n    if (isJsonObject(resolved)) {\n      schema = { ...resolved, ...schema };\n    }\n  }\n\n  if (value === null && 'default' in schema && !jsonSchemaAllowsNull(schema, root)) {\n    return true;\n  }\n\n  if ('const' in schema && value !== schema.const) {\n    return false;\n  }\n  const enumValues = schema.enum;\n  if (Array.isArray(enumValues) && !enumValues.includes(value)) {\n    return false;\n  }\n\n  const typ = schema.type;\n  if (Array.isArray(typ)) {\n    if (!typ.some((item) => typeof item === 'string' && jsonTypeMatches(value, item))) {\n      return false;\n    }\n  } else if (typeof typ === 'string' && !jsonTypeMatches(value, typ)) {\n    return false;\n  }\n\n  if (isJsonObject(value)) {\n    const required = schema.required;\n    if (\n      Array.isArray(required) &&\n      !required.every((key) => typeof key !== 'string' || key in value)\n    ) {\n      return false;\n    }\n\n    const properties = schema.properties;\n    if (isJsonObject(properties)) {\n      if (\n        (schema.additionalProperties === undefined || schema.additionalProperties === false) &&\n        Object.keys(value).some((key) => !(key in properties))\n      ) {\n        return false;\n      }\n\n      for (const [key, item] of Object.entries(value)) {\n        const propertySchema = properties[key];\n        if (isJsonObject(propertySchema) && !jsonSchemaMatches(item, propertySchema, root)) {\n          return false;\n        }\n      }\n    }\n  }\n\n  return true;\n}\n\nfunction injectSchemaDefaults(\n  value: unknown,\n  schema: Record<string, unknown>,\n  root: Record<string, unknown>,\n): unknown {\n  const ref = schema.$ref;\n  if (typeof ref === 'string') {\n    const resolved = resolveJsonSchemaRef(root, ref);\n    if (isJsonObject(resolved)) {\n      schema = { ...resolved, ...schema };\n    }\n  }\n\n  if (value === null) {\n    if ('default' in schema && !jsonSchemaAllowsNull(schema, root)) {\n      return structuredClone(schema.default);\n    }\n    return null;\n  }\n\n  const allOf = schema.allOf;\n  if (Array.isArray(allOf)) {\n    for (const variant of allOf) {\n      if (isJsonObject(variant)) {\n        value = injectSchemaDefaults(value, variant, root);\n      }\n    }\n  }\n\n  for (const unionKey of ['anyOf', 'oneOf'] as const) {\n    const variants = schema[unionKey];\n    if (Array.isArray(variants)) {\n      for (const variant of variants) {\n        if (isJsonObject(variant) && jsonSchemaMatches(value, variant, root)) {\n          return injectSchemaDefaults(value, variant, root);\n        }\n      }\n    }\n  }\n\n  if (isJsonObject(value)) {\n    const properties = schema.properties;\n    const additional = schema.additionalProperties;\n    if (isJsonObject(properties) || isJsonObject(additional)) {\n      return Object.fromEntries(\n        Object.entries(value).map(([key, item]) => {\n          const prop = isJsonObject(properties) ? properties[key] : undefined;\n          if (isJsonObject(prop)) {\n            return [key, injectSchemaDefaults(item, prop, root)];\n          }\n          if (isJsonObject(additional)) {\n            return [key, injectSchemaDefaults(item, additional, root)];\n          }\n          return [key, item];\n        }),\n      );\n    }\n  }\n\n  if (Array.isArray(value)) {\n    const prefixItems = schema.prefixItems;\n    const items = schema.items;\n    if (Array.isArray(prefixItems) || Array.isArray(items) || isJsonObject(items)) {\n      return value.map((item, index) => {\n        const prefixItem = Array.isArray(prefixItems) ? prefixItems[index] : undefined;\n        if (isJsonObject(prefixItem)) {\n          return injectSchemaDefaults(item, prefixItem, root);\n        }\n        const tupleItem = Array.isArray(items) ? items[index] : undefined;\n        if (isJsonObject(tupleItem)) {\n          return injectSchemaDefaults(item, tupleItem, root);\n        }\n        if (isJsonObject(items)) {\n          return injectSchemaDefaults(item, items, root);\n        }\n        return item;\n      });\n    }\n  }\n\n  return value;\n}\n\nexport async function executeToolCall(\n  toolCall: FunctionCall,\n  toolCtx: ToolContext,\n): Promise<FunctionCallOutput> {\n  const tool = toolCtx.getFunctionTool(toolCall.name);\n  if (!tool) {\n    const availableTools = sortedToolNames(toolCtx).join(', ');\n    return FunctionCallOutput.create({\n      callId: toolCall.callId,\n      name: toolCall.name,\n      output: `Unknown function: ${toolCall.name} - available tools: ${availableTools}`,\n      isError: true,\n    });\n  }\n\n  let args: object | undefined;\n  let params: object | undefined;\n\n  // Ensure valid JSON\n  try {\n    const rawArgs = toolCall.args || '{}';\n    args = parseFunctionArguments(rawArgs);\n    const canonicalArgs = JSON.stringify(args);\n    if (canonicalArgs !== rawArgs) {\n      toolCall.args = canonicalArgs;\n    }\n  } catch (error) {\n    return FunctionCallOutput.create({\n      callId: toolCall.callId,\n      output: `Invalid JSON: ${error}`,\n      isError: true,\n    });\n  }\n\n  // Ensure valid arguments schema\n  try {\n    if (isZodSchema(tool.parameters)) {\n      const schema = zodSchemaToJsonSchema(tool.parameters, false) as Record<string, unknown>;\n      const argsWithDefaults = injectSchemaDefaults(args, schema, schema);\n      const result = await parseZodSchema<object>(tool.parameters, argsWithDefaults);\n      if (result.success) {\n        params = result.data;\n      } else {\n        return FunctionCallOutput.create({\n          callId: toolCall.callId,\n          output: `Arguments parsing failed: ${result.error}`,\n          isError: true,\n        });\n      }\n    } else {\n      params = args;\n    }\n  } catch (error) {\n    return FunctionCallOutput.create({\n      callId: toolCall.callId,\n      output: `Arguments parsing failed: ${error}`,\n      isError: true,\n    });\n  }\n\n  try {\n    const result = await tool.execute(params, createToolOptions(toolCall.callId));\n    return FunctionCallOutput.create({\n      callId: toolCall.callId,\n      output: JSON.stringify(result),\n      isError: false,\n    });\n  } catch (error) {\n    return FunctionCallOutput.create({\n      callId: toolCall.callId,\n      output: `Tool execution failed: ${error}`,\n      isError: true,\n    });\n  }\n}\n\nexport interface FormatChatHistoryOptions {\n  includeIds?: boolean;\n  includeTimestamps?: boolean;\n}\n\nexport type ChatContextValidationSeverity = 'error' | 'warning';\n\nexport interface ChatContextValidationIssue {\n  severity: ChatContextValidationSeverity;\n  code:\n    | 'duplicate_id'\n    | 'timestamp_order'\n    | 'empty_message_content'\n    | 'empty_text_term'\n    | 'missing_image_term'\n    | 'invalid_audio_term'\n    | 'invalid_function_call'\n    | 'invalid_function_call_args'\n    | 'invalid_function_call_output'\n    | 'orphan_function_call_output';\n  index: number;\n  itemId: string;\n  message: string;\n}\n\nexport interface ChatContextValidationResult {\n  valid: boolean;\n  errors: number;\n  warnings: number;\n  issues: ChatContextValidationIssue[];\n}\n\n/**\n * Render a chat context into a readable multiline string for debugging and logging.\n */\nexport function formatChatHistory(\n  chatCtx: ChatContext,\n  options: FormatChatHistoryOptions = {},\n): string {\n  const { includeIds = false, includeTimestamps = false } = options;\n\n  if (chatCtx.items.length === 0) {\n    return 'Chat history (0 items)';\n  }\n\n  const formattedItems = chatCtx.items.map((item, index) =>\n    formatChatHistoryItem(item, index, {\n      includeIds,\n      includeTimestamps,\n    }),\n  );\n\n  return [\n    `Chat history (${chatCtx.items.length} items)`,\n    ...formattedItems.flatMap((item) => ['', item]),\n  ].join('\\n');\n}\n\n/**\n * Validate structural integrity of chat context items/terms for realtime usage.\n */\nexport function validateChatContextStructure(chatCtx: ChatContext): ChatContextValidationResult {\n  const issues: ChatContextValidationIssue[] = [];\n  const ids = new Set<string>();\n  const seenFunctionCallIds = new Set<string>();\n  let previousCreatedAt = -Infinity;\n\n  const pushIssue = (issue: ChatContextValidationIssue) => {\n    issues.push(issue);\n  };\n\n  for (let index = 0; index < chatCtx.items.length; index += 1) {\n    const item = chatCtx.items[index]!;\n\n    if (ids.has(item.id)) {\n      pushIssue({\n        severity: 'error',\n        code: 'duplicate_id',\n        index,\n        itemId: item.id,\n        message: `Duplicate item id '${item.id}'`,\n      });\n    } else {\n      ids.add(item.id);\n    }\n\n    if (item.createdAt < previousCreatedAt) {\n      pushIssue({\n        severity: 'error',\n        code: 'timestamp_order',\n        index,\n        itemId: item.id,\n        message: `Item createdAt (${item.createdAt}) is older than previous item (${previousCreatedAt})`,\n      });\n    }\n    previousCreatedAt = item.createdAt;\n\n    if (item.type === 'message') {\n      if (item.content.length === 0) {\n        pushIssue({\n          severity: 'warning',\n          code: 'empty_message_content',\n          index,\n          itemId: item.id,\n          message: 'Message has empty content array',\n        });\n      }\n\n      item.content.forEach((term, termIndex) => {\n        if (typeof term === 'string') {\n          if (term.trim().length === 0) {\n            pushIssue({\n              severity: 'warning',\n              code: 'empty_text_term',\n              index,\n              itemId: item.id,\n              message: `Message term[${termIndex}] is empty text`,\n            });\n          }\n          return;\n        }\n\n        if (term.type === 'instructions') {\n          return;\n        }\n\n        if (term.type === 'image_content') {\n          if (!term.id || term.image === undefined || term.image === null) {\n            pushIssue({\n              severity: 'error',\n              code: 'missing_image_term',\n              index,\n              itemId: item.id,\n              message: `Message term[${termIndex}] has invalid image content`,\n            });\n          }\n          return;\n        }\n\n        if (!Array.isArray(term.frame)) {\n          pushIssue({\n            severity: 'error',\n            code: 'invalid_audio_term',\n            index,\n            itemId: item.id,\n            message: `Message term[${termIndex}] has invalid audio content`,\n          });\n        }\n      });\n    } else if (item.type === 'function_call') {\n      if (!item.name || !item.callId) {\n        pushIssue({\n          severity: 'error',\n          code: 'invalid_function_call',\n          index,\n          itemId: item.id,\n          message: 'Function call is missing name or callId',\n        });\n      } else {\n        seenFunctionCallIds.add(item.callId);\n      }\n\n      try {\n        JSON.parse(item.args);\n      } catch {\n        pushIssue({\n          severity: 'warning',\n          code: 'invalid_function_call_args',\n          index,\n          itemId: item.id,\n          message: 'Function call args are not valid JSON',\n        });\n      }\n    } else if (item.type === 'function_call_output') {\n      if (!item.callId) {\n        pushIssue({\n          severity: 'error',\n          code: 'invalid_function_call_output',\n          index,\n          itemId: item.id,\n          message: 'Function call output is missing callId',\n        });\n      } else if (!seenFunctionCallIds.has(item.callId)) {\n        pushIssue({\n          severity: 'warning',\n          code: 'orphan_function_call_output',\n          index,\n          itemId: item.id,\n          message: `Function call output references unknown callId '${item.callId}'`,\n        });\n      }\n    }\n  }\n\n  const errors = issues.filter((issue) => issue.severity === 'error').length;\n  const warnings = issues.length - errors;\n  return {\n    valid: errors === 0,\n    errors,\n    warnings,\n    issues,\n  };\n}\n\nfunction formatChatHistoryItem(\n  item: ChatItem,\n  index: number,\n  options: Required<FormatChatHistoryOptions>,\n): string {\n  const headerParts = [`[${index}]`];\n\n  if (item.type === 'message') {\n    headerParts.push('message', item.role);\n  } else if (item.type === 'function_call') {\n    headerParts.push('function_call', item.name, `call_id=${item.callId}`);\n  } else if (item.type === 'function_call_output') {\n    headerParts.push('function_call_output', item.name || '(unnamed)', `call_id=${item.callId}`);\n    if (item.isError) {\n      headerParts.push('error=true');\n    }\n  } else if (item.type === 'agent_handoff') {\n    headerParts.push('agent_handoff');\n  } else {\n    headerParts.push('agent_config_update');\n  }\n\n  if (options.includeIds) {\n    headerParts.push(`id=${item.id}`);\n  }\n\n  if (options.includeTimestamps) {\n    headerParts.push(`created_at=${item.createdAt.toFixed(3)}`);\n  }\n\n  const body = formatChatHistoryItemBody(item);\n  if (!body) {\n    return headerParts.join(' ');\n  }\n\n  return `${headerParts.join(' ')}\\n${indentBlock(body, '  ')}`;\n}\n\nfunction formatChatHistoryItemBody(item: ChatItem): string {\n  if (item.type === 'message') {\n    const content = item.content.map((part) => formatMessageContentPart(part)).join('\\n');\n    return content.trim() ? content : '(empty)';\n  }\n\n  if (item.type === 'function_call') {\n    return prettyJsonText(item.args);\n  }\n\n  if (item.type === 'function_call_output') {\n    return prettyJsonText(item.output);\n  }\n\n  if (item.type === 'agent_handoff') {\n    return `${item.oldAgentId ?? '(none)'} -> ${item.newAgentId}`;\n  }\n\n  return JSON.stringify(\n    {\n      instructions: item.instructions,\n      toolsAdded: item.toolsAdded,\n      toolsRemoved: item.toolsRemoved,\n    },\n    null,\n    2,\n  );\n}\n\nfunction formatMessageContentPart(part: ChatContent): string {\n  if (typeof part === 'string') {\n    return part;\n  }\n\n  if (part.type === 'instructions') {\n    return part.value;\n  }\n\n  if (part.type === 'image_content') {\n    if (typeof part.image === 'string') {\n      return `[image url=${truncateText(part.image, 120)}]`;\n    }\n\n    return `[image frame=${part.image.width}x${part.image.height}]`;\n  }\n\n  if (part.transcript) {\n    return `[audio transcript=${JSON.stringify(truncateText(part.transcript, 120))}]`;\n  }\n\n  return `[audio frames=${part.frame.length}]`;\n}\n\nfunction prettyJsonText(text: string): string {\n  try {\n    return JSON.stringify(JSON.parse(text), null, 2);\n  } catch {\n    return text;\n  }\n}\n\nfunction truncateText(text: string, maxLength: number): string {\n  if (text.length <= maxLength) {\n    return text;\n  }\n\n  return `${text.slice(0, Math.max(0, maxLength - 3))}...`;\n}\n\nfunction indentBlock(text: string, indent: string): string {\n  return text\n    .split('\\n')\n    .map((line) => `${indent}${line}`)\n    .join('\\n');\n}\n\n/**\n * Standard dynamic-programming LCS to get the common subsequence\n * of IDs (in order) that appear in both old_ids and new_ids.\n *\n * @param oldIds - The old list of IDs.\n * @param newIds - The new list of IDs.\n * @returns The longest common subsequence of the two lists of IDs.\n */\nfunction computeLCS(oldIds: string[], newIds: string[]): string[] {\n  const n = oldIds.length;\n  const m = newIds.length;\n  const dp: number[][] = Array(n + 1)\n    .fill(null)\n    .map(() => Array(m + 1).fill(0));\n\n  // Fill DP table\n  for (let i = 1; i <= n; i++) {\n    for (let j = 1; j <= m; j++) {\n      if (oldIds[i - 1] === newIds[j - 1]) {\n        dp[i]![j] = dp[i - 1]![j - 1]! + 1;\n      } else {\n        dp[i]![j] = Math.max(dp[i - 1]![j]!, dp[i]![j - 1]!);\n      }\n    }\n  }\n\n  // Backtrack to find the actual LCS sequence\n  const lcsIds: string[] = [];\n  let i = n;\n  let j = m;\n  while (i > 0 && j > 0) {\n    if (oldIds[i - 1] === newIds[j - 1]) {\n      lcsIds.push(oldIds[i - 1]!);\n      i--;\n      j--;\n    } else if (dp[i - 1]![j]! > dp[i]![j - 1]!) {\n      i--;\n    } else {\n      j--;\n    }\n  }\n\n  return lcsIds.reverse();\n}\n\ninterface DiffOps {\n  toRemove: string[];\n  toCreate: Array<[string | null, string]>; // (previous_item_id, id), if previous_item_id is null, add to the root\n  toUpdate: Array<[string | null, string]>; // (previous_item_id, id), the items with the same id but different content\n}\n\n/**\n * Compute the minimal list of create/remove/update operations to transform oldCtx into newCtx.\n *\n * @param oldCtx - The old chat context.\n * @param newCtx - The new chat context.\n * @returns The minimal list of create/remove/update operations to transform oldCtx into newCtx.\n */\nexport function computeChatCtxDiff(oldCtx: ChatContext, newCtx: ChatContext): DiffOps {\n  const oldIds = oldCtx.items.map((item: ChatItem) => item.id);\n  const newIds = newCtx.items.map((item: ChatItem) => item.id);\n  const lcsIds = new Set(computeLCS(oldIds, newIds));\n  const oldCtxById = new Map(oldCtx.items.map((item) => [item.id, item]));\n\n  const toRemove = oldCtx.items.filter((msg) => !lcsIds.has(msg.id)).map((msg) => msg.id);\n  const toCreate: Array<[string | null, string]> = [];\n  const toUpdate: Array<[string | null, string]> = [];\n\n  let lastIdInSequence: string | null = null;\n  for (const newItem of newCtx.items) {\n    if (lcsIds.has(newItem.id)) {\n      const oldItem = oldCtxById.get(newItem.id);\n      if (\n        oldItem?.type === 'message' &&\n        newItem.type === 'message' &&\n        oldItem.rawTextContent !== newItem.rawTextContent\n      ) {\n        toUpdate.push([lastIdInSequence, newItem.id]);\n      }\n      lastIdInSequence = newItem.id;\n    } else {\n      const prevId = lastIdInSequence; // null if root\n      toCreate.push([prevId, newItem.id]);\n      lastIdInSequence = newItem.id;\n    }\n  }\n\n  return {\n    toRemove,\n    toCreate,\n    toUpdate,\n  };\n}\n\nexport function toJsonSchema(\n  schema: ToolInputSchema<any>,\n  isOpenai: boolean = true,\n  strict: boolean = false,\n): JSONSchema7 {\n  if (isZodSchema(schema)) {\n    return zodSchemaToJsonSchema(schema, isOpenai, strict);\n  }\n\n  return schema as JSONSchema7;\n}\n"],"mappings":"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","names":["idx","keep","sharp","i","j"]}