// src/index.ts
import { generateId } from "@ai-sdk/provider-utils";

// src/assistant-stream-parts.ts
var textStreamPart = {
  code: "0",
  name: "text",
  parse: (value) => {
    if (typeof value !== "string") {
      throw new Error('"text" parts expect a string value.');
    }
    return { type: "text", value };
  }
};
var errorStreamPart = {
  code: "3",
  name: "error",
  parse: (value) => {
    if (typeof value !== "string") {
      throw new Error('"error" parts expect a string value.');
    }
    return { type: "error", value };
  }
};
var assistantMessageStreamPart = {
  code: "4",
  name: "assistant_message",
  parse: (value) => {
    if (value == null || typeof value !== "object" || !("id" in value) || !("role" in value) || !("content" in value) || typeof value.id !== "string" || typeof value.role !== "string" || value.role !== "assistant" || !Array.isArray(value.content) || !value.content.every(
      (item) => item != null && typeof item === "object" && "type" in item && item.type === "text" && "text" in item && item.text != null && typeof item.text === "object" && "value" in item.text && typeof item.text.value === "string"
    )) {
      throw new Error(
        '"assistant_message" parts expect an object with an "id", "role", and "content" property.'
      );
    }
    return {
      type: "assistant_message",
      value
    };
  }
};
var assistantControlDataStreamPart = {
  code: "5",
  name: "assistant_control_data",
  parse: (value) => {
    if (value == null || typeof value !== "object" || !("threadId" in value) || !("messageId" in value) || typeof value.threadId !== "string" || typeof value.messageId !== "string") {
      throw new Error(
        '"assistant_control_data" parts expect an object with a "threadId" and "messageId" property.'
      );
    }
    return {
      type: "assistant_control_data",
      value: {
        threadId: value.threadId,
        messageId: value.messageId
      }
    };
  }
};
var dataMessageStreamPart = {
  code: "6",
  name: "data_message",
  parse: (value) => {
    if (value == null || typeof value !== "object" || !("role" in value) || !("data" in value) || typeof value.role !== "string" || value.role !== "data") {
      throw new Error(
        '"data_message" parts expect an object with a "role" and "data" property.'
      );
    }
    return {
      type: "data_message",
      value
    };
  }
};
var assistantStreamParts = [
  textStreamPart,
  errorStreamPart,
  assistantMessageStreamPart,
  assistantControlDataStreamPart,
  dataMessageStreamPart
];
var assistantStreamPartsByCode = {
  [textStreamPart.code]: textStreamPart,
  [errorStreamPart.code]: errorStreamPart,
  [assistantMessageStreamPart.code]: assistantMessageStreamPart,
  [assistantControlDataStreamPart.code]: assistantControlDataStreamPart,
  [dataMessageStreamPart.code]: dataMessageStreamPart
};
var StreamStringPrefixes = {
  [textStreamPart.name]: textStreamPart.code,
  [errorStreamPart.name]: errorStreamPart.code,
  [assistantMessageStreamPart.name]: assistantMessageStreamPart.code,
  [assistantControlDataStreamPart.name]: assistantControlDataStreamPart.code,
  [dataMessageStreamPart.name]: dataMessageStreamPart.code
};
var validCodes = assistantStreamParts.map((part) => part.code);
var parseAssistantStreamPart = (line) => {
  const firstSeparatorIndex = line.indexOf(":");
  if (firstSeparatorIndex === -1) {
    throw new Error("Failed to parse stream string. No separator found.");
  }
  const prefix = line.slice(0, firstSeparatorIndex);
  if (!validCodes.includes(prefix)) {
    throw new Error(`Failed to parse stream string. Invalid code ${prefix}.`);
  }
  const code = prefix;
  const textValue = line.slice(firstSeparatorIndex + 1);
  const jsonValue = JSON.parse(textValue);
  return assistantStreamPartsByCode[code].parse(jsonValue);
};
function formatAssistantStreamPart(type, value) {
  const streamPart = assistantStreamParts.find((part) => part.name === type);
  if (!streamPart) {
    throw new Error(`Invalid stream part type: ${type}`);
  }
  return `${streamPart.code}:${JSON.stringify(value)}
`;
}

// src/process-chat-response.ts
import { generateId as generateIdFunction } from "@ai-sdk/provider-utils";

// src/duplicated/usage.ts
function calculateLanguageModelUsage({
  promptTokens,
  completionTokens
}) {
  return {
    promptTokens,
    completionTokens,
    totalTokens: promptTokens + completionTokens
  };
}

// src/parse-partial-json.ts
import { safeParseJSON } from "@ai-sdk/provider-utils";

