+
AI Service — Settings
+
+
+
+ >
+ );
+}
diff --git a/frontend/src/pages/AppsPage.tsx b/frontend/src/pages/AppsPage.tsx
index f9b933c..6d5aeb0 100644
--- a/frontend/src/pages/AppsPage.tsx
+++ b/frontend/src/pages/AppsPage.tsx
@@ -21,6 +21,14 @@ const APPS: AppCard[] = [
path: "/apps/documents",
settingsPath: "/apps/documents/settings/admin",
},
+ {
+ slug: "ai",
+ name: "AI Service",
+ description: "Shared AI provider for all features. Configure model, credentials, and connection.",
+ status: "available",
+ path: "",
+ settingsPath: "/apps/ai/settings/admin",
+ },
];
export default function AppsPage() {
@@ -55,7 +63,7 @@ export default function AppsPage() {
- {app.status === "available" && (
+ {app.status === "available" && app.path && (
-
{title}
- {children}
-
- );
-}
-
-function Field({
- label,
- children,
-}: {
- label: string;
- children: React.ReactNode;
-}) {
- return (
-
-
- {children}
-
- );
-}
+import { getDocumentLimits, updateDocumentLimits } from "../api/client";
const inputStyle: React.CSSProperties = {
- width: "100%",
+ width: 120,
padding: "7px 10px",
fontSize: 14,
border: "1px solid #ccc",
@@ -47,78 +14,25 @@ const inputStyle: React.CSSProperties = {
export default function DocumentAdminSettingsPage() {
const { data: rawSettings, isLoading } = useQuery({
- queryKey: ["docSettings"],
- queryFn: getDocumentSettings,
+ queryKey: ["docLimits"],
+ queryFn: getDocumentLimits,
});
- const [provider, setProvider] = useState
("anthropic");
- const [anthropicKey, setAnthropicKey] = useState("");
- const [anthropicModel, setAnthropicModel] = useState("");
- const [ollamaUrl, setOllamaUrl] = useState("");
- const [ollamaModel, setOllamaModel] = useState("");
- const [ollamaKey, setOllamaKey] = useState("");
- const [lmstudioUrl, setLmstudioUrl] = useState("");
- const [lmstudioModel, setLmstudioModel] = useState("");
- const [lmstudioKey, setLmstudioKey] = useState("");
const [maxPdfMb, setMaxPdfMb] = useState(20);
- const [testResult, setTestResult] = useState<{
- ok: boolean;
- response?: string;
- error?: string;
- } | null>(null);
-
- // Populate form from loaded settings
useEffect(() => {
if (!rawSettings) return;
const s = rawSettings as Record;
- const ai = s.ai as Record | undefined;
const docs = s.documents as Record | undefined;
-
- if (ai?.provider) setProvider(ai.provider as Provider);
- const ant = ai?.anthropic as Record | undefined;
- if (ant?.api_key) setAnthropicKey(ant.api_key);
- if (ant?.model) setAnthropicModel(ant.model);
- const oll = ai?.ollama as Record | undefined;
- if (oll?.base_url) setOllamaUrl(oll.base_url);
- if (oll?.model) setOllamaModel(oll.model);
- if (oll?.api_key) setOllamaKey(oll.api_key);
- const lms = ai?.lmstudio as Record | undefined;
- if (lms?.base_url) setLmstudioUrl(lms.base_url);
- if (lms?.model) setLmstudioModel(lms.model);
- if (lms?.api_key) setLmstudioKey(lms.api_key);
if (typeof docs?.max_pdf_bytes === "number") {
setMaxPdfMb(Math.round((docs.max_pdf_bytes as number) / (1024 * 1024)));
}
}, [rawSettings]);
- const aiMut = useMutation({
- mutationFn: updateDocumentAISettings,
- });
-
- const testMut = useMutation({
- mutationFn: testDocumentAIConnection,
- onSuccess: (data) => setTestResult(data),
- });
-
const limitsMut = useMutation({
mutationFn: (mb: number) => updateDocumentLimits(mb),
});
- const saveAI = () => {
- aiMut.mutate({
- provider,
- anthropic_api_key: anthropicKey,
- anthropic_model: anthropicModel,
- ollama_base_url: ollamaUrl,
- ollama_model: ollamaModel,
- ollama_api_key: ollamaKey,
- lmstudio_base_url: lmstudioUrl,
- lmstudio_model: lmstudioModel,
- lmstudio_api_key: lmstudioKey,
- });
- };
-
if (isLoading) {
return (
<>
@@ -134,164 +48,40 @@ export default function DocumentAdminSettingsPage() {
Documents — Settings
-
-
-
-
+
+ Upload Limits
+
+
setMaxPdfMb(Number(e.target.value))}
- style={{ ...inputStyle, width: 120 }}
+ style={inputStyle}
/>
-
+
{limitsMut.isSuccess && (
Limits saved.
)}
-
+
>
);