@polderlabs/bizar 5.5.1 → 5.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/bizar-dash/dist/assets/{EnvVarsSection-BUQnyVQD.js → EnvVarsSection-DoIzqrlb.js} +3 -3
  2. package/bizar-dash/dist/assets/{EnvVarsSection-BUQnyVQD.js.map → EnvVarsSection-DoIzqrlb.js.map} +1 -1
  3. package/bizar-dash/dist/assets/{MobileChat-8FupFgTv.js → MobileChat-CoUCUsbr.js} +1 -1
  4. package/bizar-dash/dist/assets/{MobileChat-8FupFgTv.js.map → MobileChat-CoUCUsbr.js.map} +1 -1
  5. package/bizar-dash/dist/assets/MobileSettings-BeO04g52.js +1 -0
  6. package/bizar-dash/dist/assets/{MobileSettings-BkXtglA6.js.map → MobileSettings-BeO04g52.js.map} +1 -1
  7. package/bizar-dash/dist/assets/{Toast-CUwkLRms.js → Toast-D9nv5N6m.js} +1 -1
  8. package/bizar-dash/dist/assets/{Toast-CUwkLRms.js.map → Toast-D9nv5N6m.js.map} +1 -1
  9. package/bizar-dash/dist/assets/{icons-COpQr35l.js → icons-Btipv2pp.js} +65 -70
  10. package/bizar-dash/dist/assets/icons-Btipv2pp.js.map +1 -0
  11. package/bizar-dash/dist/assets/main-DHXPuddY.js +18 -0
  12. package/bizar-dash/dist/assets/main-DHXPuddY.js.map +1 -0
  13. package/bizar-dash/dist/assets/{main-Bz_zWFCw.css → main-UG4jKK-F.css} +1 -1
  14. package/bizar-dash/dist/assets/mobile-H5KH9cTL.js +1 -0
  15. package/bizar-dash/dist/assets/{mobile-B7dAkmYd.js.map → mobile-H5KH9cTL.js.map} +1 -1
  16. package/bizar-dash/dist/assets/{mobile-layout-ClC6Qa42.js → mobile-layout-BqHxVb6_.js} +2 -2
  17. package/bizar-dash/dist/assets/{mobile-layout-ClC6Qa42.js.map → mobile-layout-BqHxVb6_.js.map} +1 -1
  18. package/bizar-dash/dist/assets/{useSlashCommands-B3MZ1JXa.js → useSlashCommands-C24-O1e7.js} +2 -2
  19. package/bizar-dash/dist/assets/{useSlashCommands-B3MZ1JXa.js.map → useSlashCommands-C24-O1e7.js.map} +1 -1
  20. package/bizar-dash/dist/index.html +7 -7
  21. package/bizar-dash/dist/mobile.html +3 -3
  22. package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  23. package/bizar-dash/src/server/memory-store.mjs +74 -28
  24. package/bizar-dash/src/server/routes/memory.mjs +91 -38
  25. package/bizar-dash/src/web/App.tsx +36 -43
  26. package/bizar-dash/src/web/components/SettingsNav.tsx +92 -0
  27. package/bizar-dash/src/web/components/Sidebar.tsx +26 -7
  28. package/bizar-dash/src/web/components/Topbar.tsx +11 -48
  29. package/bizar-dash/src/web/styles/main.css +18 -3
  30. package/bizar-dash/src/web/styles/settings.css +115 -3
  31. package/bizar-dash/src/web/views/Settings.tsx +184 -205
  32. package/bizar-dash/src/web/views/memory/ConfigPanel.tsx +4 -4
  33. package/bizar-dash/tests/memory-namespace.test.mjs +2 -2
  34. package/bizar-dash/tests/memory-status-root.test.mjs +144 -0
  35. package/bizar-dash/tests/memory-store.test.mjs +5 -4
  36. package/bizar-dash/tests/memory-vault-config-endpoint.test.mjs +173 -0
  37. package/bizar-dash/tests/settings-layout.test.tsx +129 -0
  38. package/bizar-dash/tests/settings-mode-wiring.test.tsx +151 -0
  39. package/bizar-dash/tests/settings-nav.test.tsx +127 -0
  40. package/bizar-dash/tests/views/Memory.test.tsx +40 -1
  41. package/bizar-dash/tests/views/topbar.test.tsx +35 -50
  42. package/cli/doctor.mjs +4 -1
  43. package/cli/doctor.test.mjs +5 -3
  44. package/cli/memory.mjs +1 -1
  45. package/cli/post-install-smoke.mjs +93 -67
  46. package/cli/post-install-smoke.test.mjs +72 -0
  47. package/cli/provision.mjs +33 -3
  48. package/package.json +1 -1
  49. package/bizar-dash/dist/assets/MobileSettings-BkXtglA6.js +0 -1
  50. package/bizar-dash/dist/assets/icons-COpQr35l.js.map +0 -1
  51. package/bizar-dash/dist/assets/main-gqVwliHz.js +0 -18
  52. package/bizar-dash/dist/assets/main-gqVwliHz.js.map +0 -1
  53. package/bizar-dash/dist/assets/mobile-B7dAkmYd.js +0 -1
  54. package/bizar-dash/tests/views/Settings.test.tsx +0 -160