// src/fix-json.ts
function fixJson(input) {
  const stack = ["ROOT"];
  let lastValidIndex = -1;
  let literalStart = null;
  function processValueStart(char, i, swapState) {
    {
      switch (char) {
        case '"': {
          lastValidIndex = i;
          stack.pop();
          stack.push(swapState);
          stack.push("INSIDE_STRING");
          break;
        }
        case "f":
        case "t":
        case "n": {
          lastValidIndex = i;
          literalStart = i;
          stack.pop();
          stack.push(swapState);
          stack.push("INSIDE_LITERAL");
          break;
        }
        case "-": {
          stack.pop();
          stack.push(swapState);
          stack.push("INSIDE_NUMBER");
          break;
        }
        case "0":
        case "1":
        case "2":
        case "3":
        case "4":
        case "5":
        case "6":
        case "7":
        case "8":
        case "9": {
          lastValidIndex = i;
          stack.pop();
          stack.push(swapState);
          stack.push("INSIDE_NUMBER");
          break;
        }
        case "{": {
          lastValidIndex = i;
          stack.pop();
          stack.push(swapState);
          stack.push("INSIDE_OBJECT_START");
          break;
        }
        case "[": {
          lastValidIndex = i;
          stack.pop();
          stack.push(swapState);
          stack.push("INSIDE_ARRAY_START");
          break;
        }
      }
    }
  }
  function processAfterObjectValue(char, i) {
    switch (char) {
      case ",": {
        stack.pop();
        stack.push("INSIDE_OBJECT_AFTER_COMMA");
        break;
      }
      case "}": {
        lastValidIndex = i;
        stack.pop();
        break;
      }
    }
  }
  function processAfterArrayValue(char, i) {
    switch (char) {
      case ",": {
        stack.pop();
        stack.push("INSIDE_ARRAY_AFTER_COMMA");
        break;
      }
      case "]": {
        lastValidIndex = i;
        stack.pop();
        break;
      }
    }
  }
  for (let i = 0; i < input.length; i++) {
    const char = input[i];
    const currentState = stack[stack.length - 1];
    switch (currentState) {
      case "ROOT":
        processValueStart(char, i, "FINISH");
        break;
      case "INSIDE_OBJECT_START": {
        switch (char) {
          case '"': {
            stack.pop();
            stack.push("INSIDE_OBJECT_KEY");
            break;
          }
          case "}": {
            lastValidIndex = i;
            stack.pop();
            break;
          }
        }
        break;
      }
      case "INSIDE_OBJECT_AFTER_COMMA": {
        switch (char) {
          case '"': {
            stack.pop();
            stack.push("INSIDE_OBJECT_KEY");
            break;
          }
        }
        break;
      }
      case "INSIDE_OBJECT_KEY": {
        switch (char) {
          case '"': {
            stack.pop();
            stack.push("INSIDE_OBJECT_AFTER_KEY");
            break;
          }
        }
        break;
      }
      case "INSIDE_OBJECT_AFTER_KEY": {
        switch (char) {
          case ":": {
            stack.pop();
            stack.push("INSIDE_OBJECT_BEFORE_VALUE");
            break;
          }
        }
        break;
      }
      case "INSIDE_OBJECT_BEFORE_VALUE": {
        processValueStart(char, i, "INSIDE_OBJECT_AFTER_VALUE");
        break;
      }
      case "INSIDE_OBJECT_AFTER_VALUE": {
        processAfterObjectValue(char, i);
        break;
      }
      case "INSIDE_STRING": {
        switch (char) {
          case '"': {
            stack.pop();
            lastValidIndex = i;
            break;
          }
          case "\\": {
            stack.push("INSIDE_STRING_ESCAPE");
            break;
          }
          default: {
            lastValidIndex = i;
          }
        }
        break;
      }
      case "INSIDE_ARRAY_START": {
        switch (char) {
          case "]": {
            lastValidIndex = i;
            stack.pop();
            break;
          }
          default: {
            lastValidIndex = i;
            processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE");
            break;
          }
        }
        break;
      }
      case "INSIDE_ARRAY_AFTER_VALUE": {
        switch (char) {
          case ",": {
            stack.pop();
            stack.push("INSIDE_ARRAY_AFTER_COMMA");
            break;
          }
          case "]": {
            lastValidIndex = i;
            stack.pop();
            break;
          }
          default: {
            lastValidIndex = i;
            break;
          }
        }
        break;
      }
      case "INSIDE_ARRAY_AFTER_COMMA": {
        processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE");
        break;
      }
      case "INSIDE_STRING_ESCAPE": {
        stack.pop();
        lastValidIndex = i;
        break;
      }
      case "INSIDE_NUMBER": {
        switch (char) {
          case "0":
          case "1":
          case "2":
          case "3":
          case "4":
          case "5":
          case "6":
          case "7":
          case "8":
          case "9": {
            lastValidIndex = i;
            break;
          }
          case "e":
          case "E":
          case "-":
          case ".": {
            break;
          }
          case ",": {
            stack.pop();
            if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") {
              processAfterArrayValue(char, i);
            }
            if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") {
              processAfterObjectValue(char, i);
            }
            break;
          }
          case "}": {
            stack.pop();
            if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") {
              processAfterObjectValue(char, i);
            }
            break;
          }
          case "]": {
            stack.pop();
            if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") {
              processAfterArrayValue(char, i);
            }
            break;
          }
          default: {
            stack.pop();
            break;
          }
        }
        break;
      }
      case "INSIDE_LITERAL": {
        const partialLiteral = input.substring(literalStart, i + 1);
        if (!"false".startsWith(partialLiteral) && !"true".startsWith(partialLiteral) && !"null".startsWith(partialLiteral)) {
          stack.pop();
          if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") {
            processAfterObjectValue(char, i);
          } else if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") {
            processAfterArrayValue(char, i);
          }
        } else {
          lastValidIndex = i;
        }
        break;
      }
    }
  }
  let result = input.slice(0, lastValidIndex + 1);
  for (let i = stack.length - 1; i >= 0; i--) {
    const state = stack[i];
    switch (state) {
      case "INSIDE_STRING": {
        result += '"';
        break;
      }
      case "INSIDE_OBJECT_KEY":
      case "INSIDE_OBJECT_AFTER_KEY":
      case "INSIDE_OBJECT_AFTER_COMMA":
      case "INSIDE_OBJECT_START":
      case "INSIDE_OBJECT_BEFORE_VALUE":
      case "INSIDE_OBJECT_AFTER_VALUE": {
        result += "}";
        break;
      }
      case "INSIDE_ARRAY_START":
      case "INSIDE_ARRAY_AFTER_COMMA":
      case "INSIDE_ARRAY_AFTER_VALUE": {
        result += "]";
        break;
      }
      case "INSIDE_LITERAL": {
        const partialLiteral = input.substring(literalStart, input.length);
        if ("true".startsWith(partialLiteral)) {
          result += "true".slice(partialLiteral.length);
        } else if ("false".startsWith(partialLiteral)) {
          result += "false".slice(partialLiteral.length);
        } else if ("null".startsWith(partialLiteral)) {
          result += "null".slice(partialLiteral.length);
        }
      }
    }
  }
  return result;
}

