import * as React6 from 'react';
import React6__default, { useState, useRef, useMemo, useEffect, useCallback } from 'react';
import { cva } from 'class-variance-authority';
import { clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
import { X } from 'lucide-react';
import { createPortal } from 'react-dom';

// src/ai/llm/ui/web/components/AiChatDialog.tsx

// src/logger/console-adapter.ts
var ConsoleLoggerAdapter = class {
  constructor() {
    this.colors = {
      DEBUG: "\x1B[36m",
      // Cyan
      INFO: "\x1B[32m",
      // Green
      WARN: "\x1B[33m",
      // Yellow
      ERROR: "\x1B[31m",
      // Red
      RESET: "\x1B[0m"
    };
  }
  log(entry) {
    const { level, message, timestamp, data, context, error } = entry;
    let logMessage = "";
    if (timestamp) {
      logMessage += "[" + this.formatTimestamp(timestamp) + "] ";
    }
    const levelName = this.getLevelName(level);
    logMessage += levelName + ": ";
    if (context) {
      logMessage += "[" + context + "] ";
    }
    logMessage += message;
    switch (level) {
      case 0:
        console.debug(this.colorize(logMessage, "DEBUG"), data || "");
        break;
      case 1:
        console.info(this.colorize(logMessage, "INFO"), data || "");
        break;
      case 2:
        console.warn(this.colorize(logMessage, "WARN"), data || "");
        break;
      case 3:
        console.error(this.colorize(logMessage, "ERROR"), data || "");
        if (error) {
          console.error(error);
        }
        break;
    }
  }
  formatTimestamp(date) {
    return date.toISOString();
  }
  getLevelName(level) {
    const names = ["DEBUG", "INFO", "WARN", "ERROR", "NONE"];
    return names[level] || "UNKNOWN";
  }
  colorize(message, level) {
    if (typeof process !== "undefined" && process.stdout?.isTTY) {
      return this.colors[level] + message + this.colors.RESET;
    }
    return message;
  }
};

// src/logger/Logger.ts
var Logger = class _Logger {
  constructor(config, context) {
    const isProduction = typeof process !== "undefined" ? process.env.NODE_ENV === "production" : false;
    this.config = {
      minLevel: config?.minLevel ?? (isProduction ? 1 : 0),
      // INFO in prod, DEBUG in dev
      enableTimestamp: config?.enableTimestamp ?? true,
      enableContext: config?.enableContext ?? true,
      environment: config?.environment ?? (isProduction ? "production" : "development"),
      adapter: config?.adapter ?? new ConsoleLoggerAdapter()
    };
    this.adapter = this.config.adapter;
    this.context = context;
  }
  /**
   * 创建带上下文的子 Logger
   */
  createChild(context) {
    return new _Logger(this.config, context);
  }
  /**
   * 调试日志
   */
  debug(message, data) {
    this.log(0, message, data);
  }
  /**
   * 信息日志
   */
  info(message, data) {
    this.log(1, message, data);
  }
  /**
   * 警告日志
   */
  warn(message, data) {
    this.log(2, message, data);
  }
  /**
   * 错误日志
   */
  error(message, error) {
    this.log(
      3,
      // LogLevel.ERROR
      message,
      error instanceof Error ? void 0 : error,
      error instanceof Error ? error : void 0
    );
  }
  /**
   * 核心日志方法
   */
  log(level, message, data, error) {
    if (level < this.config.minLevel) {
      return;
    }
    if (typeof window !== "undefined" && typeof localStorage !== "undefined") {
      const loggerDebug = localStorage.getItem("logger-debug");
      if (loggerDebug === "false" && level < 3) {
        return;
      }
    }
    const entry = {
      level,
      message,
      timestamp: this.config.enableTimestamp ? /* @__PURE__ */ new Date() : void 0,
      data,
      context: this.config.enableContext ? this.context : void 0,
      error
    };
    this.adapter.log(entry);
  }
  /**
   * 设置日志级别
   */
  setLevel(level) {
    this.config.minLevel = level;
  }
  /**
   * 获取当前日志级别
   */
  getLevel() {
    return this.config.minLevel;
  }
};
new Logger();
function cn(...inputs) {
  return twMerge(clsx(inputs));
}

// src/components/Button.tsx
var buttonVariants = cva(
  "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
        destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
        outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
        secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
        ghost: "hover:bg-accent hover:text-accent-foreground",
        link: "text-primary underline-offset-4 hover:underline"
      },
      size: {
        default: "h-9 px-4 py-2",
        sm: "h-8 rounded-md px-3 text-xs",
        lg: "h-10 rounded-md px-8",
        icon: "h-9 w-9"
      }
    },
    defaultVariants: {
      variant: "default",
      size: "default"
    }
  }
);
var Button = React6.forwardRef(
  ({ className, variant = "default", size = "default", asChild = false, children, ...props }, ref) => {
    if (asChild && React6.isValidElement(children)) {
      const childProps = children.props;
      return React6.cloneElement(children, {
        ...props,
        className: cn(buttonVariants({ variant, size, className }), childProps.className)
      });
    }
    return /* @__PURE__ */ React6.createElement(
      "button",
      {
        className: cn(buttonVariants({ variant, size, className })),
        ref,
        ...props
      },
      children
    );
  }
);
Button.displayName = "Button";
function useControllableState({
  value,
  defaultValue,
  onChange
}) {
  const [internal, setInternal] = React6.useState(defaultValue);
  const isControlled = value !== void 0;
  const state = isControlled ? value : internal;
  const setState = React6.useCallback(
    (next) => {
      if (!isControlled) setInternal(next);
      onChange?.(next);
    },
    [isControlled, onChange]
  );
  return [state, setState];
}
function Portal({
  children,
  container
}) {
  const [mounted, setMounted] = React6.useState(false);
  React6.useEffect(() => {
    setMounted(true);
  }, []);
  if (!mounted) return null;
  return createPortal(children, container ?? document.body);
}
function useOnClickOutside(refs, handler, enabled) {
  React6.useEffect(() => {
    if (!enabled) return;
    const listener = (event) => {
      const target = event.target;
      const clickedInside = refs.some((ref) => {
        const el = ref.current;
        return el && el.contains(target);
      });
      if (!clickedInside) {
        handler(event);
      }
    };
    document.addEventListener("mousedown", listener);
    document.addEventListener("touchstart", listener);
    return () => {
      document.removeEventListener("mousedown", listener);
      document.removeEventListener("touchstart", listener);
    };
  }, [refs, handler, enabled]);
}
function mergeRefs(...refs) {
  return (value) => {
    refs.forEach((ref) => {
      if (!ref) return;
      if (typeof ref === "function") {
        ref(value);
      } else {
        ref.current = value;
      }
    });
  };
}