@@ -1 +1 @@
1
- {"version":3,"mappings":"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","names":["Button","forwardRef","variant","size","iconOnly","loading","disabled","className","children","rest","ref","jsxs","cn","Card","interactive","jsx","CardTitle","CardMeta","PACKAGES","UpdatesSection","toast","useToast","status","setStatus","useState","useEffect","ws","Ws","msg","s","m","existing","api","e","check","err","applyUpdate","restart","isBusy","Download","p","cur","lat","_a","isOutdated","pkgStatus","CheckCircle","AlertCircle","AlertTriangle","RefreshCw","useAutosave","initialValue","saveFn","delay","onSaved","onError","value","setValue","timeoutRef","useRef","pendingValueRef","lastSavedValue","hasPendingDebounceRef","save","useCallback","v","setValueAndSave","toSave","clearDebounce","flush","AutosaveField","render","handleBlur","React","Loader","Check","LAYOUTS","GeneralSection","settings","patchUi","patchTop","autoSave","Fragment","LayoutIcon","l","onChange","onBlur","TailscaleSettings","initialStatus","authKey","setAuthKey","setLoading","error","setError","r","loadStatus","handleAuthenticate","handleSetupServe","_b","_c","handleRemoveServe","isInstalled","isAuthenticated","isServeEnabled","serveUrl","Plug","LinkIcon","SystemLlmSection","Sparkles","BACKEND_OPTIONS","HeadroomSettingsCard","onPatch","stats","setStats","loadingStatus","setLoadingStatus","installing","setInstalling","wrapping","setWrapping","unwrapping","setUnwrapping","startingProxy","setStartingProxy","stoppingProxy","setStoppingProxy","st","handleInstall","handleWrap","handleUnwrap","handleStartProxy","handleStopProxy","handleOpenDashboard","spawn","__vitePreload","installed","version","proxyRunning","proxyPort","wrapped","ratio","saved","Activity","XCircle","Zap","Square","Play","ExternalLink","DEFAULT_HEADROOM_SETTINGS","HeadroomSection","setSettings","setDirty","patch","ActivityLogCard","items","setItems","hidden","setHidden","filter","setFilter","showHidden","setShowHidden","refresh","log","hid","keyOf","it","idx","k","h","i","onRestoreAll","onRestoreOne","key","next","filtered","q","Search","Eye","isHidden","AboutCard","about","Info","ActivitySection","EnvVarManager","vars","setVars","saving","setSaving","revealed","setRevealed","editing","setEditing","editValue","setEditValue","showAdd","setShowAdd","newName","setNewName","newValue","setNewValue","showBulk","setShowBulk","bulkText","setBulkText","bulkImporting","setBulkImporting","searchQ","setSearchQ","collapsed","setCollapsed","load","toggleReveal","name","prev","handleAdd","startEdit","handleUpdate","handleDelete","handleBulkImport","handleExport","blob","url","a","useMemo","grouped","groups","prefix","toggleGroup","sortedGroupKeys","known","b","ai","bi","groupMode","Plus","Upload","X","KeyRound","isCollapsed","ChevronRight","ChevronDown","VarRow","isRevealed","onToggleReveal","onStartEdit","onEditValueChange","onHandleUpdate","onCancelEdit","onDelete","isEditing","EyeOff","Pencil","Trash2","EnvVarsSection"],"ignoreList":[],"sources":["../../src/web/components/Button.tsx","../../src/web/components/Card.tsx","../../src/web/views/settings/UpdatesSection.tsx","../../src/web/hooks/useAutosave.ts","../../src/web/components/AutosaveField.tsx","../../src/web/views/settings/GeneralSection.tsx","../../src/web/components/TailscaleSettings.tsx","../../src/web/views/settings/SystemLlmSection.tsx","../../src/web/components/HeadroomSettings.tsx","../../src/web/views/settings/HeadroomSection.tsx","../../src/web/views/settings/ActivitySection.tsx","../../src/web/components/EnvVarManager.tsx","../../src/web/views/settings/EnvVarsSection.tsx"],"sourcesContent":["// src/components/Button.tsx — typed button with variants + sizes.\n\nimport { type ButtonHTMLAttributes, forwardRef } from 'react';\nimport { cn } from '../lib/utils';\n\nexport type ButtonVariant =\n | 'primary'\n | 'secondary'\n | 'ghost'\n | 'danger'\n | 'accent'\n | 'success';\nexport type ButtonSize = 'sm' | 'md' | 'lg';\n\nexport type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n variant?: ButtonVariant;\n size?: ButtonSize;\n iconOnly?: boolean;\n loading?: boolean;\n};\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n function Button(\n {\n variant = 'secondary',\n size = 'md',\n iconOnly = false,\n loading = false,\n disabled,\n className,\n children,\n ...rest\n },\n ref,\n ) {\n return (\n <button\n ref={ref}\n type={rest.type ?? 'button'}\n disabled={disabled || loading}\n className={cn(\n 'btn',\n `btn-${variant}`,\n `btn-size-${size}`,\n iconOnly && 'btn-icon',\n loading && 'btn-loading',\n className,\n )}\n {...rest}\n >\n {loading ? <span className=\"btn-spinner\" aria-hidden /> : null}\n {children}\n </button>\n );\n },\n);\n","// src/components/Card.tsx — wrapper card.\n\nimport type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../lib/utils';\n\nexport type CardProps = HTMLAttributes<HTMLDivElement> & {\n variant?: 'elevated' | 'outlined' | 'filled';\n interactive?: boolean;\n children?: ReactNode;\n};\n\nexport function Card({\n variant = 'elevated',\n interactive = false,\n className,\n children,\n ...rest\n}: CardProps) {\n return (\n <div\n className={cn(\n 'card',\n `card-${variant}`,\n interactive && 'card-interactive',\n className,\n )}\n {...rest}\n >\n {children}\n </div>\n );\n}\n\nexport function CardTitle({ children, className }: { children: ReactNode; className?: string }) {\n return <h3 className={cn('card-title', className)}>{children}</h3>;\n}\n\nexport function CardMeta({ children, className }: { children: ReactNode; className?: string }) {\n return <div className={cn('card-meta', className)}>{children}</div>;\n}\n","// src/web/views/settings/UpdatesSection.tsx\nimport React, { useEffect, useState } from 'react';\nimport { Download, RefreshCw, CheckCircle, AlertCircle, AlertTriangle } from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../../components/Card';\nimport { Button } from '../../components/Button';\nimport { useToast } from '../../components/Toast';\nimport { api } from '../../lib/api';\nimport { Ws } from '../../lib/ws';\n\ntype PkgStatus = {\n status: 'idle' | 'starting' | 'installing' | 'done' | 'error';\n error?: string;\n newVersion?: string;\n logs: string[];\n};\n\ntype StatusState = {\n current: Record<string, string | null>;\n latest: Record<string, string | null> | null;\n checking: boolean;\n updating: boolean;\n hasUpdates: boolean;\n requiresRestart: boolean;\n perPackage: Record<string, PkgStatus>;\n error?: string;\n};\n\nconst PACKAGES = [\n { id: 'bizar', name: 'Bizar CLI' },\n { id: 'bizar-dash', name: 'Dashboard' },\n { id: 'bizar-plugin', name: 'Opencode Plugin' },\n];\n\nexport function UpdatesSection() {\n const toast = useToast();\n const [status, setStatus] = useState<StatusState>({\n current: {},\n latest: null,\n checking: false,\n updating: false,\n hasUpdates: false,\n requiresRestart: false,\n perPackage: {},\n });\n\n // WebSocket subscription for live update progress\n useEffect(() => {\n const ws = new Ws();\n ws.on((msg: Record<string, unknown>) => {\n if (msg.type === 'update:progress' || msg.type === 'update:log' || msg.type === 'update:complete') {\n setStatus((s) => {\n if (msg.type === 'update:complete') {\n return {\n ...s,\n updating: false,\n requiresRestart: Boolean((msg as { requiresRestart?: boolean }).requiresRestart),\n };\n }\n if (msg.type === 'update:log') {\n const m = msg as { pkg: string; line: string };\n const existing = s.perPackage[m.pkg] || { logs: [] };\n return {\n ...s,\n perPackage: {\n ...s.perPackage,\n [m.pkg]: {\n ...existing,\n logs: [...(existing.logs || []).slice(-50), m.line],\n },\n },\n };\n }\n // update:progress\n const m = msg as { pkg: string; status: PkgStatus['status']; error?: string; newVersion?: string };\n return {\n ...s,\n perPackage: {\n ...s.perPackage,\n [m.pkg]: {\n ...s.perPackage[m.pkg],\n status: m.status,\n error: m.error,\n newVersion: m.newVersion,\n },\n },\n };\n });\n }\n });\n return () => ws.close();\n }, []);\n\n // Load current versions on mount\n useEffect(() => {\n api.get<{ current: Record<string, string | null> }>('/updates/status')\n .then((r) => setStatus((s) => ({ ...s, current: r.current })))\n .catch((e) => setStatus((s) => ({ ...s, error: e.message })));\n }, []);\n\n const check = async () => {\n setStatus((s) => ({ ...s, checking: true, error: undefined }));\n try {\n const r = await api.get<{\n current: Record<string, string | null>;\n latest: Record<string, string | null>;\n hasUpdates: boolean;\n }>('/updates/check');\n setStatus((s) => ({\n ...s,\n checking: false,\n current: r.current,\n latest: r.latest,\n hasUpdates: r.hasUpdates,\n }));\n } catch (err) {\n setStatus((s) => ({ ...s, checking: false, error: (err as Error).message }));\n }\n };\n\n const applyUpdate = async () => {\n if (!confirm('Update Bizar packages? The dashboard will restart automatically.')) return;\n setStatus((s) => ({\n ...s,\n updating: true,\n requiresRestart: false,\n perPackage: {},\n error: undefined,\n }));\n try {\n await api.post('/updates/apply', { packages: ['bizar', 'bizar-dash', 'bizar-plugin'] });\n } catch (err) {\n setStatus((s) => ({ ...s, updating: false, error: (err as Error).message }));\n }\n };\n\n const restart = async () => {\n if (!confirm('Restart the dashboard? You will be disconnected briefly.')) return;\n try {\n await api.post('/restart');\n toast.info('Restarting…', 3000);\n setTimeout(() => window.location.reload(), 3000);\n } catch {\n toast.error('Restart failed');\n }\n };\n\n const isBusy = status.checking || status.updating;\n\n return (\n <Card id=\"settings-updates\" data-section=\"updates\">\n <CardTitle><Download size={14} /> Updates</CardTitle>\n <CardMeta>Check installed Bizar packages and apply dashboard updates.</CardMeta>\n\n {/* Current versions */}\n <div className=\"updates-current\">\n <h4>Installed versions</h4>\n <ul>\n {PACKAGES.map((p) => (\n <li key={p.id}>\n <span>{p.name}</span>\n <code className=\"mono\">{status.current[p.id] || '—'}</code>\n </li>\n ))}\n </ul>\n </div>\n\n {/* Latest + per-package status */}\n {status.latest && (\n <div className=\"updates-latest\">\n <h4>Latest available</h4>\n <ul>\n {PACKAGES.map((p) => {\n const cur = status.current[p.id];\n const lat = status.latest?.[p.id];\n const isOutdated = cur && lat && cur !== lat;\n return (\n <li key={p.id} className={isOutdated ? 'updates-outdated' : 'updates-current-version'}>\n <span>{p.name}</span>\n <code className=\"mono\">\n {lat || '—'}\n {isOutdated && <span className=\"updates-badge\">update available</span>}\n </code>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n\n {/* Per-package progress rows */}\n {status.updating && (\n <div className=\"updates-progress-rows\">\n {PACKAGES.map((p) => {\n const pkgStatus = status.perPackage[p.id] || { status: 'idle', logs: [] as string[] };\n return (\n <div key={p.id} className=\"updates-pkg-row\">\n <div className=\"updates-pkg-row-header\">\n <span className=\"updates-pkg-name\">{p.name}</span>\n <div className=\"updates-pkg-status\">\n {pkgStatus.status === 'starting' && <span className=\"btn-spinner\" />}\n {pkgStatus.status === 'installing' && <span className=\"btn-spinner\" />}\n {pkgStatus.status === 'done' && <CheckCircle size={14} className=\"icon-success\" />}\n {pkgStatus.status === 'error' && <AlertCircle size={14} className=\"icon-error\" />}\n <span>{pkgStatus.status}</span>\n {pkgStatus.newVersion && (\n <code className=\"mono\" style={{ fontSize: 11 }}>→ {pkgStatus.newVersion}</code>\n )}\n </div>\n </div>\n {pkgStatus.logs.length > 0 && (\n <details className=\"updates-pkg-logs\">\n <summary>npm output ({pkgStatus.logs.length} lines)</summary>\n <pre>{pkgStatus.logs.join('\\n')}</pre>\n </details>\n )}\n {pkgStatus.status === 'error' && pkgStatus.error && (\n <div className=\"updates-pkg-error\">\n <AlertTriangle size={12} /> {pkgStatus.error}\n </div>\n )}\n </div>\n );\n })}\n </div>\n )}\n\n {/* Actions */}\n <div className=\"updates-actions\">\n <Button onClick={check} disabled={isBusy}>\n {status.checking ? <span className=\"btn-spinner\" /> : <RefreshCw size={14} />}\n Check for updates\n </Button>\n <Button\n variant=\"primary\"\n onClick={applyUpdate}\n disabled={!status.hasUpdates || status.updating}\n >\n {status.updating ? <span className=\"btn-spinner\" /> : <Download size={14} />}\n {status.updating ? 'Updating…' : (status.hasUpdates ? 'Update now' : 'Up to date')}\n </Button>\n {status.requiresRestart && (\n <Button variant=\"danger\" onClick={restart}>\n <RefreshCw size={14} /> Restart Dashboard\n </Button>\n )}\n </div>\n\n {status.error && (\n <div className=\"updates-error\">\n <AlertTriangle size={14} />\n <span>{status.error}</span>\n </div>\n )}\n </Card>\n );\n}\n","// src/web/hooks/useAutosave.ts\n// Debounced autosave hook for settings fields.\n\nimport { useState, useEffect, useRef, useCallback } from 'react';\n\nexport type AutosaveStatus = 'idle' | 'saving' | 'saved' | 'error';\n\nexport function useAutosave<T>(\n initialValue: T,\n saveFn: (value: T) => Promise<void>,\n {\n delay = 800,\n onSaved,\n onError,\n }: { delay?: number; onSaved?: () => void; onError?: (e: Error) => void } = {},\n) {\n const [value, setValue] = useState<T>(initialValue);\n const [status, setStatus] = useState<AutosaveStatus>('idle');\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingValueRef = useRef<T | null>(null);\n const lastSavedValue = useRef<T>(initialValue);\n // Tracks whether a debounce timeout is currently pending (set when timeout is scheduled, cleared when it fires)\n const hasPendingDebounceRef = useRef(false);\n\n const save = useCallback(\n async (v: T) => {\n setStatus('saving');\n try {\n await saveFn(v);\n lastSavedValue.current = v;\n pendingValueRef.current = null;\n setStatus('saved');\n onSaved?.();\n setTimeout(() => setStatus('idle'), 2000);\n } catch (err) {\n setStatus('error');\n onError?.(err as Error);\n }\n },\n [saveFn, onSaved, onError],\n );\n\n const setValueAndSave = useCallback(\n (v: T) => {\n setValue(v);\n pendingValueRef.current = v;\n hasPendingDebounceRef.current = true;\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n timeoutRef.current = setTimeout(() => {\n timeoutRef.current = null;\n hasPendingDebounceRef.current = false;\n const toSave = pendingValueRef.current;\n pendingValueRef.current = null;\n if (toSave !== null) save(toSave);\n }, delay);\n },\n [delay, save],\n );\n\n /**\n * Clear any pending debounce without saving.\n * Use this when you want the debounce to handle the save naturally.\n */\n const clearDebounce = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n hasPendingDebounceRef.current = false;\n }\n }, []);\n\n /**\n * Flush any pending save immediately (called on unmount or explicit flush).\n */\n const flush = useCallback(async () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n hasPendingDebounceRef.current = false;\n const toSave = pendingValueRef.current;\n pendingValueRef.current = null;\n if (toSave !== null) await save(toSave);\n }\n }, [save]);\n\n // Cleanup on unmount: fire pending save immediately\n useEffect(() => {\n return () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n const toSave = pendingValueRef.current;\n pendingValueRef.current = null;\n // Fire-and-forget: call saveFn directly to persist without awaiting\n if (toSave !== null) {\n setStatus('saving');\n saveFn(toSave)\n .then(() => { lastSavedValue.current = toSave; setStatus('saved'); onSaved?.(); })\n .catch((err: Error) => { setStatus('error'); onError?.(err); })\n .finally(() => { setTimeout(() => setStatus('idle'), 2000); });\n }\n }\n };\n }, [saveFn, onSaved, onError]);\n\n return { value, setValue: setValueAndSave, status, save, flush, clearDebounce, hasPendingDebounceRef, pendingValueRef };\n}\n","// src/web/components/AutosaveField.tsx\n// Generic auto-saving field wrapper with inline save status animation.\n\nimport React from 'react';\nimport { Check, Loader, AlertCircle } from 'lucide-react';\nimport { useAutosave } from '../hooks/useAutosave';\n\nexport type { AutosaveStatus } from '../hooks/useAutosave';\n\nexport function AutosaveField<T = string>({\n initialValue,\n saveFn,\n delay = 800,\n render,\n className,\n}: {\n initialValue: T;\n saveFn: (value: T) => Promise<void>;\n delay?: number;\n render: (props: {\n value: T;\n onChange: (v: T) => void;\n onBlur: () => void;\n }) => React.ReactNode;\n className?: string;\n}) {\n const { value, setValue, status, save, clearDebounce, hasPendingDebounceRef, pendingValueRef } = useAutosave(initialValue, saveFn, { delay });\n\n const handleBlur = React.useCallback(() => {\n // If a debounce is pending (user was actively typing), clear the timeout\n // and save immediately — the user is done typing.\n if (hasPendingDebounceRef.current) {\n clearDebounce();\n // pendingValueRef.current holds the typed value not yet saved by debounce\n if (pendingValueRef.current !== null) save(pendingValueRef.current);\n }\n // If no debounce is pending: do nothing (value was already saved or unchanged).\n }, [clearDebounce, hasPendingDebounceRef, save, pendingValueRef]);\n\n return (\n <div className={`autosave-field ${className || ''} ${status}`}>\n {render({ value, onChange: setValue, onBlur: handleBlur })}\n <span className=\"autosave-status\" role=\"status\" aria-live=\"polite\">\n {status === 'saving' && <Loader className=\"spinning\" size={12} />}\n {status === 'saved' && <Check size={12} />}\n {status === 'error' && <AlertCircle size={12} />}\n </span>\n </div>\n );\n}\n","// src/web/views/settings/GeneralSection.tsx\nimport React from 'react';\nimport { Layout as LayoutIcon } from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../../components/Card';\nimport { AutosaveField } from '../../components/AutosaveField';\nimport { cn } from '../../lib/utils';\nimport type { Settings } from '../../lib/types';\n\ntype Props = {\n settings: Settings;\n patchUi: (patch: Partial<Settings['ui']>) => void;\n patchTop: <K extends keyof Settings>(key: K, value: Settings[K]) => void;\n /** Called by AutosaveField after state is patched; the parent debounces the API save */\n autoSave?: (key: keyof Settings, value: Settings[keyof Settings]) => void;\n};\n\nconst LAYOUTS = [\n { id: 'topnav', label: 'Top nav' },\n { id: 'sidebar', label: 'Sidebar' },\n { id: 'both', label: 'Both' },\n] as const;\n\nexport function GeneralSection({ settings, patchUi, patchTop, autoSave }: Props) {\n return (\n <>\n {/* UI Layout */}\n <Card id=\"settings-layout\" data-section=\"layout\">\n <CardTitle><LayoutIcon size={14} /> UI layout</CardTitle>\n <CardMeta>Choose how the dashboard's navigation is presented.</CardMeta>\n <div className=\"layout-row\" data-setting-id=\"ui.layout\">\n {LAYOUTS.map((l) => (\n <button\n key={l.id}\n type=\"button\"\n className={cn('layout-card', settings.ui.layout === l.id && 'layout-card-active')}\n onClick={() => patchUi({ layout: l.id })}\n >\n <span className=\"layout-card-label\">{l.label}</span>\n </button>\n ))}\n </div>\n <label className=\"checkbox-row\" data-setting-id=\"ui.showHeader\">\n <input\n type=\"checkbox\"\n checked={settings.ui.showHeader}\n onChange={(e) => patchUi({ showHeader: e.target.checked })}\n />\n <span>Show header</span>\n </label>\n <label className=\"checkbox-row\" data-setting-id=\"ui.showStatusBar\">\n <input\n type=\"checkbox\"\n checked={settings.ui.showStatusBar}\n onChange={(e) => patchUi({ showStatusBar: e.target.checked })}\n />\n <span>Show status bar</span>\n </label>\n <div className=\"field\" data-setting-id=\"ui.defaultTab\">\n <label className=\"field-label\">Default tab</label>\n <select\n className=\"select\"\n value={settings.ui.defaultTab}\n onChange={(e) => patchUi({ defaultTab: e.target.value })}\n >\n <option value=\"overview\">Overview</option>\n <option value=\"chat\">Chat</option>\n <option value=\"agents\">Agents</option>\n <option value=\"artifacts\">Plans</option>\n <option value=\"projects\">Projects</option>\n <option value=\"tasks\">Tasks</option>\n <option value=\"config\">Config</option>\n <option value=\"settings\">Settings</option>\n <option value=\"mods\">Mods</option>\n <option value=\"schedules\">Schedules</option>\n </select>\n </div>\n </Card>\n\n {/* General */}\n <Card id=\"settings-general\" data-section=\"general\">\n <CardTitle>General</CardTitle>\n <CardMeta>Default agent + model override.</CardMeta>\n <div className=\"field\" data-setting-id=\"defaultAgent\">\n <label className=\"field-label\" htmlFor=\"set-default-agent\">Default agent</label>\n <AutosaveField\n initialValue={settings.defaultAgent || ''}\n saveFn={async (v) => {\n patchTop('defaultAgent', v);\n autoSave?.('defaultAgent', v);\n }}\n render={({ value, onChange, onBlur }) => (\n <input\n id=\"set-default-agent\"\n className=\"input\"\n type=\"text\"\n placeholder=\"e.g. odin\"\n value={value}\n onChange={e => onChange(e.target.value)}\n onBlur={onBlur}\n />\n )}\n />\n </div>\n <div className=\"field\" data-setting-id=\"defaultModel\">\n <label className=\"field-label\" htmlFor=\"set-default-model\">Model override</label>\n <AutosaveField\n initialValue={settings.defaultModel || ''}\n saveFn={async (v) => {\n patchTop('defaultModel', v);\n autoSave?.('defaultModel', v);\n }}\n render={({ value, onChange, onBlur }) => (\n <input\n id=\"set-default-model\"\n className=\"input\"\n type=\"text\"\n placeholder=\"(leave empty for provider default)\"\n value={value}\n onChange={e => onChange(e.target.value)}\n onBlur={onBlur}\n />\n )}\n />\n </div>\n </Card>\n </>\n );\n}\n","// src/web/components/TailscaleSettings.tsx\n//\n// v5.2 — Tailscale auth key integration UI.\n//\n// Allows users to authenticate with Tailscale using an auth key and\n// set up tailscale serve for the dashboard without using the CLI.\nimport React, { useEffect, useState } from 'react';\nimport { CheckCircle, Link as LinkIcon, Plug } from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from './Card';\nimport { Button } from './Button';\nimport { api } from '../lib/api';\nimport type { TailscaleStatus } from '../lib/types';\n\ntype Props = {\n /** Existing tailscale status from Settings-level fetch. If provided, used as initial value. */\n initialStatus?: TailscaleStatus | null;\n};\n\nexport function TailscaleSettings({ initialStatus }: Props) {\n const [status, setStatus] = useState<TailscaleStatus | null>(initialStatus ?? null);\n const [authKey, setAuthKey] = useState('');\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (status === null) {\n api.get<TailscaleStatus>('/tailscale/status')\n .then((r) => setStatus(r))\n .catch(() => setStatus(null));\n }\n }, []);\n\n const loadStatus = async () => {\n try {\n const r = await api.get<TailscaleStatus>('/tailscale/status');\n setStatus(r);\n } catch {\n setError('Failed to load Tailscale status');\n }\n };\n\n const handleAuthenticate = async () => {\n if (!authKey.trim()) return;\n setLoading(true);\n setError(null);\n try {\n await api.post('/tailscale/setup', { authKey: authKey.trim() });\n await loadStatus();\n setAuthKey('');\n } catch (err) {\n setError((err as Error).message || 'Authentication failed');\n } finally {\n setLoading(false);\n }\n };\n\n const handleSetupServe = async () => {\n if (!status) return;\n setLoading(true);\n setError(null);\n try {\n await api.post('/tailscale/setup', {\n port: status.settings?.port || 4321,\n https: status.settings?.https !== false,\n hostname: status.settings?.hostname || '',\n });\n await loadStatus();\n } catch (err) {\n setError((err as Error).message || 'Setup failed');\n } finally {\n setLoading(false);\n }\n };\n\n const handleRemoveServe = async () => {\n setLoading(true);\n setError(null);\n try {\n await api.post('/tailscale/unserve');\n await loadStatus();\n } catch (err) {\n setError((err as Error).message || 'Remove failed');\n } finally {\n setLoading(false);\n }\n };\n\n const isInstalled = status?.installed ?? false;\n const isAuthenticated = status?.authenticated ?? false;\n const isServeEnabled = status?.settings?.enabled ?? false;\n const serveUrl = isServeEnabled ? `https://${status?.hostname || 'bizar-dash'}` : null;\n\n if (!isInstalled) {\n return (\n <Card id=\"settings-tailscale-auth\" data-section=\"tailscale\">\n <CardTitle><Plug size={14} /> Tailscale Integration</CardTitle>\n <CardMeta>Tailscale is not installed on this machine.</CardMeta>\n <p className=\"muted\">\n Install from{' '}\n <a href=\"https://tailscale.com/download\" target=\"_blank\" rel=\"noreferrer\">\n tailscale.com/download\n </a>\n </p>\n </Card>\n );\n }\n\n return (\n <Card id=\"settings-tailscale-auth\" data-section=\"tailscale\">\n <CardTitle><Plug size={14} /> Tailscale Integration</CardTitle>\n <CardMeta>Expose the dashboard over your Tailscale network using an auth key.</CardMeta>\n\n {error && (\n <p style={{ color: 'var(--color-error, #f85149)', fontSize: '0.85rem' }}>{error}</p>\n )}\n\n {isAuthenticated ? (\n <>\n <div className=\"status-row\" style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', marginBottom: '0.75rem' }}>\n <CheckCircle size={16} style={{ color: 'var(--color-success, #3fb950)' }} />\n <span>Authenticated as <strong>{status?.hostname || 'unknown'}</strong></span>\n </div>\n\n {isServeEnabled && serveUrl ? (\n <>\n <div className=\"status-row\" style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', marginBottom: '0.75rem' }}>\n <LinkIcon size={16} />\n <a href={serveUrl} target=\"_blank\" rel=\"noreferrer\">{serveUrl}</a>\n </div>\n <Button variant=\"secondary\" size=\"sm\" onClick={handleRemoveServe} disabled={loading}>\n Remove serve\n </Button>\n </>\n ) : (\n <Button variant=\"primary\" size=\"sm\" onClick={handleSetupServe} disabled={loading}>\n Set up Tailscale serve\n </Button>\n )}\n </>\n ) : (\n <>\n <p className=\"muted\" style={{ marginBottom: '0.75rem' }}>Not authenticated with Tailscale.</p>\n <div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap' }}>\n <input\n type=\"text\"\n className=\"input\"\n placeholder=\"tskey-...\"\n value={authKey}\n onChange={(e) => setAuthKey(e.target.value)}\n style={{ flex: 1, minWidth: '200px' }}\n disabled={loading}\n />\n <Button variant=\"primary\" size=\"sm\" onClick={handleAuthenticate} disabled={loading || !authKey.trim()}>\n Authenticate\n </Button>\n </div>\n </>\n )}\n </Card>\n );\n}\n","// src/web/views/settings/SystemLlmSection.tsx\nimport React from 'react';\nimport { Sparkles } from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../../components/Card';\nimport type { Settings } from '../../lib/types';\n\ntype Props = {\n settings: Settings;\n patchTop: <K extends keyof Settings>(key: K, value: Settings[K]) => void;\n};\n\nexport function SystemLlmSection({ settings, patchTop }: Props) {\n return (\n <Card id=\"settings-system-llm\" data-section=\"system-llm\">\n <CardTitle><Sparkles size={14} /> System LLM API</CardTitle>\n <CardMeta>\n Configures the LLM used for automatic title generation, prompt enhancement,\n summarization, and other system-level calls.\n </CardMeta>\n\n <label className=\"checkbox-row\" data-setting-id=\"systemLlm.enabled\">\n <input\n type=\"checkbox\"\n checked={!!settings.systemLlm?.enabled}\n onChange={(e) => {\n const cur = settings.systemLlm || { enabled: true, provider: 'opencode', model: 'opencode/deepseek-v4-flash-free' };\n patchTop('systemLlm', { ...cur, enabled: e.target.checked });\n }}\n />\n <span>Enable system LLM calls</span>\n </label>\n\n <div className=\"field\" data-setting-id=\"systemLlm.provider\" style={{ marginTop: 'var(--space-3)' }}>\n <label className=\"field-label\" htmlFor=\"set-system-llm-provider\">Provider</label>\n <select\n id=\"set-system-llm-provider\"\n className=\"select\"\n value={settings.systemLlm?.provider || 'opencode'}\n onChange={(e) => {\n const cur = settings.systemLlm || { enabled: true, provider: 'opencode', model: 'opencode/deepseek-v4-flash-free' };\n patchTop('systemLlm', { ...cur, provider: e.target.value });\n }}\n >\n <option value=\"opencode\">Opencode</option>\n <option value=\"openrouter\">OpenRouter</option>\n <option value=\"minimax\">MiniMax</option>\n </select>\n </div>\n\n <div className=\"field\" data-setting-id=\"systemLlm.model\">\n <label className=\"field-label\" htmlFor=\"set-system-llm-model\">Model</label>\n <input\n id=\"set-system-llm-model\"\n className=\"input mono\"\n type=\"text\"\n placeholder=\"opencode/deepseek-v4-flash-free\"\n value={settings.systemLlm?.model || 'opencode/deepseek-v4-flash-free'}\n onChange={(e) => {\n const cur = settings.systemLlm || { enabled: true, provider: 'opencode', model: 'opencode/deepseek-v4-flash-free' };\n patchTop('systemLlm', { ...cur, model: e.target.value });\n }}\n />\n <p className=\"field-help\">\n The API key is read from <code>auth.json</code> for the selected provider.\n Leave the default model for best results.\n </p>\n </div>\n\n <div style={{ marginTop: 'var(--space-4)' }}>\n <h4 style={{ margin: '0 0 var(--space-2)' }}>Features using this API</h4>\n <ul className=\"settings-feature-list\" style={{ margin: 0, paddingLeft: 'var(--space-4)', lineHeight: 1.8 }}>\n <li>Auto-title generation for new chat sessions</li>\n <li>Auto-title generation for new tasks</li>\n <li>&quot;Enhance prompt&quot; button in the task input</li>\n <li>&quot;Enhance prompt&quot; button in the chat composer</li>\n <li className=\"muted\" style={{ fontSize: 12 }}>Future: summarization, name generation, and more</li>\n </ul>\n </div>\n </Card>\n );\n}\n","// src/web/components/HeadroomSettings.tsx\n//\n// v1.0.0 — Headroom settings card for the Settings view.\n// Displays live status and provides controls for install, wrap, proxy, and configuration.\nimport React, { useEffect, useState, useCallback } from 'react';\nimport {\n Activity,\n CheckCircle,\n XCircle,\n Download,\n Play,\n Square,\n RefreshCw,\n ExternalLink,\n Zap,\n} from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { useToast } from '../components/Toast';\nimport { api } from '../lib/api';\nimport { type HeadroomSettings } from '../lib/types';\n\ntype HeadroomStatus = {\n installed: boolean;\n version: string | null;\n proxyRunning: boolean;\n proxyPort: number | null;\n proxyPid: number | null;\n wrapped: boolean;\n healthy: 'ok' | 'warn' | 'fail';\n messages: string[];\n};\n\ntype HeadroomStats = {\n tokensSaved?: number;\n compressionRatio?: number;\n cacheHits?: number;\n transforms?: number;\n error?: string;\n};\n\nconst BACKEND_OPTIONS = [\n { value: 'anthropic', label: 'Anthropic' },\n { value: 'anyllm', label: 'AnyLLM' },\n { value: 'litellm-anthropic', label: 'LiteLLM (Anthropic)' },\n { value: 'litellm-openai', label: 'LiteLLM (OpenAI)' },\n];\n\ntype Props = {\n settings: HeadroomSettings;\n onPatch: (patch: Partial<HeadroomSettings>) => void;\n};\n\nexport function HeadroomSettingsCard({ settings, onPatch }: Props) {\n const toast = useToast();\n const [status, setStatus] = useState<HeadroomStatus | null>(null);\n const [stats, setStats] = useState<HeadroomStats | null>(null);\n const [loadingStatus, setLoadingStatus] = useState(false);\n const [installing, setInstalling] = useState(false);\n const [wrapping, setWrapping] = useState(false);\n const [unwrapping, setUnwrapping] = useState(false);\n const [startingProxy, setStartingProxy] = useState(false);\n const [stoppingProxy, setStoppingProxy] = useState(false);\n\n const loadStatus = useCallback(async () => {\n setLoadingStatus(true);\n try {\n const [s, st] = await Promise.all([\n api.get<HeadroomStatus>('/headroom/status'),\n api.get<HeadroomStats>('/headroom/stats?hours=24').catch(() => ({ error: 'no stats' })),\n ]);\n setStatus(s);\n if (!st.error) setStats(st);\n } catch (err) {\n toast.error(`Failed to load Headroom status: ${(err as Error).message}`);\n } finally {\n setLoadingStatus(false);\n }\n }, [toast]);\n\n useEffect(() => {\n loadStatus();\n }, [loadStatus]);\n\n const handleInstall = async () => {\n setInstalling(true);\n try {\n const r = await api.post<{ ok: boolean; installed: boolean; method: string }>('/headroom/install', { force: true });\n if (r.installed) {\n toast.success(`Headroom installed via ${r.method}.`);\n await loadStatus();\n } else {\n toast.error('Headroom install failed. Try: pip install \"headroom-ai[all]\"');\n }\n } catch (err) {\n toast.error(`Install failed: ${(err as Error).message}`);\n } finally {\n setInstalling(false);\n }\n };\n\n const handleWrap = async () => {\n setWrapping(true);\n try {\n const r = await api.post<{ ok: boolean }>('/headroom/wrap', { port: settings.port });\n if (r.ok) {\n toast.success('opencode wrapped with Headroom.');\n await loadStatus();\n } else {\n toast.error('Wrap failed.');\n }\n } catch (err) {\n toast.error(`Wrap failed: ${(err as Error).message}`);\n } finally {\n setWrapping(false);\n }\n };\n\n const handleUnwrap = async () => {\n setUnwrapping(true);\n try {\n const r = await api.post<{ ok: boolean }>('/headroom/unwrap');\n if (r.ok) {\n toast.success('opencode unwrapped from Headroom.');\n await loadStatus();\n } else {\n toast.error('Unwrap failed.');\n }\n } catch (err) {\n toast.error(`Unwrap failed: ${(err as Error).message}`);\n } finally {\n setUnwrapping(false);\n }\n };\n\n const handleStartProxy = async () => {\n setStartingProxy(true);\n try {\n const r = await api.post<{ ok: boolean }>('/headroom/proxy/start', {\n port: settings.port,\n host: settings.host,\n });\n if (r.ok) {\n toast.success(`Headroom proxy started on ${settings.host}:${settings.port}.`);\n await loadStatus();\n } else {\n toast.error('Proxy start failed.');\n }\n } catch (err) {\n toast.error(`Proxy start failed: ${(err as Error).message}`);\n } finally {\n setStartingProxy(false);\n }\n };\n\n const handleStopProxy = async () => {\n setStoppingProxy(true);\n try {\n const r = await api.post<{ ok: boolean }>('/headroom/proxy/stop');\n if (r.ok) {\n toast.success('Headroom proxy stopped.');\n await loadStatus();\n } else {\n toast.error('Proxy stop failed.');\n }\n } catch (err) {\n toast.error(`Proxy stop failed: ${(err as Error).message}`);\n } finally {\n setStoppingProxy(false);\n }\n };\n\n const handleOpenDashboard = async () => {\n try {\n const { spawn } = await import('node:child_process');\n spawn('headroom', ['dashboard'], { detached: true, stdio: 'ignore' });\n } catch {\n toast.error('Could not open Headroom dashboard. Run `headroom dashboard` manually.');\n }\n };\n\n const { installed, version, proxyRunning, proxyPort, wrapped } = status || {};\n const ratio = stats?.compressionRatio ?? 0;\n const saved = stats?.tokensSaved ?? 0;\n\n return (\n <div id=\"settings-headroom\" data-section=\"headroom\">\n <Card>\n <CardTitle>\n <Activity size={14} style={{ color: proxyRunning ? 'var(--success)' : 'var(--text-dim)' }} />\n Headroom\n {installed && version && (\n <span style={{ fontSize: 11, color: 'var(--text-dim)', marginLeft: 6 }}>\n v{version} {proxyRunning ? '✓' : '✗'}\n </span>\n )}\n {!installed && (\n <span style={{ fontSize: 11, color: 'var(--error)', marginLeft: 6 }}>not installed</span>\n )}\n </CardTitle>\n <CardMeta>\n Context compression for token efficiency. Compresses tool outputs, logs, and conversation\n history by 60–95% before they reach the model.\n </CardMeta>\n\n {/* Live status row */}\n <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap', marginTop: 12, marginBottom: 12 }}>\n <div className=\"headroom-status-item\">\n {installed ? (\n <CheckCircle size={12} style={{ color: 'var(--success)' }} />\n ) : (\n <XCircle size={12} style={{ color: 'var(--error)' }} />\n )}\n <span>{installed ? 'Installed' : 'Not installed'}</span>\n </div>\n <div className=\"headroom-status-item\">\n {proxyRunning ? (\n <CheckCircle size={12} style={{ color: 'var(--success)' }} />\n ) : (\n <XCircle size={12} style={{ color: 'var(--text-dim)' }} />\n )}\n <span>Proxy {proxyRunning ? `${proxyPort} ✓` : 'stopped'}</span>\n </div>\n <div className=\"headroom-status-item\">\n {wrapped ? (\n <CheckCircle size={12} style={{ color: 'var(--success)' }} />\n ) : (\n <XCircle size={12} style={{ color: 'var(--text-dim)' }} />\n )}\n <span>opencode {wrapped ? 'wrapped' : 'not wrapped'}</span>\n </div>\n </div>\n\n {/* Stats */}\n {(saved > 0 || ratio > 0) && (\n <div style={{ display: 'flex', gap: 24, marginBottom: 12 }}>\n <div>\n <div style={{ fontSize: 20, fontWeight: 700, color: 'var(--success)' }}>\n {ratio > 0 ? `${Math.round(ratio * 100)}%` : '—'}\n </div>\n <div className=\"muted\" style={{ fontSize: 11 }}>Compression ratio</div>\n </div>\n <div>\n <div style={{ fontSize: 20, fontWeight: 700, color: 'var(--accent)' }}>\n {saved > 0 ? saved.toLocaleString() : '—'}\n </div>\n <div className=\"muted\" style={{ fontSize: 11 }}>Tokens saved (24h)</div>\n </div>\n </div>\n )}\n\n {/* Action buttons */}\n <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginBottom: 8 }}>\n {!installed ? (\n <Button variant=\"primary\" size=\"sm\" onClick={handleInstall} disabled={installing}>\n {installing ? <span className=\"btn-spinner\" /> : <Download size={13} />}\n {installing ? 'Installing…' : 'Install Headroom'}\n </Button>\n ) : (\n <>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={handleWrap}\n disabled={wrapping || wrapped}\n title={wrapped ? 'opencode is already wrapped' : 'Wrap opencode to route through Headroom proxy'}\n >\n {wrapping ? <span className=\"btn-spinner\" /> : <Zap size={13} />}\n {wrapping ? 'Wrapping…' : wrapped ? 'Wrapped ✓' : 'Wrap opencode'}\n </Button>\n {wrapped && (\n <Button variant=\"ghost\" size=\"sm\" onClick={handleUnwrap} disabled={unwrapping}>\n {unwrapping ? <span className=\"btn-spinner\" /> : <RefreshCw size={13} />}\n {unwrapping ? 'Unwrapping…' : 'Unwrap'}\n </Button>\n )}\n </>\n )}\n\n {installed && (\n <>\n {proxyRunning ? (\n <Button variant=\"secondary\" size=\"sm\" onClick={handleStopProxy} disabled={stoppingProxy}>\n {stoppingProxy ? <span className=\"btn-spinner\" /> : <Square size={13} />}\n {stoppingProxy ? 'Stopping…' : 'Stop proxy'}\n </Button>\n ) : (\n <Button variant=\"secondary\" size=\"sm\" onClick={handleStartProxy} disabled={startingProxy}>\n {startingProxy ? <span className=\"btn-spinner\" /> : <Play size={13} />}\n {startingProxy ? 'Starting…' : 'Start proxy'}\n </Button>\n )}\n <Button variant=\"ghost\" size=\"sm\" onClick={handleOpenDashboard}>\n <ExternalLink size={13} />\n Dashboard\n </Button>\n </>\n )}\n\n <Button variant=\"ghost\" size=\"sm\" onClick={loadStatus} disabled={loadingStatus}>\n <RefreshCw size={13} className={loadingStatus ? 'spin' : ''} />\n </Button>\n </div>\n\n {/* Settings */}\n <div style={{ marginTop: 16 }}>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.enabled}\n onChange={(e) => onPatch({ enabled: e.target.checked })}\n />\n <span>Enable Headroom</span>\n </label>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.autoInstall}\n onChange={(e) => onPatch({ autoInstall: e.target.checked })}\n />\n <span>Auto-install if missing on dashboard startup</span>\n </label>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.autoStart}\n onChange={(e) => onPatch({ autoStart: e.target.checked })}\n />\n <span>Auto-start proxy on dashboard startup</span>\n </label>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.autoWrap}\n onChange={(e) => onPatch({ autoWrap: e.target.checked })}\n />\n <span>Auto-wrap opencode on dashboard startup</span>\n </label>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.routeAllProviders}\n onChange={(e) => onPatch({ routeAllProviders: e.target.checked })}\n />\n <span>Route all providers through Headroom proxy</span>\n </label>\n\n <div className=\"task-form-row\" style={{ marginTop: 12 }}>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Proxy port</label>\n <input\n type=\"number\"\n className=\"input\"\n value={settings.port}\n min={1}\n max={65535}\n onChange={(e) => onPatch({ port: Math.max(1, Math.min(65535, parseInt(e.target.value, 10) || 8787)) })}\n />\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Proxy host</label>\n <input\n type=\"text\"\n className=\"input\"\n value={settings.host}\n onChange={(e) => onPatch({ host: e.target.value })}\n />\n </div>\n </div>\n\n <div className=\"task-form-row\">\n <div className=\"task-form-field\">\n <label className=\"field-label\">Backend</label>\n <select\n className=\"select\"\n value={settings.backend}\n onChange={(e) => onPatch({ backend: e.target.value })}\n >\n {BACKEND_OPTIONS.map((o) => (\n <option key={o.value} value={o.value}>{o.label}</option>\n ))}\n </select>\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Monthly budget (USD)</label>\n <input\n type=\"number\"\n className=\"input\"\n value={settings.budget}\n min={0}\n step={1}\n onChange={(e) => onPatch({ budget: Math.max(0, parseFloat(e.target.value) || 0) })}\n />\n <span className=\"field-help\">0 = unlimited</span>\n </div>\n </div>\n\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.outputShaper}\n onChange={(e) => onPatch({ outputShaper: e.target.checked })}\n />\n <span>Enable output shaper</span>\n </label>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.telemetry}\n onChange={(e) => onPatch({ telemetry: e.target.checked })}\n />\n <span>Enable telemetry</span>\n </label>\n </div>\n </Card>\n </div>\n );\n}\n","// src/web/views/settings/HeadroomSection.tsx\nimport React from 'react';\nimport { HeadroomSettingsCard } from '../../components/HeadroomSettings';\nimport { type HeadroomSettings, type Settings } from '../../lib/types';\n\nconst DEFAULT_HEADROOM_SETTINGS: HeadroomSettings = {\n enabled: true,\n autoInstall: true,\n port: 8787,\n host: '127.0.0.1',\n outputShaper: false,\n telemetry: false,\n budget: 0,\n backend: 'anthropic',\n autoStart: true,\n autoWrap: true,\n routeAllProviders: true,\n};\n\ntype Props = {\n settings: Settings;\n setSettings: React.Dispatch<React.SetStateAction<Settings>>;\n setDirty: React.Dispatch<React.SetStateAction<boolean>>;\n};\n\nexport function HeadroomSection({ settings, setSettings, setDirty }: Props) {\n return (\n <HeadroomSettingsCard\n settings={settings.headroom || DEFAULT_HEADROOM_SETTINGS}\n onPatch={(patch) => {\n setSettings((cur) => ({\n ...cur,\n headroom: { ...(cur.headroom || DEFAULT_HEADROOM_SETTINGS), ...patch },\n }));\n setDirty(true);\n }}\n />\n );\n}\n","// src/web/views/settings/ActivitySection.tsx\nimport React, { useEffect, useState, useCallback } from 'react';\nimport { Activity, Search, Eye, RefreshCw, Info } from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../../components/Card';\nimport { Button } from '../../components/Button';\nimport { useToast } from '../../components/Toast';\nimport { api } from '../../lib/api';\nimport { cn } from '../../lib/utils';\nimport type { Settings } from '../../lib/types';\n\ntype Props = {\n about: Settings['about'];\n};\n\nfunction ActivityLogCard() {\n const toast = useToast();\n const [items, setItems] = useState<Array<{ kind?: string; ts?: string; slug?: string; message?: string }>>([]);\n const [hidden, setHidden] = useState<Set<string>>(new Set());\n const [loading, setLoading] = useState(true);\n const [filter, setFilter] = useState('');\n const [showHidden, setShowHidden] = useState(true);\n\n const refresh = useCallback(async () => {\n setLoading(true);\n try {\n const [log, hid] = await Promise.all([\n api.get<{ items: Array<{ kind?: string; ts?: string; slug?: string; message?: string }> }>('/activity'),\n api.get<{ hidden: string[] }>('/activity/hidden'),\n ]);\n setItems(Array.isArray(log.items) ? log.items : []);\n setHidden(new Set(hid.hidden || []));\n } catch (err) {\n toast.error(`Load failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n }, [toast]);\n\n useEffect(() => { refresh(); }, [refresh]);\n\n const keyOf = (it: { kind?: string; ts?: string; slug?: string }, idx: number) => {\n const k = `${it.kind || ''}|${it.ts || ''}|${it.slug || ''}|${idx}`;\n let h = 0;\n for (let i = 0; i < k.length; i++) h = ((h << 5) - h + k.charCodeAt(i)) | 0;\n return Math.abs(h).toString(16).padStart(8, '0').slice(0, 16);\n };\n\n const onRestoreAll = async () => {\n try {\n await api.del('/activity/hide');\n setHidden(new Set());\n toast.success('All hidden activity restored.');\n } catch (err) {\n toast.error(`Restore failed: ${(err as Error).message}`);\n }\n };\n\n const onRestoreOne = async (key: string) => {\n try {\n await api.del(`/activity/hide/${encodeURIComponent(key)}`);\n const next = new Set(hidden);\n next.delete(key);\n setHidden(next);\n } catch (err) {\n toast.error(`Restore failed: ${(err as Error).message}`);\n }\n };\n\n const filtered = items.filter((it, idx) => {\n const k = keyOf(it, idx);\n if (!showHidden && hidden.has(k)) return false;\n if (!filter) return true;\n const q = filter.toLowerCase();\n return [it.kind, it.slug, it.message].some((v) => typeof v === 'string' && v.toLowerCase().includes(q));\n });\n\n return (\n <Card id=\"settings-activity-log\" data-section=\"activity-log\">\n <CardTitle>\n <Activity size={14} /> Activity log\n <span className=\"muted\" style={{ fontWeight: 400, marginLeft: 8, fontSize: 12 }}>\n {items.length} total · {hidden.size} hidden\n </span>\n <Button variant=\"ghost\" size=\"sm\" style={{ marginLeft: 'auto' }} onClick={refresh} title=\"Reload\">\n <RefreshCw size={12} />\n </Button>\n </CardTitle>\n <CardMeta>\n Full history from <code>~/.bizar/activity.log</code>. Hiding an item in the Overview only hides it there — the entry stays here.\n </CardMeta>\n\n <div className=\"activity-log-toolbar\">\n <div className=\"activity-log-search\">\n <Search size={12} />\n <input\n type=\"text\"\n className=\"input\"\n placeholder=\"Filter by kind, slug, or message…\"\n value={filter}\n onChange={(e) => setFilter(e.target.value)}\n />\n </div>\n <label className=\"activity-log-toggle\">\n <input\n type=\"checkbox\"\n checked={showHidden}\n onChange={(e) => setShowHidden(e.target.checked)}\n />\n Show hidden\n </label>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n disabled={hidden.size === 0}\n onClick={onRestoreAll}\n title=\"Restore all hidden items to the Overview\"\n >\n <Eye size={12} /> Restore all\n </Button>\n </div>\n\n {loading ? (\n <div className=\"muted\" style={{ padding: '12px 0', fontSize: 12 }}>Loading…</div>\n ) : filtered.length === 0 ? (\n <div className=\"muted\" style={{ padding: '12px 0', fontSize: 12 }}>\n {items.length === 0 ? 'No activity yet.' : 'No items match the current filter.'}\n </div>\n ) : (\n <div className=\"activity-log-table-wrap\">\n <table className=\"activity-log-table\">\n <thead>\n <tr>\n <th>Kind</th>\n <th>Detail</th>\n <th>Time</th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n {filtered.slice(0, 200).map((it, idx) => {\n const k = keyOf(it, idx);\n const isHidden = hidden.has(k);\n return (\n <tr key={`${it.ts}-${idx}`} className={cn(isHidden && 'activity-log-row-hidden')}>\n <td className=\"activity-log-kind\">{it.kind || 'activity'}</td>\n <td className=\"activity-log-detail\">\n {it.message || it.slug || '—'}\n </td>\n <td className=\"activity-log-time mono\">\n {it.ts ? new Date(it.ts).toLocaleString() : '—'}\n </td>\n <td>\n {isHidden ? (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => onRestoreOne(k)} title=\"Restore to Overview\">\n <Eye size={12} />\n </Button>\n ) : (\n <span className=\"activity-log-state-tag\">shown</span>\n )}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n {filtered.length > 200 && (\n <div className=\"muted\" style={{ fontSize: 11, padding: '8px 0' }}>\n Showing first 200 of {filtered.length}.\n </div>\n )}\n </div>\n )}\n </Card>\n );\n}\n\nfunction AboutCard({ about }: Props) {\n return (\n <Card id=\"settings-about\" data-section=\"about\">\n <CardTitle><Info size={14} /> About</CardTitle>\n <CardMeta>Build metadata.</CardMeta>\n <dl className=\"about-table\">\n <dt>Version</dt>\n <dd className=\"mono\">{about?.version || '—'}</dd>\n <dt>Homepage</dt>\n <dd>\n <a href={about?.homepage || 'https://github.com/DrB0rk/BizarHarness'} target=\"_blank\" rel=\"noopener noreferrer\">\n {about?.homepage || 'https://github.com/DrB0rk/BizarHarness'}\n </a>\n </dd>\n <dt>License</dt>\n <dd>{about?.license || 'MIT'}</dd>\n </dl>\n </Card>\n );\n}\n\nexport function ActivitySection({ about }: Props) {\n return (\n <>\n <ActivityLogCard />\n <AboutCard about={about} />\n </>\n );\n}\n","// src/web/components/EnvVarManager.tsx — manage BIZAR_* env vars from ~/.config/bizar/env.json\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { Plus, Pencil, Trash2, Eye, EyeOff, RefreshCw, KeyRound, CheckCircle, X, Search, Download, Upload, ChevronDown, ChevronRight, AlertCircle } from 'lucide-react';\nimport { Button } from './Button';\nimport { useToast } from './Toast';\nimport { api } from '../lib/api';\nimport { cn } from '../lib/utils';\n\nexport type EnvVarEntry = {\n name: string;\n value: string; // masked on GET, full on edit\n createdAt: string;\n source: string;\n};\n\nexport type EnvVarGrouped = Record<string, EnvVarEntry[]>;\n\ntype Props = {\n onError?: (msg: string) => void;\n};\n\nexport function EnvVarManager({ onError }: Props) {\n const toast = useToast();\n const [vars, setVars] = useState<EnvVarEntry[]>([]);\n const [loading, setLoading] = useState(false);\n const [saving, setSaving] = useState(false);\n // Which rows have the value revealed (edit mode shows real value)\n const [revealed, setRevealed] = useState<Set<string>>(new Set());\n // Currently editing name (null = none)\n const [editing, setEditing] = useState<string | null>(null);\n const [editValue, setEditValue] = useState('');\n // New var form\n const [showAdd, setShowAdd] = useState(false);\n const [newName, setNewName] = useState('');\n const [newValue, setNewValue] = useState('');\n // Bulk operations\n const [showBulk, setShowBulk] = useState(false);\n const [bulkText, setBulkText] = useState('');\n const [bulkImporting, setBulkImporting] = useState(false);\n // Search / filter\n const [searchQ, setSearchQ] = useState('');\n // Group by prefix (collapsed state)\n const [collapsed, setCollapsed] = useState<Set<string>>(new Set());\n\n const load = useCallback(async () => {\n setLoading(true);\n try {\n const r = await api.get<EnvVarEntry[]>('/env-vars');\n setVars(r);\n } catch (err) {\n toast.error(`Load failed: ${(err as Error).message}`);\n onError?.((err as Error).message);\n } finally {\n setLoading(false);\n }\n }, [toast, onError]);\n\n useEffect(() => { load(); }, [load]);\n\n const toggleReveal = (name: string) => {\n setRevealed((prev) => {\n const next = new Set(prev);\n if (next.has(name)) next.delete(name);\n else next.add(name);\n return next;\n });\n };\n\n const handleAdd = async () => {\n const name = newName.trim().toUpperCase();\n const value = newValue.trim();\n if (!name || !/^BIZAR_[A-Z0-9_]+$/.test(name)) {\n toast.warning('Name must match BIZAR_<NAME> (e.g. BIZAR_MINIMAX_KEY)');\n return;\n }\n if (!value) {\n toast.warning('Value is required.');\n return;\n }\n if (vars.some((v) => v.name === name)) {\n toast.warning(`${name} already exists.`);\n return;\n }\n setSaving(true);\n try {\n await api.post('/env-vars', { name, value });\n toast.success(`${name} created.`);\n setShowAdd(false);\n setNewName('');\n setNewValue('');\n await load();\n } catch (err) {\n toast.error(`Create failed: ${(err as Error).message}`);\n } finally {\n setSaving(false);\n }\n };\n\n const startEdit = (v: EnvVarEntry) => {\n setEditing(v.name);\n setEditValue(v.value === v.value.replace(/\\*/g, '') ? v.value : '');\n setRevealed((prev) => { const next = new Set(prev); next.add(v.name); return next; });\n };\n\n const handleUpdate = async (name: string) => {\n if (!editValue.trim()) {\n toast.warning('Value cannot be empty.');\n return;\n }\n setSaving(true);\n try {\n await api.put(`/env-vars/${encodeURIComponent(name)}`, { value: editValue.trim() });\n toast.success(`${name} updated.`);\n setEditing(null);\n await load();\n } catch (err) {\n toast.error(`Update failed: ${(err as Error).message}`);\n } finally {\n setSaving(false);\n }\n };\n\n const handleDelete = async (name: string) => {\n if (!confirm(`Delete ${name}? This cannot be undone.`)) return;\n try {\n await api.del(`/env-vars/${encodeURIComponent(name)}`);\n toast.success(`${name} deleted.`);\n await load();\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n // ─── Bulk import ───────────────────────────────────────────────────────────\n const handleBulkImport = async () => {\n if (!bulkText.trim()) { toast.warning('Nothing to import.'); return; }\n setBulkImporting(true);\n try {\n const r = await api.post<{ ok: boolean; imported: number; skipped: number; errors: string[] }>('/env-vars/bulk-import', { envContent: bulkText });\n toast.success(`Imported ${r.imported}, skipped ${r.skipped}.`);\n if (r.errors.length > 0) {\n toast.warning(`${r.errors.length} lines had errors: ${r.errors.slice(0, 3).join('; ')}${r.errors.length > 3 ? '…' : ''}`);\n }\n setBulkText('');\n setShowBulk(false);\n await load();\n } catch (err) {\n toast.error(`Bulk import failed: ${(err as Error).message}`);\n } finally {\n setBulkImporting(false);\n }\n };\n\n // ─── Bulk export ───────────────────────────────────────────────────────────\n const handleExport = async () => {\n try {\n const r = await api.get<string>('/env-vars/export');\n // r is the raw text content\n const blob = new Blob([r as unknown as string], { type: 'text/plain' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = '.env';\n a.click();\n URL.revokeObjectURL(url);\n toast.success('Exported .env file.');\n } catch (err) {\n toast.error(`Export failed: ${(err as Error).message}`);\n }\n };\n\n // ─── Group by prefix ───────────────────────────────────────────────────────\n const filtered = useMemo(() => {\n if (!searchQ.trim()) return vars;\n const q = searchQ.toLowerCase();\n return vars.filter((v) => v.name.toLowerCase().includes(q));\n }, [vars, searchQ]);\n\n const grouped = useMemo(() => {\n const groups: Record<string, EnvVarEntry[]> = {};\n for (const v of filtered) {\n const prefix = v.name.split('_')[0] + '_';\n (groups[prefix] ??= []).push(v);\n }\n return groups;\n }, [filtered]);\n\n const toggleGroup = (prefix: string) => {\n setCollapsed((prev) => {\n const next = new Set(prev);\n if (next.has(prefix)) next.delete(prefix);\n else next.add(prefix);\n return next;\n });\n };\n\n const sortedGroupKeys = useMemo(() => {\n const known = ['BIZAR_', 'PROVIDER_', 'MODEL_', 'API_'];\n const keys = Object.keys(grouped).sort((a, b) => {\n const ai = known.indexOf(a); const bi = known.indexOf(b);\n if (ai === -1 && bi === -1) return a.localeCompare(b);\n if (ai === -1) return 1;\n if (bi === -1) return -1;\n return ai - bi;\n });\n return keys;\n }, [grouped]);\n\n if (loading) {\n return <div className=\"muted\" style={{ padding: '16px 0', fontSize: 13 }}>Loading env vars…</div>;\n }\n\n const hasGroups = sortedGroupKeys.length > 1;\n const groupMode = hasGroups;\n\n return (\n <div className=\"env-var-manager\">\n <div className=\"env-var-toolbar\">\n <Button variant=\"primary\" size=\"sm\" onClick={() => setShowAdd(true)}>\n <Plus size={12} /> New variable\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => setShowBulk((v) => !v)} className={showBulk ? 'active' : ''}>\n <Upload size={12} /> Bulk import\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={handleExport} title=\"Export as .env\">\n <Download size={12} /> Export\n </Button>\n <div className=\"env-var-search-wrap\">\n <Search size={12} className=\"env-var-search-icon\" />\n <input\n className=\"env-var-search input\"\n placeholder=\"Filter…\"\n value={searchQ}\n onChange={(e) => setSearchQ(e.target.value)}\n />\n </div>\n <Button variant=\"ghost\" size=\"sm\" onClick={load} title=\"Reload\">\n <RefreshCw size={12} />\n </Button>\n </div>\n\n {/* Bulk import panel */}\n {showBulk && (\n <div className=\"env-var-bulk-panel\">\n <div className=\"env-var-bulk-header\">\n <span>Paste <code>KEY=value</code> lines (one per line):</span>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setShowBulk(false)}><X size={12} /></Button>\n </div>\n <textarea\n className=\"input mono env-var-bulk-textarea\"\n placeholder={\"BIZAR_API_KEY=your-key-here\\nPROVIDER_OPENAI_KEY=sk-...\\nMODEL_KEY=gem-...\"}\n value={bulkText}\n onChange={(e) => setBulkText(e.target.value)}\n rows={6}\n />\n <div className=\"env-var-bulk-footer\">\n <Button variant=\"primary\" size=\"sm\" onClick={handleBulkImport} disabled={bulkImporting || !bulkText.trim()}>\n {bulkImporting ? 'Importing…' : 'Import'}\n </Button>\n <span className=\"muted\" style={{ fontSize: 11 }}>\n Existing keys are skipped unless re-created individually. Invalid lines are reported.\n </span>\n </div>\n </div>\n )}\n\n {vars.length === 0 && !showAdd && (\n <div className=\"env-var-empty\">\n <KeyRound size={20} />\n <span>No BIZAR_* env vars yet.</span>\n <span style={{ fontSize: 11 }}>Create one to store API keys securely.</span>\n </div>\n )}\n\n {/* New var form */}\n {showAdd && (\n <div className=\"env-var-add-form\">\n <div className=\"env-var-add-row\">\n <input\n className=\"input mono\"\n style={{ width: 240 }}\n placeholder=\"BIZAR_NAME\"\n value={newName}\n onChange={(e) => setNewName(e.target.value.toUpperCase())}\n onKeyDown={(e) => { if (e.key === 'Enter') handleAdd(); if (e.key === 'Escape') setShowAdd(false); }}\n autoFocus\n />\n <input\n className=\"input mono\"\n type=\"password\"\n placeholder=\"value (API key, token, etc.)\"\n value={newValue}\n onChange={(e) => setNewValue(e.target.value)}\n onKeyDown={(e) => { if (e.key === 'Enter') handleAdd(); if (e.key === 'Escape') setShowAdd(false); }}\n />\n <Button variant=\"primary\" size=\"sm\" onClick={handleAdd} disabled={saving}>\n <CheckCircle size={12} /> Create\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => { setShowAdd(false); setNewName(''); setNewValue(''); }}>\n <X size={12} />\n </Button>\n </div>\n <p style={{ fontSize: 11, color: 'var(--text-dim)', margin: 0 }}>\n Names must match <code>BIZAR_<var>NAME</var></code> (uppercase letters, digits, underscores).\n </p>\n </div>\n )}\n\n {/* Var list — grouped by prefix */}\n {filtered.length > 0 && (\n groupMode ? (\n <div className=\"env-var-groups\">\n {sortedGroupKeys.map((prefix) => {\n const items = grouped[prefix];\n const isCollapsed = collapsed.has(prefix);\n return (\n <div key={prefix} className=\"env-var-group\">\n <button\n type=\"button\"\n className=\"env-var-group-header\"\n onClick={() => toggleGroup(prefix)}\n >\n {isCollapsed ? <ChevronRight size={12} /> : <ChevronDown size={12} />}\n <span className=\"env-var-group-prefix mono\">{prefix}</span>\n <span className=\"env-var-group-count muted\">({items.length})</span>\n </button>\n {!isCollapsed && (\n <div className=\"env-var-list\">\n {items.map((v) => (\n <VarRow key={v.name} v={v} editing={editing} editValue={editValue}\n isRevealed={revealed.has(v.name)}\n onToggleReveal={toggleReveal} onStartEdit={startEdit}\n onEditValueChange={setEditValue} onHandleUpdate={handleUpdate}\n onCancelEdit={() => setEditing(null)} onDelete={handleDelete}\n saving={saving} />\n ))}\n </div>\n )}\n </div>\n );\n })}\n </div>\n ) : (\n <div className=\"env-var-list\">\n {filtered.map((v) => (\n <VarRow key={v.name} v={v} editing={editing} editValue={editValue}\n isRevealed={revealed.has(v.name)}\n onToggleReveal={toggleReveal} onStartEdit={startEdit}\n onEditValueChange={setEditValue} onHandleUpdate={handleUpdate}\n onCancelEdit={() => setEditing(null)} onDelete={handleDelete}\n saving={saving} />\n ))}\n </div>\n )\n )}\n\n {filtered.length === 0 && vars.length > 0 && (\n <div className=\"env-var-empty\">\n <Search size={16} />\n <span>No env vars match \"{searchQ}\"</span>\n </div>\n )}\n </div>\n );\n}\n\n// ─── Individual var row (extracted for reuse in group mode) ───────────────────\ntype VarRowProps = {\n v: EnvVarEntry;\n editing: string | null;\n editValue: string;\n isRevealed: boolean;\n onToggleReveal: (name: string) => void;\n onStartEdit: (v: EnvVarEntry) => void;\n onEditValueChange: (v: string) => void;\n onHandleUpdate: (name: string) => void;\n onCancelEdit: () => void;\n onDelete: (name: string) => void;\n saving: boolean;\n};\n\nfunction VarRow({ v, editing, editValue, isRevealed, onToggleReveal, onStartEdit, onEditValueChange, onHandleUpdate, onCancelEdit, onDelete, saving }: VarRowProps) {\n const isEditing = editing === v.name;\n return (\n <div className={cn('env-var-row', isEditing && 'env-var-row-editing')}>\n <span className=\"env-var-name mono\">{v.name}</span>\n {isEditing ? (\n <input\n className=\"input mono\"\n type=\"password\"\n style={{ flex: 1, minWidth: 200 }}\n value={editValue}\n onChange={(e) => onEditValueChange(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') onHandleUpdate(v.name);\n if (e.key === 'Escape') onCancelEdit();\n }}\n autoFocus\n />\n ) : (\n <span className={cn('env-var-value mono', !isRevealed && 'env-var-value-masked')}>\n {v.value}\n </span>\n )}\n <span className=\"env-var-source muted\">{v.source}</span>\n <div className=\"env-var-actions\">\n {!isEditing && (\n <button type=\"button\" className=\"icon-btn\" title={isRevealed ? 'Hide' : 'Reveal'} onClick={() => onToggleReveal(v.name)}>\n {isRevealed ? <EyeOff size={12} /> : <Eye size={12} />}\n </button>\n )}\n {isEditing ? (\n <>\n <Button variant=\"primary\" size=\"sm\" onClick={() => onHandleUpdate(v.name)} disabled={saving}>Save</Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onCancelEdit}>Cancel</Button>\n </>\n ) : (\n <>\n <button type=\"button\" className=\"icon-btn\" title=\"Edit\" onClick={() => onStartEdit(v)}>\n <Pencil size={12} />\n </button>\n <button type=\"button\" className=\"icon-btn icon-btn-danger\" title=\"Delete\" onClick={() => onDelete(v.name)}>\n <Trash2 size={12} />\n </button>\n </>\n )}\n </div>\n </div>\n );\n}\n","// src/web/views/settings/EnvVarsSection.tsx\nimport React from 'react';\nimport { KeyRound } from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../../components/Card';\nimport { EnvVarManager } from '../../components/EnvVarManager';\n\nexport function EnvVarsSection() {\n return (\n <Card id=\"settings-env-vars\" data-section=\"env-vars\">\n <CardTitle><KeyRound size={14} /> Environment Variables</CardTitle>\n <CardMeta>Manage BIZAR_* env vars (API keys, secrets). Values are stored in <code>~/.config/bizar/env.json</code> (mode 0600).</CardMeta>\n <EnvVarManager />\n </Card>\n );\n}\n"],"file":"assets/EnvVarsSection-BUQnyVQD.js"}
1
+ {"version":3,"mappings":"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","names":["Button","forwardRef","variant","size","iconOnly","loading","disabled","className","children","rest","ref","jsxs","cn","Card","interactive","jsx","CardTitle","CardMeta","PACKAGES","UpdatesSection","toast","useToast","status","setStatus","useState","useEffect","ws","Ws","msg","s","m","existing","api","e","check","err","applyUpdate","restart","isBusy","Download","p","cur","lat","_a","isOutdated","pkgStatus","CheckCircle","AlertCircle","AlertTriangle","RefreshCw","useAutosave","initialValue","saveFn","delay","onSaved","onError","value","setValue","timeoutRef","useRef","pendingValueRef","lastSavedValue","hasPendingDebounceRef","save","useCallback","v","setValueAndSave","toSave","clearDebounce","flush","AutosaveField","render","handleBlur","React","Loader","Check","LAYOUTS","GeneralSection","settings","patchUi","patchTop","autoSave","Fragment","LayoutIcon","l","onChange","onBlur","TailscaleSettings","initialStatus","authKey","setAuthKey","setLoading","error","setError","r","loadStatus","handleAuthenticate","handleSetupServe","_b","_c","handleRemoveServe","isInstalled","isAuthenticated","isServeEnabled","serveUrl","Plug","LinkIcon","SystemLlmSection","Sparkles","BACKEND_OPTIONS","HeadroomSettingsCard","onPatch","stats","setStats","loadingStatus","setLoadingStatus","installing","setInstalling","wrapping","setWrapping","unwrapping","setUnwrapping","startingProxy","setStartingProxy","stoppingProxy","setStoppingProxy","st","handleInstall","handleWrap","handleUnwrap","handleStartProxy","handleStopProxy","handleOpenDashboard","spawn","__vitePreload","installed","version","proxyRunning","proxyPort","wrapped","ratio","saved","Activity","XCircle","Zap","Square","Play","ExternalLink","DEFAULT_HEADROOM_SETTINGS","HeadroomSection","setSettings","setDirty","patch","ActivityLogCard","items","setItems","hidden","setHidden","filter","setFilter","showHidden","setShowHidden","refresh","log","hid","keyOf","it","idx","k","h","i","onRestoreAll","onRestoreOne","key","next","filtered","q","Search","Eye","isHidden","AboutCard","about","Info","ActivitySection","EnvVarManager","vars","setVars","saving","setSaving","revealed","setRevealed","editing","setEditing","editValue","setEditValue","showAdd","setShowAdd","newName","setNewName","newValue","setNewValue","showBulk","setShowBulk","bulkText","setBulkText","bulkImporting","setBulkImporting","searchQ","setSearchQ","collapsed","setCollapsed","load","toggleReveal","name","prev","handleAdd","startEdit","handleUpdate","handleDelete","handleBulkImport","handleExport","blob","url","a","useMemo","grouped","groups","prefix","toggleGroup","sortedGroupKeys","known","b","ai","bi","groupMode","Plus","Upload","X","KeyRound","isCollapsed","ChevronRight","ChevronDown","VarRow","isRevealed","onToggleReveal","onStartEdit","onEditValueChange","onHandleUpdate","onCancelEdit","onDelete","isEditing","EyeOff","Pencil","Trash2","EnvVarsSection"],"ignoreList":[],"sources":["../../src/web/components/Button.tsx","../../src/web/components/Card.tsx","../../src/web/views/settings/UpdatesSection.tsx","../../src/web/hooks/useAutosave.ts","../../src/web/components/AutosaveField.tsx","../../src/web/views/settings/GeneralSection.tsx","../../src/web/components/TailscaleSettings.tsx","../../src/web/views/settings/SystemLlmSection.tsx","../../src/web/components/HeadroomSettings.tsx","../../src/web/views/settings/HeadroomSection.tsx","../../src/web/views/settings/ActivitySection.tsx","../../src/web/components/EnvVarManager.tsx","../../src/web/views/settings/EnvVarsSection.tsx"],"sourcesContent":["// src/components/Button.tsx — typed button with variants + sizes.\n\nimport { type ButtonHTMLAttributes, forwardRef } from 'react';\nimport { cn } from '../lib/utils';\n\nexport type ButtonVariant =\n | 'primary'\n | 'secondary'\n | 'ghost'\n | 'danger'\n | 'accent'\n | 'success';\nexport type ButtonSize = 'sm' | 'md' | 'lg';\n\nexport type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n variant?: ButtonVariant;\n size?: ButtonSize;\n iconOnly?: boolean;\n loading?: boolean;\n};\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n function Button(\n {\n variant = 'secondary',\n size = 'md',\n iconOnly = false,\n loading = false,\n disabled,\n className,\n children,\n ...rest\n },\n ref,\n ) {\n return (\n <button\n ref={ref}\n type={rest.type ?? 'button'}\n disabled={disabled || loading}\n className={cn(\n 'btn',\n `btn-${variant}`,\n `btn-size-${size}`,\n iconOnly && 'btn-icon',\n loading && 'btn-loading',\n className,\n )}\n {...rest}\n >\n {loading ? <span className=\"btn-spinner\" aria-hidden /> : null}\n {children}\n </button>\n );\n },\n);\n","// src/components/Card.tsx — wrapper card.\n\nimport type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../lib/utils';\n\nexport type CardProps = HTMLAttributes<HTMLDivElement> & {\n variant?: 'elevated' | 'outlined' | 'filled';\n interactive?: boolean;\n children?: ReactNode;\n};\n\nexport function Card({\n variant = 'elevated',\n interactive = false,\n className,\n children,\n ...rest\n}: CardProps) {\n return (\n <div\n className={cn(\n 'card',\n `card-${variant}`,\n interactive && 'card-interactive',\n className,\n )}\n {...rest}\n >\n {children}\n </div>\n );\n}\n\nexport function CardTitle({ children, className }: { children: ReactNode; className?: string }) {\n return <h3 className={cn('card-title', className)}>{children}</h3>;\n}\n\nexport function CardMeta({ children, className }: { children: ReactNode; className?: string }) {\n return <div className={cn('card-meta', className)}>{children}</div>;\n}\n","// src/web/views/settings/UpdatesSection.tsx\nimport React, { useEffect, useState } from 'react';\nimport { Download, RefreshCw, CheckCircle, AlertCircle, AlertTriangle } from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../../components/Card';\nimport { Button } from '../../components/Button';\nimport { useToast } from '../../components/Toast';\nimport { api } from '../../lib/api';\nimport { Ws } from '../../lib/ws';\n\ntype PkgStatus = {\n status: 'idle' | 'starting' | 'installing' | 'done' | 'error';\n error?: string;\n newVersion?: string;\n logs: string[];\n};\n\ntype StatusState = {\n current: Record<string, string | null>;\n latest: Record<string, string | null> | null;\n checking: boolean;\n updating: boolean;\n hasUpdates: boolean;\n requiresRestart: boolean;\n perPackage: Record<string, PkgStatus>;\n error?: string;\n};\n\nconst PACKAGES = [\n { id: 'bizar', name: 'Bizar CLI' },\n { id: 'bizar-dash', name: 'Dashboard' },\n { id: 'bizar-plugin', name: 'Opencode Plugin' },\n];\n\nexport function UpdatesSection() {\n const toast = useToast();\n const [status, setStatus] = useState<StatusState>({\n current: {},\n latest: null,\n checking: false,\n updating: false,\n hasUpdates: false,\n requiresRestart: false,\n perPackage: {},\n });\n\n // WebSocket subscription for live update progress\n useEffect(() => {\n const ws = new Ws();\n ws.on((msg: Record<string, unknown>) => {\n if (msg.type === 'update:progress' || msg.type === 'update:log' || msg.type === 'update:complete') {\n setStatus((s) => {\n if (msg.type === 'update:complete') {\n return {\n ...s,\n updating: false,\n requiresRestart: Boolean((msg as { requiresRestart?: boolean }).requiresRestart),\n };\n }\n if (msg.type === 'update:log') {\n const m = msg as { pkg: string; line: string };\n const existing = s.perPackage[m.pkg] || { logs: [] };\n return {\n ...s,\n perPackage: {\n ...s.perPackage,\n [m.pkg]: {\n ...existing,\n logs: [...(existing.logs || []).slice(-50), m.line],\n },\n },\n };\n }\n // update:progress\n const m = msg as { pkg: string; status: PkgStatus['status']; error?: string; newVersion?: string };\n return {\n ...s,\n perPackage: {\n ...s.perPackage,\n [m.pkg]: {\n ...s.perPackage[m.pkg],\n status: m.status,\n error: m.error,\n newVersion: m.newVersion,\n },\n },\n };\n });\n }\n });\n return () => ws.close();\n }, []);\n\n // Load current versions on mount\n useEffect(() => {\n api.get<{ current: Record<string, string | null> }>('/updates/status')\n .then((r) => setStatus((s) => ({ ...s, current: r.current })))\n .catch((e) => setStatus((s) => ({ ...s, error: e.message })));\n }, []);\n\n const check = async () => {\n setStatus((s) => ({ ...s, checking: true, error: undefined }));\n try {\n const r = await api.get<{\n current: Record<string, string | null>;\n latest: Record<string, string | null>;\n hasUpdates: boolean;\n }>('/updates/check');\n setStatus((s) => ({\n ...s,\n checking: false,\n current: r.current,\n latest: r.latest,\n hasUpdates: r.hasUpdates,\n }));\n } catch (err) {\n setStatus((s) => ({ ...s, checking: false, error: (err as Error).message }));\n }\n };\n\n const applyUpdate = async () => {\n if (!confirm('Update Bizar packages? The dashboard will restart automatically.')) return;\n setStatus((s) => ({\n ...s,\n updating: true,\n requiresRestart: false,\n perPackage: {},\n error: undefined,\n }));\n try {\n await api.post('/updates/apply', { packages: ['bizar', 'bizar-dash', 'bizar-plugin'] });\n } catch (err) {\n setStatus((s) => ({ ...s, updating: false, error: (err as Error).message }));\n }\n };\n\n const restart = async () => {\n if (!confirm('Restart the dashboard? You will be disconnected briefly.')) return;\n try {\n await api.post('/restart');\n toast.info('Restarting…', 3000);\n setTimeout(() => window.location.reload(), 3000);\n } catch {\n toast.error('Restart failed');\n }\n };\n\n const isBusy = status.checking || status.updating;\n\n return (\n <Card id=\"settings-updates\" data-section=\"updates\">\n <CardTitle><Download size={14} /> Updates</CardTitle>\n <CardMeta>Check installed Bizar packages and apply dashboard updates.</CardMeta>\n\n {/* Current versions */}\n <div className=\"updates-current\">\n <h4>Installed versions</h4>\n <ul>\n {PACKAGES.map((p) => (\n <li key={p.id}>\n <span>{p.name}</span>\n <code className=\"mono\">{status.current[p.id] || '—'}</code>\n </li>\n ))}\n </ul>\n </div>\n\n {/* Latest + per-package status */}\n {status.latest && (\n <div className=\"updates-latest\">\n <h4>Latest available</h4>\n <ul>\n {PACKAGES.map((p) => {\n const cur = status.current[p.id];\n const lat = status.latest?.[p.id];\n const isOutdated = cur && lat && cur !== lat;\n return (\n <li key={p.id} className={isOutdated ? 'updates-outdated' : 'updates-current-version'}>\n <span>{p.name}</span>\n <code className=\"mono\">\n {lat || '—'}\n {isOutdated && <span className=\"updates-badge\">update available</span>}\n </code>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n\n {/* Per-package progress rows */}\n {status.updating && (\n <div className=\"updates-progress-rows\">\n {PACKAGES.map((p) => {\n const pkgStatus = status.perPackage[p.id] || { status: 'idle', logs: [] as string[] };\n return (\n <div key={p.id} className=\"updates-pkg-row\">\n <div className=\"updates-pkg-row-header\">\n <span className=\"updates-pkg-name\">{p.name}</span>\n <div className=\"updates-pkg-status\">\n {pkgStatus.status === 'starting' && <span className=\"btn-spinner\" />}\n {pkgStatus.status === 'installing' && <span className=\"btn-spinner\" />}\n {pkgStatus.status === 'done' && <CheckCircle size={14} className=\"icon-success\" />}\n {pkgStatus.status === 'error' && <AlertCircle size={14} className=\"icon-error\" />}\n <span>{pkgStatus.status}</span>\n {pkgStatus.newVersion && (\n <code className=\"mono\" style={{ fontSize: 11 }}>→ {pkgStatus.newVersion}</code>\n )}\n </div>\n </div>\n {pkgStatus.logs.length > 0 && (\n <details className=\"updates-pkg-logs\">\n <summary>npm output ({pkgStatus.logs.length} lines)</summary>\n <pre>{pkgStatus.logs.join('\\n')}</pre>\n </details>\n )}\n {pkgStatus.status === 'error' && pkgStatus.error && (\n <div className=\"updates-pkg-error\">\n <AlertTriangle size={12} /> {pkgStatus.error}\n </div>\n )}\n </div>\n );\n })}\n </div>\n )}\n\n {/* Actions */}\n <div className=\"updates-actions\">\n <Button onClick={check} disabled={isBusy}>\n {status.checking ? <span className=\"btn-spinner\" /> : <RefreshCw size={14} />}\n Check for updates\n </Button>\n <Button\n variant=\"primary\"\n onClick={applyUpdate}\n disabled={!status.hasUpdates || status.updating}\n >\n {status.updating ? <span className=\"btn-spinner\" /> : <Download size={14} />}\n {status.updating ? 'Updating…' : (status.hasUpdates ? 'Update now' : 'Up to date')}\n </Button>\n {status.requiresRestart && (\n <Button variant=\"danger\" onClick={restart}>\n <RefreshCw size={14} /> Restart Dashboard\n </Button>\n )}\n </div>\n\n {status.error && (\n <div className=\"updates-error\">\n <AlertTriangle size={14} />\n <span>{status.error}</span>\n </div>\n )}\n </Card>\n );\n}\n","// src/web/hooks/useAutosave.ts\n// Debounced autosave hook for settings fields.\n\nimport { useState, useEffect, useRef, useCallback } from 'react';\n\nexport type AutosaveStatus = 'idle' | 'saving' | 'saved' | 'error';\n\nexport function useAutosave<T>(\n initialValue: T,\n saveFn: (value: T) => Promise<void>,\n {\n delay = 800,\n onSaved,\n onError,\n }: { delay?: number; onSaved?: () => void; onError?: (e: Error) => void } = {},\n) {\n const [value, setValue] = useState<T>(initialValue);\n const [status, setStatus] = useState<AutosaveStatus>('idle');\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingValueRef = useRef<T | null>(null);\n const lastSavedValue = useRef<T>(initialValue);\n // Tracks whether a debounce timeout is currently pending (set when timeout is scheduled, cleared when it fires)\n const hasPendingDebounceRef = useRef(false);\n\n const save = useCallback(\n async (v: T) => {\n setStatus('saving');\n try {\n await saveFn(v);\n lastSavedValue.current = v;\n pendingValueRef.current = null;\n setStatus('saved');\n onSaved?.();\n setTimeout(() => setStatus('idle'), 2000);\n } catch (err) {\n setStatus('error');\n onError?.(err as Error);\n }\n },\n [saveFn, onSaved, onError],\n );\n\n const setValueAndSave = useCallback(\n (v: T) => {\n setValue(v);\n pendingValueRef.current = v;\n hasPendingDebounceRef.current = true;\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n timeoutRef.current = setTimeout(() => {\n timeoutRef.current = null;\n hasPendingDebounceRef.current = false;\n const toSave = pendingValueRef.current;\n pendingValueRef.current = null;\n if (toSave !== null) save(toSave);\n }, delay);\n },\n [delay, save],\n );\n\n /**\n * Clear any pending debounce without saving.\n * Use this when you want the debounce to handle the save naturally.\n */\n const clearDebounce = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n hasPendingDebounceRef.current = false;\n }\n }, []);\n\n /**\n * Flush any pending save immediately (called on unmount or explicit flush).\n */\n const flush = useCallback(async () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n hasPendingDebounceRef.current = false;\n const toSave = pendingValueRef.current;\n pendingValueRef.current = null;\n if (toSave !== null) await save(toSave);\n }\n }, [save]);\n\n // Cleanup on unmount: fire pending save immediately\n useEffect(() => {\n return () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n const toSave = pendingValueRef.current;\n pendingValueRef.current = null;\n // Fire-and-forget: call saveFn directly to persist without awaiting\n if (toSave !== null) {\n setStatus('saving');\n saveFn(toSave)\n .then(() => { lastSavedValue.current = toSave; setStatus('saved'); onSaved?.(); })\n .catch((err: Error) => { setStatus('error'); onError?.(err); })\n .finally(() => { setTimeout(() => setStatus('idle'), 2000); });\n }\n }\n };\n }, [saveFn, onSaved, onError]);\n\n return { value, setValue: setValueAndSave, status, save, flush, clearDebounce, hasPendingDebounceRef, pendingValueRef };\n}\n","// src/web/components/AutosaveField.tsx\n// Generic auto-saving field wrapper with inline save status animation.\n\nimport React from 'react';\nimport { Check, Loader, AlertCircle } from 'lucide-react';\nimport { useAutosave } from '../hooks/useAutosave';\n\nexport type { AutosaveStatus } from '../hooks/useAutosave';\n\nexport function AutosaveField<T = string>({\n initialValue,\n saveFn,\n delay = 800,\n render,\n className,\n}: {\n initialValue: T;\n saveFn: (value: T) => Promise<void>;\n delay?: number;\n render: (props: {\n value: T;\n onChange: (v: T) => void;\n onBlur: () => void;\n }) => React.ReactNode;\n className?: string;\n}) {\n const { value, setValue, status, save, clearDebounce, hasPendingDebounceRef, pendingValueRef } = useAutosave(initialValue, saveFn, { delay });\n\n const handleBlur = React.useCallback(() => {\n // If a debounce is pending (user was actively typing), clear the timeout\n // and save immediately — the user is done typing.\n if (hasPendingDebounceRef.current) {\n clearDebounce();\n // pendingValueRef.current holds the typed value not yet saved by debounce\n if (pendingValueRef.current !== null) save(pendingValueRef.current);\n }\n // If no debounce is pending: do nothing (value was already saved or unchanged).\n }, [clearDebounce, hasPendingDebounceRef, save, pendingValueRef]);\n\n return (\n <div className={`autosave-field ${className || ''} ${status}`}>\n {render({ value, onChange: setValue, onBlur: handleBlur })}\n <span className=\"autosave-status\" role=\"status\" aria-live=\"polite\">\n {status === 'saving' && <Loader className=\"spinning\" size={12} />}\n {status === 'saved' && <Check size={12} />}\n {status === 'error' && <AlertCircle size={12} />}\n </span>\n </div>\n );\n}\n","// src/web/views/settings/GeneralSection.tsx\nimport React from 'react';\nimport { Layout as LayoutIcon } from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../../components/Card';\nimport { AutosaveField } from '../../components/AutosaveField';\nimport { cn } from '../../lib/utils';\nimport type { Settings } from '../../lib/types';\n\ntype Props = {\n settings: Settings;\n patchUi: (patch: Partial<Settings['ui']>) => void;\n patchTop: <K extends keyof Settings>(key: K, value: Settings[K]) => void;\n /** Called by AutosaveField after state is patched; the parent debounces the API save */\n autoSave?: (key: keyof Settings, value: Settings[keyof Settings]) => void;\n};\n\nconst LAYOUTS = [\n { id: 'topnav', label: 'Top nav' },\n { id: 'sidebar', label: 'Sidebar' },\n { id: 'both', label: 'Both' },\n] as const;\n\nexport function GeneralSection({ settings, patchUi, patchTop, autoSave }: Props) {\n return (\n <>\n {/* UI Layout */}\n <Card id=\"settings-layout\" data-section=\"layout\">\n <CardTitle><LayoutIcon size={14} /> UI layout</CardTitle>\n <CardMeta>Choose how the dashboard's navigation is presented.</CardMeta>\n <div className=\"layout-row\" data-setting-id=\"ui.layout\">\n {LAYOUTS.map((l) => (\n <button\n key={l.id}\n type=\"button\"\n className={cn('layout-card', settings.ui.layout === l.id && 'layout-card-active')}\n onClick={() => patchUi({ layout: l.id })}\n >\n <span className=\"layout-card-label\">{l.label}</span>\n </button>\n ))}\n </div>\n <label className=\"checkbox-row\" data-setting-id=\"ui.showHeader\">\n <input\n type=\"checkbox\"\n checked={settings.ui.showHeader}\n onChange={(e) => patchUi({ showHeader: e.target.checked })}\n />\n <span>Show header</span>\n </label>\n <label className=\"checkbox-row\" data-setting-id=\"ui.showStatusBar\">\n <input\n type=\"checkbox\"\n checked={settings.ui.showStatusBar}\n onChange={(e) => patchUi({ showStatusBar: e.target.checked })}\n />\n <span>Show status bar</span>\n </label>\n <div className=\"field\" data-setting-id=\"ui.defaultTab\">\n <label className=\"field-label\">Default tab</label>\n <select\n className=\"select\"\n value={settings.ui.defaultTab}\n onChange={(e) => patchUi({ defaultTab: e.target.value })}\n >\n <option value=\"overview\">Overview</option>\n <option value=\"chat\">Chat</option>\n <option value=\"agents\">Agents</option>\n <option value=\"artifacts\">Plans</option>\n <option value=\"projects\">Projects</option>\n <option value=\"tasks\">Tasks</option>\n <option value=\"config\">Config</option>\n <option value=\"settings\">Settings</option>\n <option value=\"mods\">Mods</option>\n <option value=\"schedules\">Schedules</option>\n </select>\n </div>\n </Card>\n\n {/* General */}\n <Card id=\"settings-general\" data-section=\"general\">\n <CardTitle>General</CardTitle>\n <CardMeta>Default agent + model override.</CardMeta>\n <div className=\"field\" data-setting-id=\"defaultAgent\">\n <label className=\"field-label\" htmlFor=\"set-default-agent\">Default agent</label>\n <AutosaveField\n initialValue={settings.defaultAgent || ''}\n saveFn={async (v) => {\n patchTop('defaultAgent', v);\n autoSave?.('defaultAgent', v);\n }}\n render={({ value, onChange, onBlur }) => (\n <input\n id=\"set-default-agent\"\n className=\"input\"\n type=\"text\"\n placeholder=\"e.g. odin\"\n value={value}\n onChange={e => onChange(e.target.value)}\n onBlur={onBlur}\n />\n )}\n />\n </div>\n <div className=\"field\" data-setting-id=\"defaultModel\">\n <label className=\"field-label\" htmlFor=\"set-default-model\">Model override</label>\n <AutosaveField\n initialValue={settings.defaultModel || ''}\n saveFn={async (v) => {\n patchTop('defaultModel', v);\n autoSave?.('defaultModel', v);\n }}\n render={({ value, onChange, onBlur }) => (\n <input\n id=\"set-default-model\"\n className=\"input\"\n type=\"text\"\n placeholder=\"(leave empty for provider default)\"\n value={value}\n onChange={e => onChange(e.target.value)}\n onBlur={onBlur}\n />\n )}\n />\n </div>\n </Card>\n </>\n );\n}\n","// src/web/components/TailscaleSettings.tsx\n//\n// v5.2 — Tailscale auth key integration UI.\n//\n// Allows users to authenticate with Tailscale using an auth key and\n// set up tailscale serve for the dashboard without using the CLI.\nimport React, { useEffect, useState } from 'react';\nimport { CheckCircle, Link as LinkIcon, Plug } from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from './Card';\nimport { Button } from './Button';\nimport { api } from '../lib/api';\nimport type { TailscaleStatus } from '../lib/types';\n\ntype Props = {\n /** Existing tailscale status from Settings-level fetch. If provided, used as initial value. */\n initialStatus?: TailscaleStatus | null;\n};\n\nexport function TailscaleSettings({ initialStatus }: Props) {\n const [status, setStatus] = useState<TailscaleStatus | null>(initialStatus ?? null);\n const [authKey, setAuthKey] = useState('');\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (status === null) {\n api.get<TailscaleStatus>('/tailscale/status')\n .then((r) => setStatus(r))\n .catch(() => setStatus(null));\n }\n }, []);\n\n const loadStatus = async () => {\n try {\n const r = await api.get<TailscaleStatus>('/tailscale/status');\n setStatus(r);\n } catch {\n setError('Failed to load Tailscale status');\n }\n };\n\n const handleAuthenticate = async () => {\n if (!authKey.trim()) return;\n setLoading(true);\n setError(null);\n try {\n await api.post('/tailscale/setup', { authKey: authKey.trim() });\n await loadStatus();\n setAuthKey('');\n } catch (err) {\n setError((err as Error).message || 'Authentication failed');\n } finally {\n setLoading(false);\n }\n };\n\n const handleSetupServe = async () => {\n if (!status) return;\n setLoading(true);\n setError(null);\n try {\n await api.post('/tailscale/setup', {\n port: status.settings?.port || 4321,\n https: status.settings?.https !== false,\n hostname: status.settings?.hostname || '',\n });\n await loadStatus();\n } catch (err) {\n setError((err as Error).message || 'Setup failed');\n } finally {\n setLoading(false);\n }\n };\n\n const handleRemoveServe = async () => {\n setLoading(true);\n setError(null);\n try {\n await api.post('/tailscale/unserve');\n await loadStatus();\n } catch (err) {\n setError((err as Error).message || 'Remove failed');\n } finally {\n setLoading(false);\n }\n };\n\n const isInstalled = status?.installed ?? false;\n const isAuthenticated = status?.authenticated ?? false;\n const isServeEnabled = status?.settings?.enabled ?? false;\n const serveUrl = isServeEnabled ? `https://${status?.hostname || 'bizar-dash'}` : null;\n\n if (!isInstalled) {\n return (\n <Card id=\"settings-tailscale-auth\" data-section=\"tailscale\">\n <CardTitle><Plug size={14} /> Tailscale Integration</CardTitle>\n <CardMeta>Tailscale is not installed on this machine.</CardMeta>\n <p className=\"muted\">\n Install from{' '}\n <a href=\"https://tailscale.com/download\" target=\"_blank\" rel=\"noreferrer\">\n tailscale.com/download\n </a>\n </p>\n </Card>\n );\n }\n\n return (\n <Card id=\"settings-tailscale-auth\" data-section=\"tailscale\">\n <CardTitle><Plug size={14} /> Tailscale Integration</CardTitle>\n <CardMeta>Expose the dashboard over your Tailscale network using an auth key.</CardMeta>\n\n {error && (\n <p style={{ color: 'var(--color-error, #f85149)', fontSize: '0.85rem' }}>{error}</p>\n )}\n\n {isAuthenticated ? (\n <>\n <div className=\"status-row\" style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', marginBottom: '0.75rem' }}>\n <CheckCircle size={16} style={{ color: 'var(--color-success, #3fb950)' }} />\n <span>Authenticated as <strong>{status?.hostname || 'unknown'}</strong></span>\n </div>\n\n {isServeEnabled && serveUrl ? (\n <>\n <div className=\"status-row\" style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', marginBottom: '0.75rem' }}>\n <LinkIcon size={16} />\n <a href={serveUrl} target=\"_blank\" rel=\"noreferrer\">{serveUrl}</a>\n </div>\n <Button variant=\"secondary\" size=\"sm\" onClick={handleRemoveServe} disabled={loading}>\n Remove serve\n </Button>\n </>\n ) : (\n <Button variant=\"primary\" size=\"sm\" onClick={handleSetupServe} disabled={loading}>\n Set up Tailscale serve\n </Button>\n )}\n </>\n ) : (\n <>\n <p className=\"muted\" style={{ marginBottom: '0.75rem' }}>Not authenticated with Tailscale.</p>\n <div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap' }}>\n <input\n type=\"text\"\n className=\"input\"\n placeholder=\"tskey-...\"\n value={authKey}\n onChange={(e) => setAuthKey(e.target.value)}\n style={{ flex: 1, minWidth: '200px' }}\n disabled={loading}\n />\n <Button variant=\"primary\" size=\"sm\" onClick={handleAuthenticate} disabled={loading || !authKey.trim()}>\n Authenticate\n </Button>\n </div>\n </>\n )}\n </Card>\n );\n}\n","// src/web/views/settings/SystemLlmSection.tsx\nimport React from 'react';\nimport { Sparkles } from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../../components/Card';\nimport type { Settings } from '../../lib/types';\n\ntype Props = {\n settings: Settings;\n patchTop: <K extends keyof Settings>(key: K, value: Settings[K]) => void;\n};\n\nexport function SystemLlmSection({ settings, patchTop }: Props) {\n return (\n <Card id=\"settings-system-llm\" data-section=\"system-llm\">\n <CardTitle><Sparkles size={14} /> System LLM API</CardTitle>\n <CardMeta>\n Configures the LLM used for automatic title generation, prompt enhancement,\n summarization, and other system-level calls.\n </CardMeta>\n\n <label className=\"checkbox-row\" data-setting-id=\"systemLlm.enabled\">\n <input\n type=\"checkbox\"\n checked={!!settings.systemLlm?.enabled}\n onChange={(e) => {\n const cur = settings.systemLlm || { enabled: true, provider: 'opencode', model: 'opencode/deepseek-v4-flash-free' };\n patchTop('systemLlm', { ...cur, enabled: e.target.checked });\n }}\n />\n <span>Enable system LLM calls</span>\n </label>\n\n <div className=\"field\" data-setting-id=\"systemLlm.provider\" style={{ marginTop: 'var(--space-3)' }}>\n <label className=\"field-label\" htmlFor=\"set-system-llm-provider\">Provider</label>\n <select\n id=\"set-system-llm-provider\"\n className=\"select\"\n value={settings.systemLlm?.provider || 'opencode'}\n onChange={(e) => {\n const cur = settings.systemLlm || { enabled: true, provider: 'opencode', model: 'opencode/deepseek-v4-flash-free' };\n patchTop('systemLlm', { ...cur, provider: e.target.value });\n }}\n >\n <option value=\"opencode\">Opencode</option>\n <option value=\"openrouter\">OpenRouter</option>\n <option value=\"minimax\">MiniMax</option>\n </select>\n </div>\n\n <div className=\"field\" data-setting-id=\"systemLlm.model\">\n <label className=\"field-label\" htmlFor=\"set-system-llm-model\">Model</label>\n <input\n id=\"set-system-llm-model\"\n className=\"input mono\"\n type=\"text\"\n placeholder=\"opencode/deepseek-v4-flash-free\"\n value={settings.systemLlm?.model || 'opencode/deepseek-v4-flash-free'}\n onChange={(e) => {\n const cur = settings.systemLlm || { enabled: true, provider: 'opencode', model: 'opencode/deepseek-v4-flash-free' };\n patchTop('systemLlm', { ...cur, model: e.target.value });\n }}\n />\n <p className=\"field-help\">\n The API key is read from <code>auth.json</code> for the selected provider.\n Leave the default model for best results.\n </p>\n </div>\n\n <div style={{ marginTop: 'var(--space-4)' }}>\n <h4 style={{ margin: '0 0 var(--space-2)' }}>Features using this API</h4>\n <ul className=\"settings-feature-list\" style={{ margin: 0, paddingLeft: 'var(--space-4)', lineHeight: 1.8 }}>\n <li>Auto-title generation for new chat sessions</li>\n <li>Auto-title generation for new tasks</li>\n <li>&quot;Enhance prompt&quot; button in the task input</li>\n <li>&quot;Enhance prompt&quot; button in the chat composer</li>\n <li className=\"muted\" style={{ fontSize: 12 }}>Future: summarization, name generation, and more</li>\n </ul>\n </div>\n </Card>\n );\n}\n","// src/web/components/HeadroomSettings.tsx\n//\n// v1.0.0 — Headroom settings card for the Settings view.\n// Displays live status and provides controls for install, wrap, proxy, and configuration.\nimport React, { useEffect, useState, useCallback } from 'react';\nimport {\n Activity,\n CheckCircle,\n XCircle,\n Download,\n Play,\n Square,\n RefreshCw,\n ExternalLink,\n Zap,\n} from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { useToast } from '../components/Toast';\nimport { api } from '../lib/api';\nimport { type HeadroomSettings } from '../lib/types';\n\ntype HeadroomStatus = {\n installed: boolean;\n version: string | null;\n proxyRunning: boolean;\n proxyPort: number | null;\n proxyPid: number | null;\n wrapped: boolean;\n healthy: 'ok' | 'warn' | 'fail';\n messages: string[];\n};\n\ntype HeadroomStats = {\n tokensSaved?: number;\n compressionRatio?: number;\n cacheHits?: number;\n transforms?: number;\n error?: string;\n};\n\nconst BACKEND_OPTIONS = [\n { value: 'anthropic', label: 'Anthropic' },\n { value: 'anyllm', label: 'AnyLLM' },\n { value: 'litellm-anthropic', label: 'LiteLLM (Anthropic)' },\n { value: 'litellm-openai', label: 'LiteLLM (OpenAI)' },\n];\n\ntype Props = {\n settings: HeadroomSettings;\n onPatch: (patch: Partial<HeadroomSettings>) => void;\n};\n\nexport function HeadroomSettingsCard({ settings, onPatch }: Props) {\n const toast = useToast();\n const [status, setStatus] = useState<HeadroomStatus | null>(null);\n const [stats, setStats] = useState<HeadroomStats | null>(null);\n const [loadingStatus, setLoadingStatus] = useState(false);\n const [installing, setInstalling] = useState(false);\n const [wrapping, setWrapping] = useState(false);\n const [unwrapping, setUnwrapping] = useState(false);\n const [startingProxy, setStartingProxy] = useState(false);\n const [stoppingProxy, setStoppingProxy] = useState(false);\n\n const loadStatus = useCallback(async () => {\n setLoadingStatus(true);\n try {\n const [s, st] = await Promise.all([\n api.get<HeadroomStatus>('/headroom/status'),\n api.get<HeadroomStats>('/headroom/stats?hours=24').catch(() => ({ error: 'no stats' })),\n ]);\n setStatus(s);\n if (!st.error) setStats(st);\n } catch (err) {\n toast.error(`Failed to load Headroom status: ${(err as Error).message}`);\n } finally {\n setLoadingStatus(false);\n }\n }, [toast]);\n\n useEffect(() => {\n loadStatus();\n }, [loadStatus]);\n\n const handleInstall = async () => {\n setInstalling(true);\n try {\n const r = await api.post<{ ok: boolean; installed: boolean; method: string }>('/headroom/install', { force: true });\n if (r.installed) {\n toast.success(`Headroom installed via ${r.method}.`);\n await loadStatus();\n } else {\n toast.error('Headroom install failed. Try: pip install \"headroom-ai[all]\"');\n }\n } catch (err) {\n toast.error(`Install failed: ${(err as Error).message}`);\n } finally {\n setInstalling(false);\n }\n };\n\n const handleWrap = async () => {\n setWrapping(true);\n try {\n const r = await api.post<{ ok: boolean }>('/headroom/wrap', { port: settings.port });\n if (r.ok) {\n toast.success('opencode wrapped with Headroom.');\n await loadStatus();\n } else {\n toast.error('Wrap failed.');\n }\n } catch (err) {\n toast.error(`Wrap failed: ${(err as Error).message}`);\n } finally {\n setWrapping(false);\n }\n };\n\n const handleUnwrap = async () => {\n setUnwrapping(true);\n try {\n const r = await api.post<{ ok: boolean }>('/headroom/unwrap');\n if (r.ok) {\n toast.success('opencode unwrapped from Headroom.');\n await loadStatus();\n } else {\n toast.error('Unwrap failed.');\n }\n } catch (err) {\n toast.error(`Unwrap failed: ${(err as Error).message}`);\n } finally {\n setUnwrapping(false);\n }\n };\n\n const handleStartProxy = async () => {\n setStartingProxy(true);\n try {\n const r = await api.post<{ ok: boolean }>('/headroom/proxy/start', {\n port: settings.port,\n host: settings.host,\n });\n if (r.ok) {\n toast.success(`Headroom proxy started on ${settings.host}:${settings.port}.`);\n await loadStatus();\n } else {\n toast.error('Proxy start failed.');\n }\n } catch (err) {\n toast.error(`Proxy start failed: ${(err as Error).message}`);\n } finally {\n setStartingProxy(false);\n }\n };\n\n const handleStopProxy = async () => {\n setStoppingProxy(true);\n try {\n const r = await api.post<{ ok: boolean }>('/headroom/proxy/stop');\n if (r.ok) {\n toast.success('Headroom proxy stopped.');\n await loadStatus();\n } else {\n toast.error('Proxy stop failed.');\n }\n } catch (err) {\n toast.error(`Proxy stop failed: ${(err as Error).message}`);\n } finally {\n setStoppingProxy(false);\n }\n };\n\n const handleOpenDashboard = async () => {\n try {\n const { spawn } = await import('node:child_process');\n spawn('headroom', ['dashboard'], { detached: true, stdio: 'ignore' });\n } catch {\n toast.error('Could not open Headroom dashboard. Run `headroom dashboard` manually.');\n }\n };\n\n const { installed, version, proxyRunning, proxyPort, wrapped } = status || {};\n const ratio = stats?.compressionRatio ?? 0;\n const saved = stats?.tokensSaved ?? 0;\n\n return (\n <div id=\"settings-headroom\" data-section=\"headroom\">\n <Card>\n <CardTitle>\n <Activity size={14} style={{ color: proxyRunning ? 'var(--success)' : 'var(--text-dim)' }} />\n Headroom\n {installed && version && (\n <span style={{ fontSize: 11, color: 'var(--text-dim)', marginLeft: 6 }}>\n v{version} {proxyRunning ? '✓' : '✗'}\n </span>\n )}\n {!installed && (\n <span style={{ fontSize: 11, color: 'var(--error)', marginLeft: 6 }}>not installed</span>\n )}\n </CardTitle>\n <CardMeta>\n Context compression for token efficiency. Compresses tool outputs, logs, and conversation\n history by 60–95% before they reach the model.\n </CardMeta>\n\n {/* Live status row */}\n <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap', marginTop: 12, marginBottom: 12 }}>\n <div className=\"headroom-status-item\">\n {installed ? (\n <CheckCircle size={12} style={{ color: 'var(--success)' }} />\n ) : (\n <XCircle size={12} style={{ color: 'var(--error)' }} />\n )}\n <span>{installed ? 'Installed' : 'Not installed'}</span>\n </div>\n <div className=\"headroom-status-item\">\n {proxyRunning ? (\n <CheckCircle size={12} style={{ color: 'var(--success)' }} />\n ) : (\n <XCircle size={12} style={{ color: 'var(--text-dim)' }} />\n )}\n <span>Proxy {proxyRunning ? `${proxyPort} ✓` : 'stopped'}</span>\n </div>\n <div className=\"headroom-status-item\">\n {wrapped ? (\n <CheckCircle size={12} style={{ color: 'var(--success)' }} />\n ) : (\n <XCircle size={12} style={{ color: 'var(--text-dim)' }} />\n )}\n <span>opencode {wrapped ? 'wrapped' : 'not wrapped'}</span>\n </div>\n </div>\n\n {/* Stats */}\n {(saved > 0 || ratio > 0) && (\n <div style={{ display: 'flex', gap: 24, marginBottom: 12 }}>\n <div>\n <div style={{ fontSize: 20, fontWeight: 700, color: 'var(--success)' }}>\n {ratio > 0 ? `${Math.round(ratio * 100)}%` : '—'}\n </div>\n <div className=\"muted\" style={{ fontSize: 11 }}>Compression ratio</div>\n </div>\n <div>\n <div style={{ fontSize: 20, fontWeight: 700, color: 'var(--accent)' }}>\n {saved > 0 ? saved.toLocaleString() : '—'}\n </div>\n <div className=\"muted\" style={{ fontSize: 11 }}>Tokens saved (24h)</div>\n </div>\n </div>\n )}\n\n {/* Action buttons */}\n <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginBottom: 8 }}>\n {!installed ? (\n <Button variant=\"primary\" size=\"sm\" onClick={handleInstall} disabled={installing}>\n {installing ? <span className=\"btn-spinner\" /> : <Download size={13} />}\n {installing ? 'Installing…' : 'Install Headroom'}\n </Button>\n ) : (\n <>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={handleWrap}\n disabled={wrapping || wrapped}\n title={wrapped ? 'opencode is already wrapped' : 'Wrap opencode to route through Headroom proxy'}\n >\n {wrapping ? <span className=\"btn-spinner\" /> : <Zap size={13} />}\n {wrapping ? 'Wrapping…' : wrapped ? 'Wrapped ✓' : 'Wrap opencode'}\n </Button>\n {wrapped && (\n <Button variant=\"ghost\" size=\"sm\" onClick={handleUnwrap} disabled={unwrapping}>\n {unwrapping ? <span className=\"btn-spinner\" /> : <RefreshCw size={13} />}\n {unwrapping ? 'Unwrapping…' : 'Unwrap'}\n </Button>\n )}\n </>\n )}\n\n {installed && (\n <>\n {proxyRunning ? (\n <Button variant=\"secondary\" size=\"sm\" onClick={handleStopProxy} disabled={stoppingProxy}>\n {stoppingProxy ? <span className=\"btn-spinner\" /> : <Square size={13} />}\n {stoppingProxy ? 'Stopping…' : 'Stop proxy'}\n </Button>\n ) : (\n <Button variant=\"secondary\" size=\"sm\" onClick={handleStartProxy} disabled={startingProxy}>\n {startingProxy ? <span className=\"btn-spinner\" /> : <Play size={13} />}\n {startingProxy ? 'Starting…' : 'Start proxy'}\n </Button>\n )}\n <Button variant=\"ghost\" size=\"sm\" onClick={handleOpenDashboard}>\n <ExternalLink size={13} />\n Dashboard\n </Button>\n </>\n )}\n\n <Button variant=\"ghost\" size=\"sm\" onClick={loadStatus} disabled={loadingStatus}>\n <RefreshCw size={13} className={loadingStatus ? 'spin' : ''} />\n </Button>\n </div>\n\n {/* Settings */}\n <div style={{ marginTop: 16 }}>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.enabled}\n onChange={(e) => onPatch({ enabled: e.target.checked })}\n />\n <span>Enable Headroom</span>\n </label>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.autoInstall}\n onChange={(e) => onPatch({ autoInstall: e.target.checked })}\n />\n <span>Auto-install if missing on dashboard startup</span>\n </label>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.autoStart}\n onChange={(e) => onPatch({ autoStart: e.target.checked })}\n />\n <span>Auto-start proxy on dashboard startup</span>\n </label>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.autoWrap}\n onChange={(e) => onPatch({ autoWrap: e.target.checked })}\n />\n <span>Auto-wrap opencode on dashboard startup</span>\n </label>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.routeAllProviders}\n onChange={(e) => onPatch({ routeAllProviders: e.target.checked })}\n />\n <span>Route all providers through Headroom proxy</span>\n </label>\n\n <div className=\"task-form-row\" style={{ marginTop: 12 }}>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Proxy port</label>\n <input\n type=\"number\"\n className=\"input\"\n value={settings.port}\n min={1}\n max={65535}\n onChange={(e) => onPatch({ port: Math.max(1, Math.min(65535, parseInt(e.target.value, 10) || 8787)) })}\n />\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Proxy host</label>\n <input\n type=\"text\"\n className=\"input\"\n value={settings.host}\n onChange={(e) => onPatch({ host: e.target.value })}\n />\n </div>\n </div>\n\n <div className=\"task-form-row\">\n <div className=\"task-form-field\">\n <label className=\"field-label\">Backend</label>\n <select\n className=\"select\"\n value={settings.backend}\n onChange={(e) => onPatch({ backend: e.target.value })}\n >\n {BACKEND_OPTIONS.map((o) => (\n <option key={o.value} value={o.value}>{o.label}</option>\n ))}\n </select>\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Monthly budget (USD)</label>\n <input\n type=\"number\"\n className=\"input\"\n value={settings.budget}\n min={0}\n step={1}\n onChange={(e) => onPatch({ budget: Math.max(0, parseFloat(e.target.value) || 0) })}\n />\n <span className=\"field-help\">0 = unlimited</span>\n </div>\n </div>\n\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.outputShaper}\n onChange={(e) => onPatch({ outputShaper: e.target.checked })}\n />\n <span>Enable output shaper</span>\n </label>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.telemetry}\n onChange={(e) => onPatch({ telemetry: e.target.checked })}\n />\n <span>Enable telemetry</span>\n </label>\n </div>\n </Card>\n </div>\n );\n}\n","// src/web/views/settings/HeadroomSection.tsx\nimport React from 'react';\nimport { HeadroomSettingsCard } from '../../components/HeadroomSettings';\nimport { type HeadroomSettings, type Settings } from '../../lib/types';\n\nconst DEFAULT_HEADROOM_SETTINGS: HeadroomSettings = {\n enabled: true,\n autoInstall: true,\n port: 8787,\n host: '127.0.0.1',\n outputShaper: false,\n telemetry: false,\n budget: 0,\n backend: 'anthropic',\n autoStart: true,\n autoWrap: true,\n routeAllProviders: true,\n};\n\ntype Props = {\n settings: Settings;\n setSettings: React.Dispatch<React.SetStateAction<Settings>>;\n setDirty: React.Dispatch<React.SetStateAction<boolean>>;\n};\n\nexport function HeadroomSection({ settings, setSettings, setDirty }: Props) {\n return (\n <HeadroomSettingsCard\n settings={settings.headroom || DEFAULT_HEADROOM_SETTINGS}\n onPatch={(patch) => {\n setSettings((cur) => ({\n ...cur,\n headroom: { ...(cur.headroom || DEFAULT_HEADROOM_SETTINGS), ...patch },\n }));\n setDirty(true);\n }}\n />\n );\n}\n","// src/web/views/settings/ActivitySection.tsx\nimport React, { useEffect, useState, useCallback } from 'react';\nimport { Activity, Search, Eye, RefreshCw, Info } from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../../components/Card';\nimport { Button } from '../../components/Button';\nimport { useToast } from '../../components/Toast';\nimport { api } from '../../lib/api';\nimport { cn } from '../../lib/utils';\nimport type { Settings } from '../../lib/types';\n\ntype Props = {\n about: Settings['about'];\n};\n\nfunction ActivityLogCard() {\n const toast = useToast();\n const [items, setItems] = useState<Array<{ kind?: string; ts?: string; slug?: string; message?: string }>>([]);\n const [hidden, setHidden] = useState<Set<string>>(new Set());\n const [loading, setLoading] = useState(true);\n const [filter, setFilter] = useState('');\n const [showHidden, setShowHidden] = useState(true);\n\n const refresh = useCallback(async () => {\n setLoading(true);\n try {\n const [log, hid] = await Promise.all([\n api.get<{ items: Array<{ kind?: string; ts?: string; slug?: string; message?: string }> }>('/activity'),\n api.get<{ hidden: string[] }>('/activity/hidden'),\n ]);\n setItems(Array.isArray(log.items) ? log.items : []);\n setHidden(new Set(hid.hidden || []));\n } catch (err) {\n toast.error(`Load failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n }, [toast]);\n\n useEffect(() => { refresh(); }, [refresh]);\n\n const keyOf = (it: { kind?: string; ts?: string; slug?: string }, idx: number) => {\n const k = `${it.kind || ''}|${it.ts || ''}|${it.slug || ''}|${idx}`;\n let h = 0;\n for (let i = 0; i < k.length; i++) h = ((h << 5) - h + k.charCodeAt(i)) | 0;\n return Math.abs(h).toString(16).padStart(8, '0').slice(0, 16);\n };\n\n const onRestoreAll = async () => {\n try {\n await api.del('/activity/hide');\n setHidden(new Set());\n toast.success('All hidden activity restored.');\n } catch (err) {\n toast.error(`Restore failed: ${(err as Error).message}`);\n }\n };\n\n const onRestoreOne = async (key: string) => {\n try {\n await api.del(`/activity/hide/${encodeURIComponent(key)}`);\n const next = new Set(hidden);\n next.delete(key);\n setHidden(next);\n } catch (err) {\n toast.error(`Restore failed: ${(err as Error).message}`);\n }\n };\n\n const filtered = items.filter((it, idx) => {\n const k = keyOf(it, idx);\n if (!showHidden && hidden.has(k)) return false;\n if (!filter) return true;\n const q = filter.toLowerCase();\n return [it.kind, it.slug, it.message].some((v) => typeof v === 'string' && v.toLowerCase().includes(q));\n });\n\n return (\n <Card id=\"settings-activity-log\" data-section=\"activity-log\">\n <CardTitle>\n <Activity size={14} /> Activity log\n <span className=\"muted\" style={{ fontWeight: 400, marginLeft: 8, fontSize: 12 }}>\n {items.length} total · {hidden.size} hidden\n </span>\n <Button variant=\"ghost\" size=\"sm\" style={{ marginLeft: 'auto' }} onClick={refresh} title=\"Reload\">\n <RefreshCw size={12} />\n </Button>\n </CardTitle>\n <CardMeta>\n Full history from <code>~/.bizar/activity.log</code>. Hiding an item in the Overview only hides it there — the entry stays here.\n </CardMeta>\n\n <div className=\"activity-log-toolbar\">\n <div className=\"activity-log-search\">\n <Search size={12} />\n <input\n type=\"text\"\n className=\"input\"\n placeholder=\"Filter by kind, slug, or message…\"\n value={filter}\n onChange={(e) => setFilter(e.target.value)}\n />\n </div>\n <label className=\"activity-log-toggle\">\n <input\n type=\"checkbox\"\n checked={showHidden}\n onChange={(e) => setShowHidden(e.target.checked)}\n />\n Show hidden\n </label>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n disabled={hidden.size === 0}\n onClick={onRestoreAll}\n title=\"Restore all hidden items to the Overview\"\n >\n <Eye size={12} /> Restore all\n </Button>\n </div>\n\n {loading ? (\n <div className=\"muted\" style={{ padding: '12px 0', fontSize: 12 }}>Loading…</div>\n ) : filtered.length === 0 ? (\n <div className=\"muted\" style={{ padding: '12px 0', fontSize: 12 }}>\n {items.length === 0 ? 'No activity yet.' : 'No items match the current filter.'}\n </div>\n ) : (\n <div className=\"activity-log-table-wrap\">\n <table className=\"activity-log-table\">\n <thead>\n <tr>\n <th>Kind</th>\n <th>Detail</th>\n <th>Time</th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n {filtered.slice(0, 200).map((it, idx) => {\n const k = keyOf(it, idx);\n const isHidden = hidden.has(k);\n return (\n <tr key={`${it.ts}-${idx}`} className={cn(isHidden && 'activity-log-row-hidden')}>\n <td className=\"activity-log-kind\">{it.kind || 'activity'}</td>\n <td className=\"activity-log-detail\">\n {it.message || it.slug || '—'}\n </td>\n <td className=\"activity-log-time mono\">\n {it.ts ? new Date(it.ts).toLocaleString() : '—'}\n </td>\n <td>\n {isHidden ? (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => onRestoreOne(k)} title=\"Restore to Overview\">\n <Eye size={12} />\n </Button>\n ) : (\n <span className=\"activity-log-state-tag\">shown</span>\n )}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n {filtered.length > 200 && (\n <div className=\"muted\" style={{ fontSize: 11, padding: '8px 0' }}>\n Showing first 200 of {filtered.length}.\n </div>\n )}\n </div>\n )}\n </Card>\n );\n}\n\nfunction AboutCard({ about }: Props) {\n return (\n <Card id=\"settings-about\" data-section=\"about\">\n <CardTitle><Info size={14} /> About</CardTitle>\n <CardMeta>Build metadata.</CardMeta>\n <dl className=\"about-table\">\n <dt>Version</dt>\n <dd className=\"mono\">{about?.version || '—'}</dd>\n <dt>Homepage</dt>\n <dd>\n <a href={about?.homepage || 'https://github.com/DrB0rk/BizarHarness'} target=\"_blank\" rel=\"noopener noreferrer\">\n {about?.homepage || 'https://github.com/DrB0rk/BizarHarness'}\n </a>\n </dd>\n <dt>License</dt>\n <dd>{about?.license || 'MIT'}</dd>\n </dl>\n </Card>\n );\n}\n\nexport function ActivitySection({ about }: Props) {\n return (\n <>\n <ActivityLogCard />\n <AboutCard about={about} />\n </>\n );\n}\n","// src/web/components/EnvVarManager.tsx — manage BIZAR_* env vars from ~/.config/bizar/env.json\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { Plus, Pencil, Trash2, Eye, EyeOff, RefreshCw, KeyRound, CheckCircle, X, Search, Download, Upload, ChevronDown, ChevronRight, AlertCircle } from 'lucide-react';\nimport { Button } from './Button';\nimport { useToast } from './Toast';\nimport { api } from '../lib/api';\nimport { cn } from '../lib/utils';\n\nexport type EnvVarEntry = {\n name: string;\n value: string; // masked on GET, full on edit\n createdAt: string;\n source: string;\n};\n\nexport type EnvVarGrouped = Record<string, EnvVarEntry[]>;\n\ntype Props = {\n onError?: (msg: string) => void;\n};\n\nexport function EnvVarManager({ onError }: Props) {\n const toast = useToast();\n const [vars, setVars] = useState<EnvVarEntry[]>([]);\n const [loading, setLoading] = useState(false);\n const [saving, setSaving] = useState(false);\n // Which rows have the value revealed (edit mode shows real value)\n const [revealed, setRevealed] = useState<Set<string>>(new Set());\n // Currently editing name (null = none)\n const [editing, setEditing] = useState<string | null>(null);\n const [editValue, setEditValue] = useState('');\n // New var form\n const [showAdd, setShowAdd] = useState(false);\n const [newName, setNewName] = useState('');\n const [newValue, setNewValue] = useState('');\n // Bulk operations\n const [showBulk, setShowBulk] = useState(false);\n const [bulkText, setBulkText] = useState('');\n const [bulkImporting, setBulkImporting] = useState(false);\n // Search / filter\n const [searchQ, setSearchQ] = useState('');\n // Group by prefix (collapsed state)\n const [collapsed, setCollapsed] = useState<Set<string>>(new Set());\n\n const load = useCallback(async () => {\n setLoading(true);\n try {\n const r = await api.get<EnvVarEntry[]>('/env-vars');\n setVars(r);\n } catch (err) {\n toast.error(`Load failed: ${(err as Error).message}`);\n onError?.((err as Error).message);\n } finally {\n setLoading(false);\n }\n }, [toast, onError]);\n\n useEffect(() => { load(); }, [load]);\n\n const toggleReveal = (name: string) => {\n setRevealed((prev) => {\n const next = new Set(prev);\n if (next.has(name)) next.delete(name);\n else next.add(name);\n return next;\n });\n };\n\n const handleAdd = async () => {\n const name = newName.trim().toUpperCase();\n const value = newValue.trim();\n if (!name || !/^BIZAR_[A-Z0-9_]+$/.test(name)) {\n toast.warning('Name must match BIZAR_<NAME> (e.g. BIZAR_MINIMAX_KEY)');\n return;\n }\n if (!value) {\n toast.warning('Value is required.');\n return;\n }\n if (vars.some((v) => v.name === name)) {\n toast.warning(`${name} already exists.`);\n return;\n }\n setSaving(true);\n try {\n await api.post('/env-vars', { name, value });\n toast.success(`${name} created.`);\n setShowAdd(false);\n setNewName('');\n setNewValue('');\n await load();\n } catch (err) {\n toast.error(`Create failed: ${(err as Error).message}`);\n } finally {\n setSaving(false);\n }\n };\n\n const startEdit = (v: EnvVarEntry) => {\n setEditing(v.name);\n setEditValue(v.value === v.value.replace(/\\*/g, '') ? v.value : '');\n setRevealed((prev) => { const next = new Set(prev); next.add(v.name); return next; });\n };\n\n const handleUpdate = async (name: string) => {\n if (!editValue.trim()) {\n toast.warning('Value cannot be empty.');\n return;\n }\n setSaving(true);\n try {\n await api.put(`/env-vars/${encodeURIComponent(name)}`, { value: editValue.trim() });\n toast.success(`${name} updated.`);\n setEditing(null);\n await load();\n } catch (err) {\n toast.error(`Update failed: ${(err as Error).message}`);\n } finally {\n setSaving(false);\n }\n };\n\n const handleDelete = async (name: string) => {\n if (!confirm(`Delete ${name}? This cannot be undone.`)) return;\n try {\n await api.del(`/env-vars/${encodeURIComponent(name)}`);\n toast.success(`${name} deleted.`);\n await load();\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n // ─── Bulk import ───────────────────────────────────────────────────────────\n const handleBulkImport = async () => {\n if (!bulkText.trim()) { toast.warning('Nothing to import.'); return; }\n setBulkImporting(true);\n try {\n const r = await api.post<{ ok: boolean; imported: number; skipped: number; errors: string[] }>('/env-vars/bulk-import', { envContent: bulkText });\n toast.success(`Imported ${r.imported}, skipped ${r.skipped}.`);\n if (r.errors.length > 0) {\n toast.warning(`${r.errors.length} lines had errors: ${r.errors.slice(0, 3).join('; ')}${r.errors.length > 3 ? '…' : ''}`);\n }\n setBulkText('');\n setShowBulk(false);\n await load();\n } catch (err) {\n toast.error(`Bulk import failed: ${(err as Error).message}`);\n } finally {\n setBulkImporting(false);\n }\n };\n\n // ─── Bulk export ───────────────────────────────────────────────────────────\n const handleExport = async () => {\n try {\n const r = await api.get<string>('/env-vars/export');\n // r is the raw text content\n const blob = new Blob([r as unknown as string], { type: 'text/plain' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = '.env';\n a.click();\n URL.revokeObjectURL(url);\n toast.success('Exported .env file.');\n } catch (err) {\n toast.error(`Export failed: ${(err as Error).message}`);\n }\n };\n\n // ─── Group by prefix ───────────────────────────────────────────────────────\n const filtered = useMemo(() => {\n if (!searchQ.trim()) return vars;\n const q = searchQ.toLowerCase();\n return vars.filter((v) => v.name.toLowerCase().includes(q));\n }, [vars, searchQ]);\n\n const grouped = useMemo(() => {\n const groups: Record<string, EnvVarEntry[]> = {};\n for (const v of filtered) {\n const prefix = v.name.split('_')[0] + '_';\n (groups[prefix] ??= []).push(v);\n }\n return groups;\n }, [filtered]);\n\n const toggleGroup = (prefix: string) => {\n setCollapsed((prev) => {\n const next = new Set(prev);\n if (next.has(prefix)) next.delete(prefix);\n else next.add(prefix);\n return next;\n });\n };\n\n const sortedGroupKeys = useMemo(() => {\n const known = ['BIZAR_', 'PROVIDER_', 'MODEL_', 'API_'];\n const keys = Object.keys(grouped).sort((a, b) => {\n const ai = known.indexOf(a); const bi = known.indexOf(b);\n if (ai === -1 && bi === -1) return a.localeCompare(b);\n if (ai === -1) return 1;\n if (bi === -1) return -1;\n return ai - bi;\n });\n return keys;\n }, [grouped]);\n\n if (loading) {\n return <div className=\"muted\" style={{ padding: '16px 0', fontSize: 13 }}>Loading env vars…</div>;\n }\n\n const hasGroups = sortedGroupKeys.length > 1;\n const groupMode = hasGroups;\n\n return (\n <div className=\"env-var-manager\">\n <div className=\"env-var-toolbar\">\n <Button variant=\"primary\" size=\"sm\" onClick={() => setShowAdd(true)}>\n <Plus size={12} /> New variable\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => setShowBulk((v) => !v)} className={showBulk ? 'active' : ''}>\n <Upload size={12} /> Bulk import\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={handleExport} title=\"Export as .env\">\n <Download size={12} /> Export\n </Button>\n <div className=\"env-var-search-wrap\">\n <Search size={12} className=\"env-var-search-icon\" />\n <input\n className=\"env-var-search input\"\n placeholder=\"Filter…\"\n value={searchQ}\n onChange={(e) => setSearchQ(e.target.value)}\n />\n </div>\n <Button variant=\"ghost\" size=\"sm\" onClick={load} title=\"Reload\">\n <RefreshCw size={12} />\n </Button>\n </div>\n\n {/* Bulk import panel */}\n {showBulk && (\n <div className=\"env-var-bulk-panel\">\n <div className=\"env-var-bulk-header\">\n <span>Paste <code>KEY=value</code> lines (one per line):</span>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setShowBulk(false)}><X size={12} /></Button>\n </div>\n <textarea\n className=\"input mono env-var-bulk-textarea\"\n placeholder={\"BIZAR_API_KEY=your-key-here\\nPROVIDER_OPENAI_KEY=sk-...\\nMODEL_KEY=gem-...\"}\n value={bulkText}\n onChange={(e) => setBulkText(e.target.value)}\n rows={6}\n />\n <div className=\"env-var-bulk-footer\">\n <Button variant=\"primary\" size=\"sm\" onClick={handleBulkImport} disabled={bulkImporting || !bulkText.trim()}>\n {bulkImporting ? 'Importing…' : 'Import'}\n </Button>\n <span className=\"muted\" style={{ fontSize: 11 }}>\n Existing keys are skipped unless re-created individually. Invalid lines are reported.\n </span>\n </div>\n </div>\n )}\n\n {vars.length === 0 && !showAdd && (\n <div className=\"env-var-empty\">\n <KeyRound size={20} />\n <span>No BIZAR_* env vars yet.</span>\n <span style={{ fontSize: 11 }}>Create one to store API keys securely.</span>\n </div>\n )}\n\n {/* New var form */}\n {showAdd && (\n <div className=\"env-var-add-form\">\n <div className=\"env-var-add-row\">\n <input\n className=\"input mono\"\n style={{ width: 240 }}\n placeholder=\"BIZAR_NAME\"\n value={newName}\n onChange={(e) => setNewName(e.target.value.toUpperCase())}\n onKeyDown={(e) => { if (e.key === 'Enter') handleAdd(); if (e.key === 'Escape') setShowAdd(false); }}\n autoFocus\n />\n <input\n className=\"input mono\"\n type=\"password\"\n placeholder=\"value (API key, token, etc.)\"\n value={newValue}\n onChange={(e) => setNewValue(e.target.value)}\n onKeyDown={(e) => { if (e.key === 'Enter') handleAdd(); if (e.key === 'Escape') setShowAdd(false); }}\n />\n <Button variant=\"primary\" size=\"sm\" onClick={handleAdd} disabled={saving}>\n <CheckCircle size={12} /> Create\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => { setShowAdd(false); setNewName(''); setNewValue(''); }}>\n <X size={12} />\n </Button>\n </div>\n <p style={{ fontSize: 11, color: 'var(--text-dim)', margin: 0 }}>\n Names must match <code>BIZAR_<var>NAME</var></code> (uppercase letters, digits, underscores).\n </p>\n </div>\n )}\n\n {/* Var list — grouped by prefix */}\n {filtered.length > 0 && (\n groupMode ? (\n <div className=\"env-var-groups\">\n {sortedGroupKeys.map((prefix) => {\n const items = grouped[prefix];\n const isCollapsed = collapsed.has(prefix);\n return (\n <div key={prefix} className=\"env-var-group\">\n <button\n type=\"button\"\n className=\"env-var-group-header\"\n onClick={() => toggleGroup(prefix)}\n >\n {isCollapsed ? <ChevronRight size={12} /> : <ChevronDown size={12} />}\n <span className=\"env-var-group-prefix mono\">{prefix}</span>\n <span className=\"env-var-group-count muted\">({items.length})</span>\n </button>\n {!isCollapsed && (\n <div className=\"env-var-list\">\n {items.map((v) => (\n <VarRow key={v.name} v={v} editing={editing} editValue={editValue}\n isRevealed={revealed.has(v.name)}\n onToggleReveal={toggleReveal} onStartEdit={startEdit}\n onEditValueChange={setEditValue} onHandleUpdate={handleUpdate}\n onCancelEdit={() => setEditing(null)} onDelete={handleDelete}\n saving={saving} />\n ))}\n </div>\n )}\n </div>\n );\n })}\n </div>\n ) : (\n <div className=\"env-var-list\">\n {filtered.map((v) => (\n <VarRow key={v.name} v={v} editing={editing} editValue={editValue}\n isRevealed={revealed.has(v.name)}\n onToggleReveal={toggleReveal} onStartEdit={startEdit}\n onEditValueChange={setEditValue} onHandleUpdate={handleUpdate}\n onCancelEdit={() => setEditing(null)} onDelete={handleDelete}\n saving={saving} />\n ))}\n </div>\n )\n )}\n\n {filtered.length === 0 && vars.length > 0 && (\n <div className=\"env-var-empty\">\n <Search size={16} />\n <span>No env vars match \"{searchQ}\"</span>\n </div>\n )}\n </div>\n );\n}\n\n// ─── Individual var row (extracted for reuse in group mode) ───────────────────\ntype VarRowProps = {\n v: EnvVarEntry;\n editing: string | null;\n editValue: string;\n isRevealed: boolean;\n onToggleReveal: (name: string) => void;\n onStartEdit: (v: EnvVarEntry) => void;\n onEditValueChange: (v: string) => void;\n onHandleUpdate: (name: string) => void;\n onCancelEdit: () => void;\n onDelete: (name: string) => void;\n saving: boolean;\n};\n\nfunction VarRow({ v, editing, editValue, isRevealed, onToggleReveal, onStartEdit, onEditValueChange, onHandleUpdate, onCancelEdit, onDelete, saving }: VarRowProps) {\n const isEditing = editing === v.name;\n return (\n <div className={cn('env-var-row', isEditing && 'env-var-row-editing')}>\n <span className=\"env-var-name mono\">{v.name}</span>\n {isEditing ? (\n <input\n className=\"input mono\"\n type=\"password\"\n style={{ flex: 1, minWidth: 200 }}\n value={editValue}\n onChange={(e) => onEditValueChange(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') onHandleUpdate(v.name);\n if (e.key === 'Escape') onCancelEdit();\n }}\n autoFocus\n />\n ) : (\n <span className={cn('env-var-value mono', !isRevealed && 'env-var-value-masked')}>\n {v.value}\n </span>\n )}\n <span className=\"env-var-source muted\">{v.source}</span>\n <div className=\"env-var-actions\">\n {!isEditing && (\n <button type=\"button\" className=\"icon-btn\" title={isRevealed ? 'Hide' : 'Reveal'} onClick={() => onToggleReveal(v.name)}>\n {isRevealed ? <EyeOff size={12} /> : <Eye size={12} />}\n </button>\n )}\n {isEditing ? (\n <>\n <Button variant=\"primary\" size=\"sm\" onClick={() => onHandleUpdate(v.name)} disabled={saving}>Save</Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onCancelEdit}>Cancel</Button>\n </>\n ) : (\n <>\n <button type=\"button\" className=\"icon-btn\" title=\"Edit\" onClick={() => onStartEdit(v)}>\n <Pencil size={12} />\n </button>\n <button type=\"button\" className=\"icon-btn icon-btn-danger\" title=\"Delete\" onClick={() => onDelete(v.name)}>\n <Trash2 size={12} />\n </button>\n </>\n )}\n </div>\n </div>\n );\n}\n","// src/web/views/settings/EnvVarsSection.tsx\nimport React from 'react';\nimport { KeyRound } from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../../components/Card';\nimport { EnvVarManager } from '../../components/EnvVarManager';\n\nexport function EnvVarsSection() {\n return (\n <Card id=\"settings-env-vars\" data-section=\"env-vars\">\n <CardTitle><KeyRound size={14} /> Environment Variables</CardTitle>\n <CardMeta>Manage BIZAR_* env vars (API keys, secrets). Values are stored in <code>~/.config/bizar/env.json</code> (mode 0600).</CardMeta>\n <EnvVarManager />\n </Card>\n );\n}\n"],"file":"assets/EnvVarsSection-DoIzqrlb.js"}