// src/parse-partial-json.ts
function parsePartialJson(jsonText) {
  if (jsonText === void 0) {
    return { value: void 0, state: "undefined-input" };
  }
  let result = safeParseJSON({ text: jsonText });
  if (result.success) {
    return { value: result.value, state: "successful-parse" };
  }
  result = safeParseJSON({ text: fixJson(jsonText) });
  if (result.success) {
    return { value: result.value, state: "repaired-parse" };
  }
  return { value: void 0, state: "failed-parse" };
}

// src/data-stream-parts.ts
var textStreamPart2 = {
  code: "0",
  name: "text",
  parse: (value) => {
    if (typeof value !== "string") {
      throw new Error('"text" parts expect a string value.');
    }
    return { type: "text", value };
  }
};
var dataStreamPart = {
  code: "2",
  name: "data",
  parse: (value) => {
    if (!Array.isArray(value)) {
      throw new Error('"data" parts expect an array value.');
    }
    return { type: "data", value };
  }
};
var errorStreamPart2 = {
  code: "3",
  name: "error",
  parse: (value) => {
    if (typeof value !== "string") {
      throw new Error('"error" parts expect a string value.');
    }
    return { type: "error", value };
  }
};
var messageAnnotationsStreamPart = {
  code: "8",
  name: "message_annotations",
  parse: (value) => {
    if (!Array.isArray(value)) {
      throw new Error('"message_annotations" parts expect an array value.');
    }
    return { type: "message_annotations", value };
  }
};
var toolCallStreamPart = {
  code: "9",
  name: "tool_call",
  parse: (value) => {
    if (value == null || typeof value !== "object" || !("toolCallId" in value) || typeof value.toolCallId !== "string" || !("toolName" in value) || typeof value.toolName !== "string" || !("args" in value) || typeof value.args !== "object") {
      throw new Error(
        '"tool_call" parts expect an object with a "toolCallId", "toolName", and "args" property.'
      );
    }
    return {
      type: "tool_call",
      value
    };
  }
};
var toolResultStreamPart = {
  code: "a",
  name: "tool_result",
  parse: (value) => {
    if (value == null || typeof value !== "object" || !("toolCallId" in value) || typeof value.toolCallId !== "string" || !("result" in value)) {
      throw new Error(
        '"tool_result" parts expect an object with a "toolCallId" and a "result" property.'
      );
    }
    return {
      type: "tool_result",
      value
    };
  }
};
var toolCallStreamingStartStreamPart = {
  code: "b",
  name: "tool_call_streaming_start",
  parse: (value) => {
    if (value == null || typeof value !== "object" || !("toolCallId" in value) || typeof value.toolCallId !== "string" || !("toolName" in value) || typeof value.toolName !== "string") {
      throw new Error(
        '"tool_call_streaming_start" parts expect an object with a "toolCallId" and "toolName" property.'
      );
    }
    return {
      type: "tool_call_streaming_start",
      value
    };
  }
};
var toolCallDeltaStreamPart = {
  code: "c",
  name: "tool_call_delta",
  parse: (value) => {
    if (value == null || typeof value !== "object" || !("toolCallId" in value) || typeof value.toolCallId !== "string" || !("argsTextDelta" in value) || typeof value.argsTextDelta !== "string") {
      throw new Error(
        '"tool_call_delta" parts expect an object with a "toolCallId" and "argsTextDelta" property.'
      );
    }
    return {
      type: "tool_call_delta",
      value
    };
  }
};
var finishMessageStreamPart = {
  code: "d",
  name: "finish_message",
  parse: (value) => {
    if (value == null || typeof value !== "object" || !("finishReason" in value) || typeof value.finishReason !== "string") {
      throw new Error(
        '"finish_message" parts expect an object with a "finishReason" property.'
      );
    }
    const result = {
      finishReason: value.finishReason
    };
    if ("usage" in value && value.usage != null && typeof value.usage === "object" && "promptTokens" in value.usage && "completionTokens" in value.usage) {
      result.usage = {
        promptTokens: typeof value.usage.promptTokens === "number" ? value.usage.promptTokens : Number.NaN,
        completionTokens: typeof value.usage.completionTokens === "number" ? value.usage.completionTokens : Number.NaN
      };
    }
    return {
      type: "finish_message",
      value: result
    };
  }
};
var finishStepStreamPart = {
  code: "e",
  name: "finish_step",
  parse: (value) => {
    if (value == null || typeof value !== "object" || !("finishReason" in value) || typeof value.finishReason !== "string") {
      throw new Error(
        '"finish_step" parts expect an object with a "finishReason" property.'
      );
    }
    const result = {
      finishReason: value.finishReason,
      isContinued: false
    };
    if ("usage" in value && value.usage != null && typeof value.usage === "object" && "promptTokens" in value.usage && "completionTokens" in value.usage) {
      result.usage = {
        promptTokens: typeof value.usage.promptTokens === "number" ? value.usage.promptTokens : Number.NaN,
        completionTokens: typeof value.usage.completionTokens === "number" ? value.usage.completionTokens : Number.NaN
      };
    }
    if ("isContinued" in value && typeof value.isContinued === "boolean") {
      result.isContinued = value.isContinued;
    }
    return {
      type: "finish_step",
      value: result
    };
  }
};
var startStepStreamPart = {
  code: "f",
  name: "start_step",
  parse: (value) => {
    if (value == null || typeof value !== "object" || !("messageId" in value) || typeof value.messageId !== "string") {
      throw new Error(
        '"start_step" parts expect an object with an "id" property.'
      );
    }
    return {
      type: "start_step",
      value: {
        messageId: value.messageId
      }
    };
  }
};
var reasoningStreamPart = {
  code: "g",
  name: "reasoning",
  parse: (value) => {
    if (typeof value !== "string") {
      throw new Error('"reasoning" parts expect a string value.');
    }
    return { type: "reasoning", value };
  }
};
var sourcePart = {
  code: "h",
  name: "source",
  parse: (value) => {
    if (value == null || typeof value !== "object") {
      throw new Error('"source" parts expect a Source object.');
    }
    return {
      type: "source",
      value
    };
  }
};
var redactedReasoningStreamPart = {
  code: "i",
  name: "redacted_reasoning",
  parse: (value) => {
    if (value == null || typeof value !== "object" || !("data" in value) || typeof value.data !== "string") {
      throw new Error(
        '"redacted_reasoning" parts expect an object with a "data" property.'
      );
    }
    return { type: "redacted_reasoning", value: { data: value.data } };
  }
};
var reasoningSignatureStreamPart = {
  code: "j",
  name: "reasoning_signature",
  parse: (value) => {
    if (value == null || typeof value !== "object" || !("signature" in value) || typeof value.signature !== "string") {
      throw new Error(
        '"reasoning_signature" parts expect an object with a "signature" property.'
      );
    }
    return {
      type: "reasoning_signature",
      value: { signature: value.signature }
    };
  }
};
var fileStreamPart = {
  code: "k",
  name: "file",
  parse: (value) => {
    if (value == null || typeof value !== "object" || !("data" in value) || typeof value.data !== "string" || !("mimeType" in value) || typeof value.mimeType !== "string") {
      throw new Error(
        '"file" parts expect an object with a "data" and "mimeType" property.'
      );
    }
    return { type: "file", value };
  }
};
var dataStreamParts = [
  textStreamPart2,
  dataStreamPart,
  errorStreamPart2,
  messageAnnotationsStreamPart,
  toolCallStreamPart,
  toolResultStreamPart,
  toolCallStreamingStartStreamPart,
  toolCallDeltaStreamPart,
  finishMessageStreamPart,
  finishStepStreamPart,
  startStepStreamPart,
  reasoningStreamPart,
  sourcePart,
  redactedReasoningStreamPart,
  reasoningSignatureStreamPart,
  fileStreamPart
];
var dataStreamPartsByCode = Object.fromEntries(
  dataStreamParts.map((part) => [part.code, part])
);
var DataStreamStringPrefixes = Object.fromEntries(
  dataStreamParts.map((part) => [part.name, part.code])
);
var validCodes2 = dataStreamParts.map((part) => part.code);
var parseDataStreamPart = (line) => {
  const firstSeparatorIndex = line.indexOf(":");
  if (firstSeparatorIndex === -1) {
    throw new Error("Failed to parse stream string. No separator found.");
  }
  const prefix = line.slice(0, firstSeparatorIndex);
  if (!validCodes2.includes(prefix)) {
    throw new Error(`Failed to parse stream string. Invalid code ${prefix}.`);
  }
  const code = prefix;
  const textValue = line.slice(firstSeparatorIndex + 1);
  const jsonValue = JSON.parse(textValue);
  return dataStreamPartsByCode[code].parse(jsonValue);
};
function formatDataStreamPart(type, value) {
  const streamPart = dataStreamParts.find((part) => part.name === type);
  if (!streamPart) {
    throw new Error(`Invalid stream part type: ${type}`);
  }
  return `${streamPart.code}:${JSON.stringify(value)}
`;
}

