diff --git a/surfsense_web/components/settings/model-connections-settings.tsx b/surfsense_web/components/settings/model-connections-settings.tsx index e89fc3278..59873408f 100644 --- a/surfsense_web/components/settings/model-connections-settings.tsx +++ b/surfsense_web/components/settings/model-connections-settings.tsx @@ -51,13 +51,7 @@ const PRESETS: Preset[] = [ { id: "custom", label: "OpenAI-compatible (any URL)", protocol: "OPENAI_COMPATIBLE" }, { id: "openai", label: "OpenAI", protocol: "NATIVE", nativeProvider: "OPENAI" }, { id: "anthropic", label: "Anthropic", protocol: "NATIVE", nativeProvider: "ANTHROPIC" }, - { - id: "openrouter", - label: "OpenRouter", - protocol: "NATIVE", - nativeProvider: "OPENROUTER", - baseUrl: "https://openrouter.ai/api/v1", - }, + { id: "openrouter", label: "OpenRouter", protocol: "NATIVE", nativeProvider: "OPENROUTER" }, { id: "ollama", label: "Ollama", @@ -328,6 +322,12 @@ export function ModelConnectionsSettings({ searchSpaceId }: { searchSpaceId: num const preset = visiblePresets.find((item) => item.id === presetId) ?? visiblePresets[0]; const [baseUrl, setBaseUrl] = useState(preset?.baseUrl ?? ""); const [apiKey, setApiKey] = useState(""); + // Native providers carry their endpoint inside LiteLLM, so Base URL is hidden + // by default and only revealed for power users who want to override it. + const [showCustomEndpoint, setShowCustomEndpoint] = useState(false); + + const isNative = preset?.protocol === "NATIVE"; + const requiresUrl = !isNative; const allConnections = [...globalConnections, ...connections]; const enabledModels = flattenModels(allConnections).filter((model) => model.enabled); @@ -338,7 +338,10 @@ export function ModelConnectionsSettings({ searchSpaceId }: { searchSpaceId: num function onPresetChange(value: string) { setPresetId(value); const next = visiblePresets.find((item) => item.id === value); - setBaseUrl(next?.baseUrl ?? ""); + // Native providers use LiteLLM's built-in endpoint; everything else needs + // (and may prefill) a Base URL. + setBaseUrl(next?.protocol === "NATIVE" ? "" : (next?.baseUrl ?? "")); + setShowCustomEndpoint(false); } function handleCreate() { @@ -401,30 +404,50 @@ export function ModelConnectionsSettings({ searchSpaceId }: { searchSpaceId: num
- - setBaseUrl(event.target.value)} - placeholder="https://api.example.com/v1" - list="model-conn-url-suggestions" - /> - - {URL_SUGGESTIONS.map((url) => ( - + + {isNative && !showCustomEndpoint ? ( +
+
+ Uses provider default +
+ +
+ ) : ( + <> + setBaseUrl(event.target.value)} + placeholder="https://api.example.com/v1" + list="model-conn-url-suggestions" + /> + + {URL_SUGGESTIONS.map((url) => ( + + + )}
- + setApiKey(event.target.value)} - placeholder="Optional for local models" + placeholder={preset?.local ? "Optional for local models" : "API key"} type="password" />
-
@@ -434,10 +457,15 @@ export function ModelConnectionsSettings({ searchSpaceId }: { searchSpaceId: num Local URLs are tested from the backend container. Use host.docker.internal instead of localhost.

+ ) : isNative ? ( +

+ Just paste an API key — {preset?.label} routes through its native endpoint + automatically. After adding, hit Discover (or add model IDs manually). +

) : preset?.protocol === "OPENAI_COMPATIBLE" ? (

- Works with any OpenAI-compatible endpoint (OpenRouter, Together, Groq, vLLM, LM - Studio…). After adding, hit Discover to list models. + Enter any OpenAI-compatible endpoint (OpenRouter, Together, Groq, vLLM, LM Studio…). + After adding, hit Discover to list models.

) : null}