llm: auto-load active config from arcadia on app boot

Adds <LlmConfigBootstrap /> in root.tsx that, when localStorage has no
active LLM settings, fetches enabled configurations from arcadia and
seeds the active settings (provider/model/baseURL/secretName + reasoning
effort) from the preferred row. Idempotent and silent on auth failure;
retries on session change.

Selection: prefer metadata.default === true, otherwise first enabled row.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
jules
2026-05-04 19:41:48 +10:00
parent d1469059d8
commit 5b0281574e
2 changed files with 93 additions and 0 deletions

View File

@@ -0,0 +1,91 @@
// One-time bootstrap of the active LLM settings from arcadia.
//
// On mount (and again whenever the session changes), if the operator has no
// active LLM settings in localStorage, fetch the tenant's enabled
// configurations and seed the active settings from the preferred row:
//
// 1. Any row with `metadata.default === true` (operator-marked default).
// 2. Otherwise the first enabled row.
//
// Once active settings exist, this component does nothing — the settings
// panel remains the place to switch between configs.
import { useEffect } from "react"
import { useArcadiaClient } from "@crema/arcadia-client"
import {
loadSettings,
saveSettings,
type LLMProvidersSettings,
type ProviderId,
} from "@crema/llm-providers-ui"
import {
listConfigurations,
saveActiveReasoning,
type LlmConfiguration,
} from "~/lib/arcadia/llm-configs"
const ACTIVE_KEY = "crema.llm-providers.settings"
function hasActiveSettings(): boolean {
if (typeof window === "undefined") return false
return !!localStorage.getItem(ACTIVE_KEY)
}
function pickPreferred(configs: LlmConfiguration[]): LlmConfiguration | null {
const enabled = configs.filter((c) => c.enabled)
if (enabled.length === 0) return null
const flagged = enabled.find(
(c) => (c.metadata as { default?: boolean } | null)?.default === true,
)
return flagged ?? enabled[0]
}
function applyConfig(c: LlmConfiguration): void {
const current = loadSettings()
const next: LLMProvidersSettings = {
...current,
providerId: c.provider as ProviderId,
model: c.model,
baseURL: c.base_url || undefined,
secretName: c.secret_name || undefined,
}
saveSettings(next)
saveActiveReasoning(c.reasoning_effort ?? "off")
}
export function LlmConfigBootstrap() {
const arcadia = useArcadiaClient()
useEffect(() => {
let cancelled = false
const tryBootstrap = async () => {
if (hasActiveSettings()) return
const token =
typeof window !== "undefined"
? sessionStorage.getItem("arcadia_access_token")
: null
if (!token) return
try {
const configs = await listConfigurations(arcadia, { enabled: true })
if (cancelled) return
const pick = pickPreferred(configs)
if (pick && !hasActiveSettings()) applyConfig(pick)
} catch {
// 401 / network — silently skip; will retry on next session change.
}
}
void tryBootstrap()
const onSessionChange = () => void tryBootstrap()
window.addEventListener("crema:session-change", onSessionChange)
return () => {
cancelled = true
window.removeEventListener("crema:session-change", onSessionChange)
}
}, [arcadia])
return null
}

View File

@@ -13,6 +13,7 @@ import "./app.css"
import { ToastProvider, Toaster } from "@crema/notification-ui" import { ToastProvider, Toaster } from "@crema/notification-ui"
import { CommandBusProvider } from "@crema/action-bus" import { CommandBusProvider } from "@crema/action-bus"
import { ArcadiaProvider } from "@crema/arcadia-client" import { ArcadiaProvider } from "@crema/arcadia-client"
import { LlmConfigBootstrap } from "~/lib/llm-config-bootstrap"
// CREMA:PROVIDERS-IMPORTS // CREMA:PROVIDERS-IMPORTS
const ARCADIA_URL = import.meta.env.VITE_ARCADIA_URL ?? "http://localhost:4000" const ARCADIA_URL = import.meta.env.VITE_ARCADIA_URL ?? "http://localhost:4000"
@@ -61,6 +62,7 @@ export default function App() {
}} }}
> >
<CommandBusProvider> <CommandBusProvider>
<LlmConfigBootstrap />
<Outlet /> <Outlet />
<Toaster /> <Toaster />
</CommandBusProvider> </CommandBusProvider>