// src/process-data-stream.ts
var NEWLINE = "\n".charCodeAt(0);
function concatChunks(chunks, totalLength) {
  const concatenatedChunks = new Uint8Array(totalLength);
  let offset = 0;
  for (const chunk of chunks) {
    concatenatedChunks.set(chunk, offset);
    offset += chunk.length;
  }
  chunks.length = 0;
  return concatenatedChunks;
}
async function processDataStream({
  stream,
  onTextPart,
  onReasoningPart,
  onReasoningSignaturePart,
  onRedactedReasoningPart,
  onSourcePart,
  onFilePart,
  onDataPart,
  onErrorPart,
  onToolCallStreamingStartPart,
  onToolCallDeltaPart,
  onToolCallPart,
  onToolResultPart,
  onMessageAnnotationsPart,
  onFinishMessagePart,
  onFinishStepPart,
  onStartStepPart
}) {
  const reader = stream.getReader();
  const decoder = new TextDecoder();
  const chunks = [];
  let totalLength = 0;
  while (true) {
    const { value } = await reader.read();
    if (value) {
      chunks.push(value);
      totalLength += value.length;
      if (value[value.length - 1] !== NEWLINE) {
        continue;
      }
    }
    if (chunks.length === 0) {
      break;
    }
    const concatenatedChunks = concatChunks(chunks, totalLength);
    totalLength = 0;
    const streamParts = decoder.decode(concatenatedChunks, { stream: true }).split("\n").filter((line) => line !== "").map(parseDataStreamPart);
    for (const { type, value: value2 } of streamParts) {
      switch (type) {
        case "text":
          await (onTextPart == null ? void 0 : onTextPart(value2));
          break;
        case "reasoning":
          await (onReasoningPart == null ? void 0 : onReasoningPart(value2));
          break;
        case "reasoning_signature":
          await (onReasoningSignaturePart == null ? void 0 : onReasoningSignaturePart(value2));
          break;
        case "redacted_reasoning":
          await (onRedactedReasoningPart == null ? void 0 : onRedactedReasoningPart(value2));
          break;
        case "file":
          await (onFilePart == null ? void 0 : onFilePart(value2));
          break;
        case "source":
          await (onSourcePart == null ? void 0 : onSourcePart(value2));
          break;
        case "data":
          await (onDataPart == null ? void 0 : onDataPart(value2));
          break;
        case "error":
          await (onErrorPart == null ? void 0 : onErrorPart(value2));
          break;
        case "message_annotations":
          await (onMessageAnnotationsPart == null ? void 0 : onMessageAnnotationsPart(value2));
          break;
        case "tool_call_streaming_start":
          await (onToolCallStreamingStartPart == null ? void 0 : onToolCallStreamingStartPart(value2));
          break;
        case "tool_call_delta":
          await (onToolCallDeltaPart == null ? void 0 : onToolCallDeltaPart(value2));
          break;
        case "tool_call":
          await (onToolCallPart == null ? void 0 : onToolCallPart(value2));
          break;
        case "tool_result":
          await (onToolResultPart == null ? void 0 : onToolResultPart(value2));
          break;
        case "finish_message":
          await (onFinishMessagePart == null ? void 0 : onFinishMessagePart(value2));
          break;
        case "finish_step":
          await (onFinishStepPart == null ? void 0 : onFinishStepPart(value2));
          break;
        case "start_step":
          await (onStartStepPart == null ? void 0 : onStartStepPart(value2));
          break;
        default: {
          const exhaustiveCheck = type;
          throw new Error(`Unknown stream part type: ${exhaustiveCheck}`);
        }
      }
    }
  }
}

