import { createImmutableArray, shortuuid } from "../utils.js";
import { toChatCtx } from "./provider_format/index.js";
const INSTRUCTIONS_SYMBOL = Symbol.for("livekit.agents.Instructions");
function isInstructions(value) {
  return typeof value === "object" && value !== null && INSTRUCTIONS_SYMBOL in value && value[INSTRUCTIONS_SYMBOL] === true;
}
class Instructions {
  type = "instructions";
  _audioVariant;
  /** Raw text variant; falls back to {@link audio} when omitted. */
  _textVariant;
  /** The currently rendered string (what providers should treat as content). */
  value;
  /** @internal Symbol marker for type identification */
  [INSTRUCTIONS_SYMBOL] = true;
  constructor(options) {
    this._audioVariant = options.audio;
    this._textVariant = options.text;
    this.value = options.represent ?? options.audio;
  }
  static tpl(strings, ...values) {
    const render = (mode) => {
      let result = strings[0];
      for (let i = 0; i < values.length; i++) {
        const value = values[i];
        if (isInstructions(value)) {
          result += mode === "audio" ? value.audio : mode === "text" ? value.text : value.value;
        } else {
          result += String(value);
        }
        result += strings[i + 1];
      }
      return result;
    };
    const hasTextVariant = values.some(
      (value) => isInstructions(value) && value._textVariant !== void 0
    );
    return new Instructions({
      audio: render("audio"),
      text: hasTextVariant ? render("text") : void 0,
      represent: render("value")
    });
  }
  /** The audio (voice) variant of the instructions. */
  get audio() {
    return this._audioVariant;
  }
  /** The text variant of the instructions. Falls back to {@link audio}. */
  get text() {
    return this._textVariant ?? this.audio;
  }
  /**
   * Return a copy whose {@link value} is the variant matching `modality`.
   * Both `audio` and `text` variants are preserved on the result, so this can
   * be called again for a different modality (e.g. across tool-call turns).
   */
  asModality(modality) {
    return new Instructions({
      audio: this.audio,
      text: this._textVariant,
      represent: modality === "audio" ? this.audio : this.text
    });
  }
  /** Concatenate, propagating both variants and the current rendered value. */
  concat(other) {
    if (isInstructions(other)) {
      const hasText = this._textVariant !== void 0 || other._textVariant !== void 0;
      return new Instructions({
        audio: this.audio + other.audio,
        text: hasText ? this.text + other.text : void 0,
        represent: this.value + other.value
      });
    }
    return new Instructions({
      audio: this.audio + other,
      text: this._textVariant !== void 0 ? this._textVariant + other : void 0,
      represent: this.value + other
    });
  }
  toString() {
    return this.value;
  }
  toJSON() {
    const result = {
      type: "instructions",
      audio: this.audio
    };
    if (this._textVariant !== void 0) {
      result.text = this._textVariant;
    }
    return result;
  }
}
function renderInstructions(instructions, modality) {
  if (typeof instructions === "string") return instructions;
  return modality === void 0 ? instructions.value : instructions.asModality(modality).value;
}
function instructionsEqual(a, b) {
  if (a === b) return true;
  if (a === void 0 || b === void 0) return false;
  const aIsInstr = isInstructions(a);
  const bIsInstr = isInstructions(b);
  if (aIsInstr && bIsInstr) {
    return a.audio === b.audio && a.text === b.text;
  }
  if (!aIsInstr && !bIsInstr) {
    return a === b;
  }
  return false;
}
function concatInstructions(...parts) {
  if (parts.length === 0) return "";
  const hasInstructions = parts.some((p) => isInstructions(p));
  if (!hasInstructions) return parts.join("");
  let acc = parts[0];
  for (let i = 1; i < parts.length; i++) {
    const next = parts[i];
    if (isInstructions(acc)) {
      acc = acc.concat(next);
    } else if (isInstructions(next)) {
      acc = new Instructions({ audio: acc }).concat(next);
    } else {
      acc = acc + next;
    }
  }
  return acc;
}
function createImageContent(params) {
  const {
    image,
    id = shortuuid("img_"),
    inferenceDetail = "auto",
    inferenceWidth,
    inferenceHeight,
    mimeType
  } = params;
  return {
    id,
    type: "image_content",
    image,
    inferenceDetail,
    inferenceWidth,
    inferenceHeight,
    mimeType,
    _cache: {}
  };
}
function createAudioContent(params) {
  const { frame, transcript } = params;
  return {
    type: "audio_content",
    frame,
    transcript
  };
}
class ChatMessage {
  id;
  type = "message";
  role;
  content;
  interrupted;
  transcriptConfidence;
  extra;
  metrics;
  hash;
  createdAt;
  constructor(params) {
    const {
      role,
      content,
      id = shortuuid("item_"),
      interrupted = false,
      createdAt = Date.now(),
      transcriptConfidence,
      metrics = {},
      extra = {}
    } = params;
    this.id = id;
    this.role = role;
    this.content = Array.isArray(content) ? content : [content];
    this.interrupted = interrupted;
    this.createdAt = createdAt;
    this.transcriptConfidence = transcriptConfidence;
    this.metrics = metrics;
    this.extra = extra;
  }
  static create(params) {
    return new ChatMessage(params);
  }
  /**
   * Returns a single string with all text parts of the message joined by new
   * lines. If no string content is present, returns `null`.
   */
  get textContent() {
    const parts = this.content.filter((c) => typeof c === "string" || isInstructions(c)).map((c) => typeof c === "string" ? c : c.value);
    return parts.length > 0 ? parts.join("\n") : void 0;
  }
  toJSONContent() {
    return this.content.map((c) => {
      if (typeof c === "string") {
        return c;
      } else if (isInstructions(c)) {
        return c.toJSON();
      } else if (c.type === "image_content") {
        return {
          id: c.id,
          type: c.type,
          image: c.image,
          inferenceDetail: c.inferenceDetail,
          inferenceWidth: c.inferenceWidth,
          inferenceHeight: c.inferenceHeight,
          mimeType: c.mimeType
        };
      } else {
        return {
          type: c.type,
          transcript: c.transcript
        };
      }
    });
  }
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  toJSON(excludeTimestamp = false) {
    const result = {
      id: this.id,
      type: this.type,
      role: this.role,
      content: this.toJSONContent(),
      interrupted: this.interrupted
    };
    if (!excludeTimestamp) {
      result.createdAt = this.createdAt;
    }
    if (this.transcriptConfidence !== void 0) {
      result.transcriptConfidence = this.transcriptConfidence;
    }
    if (Object.keys(this.metrics).length > 0) {
      result.metrics = { ...this.metrics };
    }
    if (Object.keys(this.extra).length > 0) {
      result.extra = this.extra;
    }
    return result;
  }
}
class FunctionCall {
  id;
  type = "function_call";
  callId;
  args;
  name;
  createdAt;
  extra;
  /**
   * Optional grouping identifier for parallel tool calls.
   */
  groupId;
  /**
   * Opaque signature for Gemini thinking mode.
   * When using Gemini 3+ models with thinking enabled, this signature must be
   * preserved and returned with function responses to maintain thought context.
   */
  thoughtSignature;
  constructor(params) {
    const {
      callId,
      name,
      args,
      id = shortuuid("item_"),
      createdAt = Date.now(),
      extra = {},
      groupId,
      thoughtSignature
    } = params;
    this.id = id;
    this.callId = callId;
    this.args = args;
    this.name = name;
    this.createdAt = createdAt;
    this.extra = { ...extra };
    this.groupId = groupId;
    this.thoughtSignature = thoughtSignature ?? (typeof this.extra.google === "object" && this.extra.google !== null ? (
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      this.extra.google.thoughtSignature || this.extra.google.thought_signature
    ) : void 0);
  }
  static create(params) {
    return new FunctionCall(params);
  }
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  toJSON(excludeTimestamp = false) {
    const result = {
      id: this.id,
      type: this.type,
      callId: this.callId,
      name: this.name,
      args: this.args
    };
    if (Object.keys(this.extra).length > 0) {
      result.extra = this.extra;
    }
    if (this.groupId) {
      result.groupId = this.groupId;
    }
    if (this.thoughtSignature) {
      result.thoughtSignature = this.thoughtSignature;
    }
    if (!excludeTimestamp) {
      result.createdAt = this.createdAt;
    }
    return result;
  }
}
class FunctionCallOutput {
  id;
  type = "function_call_output";
  name = "";
  callId;
  output;
  isError;
  createdAt;
  constructor(params) {
    const {
      callId,
      output,
      isError,
      id = shortuuid("item_"),
      createdAt = Date.now(),
      name = ""
    } = params;
    this.id = id;
    this.callId = callId;
    this.output = output;
    this.isError = isError;
    this.name = name;
    this.createdAt = createdAt;
  }
  static create(params) {
    return new FunctionCallOutput(params);
  }
  toJSON(excludeTimestamp = false) {
    const result = {
      id: this.id,
      type: this.type,
      name: this.name,
      callId: this.callId,
      output: this.output,
      isError: this.isError
    };
    if (!excludeTimestamp) {
      result.createdAt = this.createdAt;
    }
    return result;
  }
}
class AgentHandoffItem {
  id;
  type = "agent_handoff";
  oldAgentId;
  newAgentId;
  createdAt;
  constructor(params) {
    const { oldAgentId, newAgentId, id = shortuuid("item_"), createdAt = Date.now() } = params;
    this.id = id;
    this.oldAgentId = oldAgentId;
    this.newAgentId = newAgentId;
    this.createdAt = createdAt;
  }
  static create(params) {
    return new AgentHandoffItem(params);
  }
  toJSON(excludeTimestamp = false) {
    const result = {
      id: this.id,
      type: this.type,
      newAgentId: this.newAgentId
    };
    if (this.oldAgentId !== void 0) {
      result.oldAgentId = this.oldAgentId;
    }
    if (!excludeTimestamp) {
      result.createdAt = this.createdAt;
    }
    return result;
  }
}
class AgentConfigUpdate {
  id;
  type = "agent_config_update";
  instructions;
  toolsAdded;
  toolsRemoved;
  createdAt;
  constructor(params = {}) {
    const {
      id = shortuuid("item_"),
      instructions,
      toolsAdded,
      toolsRemoved,
      createdAt = Date.now()
    } = params;
    this.id = id;
    this.instructions = instructions;
    this.toolsAdded = toolsAdded;
    this.toolsRemoved = toolsRemoved;
    this.createdAt = createdAt;
  }
  static create(params) {
    return new AgentConfigUpdate(params);
  }
  toJSON(excludeTimestamp = false) {
    const result = {
      id: this.id,
      type: this.type
    };
    if (this.instructions !== void 0) {
      result.instructions = isInstructions(this.instructions) ? this.instructions.toJSON() : this.instructions;
    }
    if (this.toolsAdded !== void 0) {
      result.toolsAdded = this.toolsAdded;
    }
    if (this.toolsRemoved !== void 0) {
      result.toolsRemoved = this.toolsRemoved;
    }
    if (!excludeTimestamp) {
      result.createdAt = this.createdAt;
    }
    return result;
  }
}
class ChatContext {
  _items;
  constructor(items) {
    this._items = items ? items : [];
  }
  static empty() {
    return new ChatContext([]);
  }
  get items() {
    return this._items;
  }
  set items(items) {
    this._items = items;
  }
  /**
   * Add a new message to the context and return it.
   */
  addMessage(params) {
    const msg = new ChatMessage(params);
    if (params.createdAt !== void 0) {
      const idx = this.findInsertionIndex(params.createdAt);
      this._items.splice(idx, 0, msg);
    } else {
      this._items.push(msg);
    }
    return msg;
  }
  /**
   * Insert a single item or multiple items based on their `createdAt` field so
   * that the array keeps its chronological order.
   */
  insert(item) {
    const arr = Array.isArray(item) ? item : [item];
    for (const it of arr) {
      const idx = this.findInsertionIndex(it.createdAt);
      this._items.splice(idx, 0, it);
    }
  }
  getById(itemId) {
    return this._items.find((i) => i.id === itemId);
  }
  indexById(itemId) {
    const idx = this._items.findIndex((i) => i.id === itemId);
    return idx !== -1 ? idx : void 0;
  }
  copy(options = {}) {
    const {
      excludeFunctionCall = false,
      excludeInstructions = false,
      excludeEmptyMessage = false,
      excludeHandoff = false,
      excludeConfigUpdate = false,
      toolCtx
    } = options;
    const items = [];
    const isToolCallOrOutput = (item) => ["function_call", "function_call_output"].includes(item.type);
    const isChatMessage = (item) => item.type === "message";
    for (const item of this._items) {
      if (excludeFunctionCall && isToolCallOrOutput(item)) {
        continue;
      }
      if (excludeInstructions && isChatMessage(item) && ["system", "developer"].includes(item.role)) {
        continue;
      }
      if (excludeEmptyMessage && isChatMessage(item) && item.content.length === 0) {
        continue;
      }
      if (excludeHandoff && item.type === "agent_handoff") {
        continue;
      }
      if (excludeConfigUpdate && item.type === "agent_config_update") {
        continue;
      }
      if (toolCtx !== void 0 && isToolCallOrOutput(item) && !toolCtx.hasTool(item.name)) {
        continue;
      }
      items.push(item);
    }
    return new ChatContext(items);
  }
  merge(other, options = {}) {
    const {
      excludeFunctionCall = false,
      excludeInstructions = false,
      excludeConfigUpdate = false
    } = options;
    const existingIds = new Set(this._items.map((item) => item.id));
    for (const item of other.items) {
      if (excludeFunctionCall && ["function_call", "function_call_output"].includes(item.type)) {
        continue;
      }
      if (excludeInstructions && item.type === "message" && (item.role === "system" || item.role === "developer")) {
        continue;
      }
      if (excludeConfigUpdate && item.type === "agent_config_update") {
        continue;
      }
      if (existingIds.has(item.id)) {
        continue;
      }
      const idx = this.findInsertionIndex(item.createdAt);
      this._items.splice(idx, 0, item);
      existingIds.add(item.id);
    }
    return this;
  }
  truncate(maxItems) {
    if (maxItems <= 0) return this;
    const instructions = this._items.find((i) => i.type === "message" && i.role === "system");
    let newItems = this._items.slice(-maxItems);
    while (newItems.length > 0 && ["function_call", "function_call_output"].includes(newItems[0].type)) {
      newItems.shift();
    }
    if (instructions) {
      if (!newItems.includes(instructions)) {
        newItems = [instructions, ...newItems];
      }
    }
    this._items.splice(0, this._items.length, ...newItems);
    return this;
  }
  toJSON(options = {}) {
    const {
      excludeImage = true,
      excludeAudio = true,
      excludeTimestamp = true,
      excludeFunctionCall = false,
      excludeConfigUpdate = false
    } = options;
    const items = [];
    for (const item of this._items) {
      let processedItem = item;
      if (excludeFunctionCall && ["function_call", "function_call_output"].includes(item.type)) {
        continue;
      }
      if (excludeConfigUpdate && item.type === "agent_config_update") {
        continue;
      }
      if (item.type === "message") {
        processedItem = ChatMessage.create({
          role: item.role,
          content: item.content,
          id: item.id,
          interrupted: item.interrupted,
          createdAt: item.createdAt,
          transcriptConfidence: item.transcriptConfidence,
          metrics: item.metrics,
          extra: item.extra
        });
        if (excludeImage) {
          processedItem.content = processedItem.content.filter((c) => {
            return !(typeof c === "object" && c.type === "image_content");
          });
        }
        if (excludeAudio) {
          processedItem.content = processedItem.content.filter((c) => {
            return !(typeof c === "object" && c.type === "audio_content");
          });
        }
      }
      items.push(processedItem);
    }
    return {
      items: items.map((item) => item.toJSON(excludeTimestamp))
    };
  }
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  async toProviderFormat(format, injectDummyUserMessage = true) {
    return await toChatCtx(format, this, injectDummyUserMessage);
  }
  /**
   * Internal helper used by `truncate` & `addMessage` to find the correct
   * insertion index for a timestamp so the list remains sorted.
   */
  findInsertionIndex(createdAt) {
    for (let i = this._items.length - 1; i >= 0; i -= 1) {
      const item = this._items[i];
      if (item.createdAt <= createdAt) {
        return i + 1;
      }
    }
    return 0;
  }
  /**
   * Return true if `other` has the same sequence of items with matching
   * essential fields (IDs, types, and payload) as this context.
   *
   * Comparison rules:
   * - Messages: compares the full `content` list, `role` and `interrupted`.
   * - Function calls: compares `name`, `callId`, and `args`.
   * - Function call outputs: compares `name`, `callId`, `output`, and `isError`.
   *
   * Does not consider timestamps or other metadata.
   */
  isEquivalent(other) {
    if (this === other) {
      return true;
    }
    if (this.items.length !== other.items.length) {
      return false;
    }
    for (let i = 0; i < this.items.length; i++) {
      const a = this.items[i];
      const b = other.items[i];
      if (a.id !== b.id || a.type !== b.type) {
        return false;
      }
      if (a.type === "message" && b.type === "message") {
        if (a.role !== b.role || a.interrupted !== b.interrupted || !this.compareContent(a.content, b.content)) {
          return false;
        }
      } else if (a.type === "function_call" && b.type === "function_call") {
        if (a.name !== b.name || a.callId !== b.callId || a.args !== b.args || a.thoughtSignature !== b.thoughtSignature || a.groupId !== b.groupId || JSON.stringify(a.extra) !== JSON.stringify(b.extra)) {
          return false;
        }
      } else if (a.type === "function_call_output" && b.type === "function_call_output") {
        if (a.name !== b.name || a.callId !== b.callId || a.output !== b.output || a.isError !== b.isError) {
          return false;
        }
      }
    }
    return true;
  }
  /**
   * Compare two content arrays for equality.
   */
  compareContent(a, b) {
    if (a.length !== b.length) {
      return false;
    }
    for (let i = 0; i < a.length; i++) {
      const contentA = a[i];
      const contentB = b[i];
      if (typeof contentA === "string" && typeof contentB === "string") {
        if (contentA !== contentB) {
          return false;
        }
        continue;
      }
      if (typeof contentA !== typeof contentB) {
        return false;
      }
      if (isInstructions(contentA) && isInstructions(contentB)) {
        if (contentA.audio !== contentB.audio || contentA.text !== contentB.text || contentA.value !== contentB.value) {
          return false;
        }
        continue;
      }
      if (isInstructions(contentA) || isInstructions(contentB)) {
        return false;
      }
      if (typeof contentA === "object" && typeof contentB === "object") {
        if (contentA.type === "image_content" && contentB.type === "image_content") {
          if (contentA.id !== contentB.id || contentA.image !== contentB.image || contentA.inferenceDetail !== contentB.inferenceDetail || contentA.inferenceWidth !== contentB.inferenceWidth || contentA.inferenceHeight !== contentB.inferenceHeight || contentA.mimeType !== contentB.mimeType) {
            return false;
          }
        } else if (contentA.type === "audio_content" && contentB.type === "audio_content") {
          if (contentA.frame.length !== contentB.frame.length) {
            return false;
          }
          if (contentA.transcript !== contentB.transcript) {
            return false;
          }
        } else {
          return false;
        }
      }
    }
    return true;
  }
  async _summarize(llm, options = {}) {
    var _a, _b;
    const { keepLastTurns = 2 } = options;
    const msgBudget = keepLastTurns * 2;
    let splitIdx = this._items.length;
    if (msgBudget > 0) {
      let msgCount = 0;
      let foundSplit = false;
      for (let i = this._items.length - 1; i >= 0; i -= 1) {
        const item = this._items[i];
        if (item.type === "message" && (item.role === "user" || item.role === "assistant")) {
          msgCount += 1;
          if (msgCount >= msgBudget) {
            splitIdx = i;
            foundSplit = true;
            break;
          }
        }
      }
      if (!foundSplit) {
        return this;
      }
    }
    if (splitIdx === 0) {
      return this;
    }
    const headItems = this._items.slice(0, splitIdx);
    const tailItems = this._items.slice(splitIdx);
    const toSummarize = [];
    for (const item of headItems) {
      if (item.type === "message") {
        if (item.role !== "user" && item.role !== "assistant") continue;
        if (((_a = item.extra) == null ? void 0 : _a.is_summary) === true) continue;
        const text = (item.textContent ?? "").trim();
        if (text) {
          toSummarize.push(item);
        }
      } else if (item.type === "function_call" || item.type === "function_call_output") {
        toSummarize.push(item);
      }
    }
    if (toSummarize.length === 0) {
      return this;
    }
    const sourceText = toSummarize.map((item) => {
      if (item.type === "message") {
        return toXml(item.role, (item.textContent ?? "").trim());
      }
      return functionCallItemToMessage(item).textContent ?? "";
    }).join("\n").trim();
    if (!sourceText) {
      return this;
    }
    const promptCtx = new ChatContext();
    promptCtx.addMessage({
      role: "system",
      content: [
        "Compress older conversation history into a short, faithful summary.",
        "",
        "The conversation is formatted as XML. Here is how to read it:",
        "- <user>...</user>  - something the user said.",
        "- <assistant>...</assistant>  - something the assistant said.",
        '- <function_call name="..." call_id="...">...</function_call>  - the assistant invoked an action.',
        '- <function_call_output name="..." call_id="...">...</function_call_output>  - the result of that action. May contain <error>...</error> if it failed.',
        "",
        "Guidelines:",
        "- Distill the information learned from function call outputs into the summary. Do not mention that a tool or function was called; just preserve the knowledge gained.",
        "- Focus on user goals, constraints, decisions, key facts, preferences, entities, and any pending or unresolved tasks.",
        "- Omit greetings, filler, and chit-chat.",
        "- Be concise."
      ].join("\n")
    });
    promptCtx.addMessage({
      role: "user",
      content: `Conversation to summarize:

${sourceText}`
    });
    const chunks = [];
    for await (const chunk of llm.chat({ chatCtx: promptCtx })) {
      if ((_b = chunk.delta) == null ? void 0 : _b.content) {
        chunks.push(chunk.delta.content);
      }
    }
    const summary = chunks.join("").trim();
    if (!summary) {
      return this;
    }
    const preserved = [];
    for (const it of headItems) {
      if (it.type === "message" && (it.role === "user" || it.role === "assistant")) {
        continue;
      }
      if (it.type === "function_call" || it.type === "function_call_output") {
        continue;
      }
      preserved.push(it);
    }
    this._items = preserved;
    const createdAtHint = tailItems.length > 0 ? tailItems[0].createdAt - 1e-6 : headItems[headItems.length - 1].createdAt + 1e-6;
    this.addMessage({
      role: "assistant",
      content: toXml("chat_history_summary", summary),
      createdAt: createdAtHint,
      extra: { is_summary: true }
    });
    this._items.push(...tailItems);
    return this;
  }
  /**
   * Indicates whether the context is read-only
   */
  get readonly() {
    return false;
  }
}
function toAttrsStr(attrs) {
  if (!attrs) {
    return void 0;
  }
  return Object.entries(attrs).map(([key, value]) => `${key}="${String(value)}"`).join(" ");
}
function toXml(tagName, content, attrs) {
  const attrsStr = toAttrsStr(attrs);
  if (content) {
    return [attrsStr ? `<${tagName} ${attrsStr}>` : `<${tagName}>`, content, `</${tagName}>`].join(
      "\n"
    );
  }
  return attrsStr ? `<${tagName} ${attrsStr} />` : `<${tagName} />`;
}
function functionCallItemToMessage(item) {
  if (item.type === "function_call") {
    return new ChatMessage({
      role: "user",
      content: [
        toXml("function_call", item.args, {
          name: item.name,
          call_id: item.callId
        })
      ],
      createdAt: item.createdAt,
      extra: { is_function_call: true }
    });
  }
  return new ChatMessage({
    role: "assistant",
    content: [
      toXml("function_call_output", item.isError ? toXml("error", item.output) : item.output, {
        name: item.name,
        call_id: item.callId
      })
    ],
    createdAt: item.createdAt,
    extra: { is_function_call_output: true }
  });
}
class ReadonlyChatContext extends ChatContext {
  static errorMsg = "Please use .copy() and agent.update_chat_ctx() to modify the chat context.";
  constructor(items) {
    super(createImmutableArray(items, ReadonlyChatContext.errorMsg));
  }
  get items() {
    return this._items;
  }
  set items(items) {
    throw new Error(
      `Cannot set items on a read-only chat context. ${ReadonlyChatContext.errorMsg}`
    );
  }
  get readonly() {
    return true;
  }
}
export {
  AgentConfigUpdate,
  AgentHandoffItem,
  ChatContext,
  ChatMessage,
  FunctionCall,
  FunctionCallOutput,
  Instructions,
  ReadonlyChatContext,
  concatInstructions,
  createAudioContent,
  createImageContent,
  instructionsEqual,
  isInstructions,
  renderInstructions
};
//# sourceMappingURL=chat_context.js.map