// src/components/Dialog.tsx
var DialogContext = React6.createContext(null);
var Dialog = ({ open, defaultOpen = false, onOpenChange, children }) => {
  const [isOpen, setIsOpen] = useControllableState({
    value: open,
    defaultValue: defaultOpen,
    onChange: onOpenChange
  });
  const triggerRef = React6.useRef(null);
  const contentRef = React6.useRef(null);
  return /* @__PURE__ */ React6.createElement(DialogContext.Provider, { value: { open: isOpen, setOpen: setIsOpen, triggerRef, contentRef } }, children);
};
var DialogTrigger = React6.forwardRef(
  ({ children, onClick, ...props }, ref) => {
    const ctx = React6.useContext(DialogContext);
    if (!ctx) return null;
    const mergedRef = mergeRefs(ctx.triggerRef, ref);
    const handleClick = (e) => {
      ctx.setOpen(true);
      onClick?.(e);
    };
    return /* @__PURE__ */ React6.createElement("button", { ref: mergedRef, type: "button", onClick: handleClick, ...props }, children);
  }
);
DialogTrigger.displayName = "DialogTrigger";
var DialogPortal = ({ children }) => {
  const ctx = React6.useContext(DialogContext);
  if (!ctx?.open) return null;
  return /* @__PURE__ */ React6.createElement(Portal, null, children);
};
var DialogClose = React6.forwardRef(({ onClick, ...props }, ref) => {
  const ctx = React6.useContext(DialogContext);
  return /* @__PURE__ */ React6.createElement(
    "button",
    {
      ref,
      type: "button",
      onClick: (e) => {
        ctx?.setOpen(false);
        onClick?.(e);
      },
      ...props
    }
  );
});
DialogClose.displayName = "DialogClose";
var DialogOverlay = React6.forwardRef(({ className, ...props }, ref) => {
  const ctx = React6.useContext(DialogContext);
  if (!ctx?.open) return null;
  return /* @__PURE__ */ React6.createElement(
    "div",
    {
      ref,
      className: cn("fixed inset-0 z-[9999] bg-black/80", className),
      ...props
    }
  );
});
DialogOverlay.displayName = "DialogOverlay";
var DialogContent = React6.forwardRef(
  ({ className, children, onPointerDownOutside, onEscapeKeyDown, showCloseButton = true, ...props }, ref) => {
    const ctx = React6.useContext(DialogContext);
    const open = !!ctx?.open;
    useOnClickOutside(
      [ctx?.contentRef ?? { current: null }, ctx?.triggerRef ?? { current: null }],
      (evt) => {
        onPointerDownOutside?.(evt);
        if (!evt.defaultPrevented) {
          ctx?.setOpen(false);
        }
      },
      open
    );
    React6.useEffect(() => {
      if (!open) return;
      const onKey = (e) => {
        if (e.key !== "Escape") return;
        onEscapeKeyDown?.(e);
        if (!e.defaultPrevented) {
          ctx?.setOpen(false);
        }
      };
      document.addEventListener("keydown", onKey);
      return () => document.removeEventListener("keydown", onKey);
    }, [ctx, onEscapeKeyDown, open]);
    if (!ctx || !open) return null;
    return /* @__PURE__ */ React6.createElement(DialogPortal, null, /* @__PURE__ */ React6.createElement(DialogOverlay, null), /* @__PURE__ */ React6.createElement(
      "div",
      {
        ref: mergeRefs(ctx.contentRef, ref),
        className: cn(
          "fixed left-[50%] top-[50%] z-[10000] grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg sm:rounded-lg",
          className
        ),
        ...props
      },
      children,
      showCloseButton ? /* @__PURE__ */ React6.createElement(DialogClose, { className: "absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100" }, /* @__PURE__ */ React6.createElement(X, { className: "h-4 w-4" }), /* @__PURE__ */ React6.createElement("span", { className: "sr-only" }, "Close")) : null
    ));
  }
);
DialogContent.displayName = "DialogContent";
var DialogHeader = ({
  className,
  ...props
}) => /* @__PURE__ */ React6.createElement(
  "div",
  {
    className: cn(
      "flex flex-col space-y-1.5 text-center sm:text-left",
      className
    ),
    ...props
  }
);
DialogHeader.displayName = "DialogHeader";
var DialogTitle = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React6.createElement(
  "h2",
  {
    ref,
    className: cn(
      "text-lg font-semibold leading-none tracking-tight",
      className
    ),
    ...props
  }
));
DialogTitle.displayName = "DialogTitle";
var DialogDescription = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React6.createElement(
  "p",
  {
    ref,
    className: cn("text-sm text-muted-foreground", className),
    ...props
  }
));
DialogDescription.displayName = "DialogDescription";