// src/process-chat-response.ts
async function processChatResponse({
  stream,
  update,
  onToolCall,
  onFinish,
  generateId: generateId2 = generateIdFunction,
  getCurrentDate = () => /* @__PURE__ */ new Date(),
  lastMessage
}) {
  var _a, _b;
  const replaceLastMessage = (lastMessage == null ? void 0 : lastMessage.role) === "assistant";
  let step = replaceLastMessage ? 1 + // find max step in existing tool invocations:
  ((_b = (_a = lastMessage.toolInvocations) == null ? void 0 : _a.reduce((max, toolInvocation) => {
    var _a2;
    return Math.max(max, (_a2 = toolInvocation.step) != null ? _a2 : 0);
  }, 0)) != null ? _b : 0) : 0;
  const message = replaceLastMessage ? structuredClone(lastMessage) : {
    id: generateId2(),
    createdAt: getCurrentDate(),
    role: "assistant",
    content: "",
    parts: []
  };
  let currentTextPart = void 0;
  let currentReasoningPart = void 0;
  let currentReasoningTextDetail = void 0;
  function updateToolInvocationPart(toolCallId, invocation) {
    const part = message.parts.find(
      (part2) => part2.type === "tool-invocation" && part2.toolInvocation.toolCallId === toolCallId
    );
    if (part != null) {
      part.toolInvocation = invocation;
    } else {
      message.parts.push({
        type: "tool-invocation",
        toolInvocation: invocation
      });
    }
  }
  const data = [];
  let messageAnnotations = replaceLastMessage ? lastMessage == null ? void 0 : lastMessage.annotations : void 0;
  const partialToolCalls = {};
  let usage = {
    completionTokens: NaN,
    promptTokens: NaN,
    totalTokens: NaN
  };
  let finishReason = "unknown";
  function execUpdate() {
    const copiedData = [...data];
    if (messageAnnotations == null ? void 0 : messageAnnotations.length) {
      message.annotations = messageAnnotations;
    }
    const copiedMessage = {
      // deep copy the message to ensure that deep changes (msg attachments) are updated
      // with SolidJS. SolidJS uses referential integration of sub-objects to detect changes.
      ...structuredClone(message),
      // add a revision id to ensure that the message is updated with SWR. SWR uses a
      // hashing approach by default to detect changes, but it only works for shallow
      // changes. This is why we need to add a revision id to ensure that the message
      // is updated with SWR (without it, the changes get stuck in SWR and are not
      // forwarded to rendering):
      revisionId: generateId2()
    };
    update({
      message: copiedMessage,
      data: copiedData,
      replaceLastMessage
    });
  }
  await processDataStream({
    stream,
    onTextPart(value) {
      if (currentTextPart == null) {
        currentTextPart = {
          type: "text",
          text: value
        };
        message.parts.push(currentTextPart);
      } else {
        currentTextPart.text += value;
      }
      message.content += value;
      execUpdate();
    },
    onReasoningPart(value) {
      var _a2;
      if (currentReasoningTextDetail == null) {
        currentReasoningTextDetail = { type: "text", text: value };
        if (currentReasoningPart != null) {
          currentReasoningPart.details.push(currentReasoningTextDetail);
        }
      } else {
        currentReasoningTextDetail.text += value;
      }
      if (currentReasoningPart == null) {
        currentReasoningPart = {
          type: "reasoning",
          reasoning: value,
          details: [currentReasoningTextDetail]
        };
        message.parts.push(currentReasoningPart);
      } else {
        currentReasoningPart.reasoning += value;
      }
      message.reasoning = ((_a2 = message.reasoning) != null ? _a2 : "") + value;
      execUpdate();
    },
    onReasoningSignaturePart(value) {
      if (currentReasoningTextDetail != null) {
        currentReasoningTextDetail.signature = value.signature;
      }
    },
    onRedactedReasoningPart(value) {
      if (currentReasoningPart == null) {
        currentReasoningPart = {
          type: "reasoning",
          reasoning: "",
          details: []
        };
        message.parts.push(currentReasoningPart);
      }
      currentReasoningPart.details.push({
        type: "redacted",
        data: value.data
      });
      currentReasoningTextDetail = void 0;
      execUpdate();
    },
    onFilePart(value) {
      message.parts.push({
        type: "file",
        mimeType: value.mimeType,
        data: value.data
      });
      execUpdate();
    },
    onSourcePart(value) {
      message.parts.push({
        type: "source",
        source: value
      });
      execUpdate();
    },
    onToolCallStreamingStartPart(value) {
      if (message.toolInvocations == null) {
        message.toolInvocations = [];
      }
      partialToolCalls[value.toolCallId] = {
        text: "",
        step,
        toolName: value.toolName,
        index: message.toolInvocations.length
      };
      const invocation = {
        state: "partial-call",
        step,
        toolCallId: value.toolCallId,
        toolName: value.toolName,
        args: void 0
      };
      message.toolInvocations.push(invocation);
      updateToolInvocationPart(value.toolCallId, invocation);
      execUpdate();
    },
    onToolCallDeltaPart(value) {
      const partialToolCall = partialToolCalls[value.toolCallId];
      partialToolCall.text += value.argsTextDelta;
      const { value: partialArgs } = parsePartialJson(partialToolCall.text);
      const invocation = {
        state: "partial-call",
        step: partialToolCall.step,
        toolCallId: value.toolCallId,
        toolName: partialToolCall.toolName,
        args: partialArgs
      };
      message.toolInvocations[partialToolCall.index] = invocation;
      updateToolInvocationPart(value.toolCallId, invocation);
      execUpdate();
    },
    async onToolCallPart(value) {
      const invocation = {
        state: "call",
        step,
        ...value
      };
      if (partialToolCalls[value.toolCallId] != null) {
        message.toolInvocations[partialToolCalls[value.toolCallId].index] = invocation;
      } else {
        if (message.toolInvocations == null) {
          message.toolInvocations = [];
        }
        message.toolInvocations.push(invocation);
      }
      updateToolInvocationPart(value.toolCallId, invocation);
      execUpdate();
      if (onToolCall) {
        const result = await onToolCall({ toolCall: value });
        if (result != null) {
          const invocation2 = {
            state: "result",
            step,
            ...value,
            result
          };
          message.toolInvocations[message.toolInvocations.length - 1] = invocation2;
          updateToolInvocationPart(value.toolCallId, invocation2);
          execUpdate();
        }
      }
    },
    onToolResultPart(value) {
      const toolInvocations = message.toolInvocations;
      if (toolInvocations == null) {
        throw new Error("tool_result must be preceded by a tool_call");
      }
      const toolInvocationIndex = toolInvocations.findIndex(
        (invocation2) => invocation2.toolCallId === value.toolCallId
      );
      if (toolInvocationIndex === -1) {
        throw new Error(
          "tool_result must be preceded by a tool_call with the same toolCallId"
        );
      }
      const invocation = {
        ...toolInvocations[toolInvocationIndex],
        state: "result",
        ...value
      };
      toolInvocations[toolInvocationIndex] = invocation;
      updateToolInvocationPart(value.toolCallId, invocation);
      execUpdate();
    },
    onDataPart(value) {
      data.push(...value);
      execUpdate();
    },
    onMessageAnnotationsPart(value) {
      if (messageAnnotations == null) {
        messageAnnotations = [...value];
      } else {
        messageAnnotations.push(...value);
      }
      execUpdate();
    },
    onFinishStepPart(value) {
      step += 1;
      currentTextPart = value.isContinued ? currentTextPart : void 0;
      currentReasoningPart = void 0;
      currentReasoningTextDetail = void 0;
    },
    onStartStepPart(value) {
      if (!replaceLastMessage) {
        message.id = value.messageId;
      }
      message.parts.push({ type: "step-start" });
      execUpdate();
    },
    onFinishMessagePart(value) {
      finishReason = value.finishReason;
      if (value.usage != null) {
        usage = calculateLanguageModelUsage(value.usage);
      }
    },
    onErrorPart(error) {
      throw new Error(error);
    }
  });
  onFinish == null ? void 0 : onFinish({ message, finishReason, usage });
}

