/** * RoutingPolicyEditor — the "Routing" tab. * * Three layers, matching the resolver's precedence: * 1. Global compute mode (local / cloud / auto) — the ex-env flag, now a * persisted setting. * 2. Per-model routes — explicit bindings that beat the defaults, each with a * live "how this resolves" preview from /compute/admin/resolve. * 3. (Per-modality defaults are edited inline via the model routes' Auto.) */ import React, { useCallback, useEffect, useState } from "react"; import { Loader2, Plus, Save, Trash2 } from "lucide-react"; import type { ComputeMode, ComputeSettings, ModelRoute, RouteCost, RouteResolution, } from "@homepilot/types"; import { computeClient } from "../../api"; import { MODALITIES } from "./targets"; const MODES: { value: ComputeMode; label: string }[] = [ { value: "local", label: "This PC only" }, { value: "auto", label: "Auto (prefer local, burst to cloud)" }, { value: "ollabridge_cloud", label: "OllaBridge Cloud" }, ]; function costLabel(c: RouteCost): string { const price = c.estimatedUsd == null ? "cost unknown" : c.estimatedUsd === 0 ? "free" : `$${c.estimatedUsd.toFixed(2)}/${c.perUnit || "request"}`; return `${c.target}: ${price}${c.overBudget ? " (over budget)" : ""}`; } export default function RoutingPolicyEditor() { const [settings, setSettings] = useState(null); const [routes, setRoutes] = useState([]); const [resolutions, setResolutions] = useState>({}); const [draft, setDraft] = useState<{ modality: string; modelId: string; primaryTarget: string; fallback: string } | null>(null); const [loading, setLoading] = useState(true); const [busy, setBusy] = useState(false); const [error, setError] = useState(null); const load = useCallback(async () => { setLoading(true); try { const [s, r] = await Promise.all([ computeClient.getComputeSettings(), computeClient.listRoutes(), ]); setSettings(s); setRoutes(r); const entries = await Promise.all( r.map(async (route) => { try { return [`${route.modality}:${route.modelId}`, await computeClient.resolveRoute(route.modality, route.modelId)] as const; } catch { return null; } }), ); setResolutions(Object.fromEntries(entries.filter(Boolean) as [string, RouteResolution][])); setError(null); } catch (e) { setError(e instanceof Error ? e.message : "Failed to load routing"); } finally { setLoading(false); } }, []); useEffect(() => { void load(); }, [load]); const saveMode = useCallback(async (mode: ComputeMode) => { setBusy(true); try { setSettings(await computeClient.putComputeSettings({ computeMode: mode })); } catch (e) { setError(e instanceof Error ? e.message : "Save failed"); } finally { setBusy(false); } }, []); const saveBudget = useCallback(async (value: string) => { const parsed = value.trim() === "" ? null : Number(value); if (parsed != null && (Number.isNaN(parsed) || parsed < 0)) return; setBusy(true); try { setSettings(await computeClient.putComputeSettings({ maxCostUsdPerRequest: parsed })); } catch (e) { setError(e instanceof Error ? e.message : "Save failed"); } finally { setBusy(false); } }, []); const addRoute = useCallback(async () => { if (!draft) return; if (!draft.modelId.trim() || !draft.primaryTarget.trim()) { setError("Model id and primary target are required."); return; } setBusy(true); try { await computeClient.upsertRoute({ modality: draft.modality as ModelRoute["modality"], modelId: draft.modelId.trim(), primaryTarget: draft.primaryTarget.trim(), fallbackTargets: draft.fallback.trim() ? [draft.fallback.trim()] : [], strategy: "pinned", privacy: "private_nodes", }); setDraft(null); await load(); } catch (e) { setError(e instanceof Error ? e.message : "Save failed"); } finally { setBusy(false); } }, [draft, load]); const removeRoute = useCallback( async (route: ModelRoute) => { await computeClient.deleteRoute(route.modality, route.modelId); await load(); }, [load], ); if (loading) return ; return (
{error && (
{error}
)} {/* Global default */}
Default compute

Used when a model has no explicit route.

{MODES.map((m) => ( ))}
{/* Per-model routes */}
Per-model routes
    {routes.map((r) => { const res = resolutions[`${r.modality}:${r.modelId}`]; return (
  • {r.modelId} · {r.modality}
    {r.primaryTarget} {r.fallbackTargets.length ? ` → ${r.fallbackTargets.join(" → ")}` : ""} · {r.strategy}
    {res && (
    Resolves to: {res.targets.join(" → ")} {res.costs?.length ? ( {res.costs.map(costLabel).join(" · ")} ) : null}
    )}
  • ); })} {routes.length === 0 &&
  • No per-model routes.
  • }
{draft && (
)}
); }