'use strict';

var react = require('react');

// src/ai/llm/client/request.ts
var requestJson = async (options) => {
  const { url, method = "POST", headers = {}, body, timeoutMs, requestAdapter } = options;
  if (requestAdapter) {
    return requestAdapter.request({
      url,
      method,
      headers,
      body
    });
  }
  const controller = timeoutMs ? new AbortController() : void 0;
  const timeoutId = timeoutMs ? setTimeout(() => {
    controller?.abort();
  }, timeoutMs) : void 0;
  try {
    const response = await fetch(url, {
      method,
      headers,
      body: body ? JSON.stringify(body) : void 0,
      signal: controller?.signal
    });
    const text = await response.text();
    let data = null;
    if (text) {
      try {
        data = JSON.parse(text);
      } catch {
        data = text;
      }
    }
    if (!response.ok) {
      const errorMessage = data?.error?.message || data?.error || data?.message || `Request failed with status ${response.status}`;
      const error = new Error(errorMessage);
      error.status = response.status;
      error.data = data;
      throw error;
    }
    return data;
  } finally {
    if (timeoutId) {
      clearTimeout(timeoutId);
    }
  }
};

// src/ai/llm/providers/openai-compatible.ts
var DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
var DEFAULT_OPENAI_MODEL = "gpt-3.5-turbo";
var joinUrl = (base, path) => {
  const trimmedBase = base.replace(/\/+$/, "");
  const trimmedPath = path.replace(/^\/+/, "");
  return `${trimmedBase}/${trimmedPath}`;
};
var normalizeToolCalls = (toolCalls) => {
  if (!toolCalls || !toolCalls.length) {
    return void 0;
  }
  return toolCalls.map((call, index) => ({
    id: call?.id ?? String(index),
    type: "function",
    function: {
      name: call?.function?.name ?? "",
      arguments: call?.function?.arguments ?? ""
    }
  }));
};
var normalizeUsage = (usage) => {
  if (!usage) {
    return void 0;
  }
  return {
    promptTokens: usage.prompt_tokens,
    completionTokens: usage.completion_tokens,
    totalTokens: usage.total_tokens
  };
};
var mapMessage = (message) => {
  const mapped = {
    role: message.role,
    content: message.content
  };
  if (message.name) {
    mapped.name = message.name;
  }
  if (message.toolCallId) {
    mapped.tool_call_id = message.toolCallId;
  }
  if (message.toolCalls?.length) {
    mapped.tool_calls = message.toolCalls.map((call) => ({
      id: call.id,
      type: call.type,
      function: {
        name: call.function.name,
        arguments: call.function.arguments
      }
    }));
  }
  return mapped;
};
var createOpenAICompatibleProvider = () => {
  return {
    id: "openai-compatible",
    sendChat: async (request, config) => {
      if (request.stream) {
        throw new Error("Streaming is not supported in sendChat. Use streamChat when available.");
      }
      const model = request.model ?? config.model ?? DEFAULT_OPENAI_MODEL;
      if (!model) {
        throw new Error("Model is required for chat completion requests.");
      }
      const payload = {
        model,
        messages: request.messages.map(mapMessage)
      };
      if (request.temperature !== void 0) {
        payload.temperature = request.temperature;
      }
      if (request.maxTokens !== void 0) {
        payload.max_tokens = request.maxTokens;
      }
      if (request.topP !== void 0) {
        payload.top_p = request.topP;
      }
      if (request.stop !== void 0) {
        payload.stop = request.stop;
      }
      if (request.tools) {
        payload.tools = request.tools;
      }
      if (request.toolChoice) {
        payload.tool_choice = request.toolChoice;
      }
      const url = joinUrl(config.baseUrl || DEFAULT_OPENAI_BASE_URL, "chat/completions");
      const response = await requestJson({
        url,
        method: "POST",
        headers: config.headers,
        body: payload,
        timeoutMs: config.timeoutMs,
        requestAdapter: config.requestAdapter
      });
      const firstMessage = response.choices?.[0]?.message;
      const toolCalls = normalizeToolCalls(firstMessage?.tool_calls);
      const content = firstMessage?.content ?? "";
      const assistantMessage = {
        role: "assistant",
        content,
        toolCalls
      };
      return {
        id: response.id ?? "",
        content,
        message: assistantMessage,
        usage: normalizeUsage(response.usage),
        toolCalls,
        raw: response
      };
    }
  };
};

