// @bun
var __create = Object.create;
var __getProtoOf = Object.getPrototypeOf;
var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __hasOwnProp = Object.prototype.hasOwnProperty;
function __accessProp(key) {
  return this[key];
}
var __toESMCache_node;
var __toESMCache_esm;
var __toESM = (mod, isNodeMode, target) => {
  var canCache = mod != null && typeof mod === "object";
  if (canCache) {
    var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
    var cached = cache.get(mod);
    if (cached)
      return cached;
  }
  target = mod != null ? __create(__getProtoOf(mod)) : {};
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
  for (let key of __getOwnPropNames(mod))
    if (!__hasOwnProp.call(to, key))
      __defProp(to, key, {
        get: __accessProp.bind(mod, key),
        enumerable: true
      });
  if (canCache)
    cache.set(mod, to);
  return to;
};
var __toCommonJS = (from) => {
  var entry = (__moduleCache ??= new WeakMap).get(from), desc;
  if (entry)
    return entry;
  entry = __defProp({}, "__esModule", { value: true });
  if (from && typeof from === "object" || typeof from === "function") {
    for (var key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(entry, key))
        __defProp(entry, key, {
          get: __accessProp.bind(from, key),
          enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
        });
  }
  __moduleCache.set(from, entry);
  return entry;
};
var __moduleCache;
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
var __returnValue = (v) => v;
function __exportSetter(name, newValue) {
  this[name] = __returnValue.bind(null, newValue);
}
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, {
      get: all[name],
      enumerable: true,
      configurable: true,
      set: __exportSetter.bind(all, name)
    });
};
var __legacyDecorateClassTS = function(decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
    r = Reflect.decorate(decorators, target, key, desc);
  else
    for (var i = decorators.length - 1;i >= 0; i--)
      if (d = decorators[i])
        r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __legacyMetadataTS = (k, v) => {
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
    return Reflect.metadata(k, v);
};
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
var __require = import.meta.require;

// src/ai/providers/ollama.ts
var DEFAULT_BASE_URL = "http://localhost:11434";
var ZERO_TOKENS = 0;
var DONE_CHUNK = { type: "done" };
var mapToolDefinitions = (tools) => tools.map((tool) => ({
  function: {
    description: tool.description,
    name: tool.name,
    parameters: tool.input_schema
  },
  type: "function"
}));
var convertMessage = (msg) => {
  if (typeof msg.content === "string") {
    return [{ content: msg.content, role: msg.role }];
  }
  const results = [];
  const toolUseBlocks = msg.content.filter((block) => block.type === "tool_use");
  const toolResultBlocks = msg.content.filter((block) => block.type === "tool_result");
  if (toolUseBlocks.length > 0) {
    results.push({
      content: "",
      role: "assistant",
      tool_calls: toolUseBlocks.map((block) => ({
        function: {
          arguments: typeof block.input === "object" && block.input !== null ? { ...block.input } : {},
          name: block.name
        }
      }))
    });
  }
  for (const block of toolResultBlocks) {
    results.push({
      content: typeof block.content === "string" ? block.content : "",
      role: "tool"
    });
  }
  return results;
};
var buildRequestBody = (params) => {
  const messages = params.messages.flatMap(convertMessage);
  if (params.systemPrompt) {
    messages.unshift({ content: params.systemPrompt, role: "system" });
  }
  const body = {
    messages,
    model: params.model,
    stream: true
  };
  if (params.tools && params.tools.length > 0) {
    body.tools = mapToolDefinitions(params.tools);
  }
  return body;
};
var isRecord = (val) => val !== null && typeof val === "object" && !Array.isArray(val);
var tryParseJSON = (text) => {
  try {
    const result = JSON.parse(text);
    if (isRecord(result)) {
      return result;
    }
    return null;
  } catch {
    return null;
  }
};
var buildDoneChunk = (parsed) => {
  const promptEvalCount = typeof parsed.prompt_eval_count === "number" ? parsed.prompt_eval_count : undefined;
  const evalCount = typeof parsed.eval_count === "number" ? parsed.eval_count : undefined;
  const totalDuration = typeof parsed.total_duration === "number" ? parsed.total_duration : undefined;
  const hasTokenCounts = promptEvalCount !== undefined || evalCount !== undefined;
  if (hasTokenCounts) {
    return {
      type: "done",
      usage: {
        inputTokens: promptEvalCount ?? ZERO_TOKENS,
        outputTokens: evalCount ?? ZERO_TOKENS
      }
    };
  }
  if (totalDuration !== undefined) {
    return {
      type: "done",
      usage: { inputTokens: ZERO_TOKENS, outputTokens: ZERO_TOKENS }
    };
  }
  return { type: "done" };
};
var buildTextChunk = (content) => ({
  content,
  type: "text"
});
var extractToolCalls = (message) => {
  const toolCalls = message.tool_calls;
  if (!Array.isArray(toolCalls) || toolCalls.length === 0) {
    return [];
  }
  return toolCalls.filter(isRecord).filter((call) => isRecord(call.function)).map((call) => {
    const func = call.function;
    if (!isRecord(func)) {
      return {
        id: crypto.randomUUID(),
        input: {},
        name: "",
        type: "tool_use"
      };
    }
    return {
      id: crypto.randomUUID(),
      input: func.arguments ?? {},
      name: typeof func.name === "string" ? func.name : "",
      type: "tool_use"
    };
  });
};
var extractChunks = (parsed) => {
  const { message } = parsed;
  if (!isRecord(message)) {
    return [];
  }
  const toolChunks = extractToolCalls(message);
  if (toolChunks.length > 0) {
    return toolChunks;
  }
  const { content } = message;
  if (typeof content !== "string" || !content) {
    return [];
  }
  return [buildTextChunk(content)];
};
var processLine = (line) => {
  const trimmed = line.trim();
  if (!trimmed) {
    return [];
  }
  const parsed = tryParseJSON(trimmed);
  if (!parsed) {
    return [];
  }
  if (parsed.done === true) {
    return [buildDoneChunk(parsed)];
  }
  return extractChunks(parsed);
};
var processBufferedLines = (lines) => lines.flatMap(processLine);
var readStreamChunks = async (reader, decoder, buffer, signal) => {
  const emptyChunks = [];
  if (signal?.aborted) {
    return {
      allChunks: emptyChunks,
      currentBuffer: buffer,
      finished: true
    };
  }
  const result = await reader.read();
  const { done, value } = result;
  if (done) {
    return {
      allChunks: emptyChunks,
      currentBuffer: buffer,
      finished: true
    };
  }
  const currentBuffer = buffer + decoder.decode(value, { stream: true });
  const lines = currentBuffer.split(`
`);
  const remainder = lines.pop() ?? "";
  const allChunks = processBufferedLines(lines);
  const finished = allChunks.some((c) => c.type === "done");
  return { allChunks, currentBuffer: remainder, finished };
};
var parseNDJSONStream = async function* (body, signal) {
  const reader = body.getReader();
  try {
    yield* parseNDJSONStreamInner(reader, signal);
  } finally {
    reader.releaseLock();
  }
};
var parseNDJSONStreamInner = async function* (reader, signal) {
  const decoder = new TextDecoder;
  let buffer = "";
  let done = false;
  while (!done) {
    const result = await readStreamChunks(reader, decoder, buffer, signal);
    buffer = result.currentBuffer;
    done = result.finished;
    yield* result.allChunks;
  }
  yield DONE_CHUNK;
};
var fetchAndStream = async function* (baseUrl, params) {
  const requestBody = buildRequestBody(params);
  const response = await fetch(`${baseUrl}/api/chat`, {
    body: JSON.stringify(requestBody),
    headers: { "Content-Type": "application/json" },
    method: "POST",
    signal: params.signal
  });
  if (!response.ok) {
    const errorText = await response.text();
    throw new Error(`Ollama API error ${response.status}: ${errorText}`);
  }
  if (!response.body) {
    throw new Error("Ollama API returned no response body");
  }
  yield* parseNDJSONStream(response.body, params.signal);
};
var ollama = (config = {}) => {
  const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
  return {
    stream: (params) => fetchAndStream(baseUrl, params)
  };
};
export {
  ollama
};

//# debugId=EE1C0DDC1029947664756E2164756E21
//# sourceMappingURL=ollama.js.map