// src/process-chat-text-response.ts
import { generateId as generateIdFunction2 } from "@ai-sdk/provider-utils";

// src/process-text-stream.ts
async function processTextStream({
  stream,
  onTextPart
}) {
  const reader = stream.pipeThrough(new TextDecoderStream()).getReader();
  while (true) {
    const { done, value } = await reader.read();
    if (done) {
      break;
    }
    await onTextPart(value);
  }
}

// src/process-chat-text-response.ts
async function processChatTextResponse({
  stream,
  update,
  onFinish,
  getCurrentDate = () => /* @__PURE__ */ new Date(),
  generateId: generateId2 = generateIdFunction2
}) {
  const textPart = { type: "text", text: "" };
  const resultMessage = {
    id: generateId2(),
    createdAt: getCurrentDate(),
    role: "assistant",
    content: "",
    parts: [textPart]
  };
  await processTextStream({
    stream,
    onTextPart: (chunk) => {
      resultMessage.content += chunk;
      textPart.text += chunk;
      update({
        message: { ...resultMessage },
        data: [],
        replaceLastMessage: false
      });
    }
  });
  onFinish == null ? void 0 : onFinish(resultMessage, {
    usage: { completionTokens: NaN, promptTokens: NaN, totalTokens: NaN },
    finishReason: "unknown"
  });
}

// src/call-chat-api.ts
var getOriginalFetch = () => fetch;
async function callChatApi({
  api,
  body,
  streamProtocol = "data",
  credentials,
  headers,
  abortController,
  restoreMessagesOnFailure,
  onResponse,
  onUpdate,
  onFinish,
  onToolCall,
  generateId: generateId2,
  fetch: fetch2 = getOriginalFetch(),
  lastMessage,
  requestType = "generate"
}) {
  var _a, _b, _c;
  const request = requestType === "resume" ? fetch2(`${api}?chatId=${body.id}`, {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
      ...headers
    },
    signal: (_a = abortController == null ? void 0 : abortController()) == null ? void 0 : _a.signal,
    credentials
  }) : fetch2(api, {
    method: "POST",
    body: JSON.stringify(body),
    headers: {
      "Content-Type": "application/json",
      ...headers
    },
    signal: (_b = abortController == null ? void 0 : abortController()) == null ? void 0 : _b.signal,
    credentials
  });
  const response = await request.catch((err) => {
    restoreMessagesOnFailure();
    throw err;
  });
  if (onResponse) {
    try {
      await onResponse(response);
    } catch (err) {
      throw err;
    }
  }
  if (!response.ok) {
    restoreMessagesOnFailure();
    throw new Error(
      (_c = await response.text()) != null ? _c : "Failed to fetch the chat response."
    );
  }
  if (!response.body) {
    throw new Error("The response body is empty.");
  }
  switch (streamProtocol) {
    case "text": {
      await processChatTextResponse({
        stream: response.body,
        update: onUpdate,
        onFinish,
        generateId: generateId2
      });
      return;
    }
    case "data": {
      await processChatResponse({
        stream: response.body,
        update: onUpdate,
        lastMessage,
        onToolCall,
        onFinish({ message, finishReason, usage }) {
          if (onFinish && message != null) {
            onFinish(message, { usage, finishReason });
          }
        },
        generateId: generateId2
      });
      return;
    }
    default: {
      const exhaustiveCheck = streamProtocol;
      throw new Error(`Unknown stream protocol: ${exhaustiveCheck}`);
    }
  }
}

