'use strict';

var core = require('@agentskit/core');

// src/stream-errors.ts
function isAbortError(err) {
  if (err instanceof DOMException && err.name === "AbortError") return true;
  if (err instanceof Error && err.name === "AbortError") return true;
  return false;
}
function adapterErrorChunk(message, options) {
  const error = new core.AdapterError({
    code: options?.code ?? core.ErrorCodes.AK_ADAPTER_STREAM_FAILED,
    message,
    cause: options?.cause
  });
  return {
    type: "error",
    content: message,
    metadata: { error }
  };
}
function parseCompleteToolArgs(args) {
  const raw = args.length > 0 ? args : "{}";
  try {
    JSON.parse(raw);
    return { ok: true, args: raw };
  } catch (cause) {
    return {
      ok: false,
      error: new core.AdapterError({
        code: core.ErrorCodes.AK_ADAPTER_STREAM_FAILED,
        message: "Incomplete or malformed tool-call arguments JSON",
        cause
      })
    };
  }
}
function raceAbort(promise, signal) {
  if (signal.aborted) {
    return Promise.reject(new DOMException("Aborted", "AbortError"));
  }
  return new Promise((resolve2, reject) => {
    let settled = false;
    const onAbort = () => {
      if (settled) return;
      settled = true;
      signal.removeEventListener("abort", onAbort);
      reject(new DOMException("Aborted", "AbortError"));
    };
    signal.addEventListener("abort", onAbort);
    promise.then(
      (value) => {
        if (settled) return;
        settled = true;
        signal.removeEventListener("abort", onAbort);
        resolve2(value);
      },
      (err) => {
        if (settled) return;
        settled = true;
        signal.removeEventListener("abort", onAbort);
        reject(err);
      }
    );
  });
}
async function abortableSleep(ms, signal, sleep) {
  if (signal.aborted) throw new DOMException("Aborted", "AbortError");
  await raceAbort(sleep(ms), signal);
  if (signal.aborted) throw new DOMException("Aborted", "AbortError");
}
async function cancelBody(body) {
  if (!body) return;
  try {
    await body.cancel();
  } catch {
  }
}

// src/createAdapter.ts
function createAdapter(config) {
  return {
    createSource: (request) => {
      const controller = new AbortController();
      let activeStream = null;
      let parseIter = null;
      const cleanup = () => {
        try {
          void activeStream?.cancel();
        } catch {
        }
        activeStream = null;
        if (parseIter && typeof parseIter.return === "function") {
          void parseIter.return(void 0).catch(() => {
          });
        }
        parseIter = null;
        try {
          config.abort?.();
        } catch {
        }
      };
      return {
        stream: async function* () {
          if (controller.signal.aborted) return;
          try {
            const result = await raceAbort(config.send(request, controller.signal), controller.signal);
            if (controller.signal.aborted) {
              if (result instanceof Response) {
                try {
                  await result.body?.cancel();
                } catch {
                }
              }
              return;
            }
            const stream = result instanceof Response ? result.body : result;
            if (!stream) {
              yield adapterErrorChunk("Adapter send() returned empty body");
              return;
            }
            activeStream = stream;
            const response = result instanceof Response ? result : void 0;
            const iterable = config.parse(stream, response);
            parseIter = iterable[Symbol.asyncIterator]();
            while (true) {
              if (controller.signal.aborted) {
                cleanup();
                return;
              }
              let next;
              try {
                next = await raceAbort(parseIter.next(), controller.signal);
              } catch (err) {
                if (isAbortError(err) || controller.signal.aborted) {
                  cleanup();
                  return;
                }
                throw err;
              }
              if (next.done) break;
              if (controller.signal.aborted) {
                cleanup();
                return;
              }
              yield next.value;
              if (next.value.type === "done" || next.value.type === "error") {
                if (typeof parseIter.return === "function") {
                  await parseIter.return(void 0).catch(() => {
                  });
                }
                parseIter = null;
                activeStream = null;
                return;
              }
            }
            yield adapterErrorChunk("Adapter parser ended without a terminal chunk");
            activeStream = null;
          } catch (err) {
            if (isAbortError(err) || controller.signal.aborted) return;
            const message = err instanceof Error ? err.message : String(err);
            yield adapterErrorChunk(message, { cause: err });
          } finally {
            if (controller.signal.aborted) cleanup();
          }
        },
        abort: () => {
          if (!controller.signal.aborted) controller.abort();
          cleanup();
        }
      };
    }
  };
}

// src/generic.ts
function generic(config) {
  return {
    createSource: (request) => {
      const controller = new AbortController();
      let reader = null;
      const decoder = new TextDecoder();
      return {
        stream: async function* () {
          if (controller.signal.aborted) return;
          try {
            const stream = await raceAbort(
              config.send(request, controller.signal),
              controller.signal
            );
            if (controller.signal.aborted) {
              try {
                await stream.cancel();
              } catch {
              }
              return;
            }
            reader = stream.getReader();
            while (true) {
              if (controller.signal.aborted) {
                try {
                  await reader.cancel();
                } catch {
                }
                return;
              }
              const { done, value } = await raceAbort(reader.read(), controller.signal);
              if (done) break;
              const text = decoder.decode(value, { stream: true });
              yield { type: "text", content: text };
            }
            if (controller.signal.aborted) return;
            yield { type: "done" };
          } catch (err) {
            if (isAbortError(err) || controller.signal.aborted) return;
            yield {
              type: "error",
              content: err instanceof Error ? err.message : String(err),
              metadata: {
                error: err instanceof Error ? err : new Error(String(err))
              }
            };
          } finally {
            try {
              reader?.releaseLock();
            } catch {
            }
          }
        },
        abort: () => {
          if (!controller.signal.aborted) controller.abort();
          void reader?.cancel().catch(() => {
          });
        }
      };
    }
  };
}

// src/stream-lines.ts
async function* readSSELines(stream) {
  const reader = stream.getReader();
  const decoder = new TextDecoder();
  let buffer = "";
  try {
    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      buffer += decoder.decode(value, { stream: true });
      const lines = buffer.split("\n");
      buffer = lines.pop() ?? "";
      for (const line of lines) {
        if (!line.startsWith("data: ")) continue;
        const data = line.slice(6).trim();
        if (data) yield data;
      }
    }
  } finally {
    reader.releaseLock();
  }
}
async function* readNDJSONLines(stream) {
  const reader = stream.getReader();
  const decoder = new TextDecoder();
  let buffer = "";
  try {
    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      buffer += decoder.decode(value, { stream: true });
      const lines = buffer.split("\n");
      buffer = lines.pop() ?? "";
      for (const line of lines) {
        const trimmed = line.trim();
        if (trimmed) yield trimmed;
      }
    }
  } finally {
    reader.releaseLock();
  }
}

// src/openai-stream.ts
var SUCCESS_FINISH_REASONS = /* @__PURE__ */ new Set(["stop", "tool_calls", "function_call"]);
async function* parseOpenAIStream(stream) {
  const pendingToolCalls = /* @__PURE__ */ new Map();
  let finishReason;
  const terminalError = (message, extra) => {
    const chunk = adapterErrorChunk(message);
    return {
      ...chunk,
      metadata: { ...chunk.metadata, ...extra, finishReason }
    };
  };
  const flushToolCalls = function* () {
    for (const [, toolCall] of pendingToolCalls) {
      const parsed = parseCompleteToolArgs(toolCall.args);
      if (!parsed.ok) {
        pendingToolCalls.clear();
        yield {
          type: "error",
          content: parsed.error.message,
          metadata: { error: parsed.error, finishReason }
        };
        return false;
      }
      yield {
        type: "tool_call",
        toolCall: { id: toolCall.id, name: toolCall.name, args: parsed.args }
      };
    }
    pendingToolCalls.clear();
    return true;
  };
  for await (const data of readSSELines(stream)) {
    if (data === "[DONE]") {
      if (finishReason !== void 0 && !SUCCESS_FINISH_REASONS.has(finishReason)) {
        pendingToolCalls.clear();
        yield terminalError(
          `OpenAI stream ended with non-success finish reason "${finishReason}".`,
          { finishReason }
        );
        return;
      }
      if (!(yield* flushToolCalls())) return;
      yield { type: "done" };
      return;
    }
    try {
      const event = JSON.parse(data);
      const delta = event.choices?.[0]?.delta;
      const candidateFinishReason = event.choices?.find(
        (choice) => typeof choice.finish_reason === "string"
      )?.finish_reason;
      if (typeof candidateFinishReason === "string") finishReason = candidateFinishReason;
      if (typeof delta?.content === "string") yield { type: "text", content: delta.content };
      if (Array.isArray(delta?.tool_calls)) {
        for (const toolCall of delta.tool_calls) {
          const index = toolCall.index ?? 0;
          const existing = pendingToolCalls.get(index);
          if (toolCall?.function?.name) {
            pendingToolCalls.set(index, {
              id: toolCall.id ?? existing?.id ?? `tool-${index}-${Date.now()}`,
              name: toolCall.function.name,
              args: (existing?.args ?? "") + (toolCall.function.arguments ?? "")
            });
          } else if (existing && toolCall?.function?.arguments) {
            existing.args += toolCall.function.arguments;
          }
        }
      }
      if (event.usage) {
        yield {
          type: "usage",
          usage: {
            promptTokens: event.usage.prompt_tokens ?? 0,
            completionTokens: event.usage.completion_tokens ?? 0,
            totalTokens: event.usage.total_tokens ?? 0
          }
        };
      }
    } catch {
    }
  }
  if (finishReason !== void 0 && !SUCCESS_FINISH_REASONS.has(finishReason)) {
    pendingToolCalls.clear();
    yield terminalError(
      `OpenAI stream ended with non-success finish reason "${finishReason}".`,
      { finishReason }
    );
    return;
  }
  if (!finishReason) {
    pendingToolCalls.clear();
    yield terminalError("OpenAI stream ended before a terminal marker.");
    return;
  }
  if (!(yield* flushToolCalls())) return;
  yield { type: "done" };
}