// src/ai/llm/client/createAiClient.ts
var DEFAULT_TIMEOUT_MS = 6e4;
var resolveApiKey = async (config) => {
  if (config.apiKey) {
    return config.apiKey;
  }
  if (config.getApiKey) {
    return await config.getApiKey();
  }
  return void 0;
};
var hasAuthorizationHeader = (headers) => {
  return Object.keys(headers).some((key) => key.toLowerCase() === "authorization");
};
var resolveHeaders = async (config) => {
  const headers = {
    "Content-Type": "application/json",
    ...config.headers ?? {}
  };
  if (!hasAuthorizationHeader(headers)) {
    const apiKey = await resolveApiKey(config);
    if (apiKey) {
      headers.Authorization = `Bearer ${apiKey}`;
    }
  }
  return headers;
};
var resolveClientConfig = async (config) => {
  const headers = await resolveHeaders(config);
  return {
    ...config,
    baseUrl: config.baseUrl ?? "https://api.openai.com/v1",
    headers,
    timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS
  };
};
var resolveProvider = (provider) => {
  return provider ?? createOpenAICompatibleProvider();
};
var createAiClient = (config) => {
  const provider = resolveProvider(config.provider);
  const sendChat = async (request) => {
    const resolvedConfig = await resolveClientConfig(config);
    config.logger?.debug?.("ai.sendChat", {
      model: request.model ?? resolvedConfig.model,
      messageCount: request.messages.length
    });
    try {
      return await provider.sendChat(request, resolvedConfig);
    } catch (error) {
      config.logger?.error?.("ai.sendChat.error", error);
      throw error;
    }
  };
  const sendMessage = async (content, options) => {
    const resolvedOptions = options ?? {};
    const { systemPrompt, ...requestOptions } = resolvedOptions;
    const messages = [];
    if (systemPrompt) {
      messages.push({ role: "system", content: systemPrompt });
    }
    messages.push({ role: "user", content });
    return sendChat({
      messages,
      ...requestOptions
    });
  };
  return {
    sendChat,
    sendMessage
  };
};

// src/ai/llm/prompt/variables.ts
var normalizePromptVariables = (variables = {}) => {
  const normalized = {};
  Object.entries(variables).forEach(([key, value]) => {
    if (value === null || value === void 0) {
      normalized[key] = "";
    } else {
      normalized[key] = String(value);
    }
  });
  return normalized;
};

// src/ai/llm/prompt/template.ts
var applyPromptTemplate = (template, variables = {}, options = {}) => {
  if (!template) {
    return "";
  }
  const resolved = normalizePromptVariables(variables);
  const missingValue = options.missingValue ?? "";
  return template.replace(/\{\{\s*([a-zA-Z0-9_.-]+)\s*\}\}/g, (_match, key) => {
    if (Object.prototype.hasOwnProperty.call(resolved, key)) {
      return resolved[key] ?? "";
    }
    return options.preserveUnknown ? `{{${key}}}` : missingValue;
  });
};

