diff --git a/desktop/src/components/memory/MemorySettings.tsx b/desktop/src/components/memory/MemorySettings.tsx index d9acd28ff..549e12edc 100644 --- a/desktop/src/components/memory/MemorySettings.tsx +++ b/desktop/src/components/memory/MemorySettings.tsx @@ -1,13 +1,219 @@ import { useState, useEffect, useCallback } from "react"; -import { Save, RefreshCw, CheckCircle, AlertTriangle } from "lucide-react"; +import { Save, RefreshCw, CheckCircle, AlertTriangle, Wifi, WifiOff, Monitor, Globe } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; -import { fetchSettingsSchema, fetchMemorySettings, updateMemorySettings } from "@/lib/memory"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { fetchSettingsSchema, fetchMemorySettings, updateMemorySettings, fetchMemoryEndpoint, updateMemoryEndpoint, fetchBackendCapabilities } from "@/lib/memory"; +import type { TaOSmdEndpoint } from "@/lib/memory"; import { fetchMemoryModel, setMemoryModel } from "@/lib/memory-api"; import { ModelPickerModal } from "@/components/ModelPickerModal"; import type { AgentModel } from "@/components/ModelPickerFlow"; import { SchemaFormRenderer } from "./SchemaFormRenderer"; +/* ------------------------------------------------------------------ */ +/* TaOSmdEndpointCard — running mode + switch-to-remote */ +/* ------------------------------------------------------------------ */ + +const LOCAL_URL = "http://localhost:7900"; + +function TaOSmdEndpointCard() { + const [endpoint, setEndpoint] = useState(null); + const [capabilities, setCapabilities] = useState<{ name: string; version: string } | null>(null); + const [loading, setLoading] = useState(true); + const [remoteUrl, setRemoteUrl] = useState(""); + const [switching, setSwitching] = useState(false); + const [switchErr, setSwitchErr] = useState(null); + + const load = useCallback(async () => { + setLoading(true); + setSwitchErr(null); + try { + const [ep, caps] = await Promise.all([ + fetchMemoryEndpoint(), + fetchBackendCapabilities(), + ]); + setEndpoint(ep); + setCapabilities({ name: caps.name, version: caps.version }); + setRemoteUrl((ep?.url && ep.url !== LOCAL_URL) ? ep.url : ""); + } catch { + /* graceful — will show fallback */ + } + setLoading(false); + }, []); + + useEffect(() => { load(); }, [load]); + + const handleSwitch = async () => { + const url = remoteUrl.trim(); + if (!url) return; + setSwitching(true); + setSwitchErr(null); + try { + const result = await updateMemoryEndpoint(url); + setEndpoint(result); + if (!result.reachable && !result.is_local) { + setSwitchErr("Server is not reachable. Check the URL and try again."); + } + } catch (e: any) { + setSwitchErr(String(e?.message ?? e)); + } + setSwitching(false); + }; + + const handleRevert = async () => { + setSwitching(true); + setSwitchErr(null); + try { + const result = await updateMemoryEndpoint(LOCAL_URL); + setEndpoint(result); + setRemoteUrl(""); + } catch (e: any) { + setSwitchErr(String(e?.message ?? e)); + } + setSwitching(false); + }; + + if (loading) { + return ( + + +

+ Loading taOSmd status… +

+
+
+ ); + } + + if (!endpoint) return null; + + const isLocal = endpoint.is_local; + const modeLabel = isLocal ? "LOCAL" : "REMOTE"; + const ModeIcon = isLocal ? Monitor : Globe; + const modeClasses = isLocal + ? "bg-green-500/15 text-green-400 border-green-500/30" + : "bg-blue-500/15 text-blue-400 border-blue-500/30"; + + return ( + + + {/* Header */} +
+
+

taOSmd Status

+ + +
+ +
+ + {/* Reachability */} +
+ {endpoint.reachable ? ( +
+ + {/* Capabilities / Tier */} +
+ {capabilities && ( + + {capabilities.name} v{capabilities.version} + + )} + {endpoint.tier && ( + + Tier: {endpoint.tier} + + )} +
+ + {/* Switch to remote */} +
+ +
+ { setRemoteUrl(e.target.value); setSwitchErr(null); }} + disabled={switching} + className="h-8 text-xs bg-white/[0.04] border-white/10" + aria-label="Remote taOSmd URL" + /> + +
+
+ + {/* Revert to local */} + {!isLocal && ( +
+ +
+ )} + + {/* Errors */} + {switchErr && ( +
+
+ )} +
+
+ ); +} + /* ------------------------------------------------------------------ */ /* MemoryModelSection */ /* ------------------------------------------------------------------ */ @@ -189,6 +395,9 @@ export function MemorySettings() { {/* System-wide memory model */} + {/* taOSmd endpoint status */} + +

Backend Settings