// src/call-completion-api.ts
var getOriginalFetch2 = () => fetch;
async function callCompletionApi({
  api,
  prompt,
  credentials,
  headers,
  body,
  streamProtocol = "data",
  setCompletion,
  setLoading,
  setError,
  setAbortController,
  onResponse,
  onFinish,
  onError,
  onData,
  fetch: fetch2 = getOriginalFetch2()
}) {
  var _a;
  try {
    setLoading(true);
    setError(void 0);
    const abortController = new AbortController();
    setAbortController(abortController);
    setCompletion("");
    const response = await fetch2(api, {
      method: "POST",
      body: JSON.stringify({
        prompt,
        ...body
      }),
      credentials,
      headers: {
        "Content-Type": "application/json",
        ...headers
      },
      signal: abortController.signal
    }).catch((err) => {
      throw err;
    });
    if (onResponse) {
      try {
        await onResponse(response);
      } catch (err) {
        throw err;
      }
    }
    if (!response.ok) {
      throw new Error(
        (_a = await response.text()) != null ? _a : "Failed to fetch the chat response."
      );
    }
    if (!response.body) {
      throw new Error("The response body is empty.");
    }
    let result = "";
    switch (streamProtocol) {
      case "text": {
        await processTextStream({
          stream: response.body,
          onTextPart: (chunk) => {
            result += chunk;
            setCompletion(result);
          }
        });
        break;
      }
      case "data": {
        await processDataStream({
          stream: response.body,
          onTextPart(value) {
            result += value;
            setCompletion(result);
          },
          onDataPart(value) {
            onData == null ? void 0 : onData(value);
          },
          onErrorPart(value) {
            throw new Error(value);
          }
        });
        break;
      }
      default: {
        const exhaustiveCheck = streamProtocol;
        throw new Error(`Unknown stream protocol: ${exhaustiveCheck}`);
      }
    }
    if (onFinish) {
      onFinish(prompt, result);
    }
    setAbortController(null);
    return result;
  } catch (err) {
    if (err.name === "AbortError") {
      setAbortController(null);
      return null;
    }
    if (err instanceof Error) {
      if (onError) {
        onError(err);
      }
    }
    setError(err);
  } finally {
    setLoading(false);
  }
}

// src/data-url.ts
function getTextFromDataUrl(dataUrl) {
  const [header, base64Content] = dataUrl.split(",");
  const mimeType = header.split(";")[0].split(":")[1];
  if (mimeType == null || base64Content == null) {
    throw new Error("Invalid data URL format");
  }
  try {
    return window.atob(base64Content);
  } catch (error) {
    throw new Error(`Error decoding data URL`);
  }
}

// src/extract-max-tool-invocation-step.ts
function extractMaxToolInvocationStep(toolInvocations) {
  return toolInvocations == null ? void 0 : toolInvocations.reduce((max, toolInvocation) => {
    var _a;
    return Math.max(max, (_a = toolInvocation.step) != null ? _a : 0);
  }, 0);
}

// src/get-message-parts.ts
function getMessageParts(message) {
  var _a;
  return (_a = message.parts) != null ? _a : [
    ...message.toolInvocations ? message.toolInvocations.map((toolInvocation) => ({
      type: "tool-invocation",
      toolInvocation
    })) : [],
    ...message.reasoning ? [
      {
        type: "reasoning",
        reasoning: message.reasoning,
        details: [{ type: "text", text: message.reasoning }]
      }
    ] : [],
    ...message.content ? [{ type: "text", text: message.content }] : []
  ];
}

// src/fill-message-parts.ts
function fillMessageParts(messages) {
  return messages.map((message) => ({
    ...message,
    parts: getMessageParts(message)
  }));
}

// src/is-deep-equal-data.ts
function isDeepEqualData(obj1, obj2) {
  if (obj1 === obj2)
    return true;
  if (obj1 == null || obj2 == null)
    return false;
  if (typeof obj1 !== "object" && typeof obj2 !== "object")
    return obj1 === obj2;
  if (obj1.constructor !== obj2.constructor)
    return false;
  if (obj1 instanceof Date && obj2 instanceof Date) {
    return obj1.getTime() === obj2.getTime();
  }
  if (Array.isArray(obj1)) {
    if (obj1.length !== obj2.length)
      return false;
    for (let i = 0; i < obj1.length; i++) {
      if (!isDeepEqualData(obj1[i], obj2[i]))
        return false;
    }
    return true;
  }
  const keys1 = Object.keys(obj1);
  const keys2 = Object.keys(obj2);
  if (keys1.length !== keys2.length)
    return false;
  for (const key of keys1) {
    if (!keys2.includes(key))
      return false;
    if (!isDeepEqualData(obj1[key], obj2[key]))
      return false;
  }
  return true;
}

// src/prepare-attachments-for-request.ts
async function prepareAttachmentsForRequest(attachmentsFromOptions) {
  if (!attachmentsFromOptions) {
    return [];
  }
  if (globalThis.FileList && attachmentsFromOptions instanceof globalThis.FileList) {
    return Promise.all(
      Array.from(attachmentsFromOptions).map(async (attachment) => {
        const { name, type } = attachment;
        const dataUrl = await new Promise((resolve, reject) => {
          const reader = new FileReader();
          reader.onload = (readerEvent) => {
            var _a;
            resolve((_a = readerEvent.target) == null ? void 0 : _a.result);
          };
          reader.onerror = (error) => reject(error);
          reader.readAsDataURL(attachment);
        });
        return {
          name,
          contentType: type,
          url: dataUrl
        };
      })
    );
  }
  if (Array.isArray(attachmentsFromOptions)) {
    return attachmentsFromOptions;
  }
  throw new Error("Invalid attachments type");
}