// src/utils.ts
function toProviderMessages(messages) {
  const knownToolCallIds = /* @__PURE__ */ new Set();
  const output = [];
  for (const message of messages) {
    if (message.role === "tool") {
      const id = message.toolCallId;
      if (!id || !knownToolCallIds.has(id)) continue;
      output.push({
        role: "tool",
        content: message.content,
        tool_call_id: id
      });
      continue;
    }
    if (message.role === "assistant" && message.toolCalls && message.toolCalls.length > 0) {
      for (const tc of message.toolCalls) knownToolCallIds.add(tc.id);
      output.push({
        role: "assistant",
        content: message.content || null,
        tool_calls: message.toolCalls.map((tc) => ({
          id: tc.id,
          type: "function",
          function: {
            name: tc.name,
            arguments: typeof tc.args === "string" ? tc.args : JSON.stringify(tc.args ?? {})
          }
        }))
      });
      continue;
    }
    if (message.role === "assistant" && !message.content) continue;
    output.push({ role: message.role, content: message.content });
  }
  return output;
}
async function* parseAnthropicStream(stream) {
  const pendingToolCalls = /* @__PURE__ */ new Map();
  let sawMessageStop = false;
  const emitToolCall = function* (tc) {
    const parsed = parseCompleteToolArgs(tc.args);
    if (!parsed.ok) {
      yield {
        type: "error",
        content: parsed.error.message,
        metadata: { error: parsed.error }
      };
      return false;
    }
    yield {
      type: "tool_call",
      toolCall: { id: tc.id, name: tc.name, args: parsed.args }
    };
    return true;
  };
  for await (const data of readSSELines(stream)) {
    if (data === "[DONE]") continue;
    try {
      const event = JSON.parse(data);
      if (event.type === "error") {
        const msg = event.error?.message ?? event.error?.type ?? "Anthropic stream error";
        yield adapterErrorChunk(String(msg));
        return;
      }
      if (event.type === "content_block_delta" && event.delta?.type === "text_delta" && event.delta?.text) {
        yield { type: "text", content: event.delta.text };
      } else if (event.type === "content_block_delta" && event.delta?.type === "input_json_delta") {
        const index = event.index ?? 0;
        const existing = pendingToolCalls.get(index);
        if (existing) {
          existing.args += event.delta.partial_json ?? "";
        }
      } else if (event.type === "content_block_start" && event.content_block?.type === "tool_use") {
        const index = event.index ?? 0;
        pendingToolCalls.set(index, {
          id: event.content_block.id ?? `tool-${index}`,
          name: event.content_block.name ?? "unknown",
          args: ""
        });
      } else if (event.type === "content_block_stop") {
        const index = event.index ?? 0;
        const tc = pendingToolCalls.get(index);
        if (tc) {
          if (!(yield* emitToolCall(tc))) {
            pendingToolCalls.clear();
            return;
          }
          pendingToolCalls.delete(index);
        }
      } else if (event.type === "message_delta" && event.usage) {
        yield {
          type: "usage",
          usage: {
            promptTokens: event.usage.input_tokens ?? 0,
            completionTokens: event.usage.output_tokens ?? 0,
            totalTokens: (event.usage.input_tokens ?? 0) + (event.usage.output_tokens ?? 0)
          }
        };
      } else if (event.type === "message_start" && event.message?.usage) {
        yield {
          type: "usage",
          usage: {
            promptTokens: event.message.usage.input_tokens ?? 0,
            completionTokens: 0,
            totalTokens: event.message.usage.input_tokens ?? 0
          }
        };
      } else if (event.type === "message_stop") {
        sawMessageStop = true;
        for (const [, tc] of pendingToolCalls) {
          if (!(yield* emitToolCall(tc))) {
            pendingToolCalls.clear();
            return;
          }
        }
        pendingToolCalls.clear();
        yield { type: "done" };
        return;
      }
    } catch {
    }
  }
  pendingToolCalls.clear();
  if (!sawMessageStop) {
    yield adapterErrorChunk("Anthropic stream ended before message_stop");
    return;
  }
  yield { type: "done" };
}
var GEMINI_SUCCESS_FINISH = /* @__PURE__ */ new Set([
  "STOP",
  "stop",
  "FINISH_REASON_STOP"
]);
async function* parseGeminiStream(stream) {
  let finishReason;
  for await (const data of readSSELines(stream)) {
    try {
      const event = JSON.parse(data);
      if (event.usageMetadata) {
        yield {
          type: "usage",
          usage: {
            promptTokens: event.usageMetadata.promptTokenCount ?? 0,
            completionTokens: event.usageMetadata.candidatesTokenCount ?? 0,
            totalTokens: event.usageMetadata.totalTokenCount ?? 0
          }
        };
      }
      const candidate = event.candidates?.[0];
      if (typeof candidate?.finishReason === "string") {
        finishReason = candidate.finishReason;
      }
      const parts = candidate?.content?.parts;
      if (!Array.isArray(parts)) continue;
      for (const part of parts) {
        if (typeof part.text === "string" && part.text) {
          yield { type: "text", content: part.text };
        } else if (part.functionCall) {
          const fc = part.functionCall;
          const args = typeof fc.args === "string" ? fc.args : JSON.stringify(fc.args ?? {});
          const parsed = parseCompleteToolArgs(args);
          if (!parsed.ok) {
            yield {
              type: "error",
              content: parsed.error.message,
              metadata: { error: parsed.error }
            };
            return;
          }
          yield {
            type: "tool_call",
            toolCall: {
              id: fc.id ?? `${fc.name}-${Date.now()}`,
              name: fc.name ?? "unknown",
              args: parsed.args
            }
          };
        }
      }
    } catch {
    }
  }
  if (!finishReason || !GEMINI_SUCCESS_FINISH.has(finishReason)) {
    if (finishReason && !GEMINI_SUCCESS_FINISH.has(finishReason)) {
      yield adapterErrorChunk(
        `Gemini stream ended with non-success finish reason "${finishReason}"`
      );
      return;
    }
    yield adapterErrorChunk("Gemini stream ended without a successful finishReason");
    return;
  }
  yield { type: "done" };
}
async function* parseOllamaStream(stream) {
  let sawDone = false;
  for await (const data of readNDJSONLines(stream)) {
    try {
      const event = JSON.parse(data);
      if (event.message?.content) {
        yield { type: "text", content: event.message.content };
      }
      if (Array.isArray(event.message?.tool_calls)) {
        for (const tc of event.message.tool_calls) {
          if (tc?.function?.name) {
            const args = typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments ?? {});
            const parsed = parseCompleteToolArgs(args);
            if (!parsed.ok) {
              yield {
                type: "error",
                content: parsed.error.message,
                metadata: { error: parsed.error }
              };
              return;
            }
            yield {
              type: "tool_call",
              toolCall: {
                id: tc.id ?? `${tc.function.name}-${Date.now()}`,
                name: tc.function.name,
                args: parsed.args
              }
            };
          }
        }
      }
      if (event.done) {
        sawDone = true;
        if (typeof event.prompt_eval_count === "number" || typeof event.eval_count === "number") {
          const promptTokens = event.prompt_eval_count ?? 0;
          const completionTokens = event.eval_count ?? 0;
          yield {
            type: "usage",
            usage: {
              promptTokens,
              completionTokens,
              totalTokens: promptTokens + completionTokens
            }
          };
        }
        yield { type: "done" };
        return;
      }
    } catch {
    }
  }
  if (!sawDone) {
    yield adapterErrorChunk("Ollama stream ended without done:true");
    return;
  }
  yield { type: "done" };
}
var DEFAULT_RETRY = {
  maxAttempts: 3,
  baseDelayMs: 500,
  maxDelayMs: 8e3,
  jitter: true,
  retryOn: ({ error, response }) => {
    if (response) {
      return [408, 429, 500, 502, 503, 504].includes(response.status);
    }
    if (isAbortError(error)) return false;
    return true;
  }
};
function defaultSleep(ms) {
  return new Promise((resolve2) => setTimeout(resolve2, ms));
}
function computeDelay(attempt, opts) {
  const exp = Math.min(opts.maxDelayMs, opts.baseDelayMs * Math.pow(2, attempt - 1));
  if (!opts.jitter) return exp;
  return Math.floor(Math.random() * exp);
}
function parseRetryAfter(value) {
  if (!value) return void 0;
  const n = Number(value);
  if (!Number.isNaN(n)) return n * 1e3;
  const date = Date.parse(value);
  if (!Number.isNaN(date)) return Math.max(0, date - Date.now());
  return void 0;
}
async function fetchWithRetry(doFetch, signal, retryOpt = {}) {
  const opts = {
    ...DEFAULT_RETRY,
    ...retryOpt
  };
  const sleep = retryOpt.sleep ?? defaultSleep;
  let lastError;
  for (let attempt = 1; attempt <= opts.maxAttempts; attempt++) {
    if (signal.aborted) throw new DOMException("Aborted", "AbortError");
    try {
      const response = await doFetch(signal);
      if (response.ok) return response;
      if (attempt >= opts.maxAttempts || !opts.retryOn({ response, attempt })) {
        return response;
      }
      const retryAfterMs = parseRetryAfter(response.headers.get("retry-after"));
      const delay = retryAfterMs ?? computeDelay(attempt, opts);
      retryOpt.onRetry?.({ attempt, delayMs: delay, reason: `HTTP ${response.status}` });
      await cancelBody(response.body);
      await abortableSleep(delay, signal, sleep);
    } catch (err) {
      lastError = err;
      if (isAbortError(err)) throw err;
      if (attempt >= opts.maxAttempts || !opts.retryOn({ error: err, attempt })) throw err;
      const delay = computeDelay(attempt, opts);
      retryOpt.onRetry?.({
        attempt,
        delayMs: delay,
        reason: err instanceof Error ? err.message : String(err)
      });
      await abortableSleep(delay, signal, sleep);
    }
  }
  throw lastError ?? new Error("fetchWithRetry: exhausted attempts");
}
function chunkText(text, targetSize = 32) {
  if (text.length <= targetSize) return [text];
  const out = [];
  let i = 0;
  while (i < text.length) {
    let end = Math.min(text.length, i + targetSize);
    if (end < text.length) {
      const nextSpace = text.indexOf(" ", end);
      if (nextSpace !== -1 && nextSpace - end <= 8) end = nextSpace + 1;
    }
    out.push(text.slice(i, end));
    i = end;
  }
  return out;
}
function simulateStream(doFetch, extractText, errorLabel, options = {}) {
  const { chunkSize = 32, delayMs = 8, retry } = options;
  let abortController = new AbortController();
  return {
    stream: async function* () {
      const controller = abortController;
      if (!controller) return;
      try {
        const response = await fetchWithRetry(doFetch, controller.signal, retry ?? {});
        if (!response.ok) {
          await cancelBody(response.body);
          yield adapterErrorChunk(`${errorLabel} error: ${response.status}`);
          return;
        }
        let text;
        try {
          text = await extractText(response);
        } catch (err) {
          await cancelBody(response.body);
          if (isAbortError(err)) return;
          const message = err instanceof Error ? err.message : String(err);
          yield adapterErrorChunk(message, { cause: err });
          return;
        }
        const chunks = chunkText(text, chunkSize);
        for (const chunk of chunks) {
          if (abortController === null || controller.signal.aborted) return;
          if (delayMs > 0) {
            await abortableSleep(delayMs, controller.signal, defaultSleep);
          }
          yield { type: "text", content: chunk };
        }
        yield { type: "done" };
      } catch (err) {
        if (isAbortError(err)) return;
        const message = err instanceof Error ? err.message : String(err);
        yield adapterErrorChunk(message, { cause: err });
      }
    },
    abort: () => {
      abortController?.abort();
      abortController = null;
    }
  };
}

// src/stream-source.ts
function createStreamSource(doFetch, parse, errorLabel, retry) {
  let abortController = new AbortController();
  return {
    stream: async function* () {
      const controller = abortController;
      if (!controller) return;
      try {
        const response = await fetchWithRetry(doFetch, controller.signal, retry ?? {});
        if (!response.ok) {
          await cancelBody(response.body);
          yield adapterErrorChunk(`${errorLabel} error: ${response.status}`);
          return;
        }
        if (!response.body) {
          yield adapterErrorChunk(`${errorLabel} error: empty response body`);
          return;
        }
        for await (const chunk of parse(response.body, response)) {
          if (controller.signal.aborted || abortController === null) return;
          yield chunk;
        }
      } catch (err) {
        if (isAbortError(err) || controller.signal.aborted || abortController === null) return;
        const message = err instanceof Error ? err.message : String(err);
        yield adapterErrorChunk(message, { cause: err });
      }
    },
    abort: () => {
      abortController?.abort();
      abortController = null;
    }
  };
}