// src/ai/llm/client/createChatSession.ts
var buildBaseMessages = (systemPrompt, initialMessages) => {
  const baseMessages = [];
  if (systemPrompt) {
    baseMessages.push({ role: "system", content: systemPrompt });
  }
  if (initialMessages?.length) {
    baseMessages.push(...initialMessages);
  }
  return baseMessages;
};
var createChatSession = (options) => {
  let systemPrompt = options.systemPrompt;
  let messages = buildBaseMessages(systemPrompt, options.initialMessages);
  const reset = () => {
    messages = buildBaseMessages(systemPrompt, options.initialMessages);
  };
  const setSystemPrompt = (prompt) => {
    systemPrompt = prompt;
    reset();
  };
  const sendMessage = async (input, requestOptions = {}) => {
    const { template, variables, ...chatOptions } = requestOptions;
    const activeTemplate = template ?? options.template;
    const mergedVariables = { input, ...variables ?? {} };
    const content = activeTemplate ? applyPromptTemplate(activeTemplate, mergedVariables) : input;
    const userMessage = { role: "user", content };
    const nextMessages = [...messages, userMessage];
    const response = await options.client.sendChat({
      messages: nextMessages,
      ...chatOptions
    });
    const assistantMessage = response.message ?? {
      role: "assistant",
      content: response.content,
      toolCalls: response.toolCalls
    };
    messages = [...nextMessages, assistantMessage];
    return response;
  };
  return {
    getMessages: () => messages,
    setSystemPrompt,
    reset,
    sendMessage
  };
};
var buildBaseMessages2 = (systemPrompt, initialMessages) => {
  const baseMessages = [];
  if (systemPrompt) {
    baseMessages.push({ role: "system", content: systemPrompt });
  }
  if (initialMessages?.length) {
    baseMessages.push(...initialMessages);
  }
  return baseMessages;
};
var useAiChat = (options) => {
  const systemPromptRef = react.useRef(options.systemPrompt);
  const templateRef = react.useRef(options.template);
  const [messages, setMessages] = react.useState(
    () => buildBaseMessages2(systemPromptRef.current, options.initialMessages)
  );
  const messagesRef = react.useRef(messages);
  const [status, setStatus] = react.useState("idle");
  const [error, setError] = react.useState(null);
  const [lastResponse, setLastResponse] = react.useState(null);
  const syncMessages = (nextMessages) => {
    messagesRef.current = nextMessages;
    setMessages(nextMessages);
  };
  const reset = react.useCallback(() => {
    syncMessages(buildBaseMessages2(systemPromptRef.current, options.initialMessages));
    setStatus("idle");
    setError(null);
    setLastResponse(null);
  }, [options.initialMessages]);
  const setSystemPrompt = react.useCallback(
    (prompt) => {
      systemPromptRef.current = prompt;
      reset();
    },
    [reset]
  );
  const sendMessage = react.useCallback(
    async (input, requestOptions = {}) => {
      const { template, variables, ...chatOptions } = requestOptions;
      const activeTemplate = template ?? templateRef.current;
      const mergedVariables = { input, ...variables ?? {} };
      const content = activeTemplate ? applyPromptTemplate(activeTemplate, mergedVariables) : input;
      const userMessage = { role: "user", content };
      const nextMessages = [...messagesRef.current, userMessage];
      syncMessages(nextMessages);
      setStatus("loading");
      setError(null);
      try {
        const response = await options.client.sendChat({
          messages: nextMessages,
          ...chatOptions
        });
        const assistantMessage = response.message ?? {
          role: "assistant",
          content: response.content,
          toolCalls: response.toolCalls
        };
        const updatedMessages = [...nextMessages, assistantMessage];
        syncMessages(updatedMessages);
        setStatus("success");
        setLastResponse(response);
        return response;
      } catch (err) {
        const nextError = err instanceof Error ? err : new Error(String(err));
        setStatus("error");
        setError(nextError);
        throw nextError;
      }
    },
    [options.client]
  );
  return {
    status,
    isLoading: status === "loading",
    error,
    messages,
    lastResponse,
    sendMessage,
    reset,
    setSystemPrompt
  };
};

// src/ai/llm/skills/registry.ts
var skillToToolDefinition = (skill) => {
  const toolDefinition = {
    type: "function",
    function: {
      name: skill.name,
      description: skill.description
    }
  };
  if (skill.inputSchema) {
    toolDefinition.function.parameters = skill.inputSchema;
  }
  return toolDefinition;
};
var InMemorySkillRegistry = class {
  constructor(initialSkills) {
    this.skills = /* @__PURE__ */ new Map();
    initialSkills?.forEach((skill) => {
      this.skills.set(skill.name, skill);
    });
  }
  registerSkill(skill) {
    this.skills.set(skill.name, skill);
  }
  unregisterSkill(name) {
    return this.skills.delete(name);
  }
  getSkill(name) {
    return this.skills.get(name);
  }
  listSkills() {
    return Array.from(this.skills.values());
  }
  async executeSkill(name, input, context) {
    const skill = this.skills.get(name);
    if (!skill) {
      throw new Error(`Skill not found: ${name}`);
    }
    return await skill.execute(input, context);
  }
  toToolDefinitions() {
    return this.listSkills().map(skillToToolDefinition);
  }
};
var createSkillRegistry = (initialSkills) => {
  return new InMemorySkillRegistry(initialSkills);
};

exports.DEFAULT_OPENAI_BASE_URL = DEFAULT_OPENAI_BASE_URL;
exports.DEFAULT_OPENAI_MODEL = DEFAULT_OPENAI_MODEL;
exports.InMemorySkillRegistry = InMemorySkillRegistry;
exports.applyPromptTemplate = applyPromptTemplate;
exports.createAiClient = createAiClient;
exports.createChatSession = createChatSession;
exports.createOpenAICompatibleProvider = createOpenAICompatibleProvider;
exports.createSkillRegistry = createSkillRegistry;
exports.normalizePromptVariables = normalizePromptVariables;
exports.skillToToolDefinition = skillToToolDefinition;
exports.useAiChat = useAiChat;
//# sourceMappingURL=index.js.map
//# sourceMappingURL=index.js.map