// 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/hooks/useAiChat.ts
var buildBaseMessages = (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 = useRef(options.systemPrompt);
  const templateRef = useRef(options.template);
  const [messages, setMessages] = useState(
    () => buildBaseMessages(systemPromptRef.current, options.initialMessages)
  );
  const messagesRef = useRef(messages);
  const [status, setStatus] = useState("idle");
  const [error, setError] = useState(null);
  const [lastResponse, setLastResponse] = useState(null);
  const syncMessages = (nextMessages) => {
    messagesRef.current = nextMessages;
    setMessages(nextMessages);
  };
  const reset = useCallback(() => {
    syncMessages(buildBaseMessages(systemPromptRef.current, options.initialMessages));
    setStatus("idle");
    setError(null);
    setLastResponse(null);
  }, [options.initialMessages]);
  const setSystemPrompt = useCallback(
    (prompt) => {
      systemPromptRef.current = prompt;
      reset();
    },
    [reset]
  );
  const sendMessage = 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/ui/web/components/AiChatDialog.tsx
var AiChatDialog = ({
  open,
  onOpenChange,
  client,
  title = "AI \u5BF9\u8BDD",
  placeholder = "\u8F93\u5165\u4F60\u60F3\u54A8\u8BE2\u7684\u95EE\u9898...",
  systemPrompt,
  template,
  templateVariables,
  initialMessages,
  requestOptions,
  onResponse,
  onError,
  className,
  contentClassName
}) => {
  const { messages, sendMessage, isLoading, error } = useAiChat({
    client,
    systemPrompt,
    template,
    initialMessages
  });
  const [input, setInput] = useState("");
  const listRef = useRef(null);
  const hasMessages = messages.length > 0;
  const helperText = useMemo(() => {
    return template ? "\u6A21\u677F\u5DF2\u542F\u7528\uFF0C\u652F\u6301 {{input}} \u53D8\u91CF\u3002" : "\u76F4\u63A5\u8F93\u5165\u5373\u53EF\u5F00\u59CB\u5BF9\u8BDD\u3002";
  }, [template]);
  useEffect(() => {
    if (!listRef.current) return;
    listRef.current.scrollTop = listRef.current.scrollHeight;
  }, [messages, open, isLoading]);
  const handleSend = async () => {
    const content = input.trim();
    if (!content || isLoading) return;
    setInput("");
    try {
      const response = await sendMessage(content, {
        ...requestOptions,
        template,
        variables: templateVariables
      });
      onResponse?.(response);
    } catch (err) {
      const nextError = err instanceof Error ? err : new Error(String(err));
      onError?.(nextError);
    }
  };
  const handleKeyDown = (event) => {
    if (event.key === "Enter" && !event.shiftKey) {
      event.preventDefault();
      handleSend();
    }
  };
  return /* @__PURE__ */ React6__default.createElement(Dialog, { open, onOpenChange }, /* @__PURE__ */ React6__default.createElement(
    DialogContent,
    {
      className: cn(
        "max-w-3xl border border-slate-200 bg-white p-0",
        contentClassName
      )
    },
    /* @__PURE__ */ React6__default.createElement("div", { className: cn("flex flex-col", className) }, /* @__PURE__ */ React6__default.createElement(DialogHeader, { className: "border-b border-slate-100 px-6 py-4" }, /* @__PURE__ */ React6__default.createElement(DialogTitle, { className: "text-base font-semibold text-slate-900" }, title)), /* @__PURE__ */ React6__default.createElement("div", { className: "flex flex-1 flex-col gap-4 px-6 py-4" }, /* @__PURE__ */ React6__default.createElement(
      "div",
      {
        ref: listRef,
        className: "max-h-[60vh] min-h-[240px] overflow-y-auto rounded-xl border border-slate-100 bg-slate-50/60 p-4"
      },
      !hasMessages && /* @__PURE__ */ React6__default.createElement("div", { className: "flex h-full flex-col items-center justify-center gap-2 text-sm text-slate-400" }, /* @__PURE__ */ React6__default.createElement("span", null, "\u6682\u65E0\u5BF9\u8BDD\u5185\u5BB9"), /* @__PURE__ */ React6__default.createElement("span", null, "\u8F93\u5165\u6D88\u606F\u5F00\u59CB\u4F53\u9A8C AI \u5BF9\u8BDD\u3002")),
      /* @__PURE__ */ React6__default.createElement("div", { className: "flex flex-col gap-3" }, messages.map((message, index) => {
        const isUser = message.role === "user";
        return /* @__PURE__ */ React6__default.createElement(
          "div",
          {
            key: `${message.role}-${index}`,
            className: cn(
              "max-w-[85%] whitespace-pre-wrap rounded-2xl px-4 py-2 text-sm leading-relaxed",
              isUser ? "ml-auto bg-slate-900 text-white" : "mr-auto border border-slate-200 bg-white text-slate-800"
            )
          },
          message.content
        );
      }), isLoading && /* @__PURE__ */ React6__default.createElement("div", { className: "mr-auto max-w-[70%] rounded-2xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-500" }, "AI \u6B63\u5728\u601D\u8003..."))
    ), /* @__PURE__ */ React6__default.createElement("div", { className: "rounded-xl border border-slate-100 bg-white p-4 shadow-sm" }, /* @__PURE__ */ React6__default.createElement(
      "textarea",
      {
        value: input,
        onChange: (event) => setInput(event.target.value),
        onKeyDown: handleKeyDown,
        placeholder,
        className: "min-h-[96px] w-full resize-none rounded-lg border border-slate-200 px-3 py-2 text-sm text-slate-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-300"
      }
    ), /* @__PURE__ */ React6__default.createElement("div", { className: "mt-3 flex flex-wrap items-center justify-between gap-3" }, /* @__PURE__ */ React6__default.createElement("span", { className: "text-xs text-slate-400" }, helperText), /* @__PURE__ */ React6__default.createElement(Button, { onClick: handleSend, disabled: !input.trim() || isLoading }, isLoading ? "\u53D1\u9001\u4E2D..." : "\u53D1\u9001")), error && /* @__PURE__ */ React6__default.createElement("div", { className: "mt-2 rounded-md border border-rose-200 bg-rose-50 px-3 py-2 text-xs text-rose-600" }, error.message || "\u5BF9\u8BDD\u51FA\u9519\uFF0C\u8BF7\u91CD\u8BD5\u3002"))))
  ));
};
var Input = React6.forwardRef(
  ({ className, type, ...props }, ref) => {
    return /* @__PURE__ */ React6.createElement(
      "input",
      {
        type,
        className: cn(
          "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
          className
        ),
        ref,
        ...props
      }
    );
  }
);
Input.displayName = "Input";

// src/ai/llm/ui/web/components/AiConfigPage.tsx
var DEFAULT_AI_CONFIG = {
  apiKey: "",
  baseUrl: "https://api.openai.com/v1",
  model: "gpt-3.5-turbo",
  systemPrompt: "",
  template: "{{input}}",
  temperature: 0.7,
  topP: 1,
  maxTokens: 1024
};
var mergeConfig = (base, overrides, stored) => {
  return {
    ...base,
    ...overrides ?? {},
    ...stored ?? {}
  };
};
var AiConfigPage = ({
  storageKey = "sa2kit-ai-config",
  initialConfig,
  title = "AI \u914D\u7F6E",
  description = "\u914D\u7F6E API Key\u3001\u6A21\u578B\u4E0E\u63D0\u793A\u8BCD\u6A21\u677F\uFF0C\u7528\u4E8E AI \u5BF9\u8BDD\u80FD\u529B\u3002",
  onSave,
  onChange
}) => {
  const baseConfig = useMemo(
    () => mergeConfig(DEFAULT_AI_CONFIG, initialConfig),
    [initialConfig]
  );
  const [config, setConfig] = useState(baseConfig);
  const [status, setStatus] = useState(null);
  const [showApiKey, setShowApiKey] = useState(false);
  useEffect(() => {
    if (typeof window === "undefined") {
      return;
    }
    if (!storageKey) {
      return;
    }
    const storedRaw = localStorage.getItem(storageKey);
    if (!storedRaw) {
      return;
    }
    try {
      const stored = JSON.parse(storedRaw);
      setConfig(mergeConfig(DEFAULT_AI_CONFIG, initialConfig, stored));
    } catch (error) {
      console.warn("[AiConfigPage] Failed to parse stored config:", error);
    }
  }, [storageKey, initialConfig]);
  const updateConfig = (updates) => {
    setConfig((prev) => {
      const next = { ...prev, ...updates };
      onChange?.(next);
      return next;
    });
  };
  const updateNumber = (key, value) => {
    const nextValue = Number(value);
    if (Number.isNaN(nextValue)) {
      return;
    }
    updateConfig({ [key]: nextValue });
  };
  const saveConfig = () => {
    if (typeof window !== "undefined" && storageKey) {
      try {
        localStorage.setItem(storageKey, JSON.stringify(config));
      } catch (error) {
        setStatus({ type: "error", text: "\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u6D4F\u89C8\u5668\u5B58\u50A8\u6743\u9650\u3002" });
        return;
      }
    }
    setStatus({ type: "success", text: "\u5DF2\u4FDD\u5B58\u914D\u7F6E\u3002" });
    onSave?.(config);
  };
  const resetConfig = () => {
    const next = mergeConfig(DEFAULT_AI_CONFIG, initialConfig);
    setConfig(next);
    onChange?.(next);
    if (typeof window !== "undefined" && storageKey) {
      localStorage.removeItem(storageKey);
    }
    setStatus({ type: "success", text: "\u5DF2\u6062\u590D\u9ED8\u8BA4\u914D\u7F6E\u3002" });
  };
  return /* @__PURE__ */ React6__default.createElement("div", { className: "w-full rounded-2xl border border-slate-200 bg-white p-6 shadow-sm" }, /* @__PURE__ */ React6__default.createElement("div", { className: "flex flex-col gap-2 border-b border-slate-100 pb-4" }, /* @__PURE__ */ React6__default.createElement("h2", { className: "text-xl font-semibold text-slate-900" }, title), /* @__PURE__ */ React6__default.createElement("p", { className: "text-sm text-slate-500" }, description)), /* @__PURE__ */ React6__default.createElement("div", { className: "mt-6 grid gap-6" }, /* @__PURE__ */ React6__default.createElement("section", { className: "rounded-xl border border-slate-100 bg-slate-50/60 p-4" }, /* @__PURE__ */ React6__default.createElement("h3", { className: "text-sm font-semibold text-slate-700" }, "API \u4FE1\u606F"), /* @__PURE__ */ React6__default.createElement("div", { className: "mt-4 grid gap-4" }, /* @__PURE__ */ React6__default.createElement("div", null, /* @__PURE__ */ React6__default.createElement("label", { className: "text-xs font-medium text-slate-500" }, "Base URL"), /* @__PURE__ */ React6__default.createElement(
    Input,
    {
      value: config.baseUrl,
      onChange: (event) => updateConfig({ baseUrl: event.target.value }),
      placeholder: "https://api.openai.com/v1",
      className: "mt-2"
    }
  )), /* @__PURE__ */ React6__default.createElement("div", null, /* @__PURE__ */ React6__default.createElement("label", { className: "text-xs font-medium text-slate-500" }, "API Key"), /* @__PURE__ */ React6__default.createElement("div", { className: "mt-2 flex gap-2" }, /* @__PURE__ */ React6__default.createElement(
    Input,
    {
      value: config.apiKey,
      onChange: (event) => updateConfig({ apiKey: event.target.value }),
      placeholder: "sk-...",
      type: showApiKey ? "text" : "password"
    }
  ), /* @__PURE__ */ React6__default.createElement(
    Button,
    {
      type: "button",
      variant: "outline",
      onClick: () => setShowApiKey((prev) => !prev)
    },
    showApiKey ? "\u9690\u85CF" : "\u663E\u793A"
  ))), /* @__PURE__ */ React6__default.createElement("div", null, /* @__PURE__ */ React6__default.createElement("label", { className: "text-xs font-medium text-slate-500" }, "\u6A21\u578B"), /* @__PURE__ */ React6__default.createElement(
    Input,
    {
      value: config.model,
      onChange: (event) => updateConfig({ model: event.target.value }),
      placeholder: "gpt-3.5-turbo",
      className: "mt-2"
    }
  )))), /* @__PURE__ */ React6__default.createElement("section", { className: "rounded-xl border border-slate-100 bg-white p-4 shadow-sm" }, /* @__PURE__ */ React6__default.createElement("h3", { className: "text-sm font-semibold text-slate-700" }, "\u63D0\u793A\u8BCD\u4E0E\u4E0A\u4E0B\u6587"), /* @__PURE__ */ React6__default.createElement("div", { className: "mt-4 grid gap-4" }, /* @__PURE__ */ React6__default.createElement("div", null, /* @__PURE__ */ React6__default.createElement("label", { className: "text-xs font-medium text-slate-500" }, "\u7CFB\u7EDF\u63D0\u793A\u8BCD"), /* @__PURE__ */ React6__default.createElement(
    "textarea",
    {
      value: config.systemPrompt,
      onChange: (event) => updateConfig({ systemPrompt: event.target.value }),
      placeholder: "\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684 AI \u52A9\u624B...",
      className: "mt-2 min-h-[96px] w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-900 shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-300"
    }
  )), /* @__PURE__ */ React6__default.createElement("div", null, /* @__PURE__ */ React6__default.createElement("label", { className: "text-xs font-medium text-slate-500" }, "\u63D0\u793A\u8BCD\u6A21\u677F"), /* @__PURE__ */ React6__default.createElement(
    "textarea",
    {
      value: config.template,
      onChange: (event) => updateConfig({ template: event.target.value }),
      placeholder: "\u8BF7\u56DE\u7B54\uFF1A{{input}}",
      className: "mt-2 min-h-[96px] w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-900 shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-300"
    }
  ), /* @__PURE__ */ React6__default.createElement("p", { className: "mt-2 text-xs text-slate-400" }, "\u652F\u6301\u53D8\u91CF\u63D2\u5165\uFF1A", /* @__PURE__ */ React6__default.createElement("code", { className: "rounded bg-slate-100 px-1" }, "{{input}}"))))), /* @__PURE__ */ React6__default.createElement("section", { className: "rounded-xl border border-slate-100 bg-slate-50/60 p-4" }, /* @__PURE__ */ React6__default.createElement("h3", { className: "text-sm font-semibold text-slate-700" }, "\u6A21\u578B\u53C2\u6570"), /* @__PURE__ */ React6__default.createElement("div", { className: "mt-4 grid gap-4 md:grid-cols-3" }, /* @__PURE__ */ React6__default.createElement("div", null, /* @__PURE__ */ React6__default.createElement("label", { className: "text-xs font-medium text-slate-500" }, "Temperature"), /* @__PURE__ */ React6__default.createElement(
    Input,
    {
      type: "number",
      value: config.temperature,
      onChange: (event) => updateNumber("temperature", event.target.value),
      className: "mt-2"
    }
  )), /* @__PURE__ */ React6__default.createElement("div", null, /* @__PURE__ */ React6__default.createElement("label", { className: "text-xs font-medium text-slate-500" }, "Top P"), /* @__PURE__ */ React6__default.createElement(
    Input,
    {
      type: "number",
      value: config.topP,
      onChange: (event) => updateNumber("topP", event.target.value),
      className: "mt-2"
    }
  )), /* @__PURE__ */ React6__default.createElement("div", null, /* @__PURE__ */ React6__default.createElement("label", { className: "text-xs font-medium text-slate-500" }, "Max Tokens"), /* @__PURE__ */ React6__default.createElement(
    Input,
    {
      type: "number",
      value: config.maxTokens,
      onChange: (event) => updateNumber("maxTokens", event.target.value),
      className: "mt-2"
    }
  )))), /* @__PURE__ */ React6__default.createElement("div", { className: "flex flex-wrap items-center gap-3" }, /* @__PURE__ */ React6__default.createElement(Button, { onClick: saveConfig }, "\u4FDD\u5B58\u914D\u7F6E"), /* @__PURE__ */ React6__default.createElement(Button, { variant: "outline", onClick: resetConfig }, "\u6062\u590D\u9ED8\u8BA4"), status && /* @__PURE__ */ React6__default.createElement(
    "span",
    {
      className: cn(
        "text-xs",
        status.type === "success" ? "text-emerald-600" : "text-rose-600"
      )
    },
    status.text
  ))));
};

export { AiChatDialog, AiConfigPage };
//# sourceMappingURL=index.mjs.map
//# sourceMappingURL=index.mjs.map