// src/tool-history.ts
function toolInput(args) {
  if (args == null) return {};
  if (typeof args === "string") {
    try {
      const parsed = JSON.parse(args);
      if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
        return parsed;
      }
      return { value: parsed };
    } catch {
      return {};
    }
  }
  if (typeof args === "object" && !Array.isArray(args)) {
    return args;
  }
  return { value: args };
}
function toolResponsePayload(content) {
  try {
    const parsed = JSON.parse(content);
    if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
      return parsed;
    }
    return { result: parsed };
  } catch {
    return { result: content };
  }
}
function toAnthropicMessages(messages) {
  const knownNames = /* @__PURE__ */ new Map();
  const output = [];
  for (const message of messages) {
    if (message.role === "system") continue;
    if (message.role === "assistant" && message.toolCalls && message.toolCalls.length > 0) {
      for (const tc of message.toolCalls) knownNames.set(tc.id, tc.name);
      const blocks = [];
      if (message.content) {
        blocks.push({ type: "text", text: message.content });
      }
      for (const tc of message.toolCalls) {
        blocks.push({
          type: "tool_use",
          id: tc.id,
          name: tc.name,
          input: toolInput(tc.args)
        });
      }
      output.push({ role: "assistant", content: blocks });
      continue;
    }
    if (message.role === "tool") {
      const id = message.toolCallId;
      if (!id || !knownNames.has(id)) continue;
      const block = {
        type: "tool_result",
        tool_use_id: id,
        content: message.content
      };
      const previous2 = output[output.length - 1];
      if (previous2?.role === "user" && Array.isArray(previous2.content) && previous2.content.every((item) => item && typeof item === "object" && item.type === "tool_result")) {
        previous2.content.push(block);
      } else {
        output.push({ role: "user", content: [block] });
      }
      continue;
    }
    if (message.role === "assistant" && !message.content) continue;
    const previous = output[output.length - 1];
    if (message.role === "user" && previous?.role === "user") {
      const previousBlocks = Array.isArray(previous.content) ? previous.content : [{ type: "text", text: previous.content }];
      previous.content = [...previousBlocks, { type: "text", text: message.content }];
    } else {
      output.push({ role: message.role, content: message.content });
    }
  }
  return output;
}
function toGeminiContents(messages) {
  const knownNames = /* @__PURE__ */ new Map();
  const output = [];
  for (const message of messages) {
    if (message.role === "system") continue;
    if (message.role === "assistant" && message.toolCalls && message.toolCalls.length > 0) {
      for (const tc of message.toolCalls) knownNames.set(tc.id, tc.name);
      const parts = [];
      if (message.content) {
        parts.push({ text: message.content });
      }
      for (const tc of message.toolCalls) {
        parts.push({
          functionCall: {
            id: tc.id,
            name: tc.name,
            args: toolInput(tc.args)
          }
        });
      }
      output.push({ role: "model", parts });
      continue;
    }
    if (message.role === "tool") {
      const id = message.toolCallId;
      const name = id ? knownNames.get(id) : void 0;
      if (!name) continue;
      const part = {
        functionResponse: {
          id,
          name,
          response: toolResponsePayload(message.content)
        }
      };
      const previous2 = output[output.length - 1];
      if (previous2?.role === "user" && previous2.parts.every((item) => item.functionResponse !== void 0)) {
        previous2.parts.push(part);
      } else {
        output.push({ role: "user", parts: [part] });
      }
      continue;
    }
    if (message.role === "assistant" && !message.content) continue;
    const role = message.role === "assistant" ? "model" : "user";
    const previous = output[output.length - 1];
    if (previous?.role === role) {
      previous.parts.push({ text: message.content });
    } else {
      output.push({ role, parts: [{ text: message.content }] });
    }
  }
  return output;
}

// src/anthropic.ts
function anthropic(config) {
  const { apiKey, model, baseUrl = "https://api.anthropic.com", maxTokens = 4096, retry } = config;
  return {
    capabilities: {
      streaming: true,
      tools: true,
      reasoning: model.includes("sonnet") || model.includes("opus"),
      multiModal: true,
      usage: true
    },
    createSource: (request) => {
      const body = {
        model,
        max_tokens: request.context?.maxTokens ?? maxTokens,
        messages: toAnthropicMessages(request.messages),
        system: request.messages.find((message) => message.role === "system")?.content,
        tools: request.context?.tools?.map((tool) => ({
          name: tool.name,
          description: tool.description,
          input_schema: tool.schema
        })),
        stream: true
      };
      return createStreamSource(
        (signal) => fetch(`${baseUrl}/v1/messages`, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "x-api-key": apiKey,
            "anthropic-version": "2023-06-01"
          },
          body: JSON.stringify(body),
          signal
        }),
        parseAnthropicStream,
        "Anthropic API",
        retry
      );
    }
  };
}

// src/openai.ts
function openai(config) {
  const { apiKey, model, baseUrl = "https://api.openai.com", retry } = config;
  const apiRoot = baseUrl.replace(/\/v1\/?$/, "");
  const isCanonicalOpenAI = (() => {
    try {
      return new URL(baseUrl).host === "api.openai.com";
    } catch {
      return false;
    }
  })();
  const includeUsage = config.includeUsage ?? isCanonicalOpenAI;
  return {
    capabilities: {
      streaming: true,
      tools: true,
      // o1 / o3 models emit reasoning; older models don't. Accurate per-model
      // detection would need a model registry; 'true' is the safer default here.
      reasoning: model.startsWith("o1") || model.startsWith("o3"),
      multiModal: model.startsWith("gpt-4") || model.startsWith("o"),
      usage: true
    },
    createSource: (request) => {
      const body = {
        model,
        messages: toProviderMessages(request.messages),
        tools: request.context?.tools?.map((tool) => ({
          type: "function",
          function: {
            name: tool.name,
            description: tool.description,
            parameters: tool.schema
          }
        })),
        temperature: request.context?.temperature,
        max_tokens: request.context?.maxTokens,
        stream: true
      };
      if (includeUsage) body.stream_options = { include_usage: true };
      return createStreamSource(
        (signal) => fetch(`${apiRoot}/v1/chat/completions`, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "Authorization": `Bearer ${apiKey}`
          },
          body: JSON.stringify(body),
          signal
        }),
        parseOpenAIStream,
        "OpenAI API",
        retry
      );
    }
  };
}

// src/gemini.ts
function gemini(config) {
  const { apiKey, model, baseUrl = "https://generativelanguage.googleapis.com", retry } = config;
  return {
    capabilities: {
      streaming: true,
      tools: true,
      multiModal: true,
      usage: true
    },
    createSource: (request) => {
      const systemMessage = request.messages.find((message) => message.role === "system");
      const body = {
        contents: toGeminiContents(request.messages),
        systemInstruction: systemMessage ? { role: "system", parts: [{ text: systemMessage.content }] } : void 0,
        tools: request.context?.tools && request.context.tools.length > 0 ? [{
          functionDeclarations: request.context.tools.map((tool) => ({
            name: tool.name,
            description: tool.description,
            parameters: tool.schema
          }))
        }] : void 0
      };
      return createStreamSource(
        (signal) => fetch(
          `${baseUrl}/v1beta/models/${model}:streamGenerateContent?alt=sse`,
          {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
              "x-goog-api-key": apiKey
            },
            body: JSON.stringify(body),
            signal
          }
        ),
        parseGeminiStream,
        "Gemini API",
        retry
      );
    }
  };
}

// src/openai-compatible.ts
function createOpenAICompatibleAdapter(defaultBaseUrl) {
  return function openAICompatibleAdapter(config) {
    return openai({
      ...config,
      baseUrl: config.baseUrl ?? defaultBaseUrl
    });
  };
}

// src/grok.ts
var grok = createOpenAICompatibleAdapter("https://api.x.ai");

// src/ollama.ts
function ollama(config) {
  const { model, baseUrl = "http://localhost:11434", retry } = config;
  return {
    capabilities: {
      streaming: true,
      tools: false,
      // varies by model; default 'false' — enable via capabilities.extensions if your model supports it
      multiModal: model.includes("llava") || model.includes("vision")
    },
    createSource: (request) => {
      const body = {
        model,
        stream: true,
        messages: request.messages.map((message) => ({
          role: message.role,
          content: message.content
        }))
      };
      return createStreamSource(
        (signal) => fetch(`${baseUrl}/api/chat`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(body),
          signal
        }),
        parseOllamaStream,
        "Ollama API",
        retry
      );
    }
  };
}

// src/deepseek.ts
var deepseek = createOpenAICompatibleAdapter("https://api.deepseek.com");

// src/kimi.ts
var kimi = createOpenAICompatibleAdapter("https://api.moonshot.ai");

// src/langchain.ts
function asText(value) {
  if (typeof value === "string") return value;
  if (value && typeof value === "object" && "content" in value) {
    const content = value.content;
    if (typeof content === "string") return content;
  }
  return "";
}
function isToolStartEvent(eventName) {
  return eventName === "on_tool_start" || eventName.endsWith("_tool_start");
}
function langchain(config) {
  const { runnable, mode = "stream" } = config;
  return {
    createSource: (request) => {
      const controller = new AbortController();
      return {
        stream: async function* () {
          if (controller.signal.aborted) return;
          try {
            const runnableConfig = {
              version: "v2",
              signal: controller.signal
            };
            if (mode === "events" && runnable.streamEvents) {
              const events = await runnable.streamEvents(
                { messages: request.messages },
                runnableConfig
              );
              for await (const event of events) {
                if (controller.signal.aborted) return;
                const eventName = String(event.event ?? "");
                if (eventName.endsWith("_stream")) {
                  const chunk = asText(event.data);
                  if (chunk) yield { type: "text", content: chunk };
                } else if (isToolStartEvent(eventName) && event.name) {
                  yield {
                    type: "tool_call",
                    toolCall: {
                      id: String(event.run_id ?? `${event.name}-${Date.now()}`),
                      name: String(event.name),
                      args: JSON.stringify(event.data ?? {})
                    }
                  };
                }
              }
            } else if (runnable.stream) {
              const stream = await runnable.stream(
                { messages: request.messages },
                runnableConfig
              );
              for await (const value of stream) {
                if (controller.signal.aborted) return;
                const chunk = asText(value);
                if (chunk) yield { type: "text", content: chunk };
              }
            } else {
              yield adapterErrorChunk("Runnable does not implement stream() or streamEvents()");
              return;
            }
            if (controller.signal.aborted) return;
            yield { type: "done" };
          } catch (error) {
            if (isAbortError(error) || controller.signal.aborted) return;
            const message = error instanceof Error ? error.message : String(error);
            yield adapterErrorChunk(message, { cause: error });
          }
        },
        abort: () => {
          controller.abort();
        }
      };
    }
  };
}
function langgraph(config) {
  return langchain({
    runnable: config.graph,
    mode: "events"
  });
}

