import { useState } from "react";
import {
Copy, Check, Pencil, Trash2, ToggleLeft, ToggleRight,
ChevronDown, ChevronUp, Terminal, Globe, Key
} from "lucide-react";
import { api } from "../api";
const TYPE_BADGE = {
chat: "badge-green",
embedding: "badge-cyan",
image: "badge-purple",
audio: "badge-orange",
completion: "badge-gray",
};
export default function ModelCard({ model, onEdit, onDelete, onToggle }) {
const [copied, setCopied] = useState(null);
const [expanded, setExpanded] = useState(false);
const [testing, setTesting] = useState(false);
const [testResult, setTestResult] = useState(null);
const copy = (text, key) => {
navigator.clipboard.writeText(text);
setCopied(key);
setTimeout(() => setCopied(null), 1500);
};
const runTest = async () => {
setTesting(true);
setTestResult(null);
try {
const res = await api.testModel(model.id);
setTestResult(res.data);
} catch (e) {
setTestResult({ success: false, error: e.message });
} finally {
setTesting(false);
}
};
return (
{model.modelType || "chat"}
{model.provider}
{!model.enabled && disabled}
{model.displayName}
{model.description && (
{model.description}
)}
copy(model.openaiEndpoint, "endpoint")}
copied={copied === "endpoint"}
mono
/>
copy(model.openaiModelName, "model")}
copied={copied === "model"}
mono
accent
/>
{model.apiBase && (
)}
{expanded && (
curl
{model.curlExample}
{testResult && (
{testResult.success
? "OK -- " + testResult.latencyMs + "ms"
:
}
)}
)}
);
}
function ErrorDisplay({ error }) {
const [showFull, setShowFull] = useState(false);
const text = typeof error === "string" ? error : JSON.stringify(error, null, 2);
const LIMIT = 200;
const isLong = text.length > LIMIT;
return (
{showFull ? text : text.slice(0, LIMIT)}
{isLong && (
)}
);
}
function InfoRow({ icon: Icon, label, value, onCopy, copied, mono, accent, className }) {
return (
{label}
{value}
{onCopy && (
)}
);
}
function RefreshCwIcon({ size, className }) {
return (
);
}