'use client'; import { useEffect, useState } from 'react'; import { Sparkles, Loader2 } from 'lucide-react'; import { SettingsSection, SettingItem } from './settings-section'; import { apiFetch } from '@/lib/browser-navigation'; import { DEFAULT_AI_POLICY, type AiPolicy } from '@/lib/ai/types'; import { supportsLocalLlm, localLlmNeedsCorsSetup } from '@/lib/platform-capabilities'; /** * P0 scope only (docs/AI-ASSISTANT-CONCEPT.md §12): proves capability * gating and the policy-fetch round trip. No provider is called from here — * that's P1 (server class) onward. Once entitlement is real (P2), this pane * grows the Model/Scope/Index sections from §4. */ export function AiAssistantSettings() { const [policy, setPolicy] = useState(DEFAULT_AI_POLICY); const [loading, setLoading] = useState(true); useEffect(() => { let cancelled = false; (async () => { try { const res = await apiFetch('/api/ai/policy'); if (res.ok && !cancelled) { setPolicy(await res.json()); } } finally { if (!cancelled) setLoading(false); } })(); return () => { cancelled = true; }; }, []); return (
{loading ? ( Checking availability… ) : policy.entitlement.licensed ? ( Licensed ({policy.entitlement.tier}) — no model provider is configured yet. ) : ( Not yet licensed for this account. )}

Local, VNC-hosted, and bring-your-own-key providers are planned (see the AI Assistant concept doc). {supportsLocalLlm() ? localLlmNeedsCorsSetup() ? 'A local runtime will need its CORS setting adjusted to allow this browser origin.' : 'This desktop app can reach a local runtime with no extra setup.' : null}

); }