// src/vercel-ai.ts
var UI_STREAM_HEADER = "x-vercel-ai-ui-message-stream";
async function* parseVercelTextStream(stream) {
  const reader = stream.getReader();
  const decoder = new TextDecoder();
  try {
    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      const text = decoder.decode(value, { stream: true });
      if (text) yield { type: "text", content: text };
    }
  } finally {
    reader.releaseLock();
  }
  yield { type: "done" };
}
async function* parseVercelUiMessageStreamV1(stream) {
  for await (const data of readSSELines(stream)) {
    if (data === "[DONE]") {
      yield { type: "done" };
      return;
    }
    try {
      const part = JSON.parse(data);
      const type = part.type;
      if (type === "text-delta") {
        const delta = part.delta ?? part.textDelta;
        if (typeof delta === "string" && delta) {
          yield { type: "text", content: delta };
        }
      } else if (type === "reasoning-delta") {
        const delta = part.delta ?? part.textDelta;
        if (typeof delta === "string" && delta) {
          yield { type: "reasoning", content: delta };
        }
      } else if (type === "error") {
        const message = part.errorText ?? part.message ?? "Vercel AI UI stream error";
        yield adapterErrorChunk(String(message));
        return;
      } else if (type === "abort") {
        yield adapterErrorChunk(part.reason ?? "Vercel AI UI stream aborted by provider");
        return;
      } else if (type === "finish") {
        continue;
      }
    } catch {
    }
  }
  yield adapterErrorChunk("Vercel AI UI stream truncated before [DONE]");
}
async function* parseVercelStream(stream, response) {
  const header = response?.headers.get(UI_STREAM_HEADER) ?? response?.headers.get(UI_STREAM_HEADER.toLowerCase());
  if (header === "v1") {
    yield* parseVercelUiMessageStreamV1(stream);
    return;
  }
  yield* parseVercelTextStream(stream);
}
function vercelAI(config) {
  const { api, headers = {}, retry } = config;
  return {
    capabilities: {
      // Vercel AI routes can do any of these — whether they do depends on
      // your route handler. Omit the field instead of lying.
    },
    createSource: (request) => {
      const body = {
        messages: request.messages.map((message) => ({ role: message.role, content: message.content })),
        tools: request.context?.tools,
        systemPrompt: request.context?.systemPrompt
      };
      return createStreamSource(
        (signal) => fetch(api, {
          method: "POST",
          headers: { "Content-Type": "application/json", ...headers },
          body: JSON.stringify(body),
          signal
        }),
        parseVercelStream,
        "API",
        retry
      );
    }
  };
}

// src/mistral.ts
var mistral = createOpenAICompatibleAdapter("https://api.mistral.ai/v1");

// src/cohere.ts
var COHERE_BASE_URL = "https://api.cohere.com/compatibility/v1";
var DEFAULT_MODEL = "command-r-plus";
var baseFactory = createOpenAICompatibleAdapter(COHERE_BASE_URL);
function cohere(config) {
  const factory = baseFactory({
    model: DEFAULT_MODEL,
    ...config
  });
  return {
    ...factory,
    capabilities: {
      streaming: true,
      tools: true,
      usage: true
    }
  };
}
var cohereAdapter = cohere;

// src/together.ts
var together = createOpenAICompatibleAdapter("https://api.together.xyz/v1");

// src/groq.ts
var GROQ_BASE_URL = "https://api.groq.com/openai/v1";
var DEFAULT_MODEL2 = "llama-3.3-70b-versatile";
var baseFactory2 = createOpenAICompatibleAdapter(GROQ_BASE_URL);
function groq(config) {
  const factory = baseFactory2({
    model: DEFAULT_MODEL2,
    ...config
  });
  return {
    ...factory,
    capabilities: {
      streaming: true,
      tools: true,
      usage: true
    }
  };
}
var groqAdapter = groq;

// src/fireworks.ts
var fireworks = createOpenAICompatibleAdapter("https://api.fireworks.ai/inference/v1");

// src/openrouter.ts
var openrouter = createOpenAICompatibleAdapter("https://openrouter.ai/api/v1");

// src/huggingface.ts
var huggingface = createOpenAICompatibleAdapter("https://router.huggingface.co/v1");

// src/lmstudio.ts
var lmstudio = createOpenAICompatibleAdapter("http://localhost:1234/v1");

// src/vllm.ts
var vllm = createOpenAICompatibleAdapter("http://localhost:8000/v1");

// src/llamacpp.ts
var llamacpp = createOpenAICompatibleAdapter("http://localhost:8080/v1");

// src/cerebras.ts
var CEREBRAS_BASE_URL = "https://api.cerebras.ai/v1";
var DEFAULT_MODEL3 = "llama-3.3-70b";
var baseFactory3 = createOpenAICompatibleAdapter(CEREBRAS_BASE_URL);
function cerebras(config) {
  const factory = baseFactory3({
    model: DEFAULT_MODEL3,
    ...config
  });
  return {
    ...factory,
    capabilities: {
      streaming: true,
      tools: true,
      usage: true
    }
  };
}
var cerebrasAdapter = cerebras;

// src/azure-openai.ts
var DEFAULT_API_VERSION = "2024-10-21";
function azureOpenAI(config) {
  const { apiKey, endpoint, deployment, apiVersion = DEFAULT_API_VERSION, retry } = config;
  const includeUsage = config.includeUsage ?? true;
  const url = `${endpoint.replace(/\/$/, "")}/openai/deployments/${encodeURIComponent(deployment)}/chat/completions?api-version=${encodeURIComponent(apiVersion)}`;
  return {
    capabilities: {
      streaming: true,
      tools: true,
      usage: true
    },
    createSource: (request) => {
      const body = {
        messages: toProviderMessages(request.messages),
        tools: request.context?.tools?.map((tool) => ({
          type: "function",
          function: {
            name: tool.name,
            description: tool.description,
            parameters: tool.schema
          }
        })),
        temperature: request.context?.temperature,
        max_tokens: request.context?.maxTokens,
        stream: true
      };
      if (includeUsage) body.stream_options = { include_usage: true };
      return createStreamSource(
        (signal) => fetch(url, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "api-key": apiKey
          },
          body: JSON.stringify(body),
          signal
        }),
        parseOpenAIStream,
        "Azure OpenAI API",
        retry
      );
    }
  };
}
var azureOpenAIAdapter = azureOpenAI;

// src/replicate.ts
var DEFAULT_BASE_URL = "https://api.replicate.com";
function defaultPrompt(request) {
  return request.messages.map((m) => {
    if (m.role === "system") return `[SYSTEM] ${m.content}`;
    if (m.role === "assistant") return `[ASSISTANT] ${m.content}`;
    return `[USER] ${m.content}`;
  }).join("\n\n") + "\n\n[ASSISTANT] ";
}
async function* parseReplicateStream(stream) {
  const reader = stream.getReader();
  const decoder = new TextDecoder();
  let buffer = "";
  let currentEvent = "";
  let sawDone = false;
  try {
    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      buffer += decoder.decode(value, { stream: true });
      const lines = buffer.split("\n");
      buffer = lines.pop() ?? "";
      for (const line of lines) {
        if (line.startsWith("event: ")) {
          currentEvent = line.slice(7).trim();
          continue;
        }
        if (!line.startsWith("data: ")) continue;
        const data = line.slice(6);
        if (currentEvent === "output" && data) {
          yield { type: "text", content: data };
        } else if (currentEvent === "done") {
          sawDone = true;
          yield { type: "done" };
          return;
        } else if (currentEvent === "error") {
          yield adapterErrorChunk(data || "replicate stream error");
          return;
        }
      }
    }
  } finally {
    reader.releaseLock();
  }
  if (!sawDone) {
    yield adapterErrorChunk("Replicate stream ended without done event");
    return;
  }
  yield { type: "done" };
}
function replicate(config) {
  const { apiKey, model, version, baseUrl = DEFAULT_BASE_URL, toInput = (r) => ({ prompt: defaultPrompt(r) }) } = config;
  const predictionUrl = version ? `${baseUrl}/v1/predictions` : `${baseUrl}/v1/models/${model}/predictions`;
  return {
    capabilities: {
      streaming: true,
      tools: false
    },
    createSource: (request) => {
      const controller = new AbortController();
      let aborted = false;
      return {
        stream: async function* () {
          if (aborted) return;
          try {
            const body = {
              input: toInput(request),
              stream: true
            };
            if (version) body.version = version;
            const response = await fetch(predictionUrl, {
              method: "POST",
              headers: {
                "Content-Type": "application/json",
                "Authorization": `Bearer ${apiKey}`
              },
              body: JSON.stringify(body),
              signal: controller.signal
            });
            if (!response.ok) {
              yield adapterErrorChunk(`Replicate API error: ${response.status}`);
              return;
            }
            const prediction = await response.json();
            if (prediction.error) {
              yield adapterErrorChunk(prediction.error);
              return;
            }
            const streamUrl = prediction.urls?.stream;
            if (!streamUrl) {
              yield adapterErrorChunk("Replicate prediction has no stream URL");
              return;
            }
            const streamResponse = await fetch(streamUrl, {
              method: "GET",
              headers: { Accept: "text/event-stream" },
              signal: controller.signal
            });
            if (!streamResponse.ok || !streamResponse.body) {
              yield adapterErrorChunk(`Replicate stream error: ${streamResponse.status}`);
              return;
            }
            for await (const chunk of parseReplicateStream(streamResponse.body)) {
              if (aborted) return;
              yield chunk;
            }
          } catch (err) {
            if (isAbortError(err) || aborted) return;
            const message = err instanceof Error ? err.message : String(err);
            yield adapterErrorChunk(message, { cause: err });
          }
        },
        abort: () => {
          aborted = true;
          controller.abort();
        }
      };
    }
  };
}
var replicateAdapter = replicate;

// src/bail.ts
var BAIL_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1";
var DEFAULT_MODEL4 = "qwen-max";
var baseFactory4 = createOpenAICompatibleAdapter(BAIL_BASE_URL);
function bail(config) {
  const factory = baseFactory4({
    model: DEFAULT_MODEL4,
    ...config
  });
  return {
    ...factory,
    capabilities: {
      streaming: true,
      tools: true,
      multiModal: true,
      usage: true
    }
  };
}
var bailAdapter = bail;
var qwen = bail;