// src/process-assistant-stream.ts
var NEWLINE2 = "\n".charCodeAt(0);
function concatChunks2(chunks, totalLength) {
  const concatenatedChunks = new Uint8Array(totalLength);
  let offset = 0;
  for (const chunk of chunks) {
    concatenatedChunks.set(chunk, offset);
    offset += chunk.length;
  }
  chunks.length = 0;
  return concatenatedChunks;
}
async function processAssistantStream({
  stream,
  onTextPart,
  onErrorPart,
  onAssistantMessagePart,
  onAssistantControlDataPart,
  onDataMessagePart
}) {
  const reader = stream.getReader();
  const decoder = new TextDecoder();
  const chunks = [];
  let totalLength = 0;
  while (true) {
    const { value } = await reader.read();
    if (value) {
      chunks.push(value);
      totalLength += value.length;
      if (value[value.length - 1] !== NEWLINE2) {
        continue;
      }
    }
    if (chunks.length === 0) {
      break;
    }
    const concatenatedChunks = concatChunks2(chunks, totalLength);
    totalLength = 0;
    const streamParts = decoder.decode(concatenatedChunks, { stream: true }).split("\n").filter((line) => line !== "").map(parseAssistantStreamPart);
    for (const { type, value: value2 } of streamParts) {
      switch (type) {
        case "text":
          await (onTextPart == null ? void 0 : onTextPart(value2));
          break;
        case "error":
          await (onErrorPart == null ? void 0 : onErrorPart(value2));
          break;
        case "assistant_message":
          await (onAssistantMessagePart == null ? void 0 : onAssistantMessagePart(value2));
          break;
        case "assistant_control_data":
          await (onAssistantControlDataPart == null ? void 0 : onAssistantControlDataPart(value2));
          break;
        case "data_message":
          await (onDataMessagePart == null ? void 0 : onDataMessagePart(value2));
          break;
        default: {
          const exhaustiveCheck = type;
          throw new Error(`Unknown stream part type: ${exhaustiveCheck}`);
        }
      }
    }
  }
}

// src/schema.ts
import { validatorSymbol } from "@ai-sdk/provider-utils";

// src/zod-schema.ts
import zodToJsonSchema from "zod-to-json-schema";
function zodSchema(zodSchema2, options) {
  var _a;
  const useReferences = (_a = options == null ? void 0 : options.useReferences) != null ? _a : false;
  return jsonSchema(
    zodToJsonSchema(zodSchema2, {
      $refStrategy: useReferences ? "root" : "none",
      target: "jsonSchema7"
      // note: openai mode breaks various gemini conversions
    }),
    {
      validate: (value) => {
        const result = zodSchema2.safeParse(value);
        return result.success ? { success: true, value: result.data } : { success: false, error: result.error };
      }
    }
  );
}

// src/schema.ts
var schemaSymbol = Symbol.for("vercel.ai.schema");
function jsonSchema(jsonSchema2, {
  validate
} = {}) {
  return {
    [schemaSymbol]: true,
    _type: void 0,
    // should never be used directly
    [validatorSymbol]: true,
    jsonSchema: jsonSchema2,
    validate
  };
}
function isSchema(value) {
  return typeof value === "object" && value !== null && schemaSymbol in value && value[schemaSymbol] === true && "jsonSchema" in value && "validate" in value;
}
function asSchema(schema) {
  return isSchema(schema) ? schema : zodSchema(schema);
}

// src/should-resubmit-messages.ts
function shouldResubmitMessages({
  originalMaxToolInvocationStep,
  originalMessageCount,
  maxSteps,
  messages
}) {
  var _a;
  const lastMessage = messages[messages.length - 1];
  return (
    // check if the feature is enabled:
    maxSteps > 1 && // ensure there is a last message:
    lastMessage != null && // ensure we actually have new steps (to prevent infinite loops in case of errors):
    (messages.length > originalMessageCount || extractMaxToolInvocationStep(lastMessage.toolInvocations) !== originalMaxToolInvocationStep) && // check that next step is possible:
    isAssistantMessageWithCompletedToolCalls(lastMessage) && // limit the number of automatic steps:
    ((_a = extractMaxToolInvocationStep(lastMessage.toolInvocations)) != null ? _a : 0) < maxSteps
  );
}
function isAssistantMessageWithCompletedToolCalls(message) {
  if (message.role !== "assistant") {
    return false;
  }
  const lastStepStartIndex = message.parts.reduce((lastIndex, part, index) => {
    return part.type === "step-start" ? index : lastIndex;
  }, -1);
  const lastStepToolInvocations = message.parts.slice(lastStepStartIndex + 1).filter((part) => part.type === "tool-invocation");
  return lastStepToolInvocations.length > 0 && lastStepToolInvocations.every((part) => "result" in part.toolInvocation);
}

// src/update-tool-call-result.ts
function updateToolCallResult({
  messages,
  toolCallId,
  toolResult: result
}) {
  var _a;
  const lastMessage = messages[messages.length - 1];
  const invocationPart = lastMessage.parts.find(
    (part) => part.type === "tool-invocation" && part.toolInvocation.toolCallId === toolCallId
  );
  if (invocationPart == null) {
    return;
  }
  const toolResult = {
    ...invocationPart.toolInvocation,
    state: "result",
    result
  };
  invocationPart.toolInvocation = toolResult;
  lastMessage.toolInvocations = (_a = lastMessage.toolInvocations) == null ? void 0 : _a.map(
    (toolInvocation) => toolInvocation.toolCallId === toolCallId ? toolResult : toolInvocation
  );
}
export {
  asSchema,
  callChatApi,
  callCompletionApi,
  extractMaxToolInvocationStep,
  fillMessageParts,
  formatAssistantStreamPart,
  formatDataStreamPart,
  generateId,
  getMessageParts,
  getTextFromDataUrl,
  isAssistantMessageWithCompletedToolCalls,
  isDeepEqualData,
  jsonSchema,
  parseAssistantStreamPart,
  parseDataStreamPart,
  parsePartialJson,
  prepareAttachmentsForRequest,
  processAssistantStream,
  processDataStream,
  processTextStream,
  shouldResubmitMessages,
  updateToolCallResult,
  zodSchema
};
//# sourceMappingURL=index.mjs.map