diff --git a/src/apps/officer-web/Screens/Dashboard/Settings/ServerSettings/AIHarnessesSection.tsx b/src/apps/officer-web/Screens/Dashboard/Settings/ServerSettings/AIHarnessesSection.tsx index 25b8abcf..20568cc8 100644 --- a/src/apps/officer-web/Screens/Dashboard/Settings/ServerSettings/AIHarnessesSection.tsx +++ b/src/apps/officer-web/Screens/Dashboard/Settings/ServerSettings/AIHarnessesSection.tsx @@ -227,6 +227,7 @@ export const AIHarnessesSection = () => { auth, }); queryClient.invalidateQueries({ queryKey: ['PI_MONO_LOCAL_PROVIDERS'] }); + queryClient.invalidateQueries({ queryKey: ['PI_MONO_LOCAL_HEALTH'] }); queryClient.invalidateQueries({ queryKey: ['PI_MODELS'] }); toast.success(`Connected to ${probe.name}`); resetLocalForm(); @@ -239,6 +240,7 @@ export const AIHarnessesSection = () => { const removeLocalProvider = async (id: string) => { await client.delete(`/server-settings/pi-mono/local-providers/${id}`); queryClient.invalidateQueries({ queryKey: ['PI_MONO_LOCAL_PROVIDERS'] }); + queryClient.invalidateQueries({ queryKey: ['PI_MONO_LOCAL_HEALTH'] }); queryClient.invalidateQueries({ queryKey: ['PI_MODELS'] }); }; diff --git a/src/apps/officer-web/Screens/Dashboard/Settings/SystemSettings.tsx b/src/apps/officer-web/Screens/Dashboard/Settings/SystemSettings.tsx index eca86f53..4df5b5c4 100644 --- a/src/apps/officer-web/Screens/Dashboard/Settings/SystemSettings.tsx +++ b/src/apps/officer-web/Screens/Dashboard/Settings/SystemSettings.tsx @@ -1,6 +1,6 @@ import { useState, useEffect, useMemo, useCallback, type DragEvent } from 'react'; import { toast } from 'sonner'; -import { Terminal, Eye, Bot, Settings, X, Plus, Mail, Volume2, Mic, ScanText } from 'lucide-react'; +import { Terminal, Eye, Bot, Settings, X, Plus, Mail, Volume2, Mic, ScanText, RefreshCw } from 'lucide-react'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Button } from '@/components/ui/button'; @@ -8,6 +8,7 @@ import { Textarea } from '@/components/ui/textarea'; import { Slider } from '@/components/ui/slider'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { useQueryClient } from '@tanstack/react-query'; +import { useClient } from 'hooks/useClient'; import type { LayoutNode, PanelComponents } from 'officerdev'; import { WorkspaceLayout, TerminalView } from 'officerdev'; import { usePanelChannel } from 'hooks/usePanelChannel'; @@ -338,9 +339,25 @@ const DropZone = ({ label, children, onDrop }: DropZoneProps) => { }; function ModelVisibilitySection() { + const client = useClient(); + const queryClient = useQueryClient(); const { policy, savePolicy } = useAccessPolicy(); const piModels = usePiModels(); const [activeProvider, setActiveProvider] = useUserState('model-visibility-provider', ''); + const [refreshing, setRefreshing] = useState(false); + + const refreshModels = async () => { + setRefreshing(true); + try { + await client.post('/server-settings/pi-mono/local-providers/refresh'); + queryClient.invalidateQueries({ queryKey: ['PI_MODELS'] }); + toast.success('Models refreshed'); + } catch { + toast.error('Failed to refresh models'); + } finally { + setRefreshing(false); + } + }; const enabledModels = policy.allowedModels; @@ -419,7 +436,7 @@ function ModelVisibilitySection() { return (
{/* Provider tabs */} -
+
{providers.map((p) => (
{/* Enabled section */} diff --git a/src/servers/api/server-settings/pi-mono.ts b/src/servers/api/server-settings/pi-mono.ts index 4ed0b86f..41b9552e 100644 --- a/src/servers/api/server-settings/pi-mono.ts +++ b/src/servers/api/server-settings/pi-mono.ts @@ -361,6 +361,13 @@ piMonoRouter.put('/access-policy', async (ctx) => { return ctx.json({ ok: true }); }); +piMonoRouter.post('/local-providers/refresh', async (ctx) => { + await syncLocalProvidersToPiConfig(); + syncAllUserPiConfigs().catch(() => {}); + invalidateModelCache(); + return ctx.json({ ok: true }); +}); + piMonoRouter.get('/local-providers/health', async (ctx) => { const providers = await readLocalProviders(); const results: Record = {};