// src/vertex.ts
function vertex(config) {
  const { project, region, model, accessToken, publisher = "google", retry } = config;
  const url = `https://${region}-aiplatform.googleapis.com/v1/projects/${project}/locations/${region}/publishers/${publisher}/models/${model}:streamGenerateContent?alt=sse`;
  return {
    capabilities: {
      streaming: true,
      tools: true,
      multiModal: true,
      usage: true,
      reasoning: model.includes("pro")
    },
    createSource: (request) => {
      const systemMessage = request.messages.find((message) => message.role === "system");
      const body = {
        contents: toGeminiContents(request.messages),
        systemInstruction: systemMessage ? { role: "system", parts: [{ text: systemMessage.content }] } : void 0,
        tools: request.context?.tools && request.context.tools.length > 0 ? [{
          functionDeclarations: request.context.tools.map((tool) => ({
            name: tool.name,
            description: tool.description,
            parameters: tool.schema
          }))
        }] : void 0
      };
      return createStreamSource(
        async (signal) => {
          const token = typeof accessToken === "string" ? accessToken : await accessToken();
          return fetch(url, {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
              "Authorization": `Bearer ${token}`
            },
            body: JSON.stringify(body),
            signal
          });
        },
        parseGeminiStream,
        "Vertex AI",
        retry
      );
    }
  };
}
var vertexAdapter = vertex;
var cachedSdk = null;
async function loadSdk() {
  if (!cachedSdk) {
    cachedSdk = (async () => {
      try {
        const moduleId = "@aws-sdk/client-bedrock-runtime";
        return await import(
          /* @vite-ignore */
          moduleId
        );
      } catch {
        throw new core.AdapterError({
          code: core.ErrorCodes.AK_ADAPTER_MISSING,
          message: "Install @aws-sdk/client-bedrock-runtime to use the bedrock adapter: npm install @aws-sdk/client-bedrock-runtime",
          hint: "bedrock depends on the optional peer @aws-sdk/client-bedrock-runtime."
        });
      }
    })();
  }
  return cachedSdk;
}
function isAnthropicModel(model) {
  return model.startsWith("anthropic.");
}
function buildAnthropicBody(request, maxTokens) {
  const messages = toAnthropicMessages(request.messages);
  const system = request.messages.find((m) => m.role === "system")?.content;
  const tools = request.context?.tools?.map((tool) => ({
    name: tool.name,
    description: tool.description,
    input_schema: tool.schema
  }));
  const body = {
    anthropic_version: "bedrock-2023-05-31",
    max_tokens: request.context?.maxTokens ?? maxTokens,
    messages
  };
  if (system) body.system = system;
  if (tools && tools.length > 0) body.tools = tools;
  return JSON.stringify(body);
}
async function* parseAnthropicBedrockEvents(events) {
  const decoder = new TextDecoder();
  const pendingToolCalls = /* @__PURE__ */ new Map();
  const emitTool = function* (tc) {
    const parsed = parseCompleteToolArgs(tc.args);
    if (!parsed.ok) {
      yield {
        type: "error",
        content: parsed.error.message,
        metadata: { error: parsed.error }
      };
      return false;
    }
    yield { type: "tool_call", toolCall: { id: tc.id, name: tc.name, args: parsed.args } };
    return true;
  };
  for await (const item of events) {
    const bytes = item.chunk?.bytes;
    if (!bytes) continue;
    let event;
    try {
      event = JSON.parse(decoder.decode(bytes));
    } catch {
      continue;
    }
    const type = event.type;
    if (type === "content_block_delta") {
      const delta = event.delta;
      if (delta?.type === "text_delta" && delta.text) {
        yield { type: "text", content: delta.text };
      } else if (delta?.type === "input_json_delta") {
        const index = event.index ?? 0;
        const existing = pendingToolCalls.get(index);
        if (existing) existing.args += delta.partial_json ?? "";
      }
    } else if (type === "content_block_start") {
      const index = event.index ?? 0;
      const block = event.content_block;
      if (block?.type === "tool_use" && block.id && block.name) {
        pendingToolCalls.set(index, { id: block.id, name: block.name, args: "" });
      }
    } else if (type === "content_block_stop") {
      const index = event.index ?? 0;
      const tc = pendingToolCalls.get(index);
      if (tc) {
        if (!(yield* emitTool(tc))) {
          pendingToolCalls.clear();
          return;
        }
        pendingToolCalls.delete(index);
      }
    } else if (type === "message_delta") {
      const usage = event.usage;
      if (usage) {
        const promptTokens = usage.input_tokens ?? 0;
        const completionTokens = usage.output_tokens ?? 0;
        yield {
          type: "usage",
          usage: { promptTokens, completionTokens, totalTokens: promptTokens + completionTokens }
        };
      }
    } else if (type === "message_start") {
      const usage = event.message?.usage;
      if (usage) {
        yield {
          type: "usage",
          usage: {
            promptTokens: usage.input_tokens ?? 0,
            completionTokens: 0,
            totalTokens: usage.input_tokens ?? 0
          }
        };
      }
    } else if (type === "message_stop") {
      for (const [, tc] of pendingToolCalls) {
        if (!(yield* emitTool(tc))) {
          pendingToolCalls.clear();
          return;
        }
      }
      pendingToolCalls.clear();
      yield { type: "done" };
      return;
    }
  }
  pendingToolCalls.clear();
  yield adapterErrorChunk("Bedrock stream ended before message_stop");
}
function bedrock(config) {
  const { model, region, maxTokens = 4096 } = config;
  if (!isAnthropicModel(model)) {
    throw new core.ConfigError({
      code: core.ErrorCodes.AK_CONFIG_INVALID,
      message: `bedrock: model "${model}" is not supported in v1. Only anthropic.* models are wired up; Titan + others are tracked as a follow-up.`,
      hint: 'Pass an anthropic.* model id like "anthropic.claude-3-5-sonnet-20241022-v2:0".'
    });
  }
  let clientPromise = null;
  const getClient = async () => {
    if (config.client) return config.client;
    if (!clientPromise) {
      clientPromise = (async () => {
        const sdk = await loadSdk();
        return new sdk.BedrockRuntimeClient({ region });
      })();
    }
    return clientPromise;
  };
  return {
    capabilities: {
      streaming: true,
      tools: true,
      reasoning: model.includes("sonnet") || model.includes("opus"),
      multiModal: true,
      usage: true
    },
    createSource: (request) => {
      const controller = new AbortController();
      let aborted = false;
      return {
        stream: async function* () {
          if (aborted || controller.signal.aborted) return;
          try {
            const client = await getClient();
            if (aborted || controller.signal.aborted) return;
            const sdk = config.client ? null : await loadSdk();
            const input = {
              modelId: model,
              contentType: "application/json",
              accept: "application/json",
              body: buildAnthropicBody(request, maxTokens)
            };
            const command = sdk ? new sdk.InvokeModelWithResponseStreamCommand(input) : { input };
            const response = await client.send(command, { abortSignal: controller.signal });
            if (!response.body) {
              yield adapterErrorChunk("Bedrock: empty response body");
              return;
            }
            for await (const chunk of parseAnthropicBedrockEvents(response.body)) {
              if (aborted || controller.signal.aborted) return;
              yield chunk;
            }
          } catch (err) {
            if (isAbortError(err) || aborted) return;
            const message = err instanceof Error ? err.message : String(err);
            yield adapterErrorChunk(message, { cause: err });
          }
        },
        abort: () => {
          aborted = true;
          controller.abort();
        }
      };
    }
  };
}
var bedrockAdapter = bedrock;
var cachedSdk2 = null;
async function loadSdk2() {
  if (!cachedSdk2) {
    cachedSdk2 = (async () => {
      try {
        const moduleId = "@mlc-ai/web-llm";
        return await import(
          /* @vite-ignore */
          moduleId
        );
      } catch {
        throw new core.AdapterError({
          code: core.ErrorCodes.AK_ADAPTER_MISSING,
          message: "Install @mlc-ai/web-llm to use the webllm adapter: npm install @mlc-ai/web-llm",
          hint: "webllm is browser-only and depends on the optional peer @mlc-ai/web-llm."
        });
      }
    })();
  }
  return cachedSdk2;
}
function webllm(config) {
  let enginePromise = null;
  const getEngine = () => {
    if (config.engine) return Promise.resolve(config.engine);
    if (!enginePromise) {
      enginePromise = (async () => {
        const sdk = await loadSdk2();
        return sdk.CreateMLCEngine(config.model, { initProgressCallback: config.onProgress });
      })();
    }
    return enginePromise;
  };
  return {
    capabilities: {
      streaming: true,
      tools: false
    },
    createSource: (request) => {
      const controller = new AbortController();
      let aborted = false;
      let activeIter = null;
      const softAbort = () => {
        aborted = true;
        if (!controller.signal.aborted) controller.abort();
        if (activeIter && typeof activeIter.return === "function") {
          void activeIter.return(void 0).catch(() => {
          });
        }
      };
      return {
        stream: async function* () {
          if (aborted || controller.signal.aborted) return;
          try {
            const engine = await raceAbort(getEngine(), controller.signal);
            if (aborted || controller.signal.aborted) return;
            const messages = request.messages.map((m) => ({ role: m.role, content: m.content }));
            const completion = await raceAbort(
              Promise.resolve(
                engine.chat.completions.create({ messages, stream: true })
              ),
              controller.signal
            );
            if (aborted || controller.signal.aborted) return;
            activeIter = completion[Symbol.asyncIterator]();
            while (true) {
              if (aborted || controller.signal.aborted) {
                if (typeof activeIter.return === "function") {
                  await activeIter.return(void 0).catch(() => {
                  });
                }
                return;
              }
              const next = await raceAbort(activeIter.next(), controller.signal);
              if (next.done) break;
              if (aborted || controller.signal.aborted) {
                if (typeof activeIter.return === "function") {
                  await activeIter.return(void 0).catch(() => {
                  });
                }
                return;
              }
              const delta = next.value.choices[0]?.delta?.content;
              if (delta) yield { type: "text", content: delta };
            }
            if (aborted || controller.signal.aborted) return;
            yield { type: "done" };
          } catch (err) {
            if (isAbortError(err) || aborted || controller.signal.aborted) return;
            const message = err instanceof Error ? err.message : String(err);
            yield adapterErrorChunk(message, { cause: err });
          }
        },
        abort: () => {
          softAbort();
        }
      };
    }
  };
}
var webllmAdapter = webllm;
function requireCapabilities(request) {
  const needs = {};
  if (request.context?.tools && request.context.tools.length > 0) needs.tools = true;
  return needs;
}
function matchesCapabilities(need, have) {
  if (!have) return true;
  for (const key of Object.keys(need)) {
    if (key === "extensions") continue;
    if (need[key] && have[key] === false) return false;
  }
  return true;
}
function pickSyncPolicy(pool, policy) {
  if (policy === "cheapest") {
    const c = pool.reduce((best, x) => (x.cost ?? Infinity) < (best.cost ?? Infinity) ? x : best, pool[0]);
    return { c, reason: "cheapest" };
  }
  if (policy === "fastest") {
    const c = pool.reduce((best, x) => (x.latencyMs ?? Infinity) < (best.latencyMs ?? Infinity) ? x : best, pool[0]);
    return { c, reason: "fastest" };
  }
  if (policy === "greenest") {
    const c = pool.reduce((best, x) => (x.gCO2PerKtok ?? Infinity) < (best.gCO2PerKtok ?? Infinity) ? x : best, pool[0]);
    return { c, reason: "greenest" };
  }
  if (policy === "green-cost") {
    const carbonValues = pool.map((p) => p.gCO2PerKtok).filter((v) => v != null);
    const costValues = pool.map((p) => p.cost).filter((v) => v != null);
    const maxC = Math.max(1, ...carbonValues);
    const maxCost = Math.max(1, ...costValues);
    const score = (x) => {
      const carbon = (x.gCO2PerKtok ?? maxC / 2) / maxC;
      const cost = (x.cost ?? maxCost / 2) / maxCost;
      return carbon + cost;
    };
    const c = pool.reduce((best, x) => score(x) < score(best) ? x : best, pool[0]);
    return { c, reason: "green-cost" };
  }
  return { c: pool[0], reason: "capability-match" };
}
function matchesRegion(candidate, region) {
  return region === void 0 || candidate.region === region;
}
function createRouter(options) {
  const { candidates } = options;
  if (candidates.length === 0) {
    throw new core.ConfigError({
      code: core.ErrorCodes.AK_CONFIG_INVALID,
      message: "createRouter requires at least one candidate",
      hint: "Pass at least one candidate, e.g. createRouter({ candidates: [{ id, adapter, capabilities }] })."
    });
  }
  const policy = options.policy ?? "cheapest";
  return {
    createSource: (request) => {
      const need = requireCapabilities(request);
      const region = options.regionOf?.(request) ?? options.region;
      const capable = candidates.filter((c2) => matchesCapabilities(need, c2.capabilities ?? c2.adapter.capabilities));
      const eligible = capable.filter((c2) => matchesRegion(c2, region));
      if (capable.length > 0 && eligible.length === 0 && region !== void 0) {
        throw new core.ConfigError({
          code: core.ErrorCodes.AK_CONFIG_INVALID,
          message: `no candidate satisfies required region: ${region}`,
          hint: "Set candidate.region to the requested data-residency region, or remove the router region requirement."
        });
      }
      const classified = options.classify?.(request);
      if (typeof classified === "string") {
        const c2 = eligible.find((x) => x.id === classified);
        if (c2) {
          options.onRoute?.({ id: c2.id, reason: region ? `classify:id:${region}` : "classify:id", request });
          return c2.adapter.createSource(request);
        }
      }
      let pool = eligible;
      let pickedBy;
      if (Array.isArray(classified) && classified.length > 0) {
        const filtered = eligible.filter((c2) => c2.tags && classified.every((t) => c2.tags.includes(t)));
        if (filtered.length > 0) {
          pool = filtered;
          pickedBy = region ? `classify:tags:${region}` : "classify:tags";
        }
      }
      if (pool.length === 0) {
        throw new core.AdapterError({
          code: core.ErrorCodes.AK_ADAPTER_STREAM_FAILED,
          message: "no candidate satisfies the request",
          hint: "Ensure at least one candidate declares the required capabilities (tools, json, etc.)."
        });
      }
      if (typeof policy === "function") {
        const maybe = policy({ request, candidates: pool });
        if (typeof maybe !== "string") {
          const controller = new AbortController();
          let child;
          return {
            abort: () => {
              controller.abort();
              child?.abort();
            },
            stream: async function* () {
              let id;
              try {
                id = await raceAbort(maybe, controller.signal);
              } catch (err) {
                if (isAbortError(err)) return;
                const error = err instanceof Error ? err : new Error(String(err));
                yield {
                  type: "error",
                  content: error.message,
                  metadata: { error }
                };
                return;
              }
              const c3 = pool.find((x) => x.id === id);
              if (!c3) {
                const error = new core.ConfigError({
                  code: core.ErrorCodes.AK_CONFIG_INVALID,
                  message: `policy returned unknown id: ${id}`,
                  hint: "Custom policy functions must return one of the candidate ids."
                });
                yield {
                  type: "error",
                  content: error.message,
                  metadata: { error }
                };
                return;
              }
              try {
                options.onRoute?.({ id: c3.id, reason: pickedBy ?? "custom policy", request });
                child = c3.adapter.createSource(request);
                for await (const chunk of child.stream()) {
                  yield chunk;
                }
              } catch (err) {
                if (controller.signal.aborted || isAbortError(err)) return;
                const error = err instanceof Error ? err : new Error(String(err));
                yield {
                  type: "error",
                  content: error.message,
                  metadata: { error }
                };
              }
            }
          };
        }
        const c2 = pool.find((x) => x.id === maybe);
        if (!c2) {
          throw new core.ConfigError({
            code: core.ErrorCodes.AK_CONFIG_INVALID,
            message: `policy returned unknown id: ${maybe}`,
            hint: "Custom policy functions must return one of the candidate ids."
          });
        }
        options.onRoute?.({ id: c2.id, reason: pickedBy ?? "custom policy", request });
        return c2.adapter.createSource(request);
      }
      const { c, reason } = pickSyncPolicy(pool, policy);
      options.onRoute?.({ id: c.id, reason: pickedBy ?? reason, request });
      return c.adapter.createSource(request);
    }
  };
}

// src/carbon.ts
var DEFAULT_CARBON_TABLE = {
  // Anthropic — primarily AWS us-east-* / eu-west-* via Bedrock-style fronts.
  "anthropic:us-east-1": 0.42,
  "anthropic:us-west-2": 0.18,
  "anthropic:eu-central-1": 0.32,
  "anthropic:eu-west-1": 0.27,
  // OpenAI — Azure East US / West Europe / Sweden Central.
  "openai:eastus": 0.4,
  "openai:westus3": 0.19,
  "openai:swedencentral": 0.04,
  "openai:westeurope": 0.28,
  // Google (Vertex / Gemini) — typically reports lowest PUE.
  "google:us-central1": 0.34,
  "google:us-west1": 0.16,
  "google:europe-west1": 0.21,
  "google:europe-north1": 0.05,
  // AWS Bedrock direct.
  "aws:us-east-1": 0.42,
  "aws:us-west-2": 0.18,
  "aws:eu-west-1": 0.27,
  // Local / on-device — only the device's grid matters.
  "ollama:local": 0.3,
  "webllm:browser": 0.3,
  "lmstudio:local": 0.3,
  // Self-hosted / community.
  "groq:us-east-1": 0.4,
  "fireworks:us-west-2": 0.18,
  "together:us-east-1": 0.42,
  "cerebras:us-west-2": 0.18
};
function defaultKey(candidate) {
  if (!candidate.region) return void 0;
  const provider = candidate.id.split(/[-:]/)[0];
  return `${provider}:${candidate.region}`;
}
function applyCarbonTable(candidates, options = {}) {
  const table = options.table ?? DEFAULT_CARBON_TABLE;
  const keyFor = options.keyFor ?? defaultKey;
  return candidates.map((c) => {
    if (c.gCO2PerKtok != null) return c;
    const key = keyFor(c);
    const value = key ? table[key] : void 0;
    return { ...c, gCO2PerKtok: value ?? options.fallback };
  });
}
function estimateCO2Grams(gCO2PerKtok, tokens) {
  if (gCO2PerKtok == null) return 0;
  return tokens / 1e3 * gCO2PerKtok;
}
async function drain(source, timeoutMs) {
  const chunks = [];
  let text = "";
  let timer;
  let timedOut = false;
  let error;
  if (timeoutMs !== void 0) {
    timer = setTimeout(() => {
      timedOut = true;
      source.abort();
    }, timeoutMs);
  }
  try {
    for await (const chunk of source.stream()) {
      chunks.push(chunk);
      if (chunk.type === "text" && typeof chunk.content === "string") text += chunk.content;
      if (chunk.type === "error") {
        const metaErr = chunk.metadata?.error;
        error = metaErr instanceof Error ? metaErr : new Error(chunk.content ?? "stream error");
      }
    }
  } catch (err) {
    if (!isAbortError(err)) {
      error = err instanceof Error ? err : new Error(String(err));
    } else if (!timedOut) {
      error = err instanceof Error ? err : new Error(String(err));
    }
  } finally {
    if (timer) clearTimeout(timer);
  }
  if (timedOut) error = new Error(`timeout after ${timeoutMs}ms`);
  return { chunks, text, error };
}
function majorityVote(branches, candidates) {
  const counts = /* @__PURE__ */ new Map();
  const weightById = new Map(candidates.map((c) => [c.id, c.weight ?? 1]));
  for (const b of branches) {
    if (b.error) continue;
    counts.set(b.text, (counts.get(b.text) ?? 0) + (weightById.get(b.id) ?? 1));
  }
  let best = "";
  let bestScore = -1;
  for (const [text, score] of counts) {
    if (score > bestScore) {
      bestScore = score;
      best = text;
    }
  }
  return best;
}
function createEnsembleAdapter(options) {
  if (options.candidates.length === 0) {
    throw new core.ConfigError({
      code: core.ErrorCodes.AK_CONFIG_INVALID,
      message: "createEnsembleAdapter requires at least one candidate",
      hint: "Pass at least one candidate, e.g. createEnsembleAdapter({ candidates: [{ id, adapter }] })."
    });
  }
  const aggregate = options.aggregate ?? "majority-vote";
  return {
    createSource: (request) => {
      let aborted = false;
      const sources = [];
      const run = async () => {
        const tasks = options.candidates.map(async (c, i) => {
          try {
            const source = c.adapter.createSource(request);
            sources[i] = source;
            if (aborted) {
              source.abort();
              return { id: c.id, chunks: [], text: "", error: new Error("aborted") };
            }
            const { chunks, text, error } = await drain(source, options.timeoutMs);
            return { id: c.id, chunks, text, error };
          } catch (err) {
            const error = err instanceof Error ? err : new Error(String(err));
            return { id: c.id, chunks: [], text: "", error };
          }
        });
        return Promise.all(tasks);
      };
      const finalText = async (branches) => {
        if (typeof aggregate === "function") return aggregate(branches);
        if (aggregate === "concat") {
          return branches.filter((b) => !b.error).map((b) => b.text).join("\n---\n");
        }
        if (aggregate === "longest") {
          return branches.filter((b) => !b.error).reduce(
            (best, b) => b.text.length > best.length ? b.text : best,
            ""
          );
        }
        return majorityVote(branches, options.candidates);
      };
      return {
        abort: () => {
          aborted = true;
          for (const s of sources) s?.abort();
        },
        stream: async function* () {
          if (aborted) return;
          const branches = await run();
          options.onBranches?.(branches);
          if (aborted) {
            for (const s of sources) s?.abort();
            return;
          }
          try {
            const text = await finalText(branches);
            if (!text && branches.every((b) => b.error)) {
              const summary = branches.map((b) => `${b.id}: ${b.error?.message ?? "unknown"}`).join("; ");
              const err = new core.AdapterError({
                code: core.ErrorCodes.AK_ADAPTER_STREAM_FAILED,
                message: `all ensemble branches failed (${summary})`,
                hint: "Inspect each branch error via options.onBranches or the err.branchErrors field."
              });
              err.branchErrors = branches.map((b) => ({ id: b.id, error: b.error }));
              yield {
                type: "error",
                content: err.message,
                metadata: { error: err }
              };
              return;
            }
            yield {
              type: "text",
              content: text,
              metadata: {
                ensemble: branches.map((b) => ({
                  id: b.id,
                  bytes: b.text.length,
                  error: b.error?.message
                }))
              }
            };
            yield { type: "done" };
          } catch (err) {
            if (aborted || isAbortError(err)) return;
            const error = err instanceof Error ? err : new Error(String(err));
            yield {
              type: "error",
              content: error.message,
              metadata: { error }
            };
          }
        }
      };
    }
  };
}
function createFallbackAdapter(candidates, options = {}) {
  if (candidates.length === 0) {
    throw new core.ConfigError({
      code: core.ErrorCodes.AK_CONFIG_INVALID,
      message: "createFallbackAdapter requires at least one candidate",
      hint: 'Pass at least one candidate, e.g. createFallbackAdapter([{ id: "primary", adapter }]).'
    });
  }
  return {
    createSource: (request) => {
      let active;
      let aborted = false;
      return {
        abort: () => {
          aborted = true;
          active?.abort();
        },
        stream: async function* () {
          const errors = [];
          for (let i = 0; i < candidates.length; i++) {
            if (aborted) return;
            const candidate = candidates[i];
            let source;
            try {
              source = candidate.adapter.createSource(request);
            } catch (err2) {
              const error = err2 instanceof Error ? err2 : new Error(String(err2));
              errors.push({ id: candidate.id, error });
              options.onFallback?.({ id: candidate.id, index: i, error });
              if (options.shouldRetry && !options.shouldRetry(error, i)) {
                yield {
                  type: "error",
                  content: error.message,
                  metadata: { error }
                };
                return;
              }
              continue;
            }
            active = source;
            const iter = source.stream()[Symbol.asyncIterator]();
            let firstReal;
            let branchError;
            const leadingUsage = [];
            try {
              while (true) {
                if (aborted) {
                  source.abort();
                  return;
                }
                const r = await iter.next();
                if (r.done) {
                  branchError = new Error(`candidate ${candidate.id} emitted no chunks`);
                  break;
                }
                if (r.value.type === "error") {
                  const metaErr = r.value.metadata?.error;
                  branchError = metaErr instanceof Error ? metaErr : new Error(
                    `candidate ${candidate.id}: ${r.value.content ?? "stream error"}`
                  );
                  break;
                }
                if (r.value.type === "usage") {
                  leadingUsage.push(r.value);
                  continue;
                }
                firstReal = r.value;
                break;
              }
            } catch (err2) {
              if (isAbortError(err2) || aborted) {
                source.abort();
                return;
              }
              branchError = err2 instanceof Error ? err2 : new Error(String(err2));
            }
            if (branchError || !firstReal) {
              const error = branchError ?? new Error(`candidate ${candidate.id} emitted no chunks`);
              errors.push({ id: candidate.id, error });
              options.onFallback?.({ id: candidate.id, index: i, error });
              try {
                source.abort();
              } catch {
              }
              if (typeof iter.return === "function") {
                try {
                  await iter.return(void 0);
                } catch {
                }
              }
              if (options.shouldRetry && !options.shouldRetry(error, i)) {
                yield {
                  type: "error",
                  content: error.message,
                  metadata: { error }
                };
                return;
              }
              active = void 0;
              continue;
            }
            for (const chunk of leadingUsage) yield chunk;
            yield firstReal;
            while (true) {
              if (aborted) {
                source.abort();
                return;
              }
              try {
                const next = await iter.next();
                if (next.done) return;
                yield next.value;
              } catch (err2) {
                if (isAbortError(err2) || aborted) {
                  source.abort();
                  return;
                }
                const error = err2 instanceof Error ? err2 : new Error(String(err2));
                yield {
                  type: "error",
                  content: error.message,
                  metadata: { error }
                };
                return;
              }
            }
          }
          const summary = errors.map((e) => `${e.id}: ${e.error.message}`).join("; ");
          const err = new core.AdapterError({
            code: core.ErrorCodes.AK_ADAPTER_STREAM_FAILED,
            message: `all fallback candidates failed (${summary})`,
            hint: "Check each candidate adapter's configuration and provider keys."
          });
          yield {
            type: "error",
            content: err.message,
            metadata: { error: err }
          };
        }
      };
    }
  };
}
function mockAdapter(options) {
  const { response, delayMs = 0, history } = options;
  let callIndex = 0;
  return {
    capabilities: {
      streaming: true,
      tools: true,
      reasoning: true,
      multiModal: true,
      usage: true
    },
    createSource: (request) => {
      const controller = new AbortController();
      let myCall;
      let cancelled = false;
      return {
        stream: async function* () {
          if (cancelled || controller.signal.aborted) return;
          try {
            if (myCall === void 0) {
              myCall = callIndex++;
              history?.push(request);
            }
            const chunks = resolve(response, myCall, request);
            for (const chunk of chunks) {
              if (cancelled || controller.signal.aborted) return;
              if (delayMs > 0) {
                await abortableSleep(delayMs, controller.signal, (ms) => new Promise((resolveTimer) => setTimeout(resolveTimer, ms)));
              }
              if (cancelled || controller.signal.aborted) return;
              if (chunk.type === "error" && !(chunk.metadata?.error instanceof Error)) {
                const normalized = adapterErrorChunk(
                  chunk.content ?? "Mock adapter error",
                  { cause: chunk.metadata?.error }
                );
                yield {
                  ...chunk,
                  metadata: { ...chunk.metadata, ...normalized.metadata }
                };
                return;
              }
              yield chunk;
              if (chunk.type === "done" || chunk.type === "error") return;
            }
            yield { type: "done" };
          } catch (error) {
            if (cancelled || controller.signal.aborted || isAbortError(error)) return;
            const message = error instanceof Error ? error.message : String(error);
            yield adapterErrorChunk(message, { cause: error });
          }
        },
        abort: () => {
          cancelled = true;
          controller.abort();
        }
      };
    }
  };
}
function resolve(response, callIndex, request) {
  if (Array.isArray(response) && response.length > 0 && Array.isArray(response[0])) {
    const sequence = response;
    const item = sequence[callIndex % sequence.length];
    return item;
  }
  if (Array.isArray(response) && response.length > 0 && typeof response[0] === "function") {
    const sequence = response;
    return sequence[callIndex % sequence.length](request);
  }
  if (typeof response === "function") {
    return response(request);
  }
  return response;
}
function recordingAdapter(inner, sink) {
  return {
    capabilities: inner.capabilities,
    createSource: (request) => {
      let innerSource;
      const captured = [];
      let aborted = false;
      return {
        stream: async function* () {
          if (aborted) return;
          const recordedAt = (/* @__PURE__ */ new Date()).toISOString();
          try {
            innerSource = inner.createSource(request);
            for await (const chunk of innerSource.stream()) {
              if (aborted) return;
              captured.push(chunk);
              yield chunk;
              if (chunk.type === "done" || chunk.type === "error") return;
            }
            const errorChunk = adapterErrorChunk("Recorded adapter ended without a terminal chunk");
            captured.push(errorChunk);
            yield errorChunk;
          } catch (error) {
            if (aborted || isAbortError(error)) return;
            const message = error instanceof Error ? error.message : String(error);
            const errorChunk = adapterErrorChunk(message, { cause: error });
            captured.push(errorChunk);
            yield errorChunk;
          } finally {
            try {
              await sink.push({ recordedAt, request, chunks: captured });
            } catch {
            }
          }
        },
        abort: () => {
          aborted = true;
          innerSource?.abort();
        }
      };
    }
  };
}
function inMemorySink() {
  const fixture = [];
  return {
    fixture,
    push(turn) {
      fixture.push(turn);
    }
  };
}
function replayAdapter(fixture) {
  if (fixture.length === 0) {
    throw new core.ConfigError({
      code: core.ErrorCodes.AK_CONFIG_INVALID,
      message: "replayAdapter: fixture is empty",
      hint: "Pass a non-empty fixture; record one with recordingAdapter() first."
    });
  }
  return mockAdapter({
    response: fixture.map((turn) => turn.chunks)
  });
}
async function throwIfNotOk(response, label, _url) {
  if (response.ok) return;
  void response.body?.cancel().catch(() => {
  });
  throw embeddingError(label, `HTTP ${response.status}`);
}
function embeddingError(label, detail, cause) {
  return new core.AdapterError({
    code: core.ErrorCodes.AK_ADAPTER_STREAM_FAILED,
    message: `${label} embedding failed: ${detail}`,
    cause
  });
}
function requireEmbeddingVector(value, label) {
  if (!Array.isArray(value) || value.length === 0) {
    throw new core.AdapterError({
      code: core.ErrorCodes.AK_ADAPTER_STREAM_FAILED,
      message: `${label} returned an empty or missing embedding vector`,
      hint: "The provider responded 2xx but the embedding payload was empty or malformed."
    });
  }
  const vector = [];
  for (let i = 0; i < value.length; i++) {
    const n = value[i];
    if (typeof n !== "number" || !Number.isFinite(n)) {
      throw new core.AdapterError({
        code: core.ErrorCodes.AK_ADAPTER_STREAM_FAILED,
        message: `${label} returned a non-finite embedding value at index ${i}`,
        hint: "Embedding vectors must be finite numbers only."
      });
    }
    vector.push(n);
  }
  return vector;
}

// src/embedders/openai.ts
async function fetchAvailableModels(baseUrl, apiKey) {
  const url = `${baseUrl}/v1/models`;
  const response = await fetch(url, {
    headers: { "Authorization": `Bearer ${apiKey}` }
  });
  await throwIfNotOk(response, "openai");
  const data = await response.json();
  return data.data.map((m) => m.id).filter((id) => id.includes("embed")).sort();
}
async function buildModelError(baseUrl, apiKey, originalError) {
  try {
    const models = await fetchAvailableModels(baseUrl, apiKey);
    const list = models.length > 0 ? models.join(", ") : "none found";
    return embeddingError("OpenAI", `${originalError}. Available embedding models: ${list}`);
  } catch (fetchError) {
    return embeddingError("OpenAI", `${originalError}. Could not fetch available models`, fetchError);
  }
}
function openaiEmbedder(config) {
  const { apiKey, model = "text-embedding-3-small", baseUrl = "https://api.openai.com" } = config;
  return async (text) => {
    const response = await fetch(`${baseUrl}/v1/embeddings`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${apiKey}`
      },
      body: JSON.stringify({ model, input: text })
    });
    if (!response.ok) {
      void response.body?.cancel().catch(() => {
      });
      const message = `HTTP ${response.status}`;
      throw await buildModelError(baseUrl, apiKey, message);
    }
    const data = await response.json();
    const embedding = data.data?.[0]?.embedding;
    return requireEmbeddingVector(embedding, "OpenAI");
  };
}

// src/embedders/gemini.ts
async function fetchAvailableModels2(baseUrl, apiKey) {
  const url = `${baseUrl}/v1beta/models`;
  const response = await fetch(url, {
    headers: { "x-goog-api-key": apiKey }
  });
  await throwIfNotOk(response, "gemini");
  const data = await response.json();
  return data.models.filter((m) => m.supportedGenerationMethods.includes("embedContent")).map((m) => m.name.replace("models/", "")).sort();
}
async function buildModelError2(baseUrl, apiKey, originalError) {
  try {
    const models = await fetchAvailableModels2(baseUrl, apiKey);
    const list = models.length > 0 ? models.join(", ") : "none found";
    return embeddingError("Gemini", `${originalError}. Available embedding models: ${list}`);
  } catch (fetchError) {
    return embeddingError("Gemini", `${originalError}. Could not fetch available models`, fetchError);
  }
}
function geminiEmbedder(config) {
  const {
    apiKey,
    model = "text-embedding-004",
    baseUrl = "https://generativelanguage.googleapis.com"
  } = config;
  return async (text) => {
    const response = await fetch(
      `${baseUrl}/v1beta/models/${model}:embedContent`,
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "x-goog-api-key": apiKey
        },
        body: JSON.stringify({
          model: `models/${model}`,
          content: { parts: [{ text }] }
        })
      }
    );
    if (!response.ok) {
      void response.body?.cancel().catch(() => {
      });
      const message = `HTTP ${response.status}`;
      throw await buildModelError2(baseUrl, apiKey, message);
    }
    const data = await response.json();
    return requireEmbeddingVector(data.embedding?.values, "Gemini");
  };
}

// src/embedders/ollama.ts
async function fetchAvailableModels3(baseUrl) {
  const url = `${baseUrl}/api/tags`;
  const response = await fetch(url);
  await throwIfNotOk(response, "ollama");
  const data = await response.json();
  return data.models.map((m) => m.name).filter((name) => name.includes("embed")).sort();
}
async function buildModelError3(baseUrl, originalError) {
  try {
    const models = await fetchAvailableModels3(baseUrl);
    const list = models.length > 0 ? models.join(", ") : "none found";
    return embeddingError("Ollama", `${originalError}. Available embedding models: ${list}`);
  } catch (fetchError) {
    return embeddingError("Ollama", `${originalError}. Could not fetch available models`, fetchError);
  }
}
function ollamaEmbedder(config) {
  const { model = "nomic-embed-text", baseUrl = "http://localhost:11434" } = config;
  return async (text) => {
    const response = await fetch(`${baseUrl}/api/embed`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ model, input: text })
    });
    if (!response.ok) {
      void response.body?.cancel().catch(() => {
      });
      const message = `HTTP ${response.status}`;
      throw await buildModelError3(baseUrl, message);
    }
    const data = await response.json();
    const first = Array.isArray(data.embeddings) ? data.embeddings[0] : void 0;
    return requireEmbeddingVector(first, "Ollama");
  };
}
async function fetchAvailableModels4(provider, baseUrl, apiKey) {
  const url = `${baseUrl}/v1/models`;
  const response = await fetch(url, {
    headers: { "Authorization": `Bearer ${apiKey}` }
  });
  await throwIfNotOk(response, provider);
  const data = await response.json();
  return data.data.map((m) => m.id).filter((id) => id.includes("embed")).sort();
}
async function buildModelError4(provider, baseUrl, apiKey, originalError) {
  try {
    const models = await fetchAvailableModels4(provider, baseUrl, apiKey);
    const list = models.length > 0 ? models.join(", ") : "none found";
    return embeddingError(provider, `${originalError}. Available embedding models: ${list}`);
  } catch (fetchError) {
    return embeddingError(provider, `${originalError}. Could not fetch available models`, fetchError);
  }
}
function createOpenAICompatibleEmbedder(provider, defaultBaseUrl) {
  return function embedder(config) {
    if (!config.model) {
      throw new core.ConfigError({
        code: core.ErrorCodes.AK_CONFIG_INVALID,
        message: `Model is required for ${provider}. Pass { model: "<model-name>" }.`,
        hint: `${provider} does not infer a default; pick a recent embedding model and pass it explicitly.`
      });
    }
    const { apiKey, model, baseUrl = defaultBaseUrl } = config;
    return async (text) => {
      const response = await fetch(`${baseUrl}/v1/embeddings`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "Authorization": `Bearer ${apiKey}`
        },
        body: JSON.stringify({ model, input: text })
      });
      if (!response.ok) {
        void response.body?.cancel().catch(() => {
        });
        const message = `HTTP ${response.status}`;
        throw await buildModelError4(provider, baseUrl, apiKey, message);
      }
      const data = await response.json();
      const embedding = data.data?.[0]?.embedding;
      return requireEmbeddingVector(embedding, provider);
    };
  };
}

// src/embedders/deepseek.ts
var deepseekEmbedder = createOpenAICompatibleEmbedder("DeepSeek", "https://api.deepseek.com");

// src/embedders/grok.ts
var grokEmbedder = createOpenAICompatibleEmbedder("Grok", "https://api.x.ai");

// src/embedders/kimi.ts
var kimiEmbedder = createOpenAICompatibleEmbedder("Kimi", "https://api.moonshot.ai");
var DEFAULT_DEPRECATION_TABLE = [
  // OpenAI
  { provider: "openai", model: "gpt-3.5-turbo-0301", successor: "gpt-4o-mini", sunsetOn: "2024-09-13" },
  { provider: "openai", model: "gpt-3.5-turbo-0613", successor: "gpt-4o-mini", sunsetOn: "2024-09-13" },
  { provider: "openai", model: "gpt-4-0314", successor: "gpt-4o", sunsetOn: "2024-06-13" },
  { provider: "openai", model: "gpt-4-32k", successor: "gpt-4o", sunsetOn: "2024-06-06" },
  { provider: "openai", model: "text-davinci-003", successor: "gpt-4o-mini", sunsetOn: "2024-01-04" },
  // Anthropic
  { provider: "anthropic", model: "claude-2.0", successor: "claude-3-5-sonnet-latest", sunsetOn: "2025-07-21" },
  { provider: "anthropic", model: "claude-2.1", successor: "claude-3-5-sonnet-latest", sunsetOn: "2025-07-21" },
  { provider: "anthropic", model: "claude-instant-1.2", successor: "claude-3-5-haiku-latest", sunsetOn: "2024-07-22" },
  { provider: "anthropic", model: "claude-3-sonnet-20240229", successor: "claude-3-5-sonnet-latest", sunsetOn: "2025-07-21" },
  // Google
  { provider: "google", model: "gemini-1.0-pro", successor: "gemini-1.5-pro", sunsetOn: "2025-02-15" },
  { provider: "google", model: "gemini-pro-vision", successor: "gemini-1.5-pro", sunsetOn: "2024-07-12" }
];
function resolveModel(input, policy) {
  const table = policy.table ?? DEFAULT_DEPRECATION_TABLE;
  const hit = table.find((d) => d.provider === input.provider && d.model === input.model);
  if (!hit) return { model: input.model, remapped: false };
  const log = policy.logger ?? ((msg) => console.warn(msg));
  const sunset = hit.sunsetOn ? ` (sunset ${hit.sunsetOn})` : "";
  const successor = hit.successor ? ` Suggested successor: ${hit.successor}.` : "";
  const base = `[agentskit] Model "${input.provider}:${input.model}" is deprecated${sunset}.${successor}`;
  switch (policy.onDeprecation) {
    case "fail":
      throw new core.ConfigError({
        code: core.ErrorCodes.AK_CONFIG_INVALID,
        message: base,
        hint: hit.successor ? `Set model to "${hit.successor}".` : "Pick a supported model from the provider."
      });
    case "remap": {
      if (!hit.successor) {
        throw new core.ConfigError({
          code: core.ErrorCodes.AK_CONFIG_INVALID,
          message: `${base} No successor available \u2014 cannot remap.`
        });
      }
      log(`${base} Auto-remapping to "${hit.successor}".`);
      return { model: hit.successor, remapped: true, deprecation: hit };
    }
    case "warn":
    default:
      log(base);
      return { model: input.model, remapped: false, deprecation: hit };
  }
}
function withDeprecationPolicy(factory, options) {
  resolveModel({ provider: options.provider, model: options.model }, options);
  return factory;
}

// src/credential-rotation.ts
function createRotatingCredentials(initial, options) {
  let value = initial;
  const handlers = /* @__PURE__ */ new Set();
  return {
    current: () => value,
    rotate: async (next) => {
      value = next;
      const event = {
        rotatedAt: (/* @__PURE__ */ new Date()).toISOString(),
        id: options.id,
        fingerprint: next.slice(-4)
      };
      for (const h of handlers) h(event);
      return next;
    },
    onRotate: (handler) => {
      handlers.add(handler);
      return () => handlers.delete(handler);
    }
  };
}
async function refreshCredentials(adapter, next, options) {
  const log = options?.logger ?? ((msg) => console.log(msg));
  if (adapter && typeof adapter === "object" && "refreshCredentials" in adapter && typeof adapter.refreshCredentials === "function") {
    await adapter.refreshCredentials(next);
    log(`[agentskit] credentials refreshed${options?.id ? ` (${options.id})` : ""}`);
    return true;
  }
  log(`[agentskit] adapter does not support credential rotation; restart required${options?.id ? ` (${options.id})` : ""}`);
  return false;
}

exports.DEFAULT_CARBON_TABLE = DEFAULT_CARBON_TABLE;
exports.DEFAULT_DEPRECATION_TABLE = DEFAULT_DEPRECATION_TABLE;
exports.anthropic = anthropic;
exports.applyCarbonTable = applyCarbonTable;
exports.azureOpenAI = azureOpenAI;
exports.azureOpenAIAdapter = azureOpenAIAdapter;
exports.bail = bail;
exports.bailAdapter = bailAdapter;
exports.bedrock = bedrock;
exports.bedrockAdapter = bedrockAdapter;
exports.cerebras = cerebras;
exports.cerebrasAdapter = cerebrasAdapter;
exports.chunkText = chunkText;
exports.cohere = cohere;
exports.cohereAdapter = cohereAdapter;
exports.createAdapter = createAdapter;
exports.createEnsembleAdapter = createEnsembleAdapter;
exports.createFallbackAdapter = createFallbackAdapter;
exports.createOpenAICompatibleEmbedder = createOpenAICompatibleEmbedder;
exports.createRotatingCredentials = createRotatingCredentials;
exports.createRouter = createRouter;
exports.deepseek = deepseek;
exports.deepseekEmbedder = deepseekEmbedder;
exports.estimateCO2Grams = estimateCO2Grams;
exports.fetchWithRetry = fetchWithRetry;
exports.fireworks = fireworks;
exports.gemini = gemini;
exports.geminiEmbedder = geminiEmbedder;
exports.generic = generic;
exports.grok = grok;
exports.grokEmbedder = grokEmbedder;
exports.groq = groq;
exports.groqAdapter = groqAdapter;
exports.huggingface = huggingface;
exports.inMemorySink = inMemorySink;
exports.kimi = kimi;
exports.kimiEmbedder = kimiEmbedder;
exports.langchain = langchain;
exports.langgraph = langgraph;
exports.llamacpp = llamacpp;
exports.lmstudio = lmstudio;
exports.mistral = mistral;
exports.mockAdapter = mockAdapter;
exports.ollama = ollama;
exports.ollamaEmbedder = ollamaEmbedder;
exports.openai = openai;
exports.openaiEmbedder = openaiEmbedder;
exports.openrouter = openrouter;
exports.qwen = qwen;
exports.recordingAdapter = recordingAdapter;
exports.refreshCredentials = refreshCredentials;
exports.replayAdapter = replayAdapter;
exports.replicate = replicate;
exports.replicateAdapter = replicateAdapter;
exports.resolveModel = resolveModel;
exports.simulateStream = simulateStream;
exports.together = together;
exports.vercelAI = vercelAI;
exports.vertex = vertex;
exports.vertexAdapter = vertexAdapter;
exports.vllm = vllm;
exports.webllm = webllm;
exports.webllmAdapter = webllmAdapter;
exports.withDeprecationPolicy = withDeprecationPolicy;
//# sourceMappingURL=index.cjs.map
//# sourceMappingURL=index.cjs.map