agent-relay-server 0.94.5 → 0.95.0
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.
- package/docs/openapi.json +1 -1
- package/package.json +2 -2
- package/public/assets/MessageBubble-CkPnAwxJ.js +3 -0
- package/public/assets/{MessageBubble-g4NKZBDI.js.map → MessageBubble-CkPnAwxJ.js.map} +1 -1
- package/public/assets/{PlanGraphPanel-Chydc7yG.js → PlanGraphPanel-DPgW_Ohe.js} +2 -2
- package/public/assets/{PlanGraphPanel-Chydc7yG.js.map → PlanGraphPanel-DPgW_Ohe.js.map} +1 -1
- package/public/assets/{activity-BXLw6f9y.js → activity-CRebaL8O.js} +2 -2
- package/public/assets/{activity-BXLw6f9y.js.map → activity-CRebaL8O.js.map} +1 -1
- package/public/assets/{agent-profiles-B6PsZZmM.js → agent-profiles-BFpEQHKo.js} +2 -2
- package/public/assets/{agent-profiles-B6PsZZmM.js.map → agent-profiles-BFpEQHKo.js.map} +1 -1
- package/public/assets/{agents-B0POygaD.js → agents-7WtV1Pf3.js} +2 -2
- package/public/assets/{agents-B0POygaD.js.map → agents-7WtV1Pf3.js.map} +1 -1
- package/public/assets/{analytics-B50LtRMU.js → analytics-DpnJh9UQ.js} +3 -3
- package/public/assets/{analytics-B50LtRMU.js.map → analytics-DpnJh9UQ.js.map} +1 -1
- package/public/assets/{automation-CeYilS-s.js → automation-CjQNCXlO.js} +2 -2
- package/public/assets/{automation-CeYilS-s.js.map → automation-CjQNCXlO.js.map} +1 -1
- package/public/assets/{badge-CcTIPkUa.js → badge-BbfOskRI.js} +2 -2
- package/public/assets/{badge-CcTIPkUa.js.map → badge-BbfOskRI.js.map} +1 -1
- package/public/assets/branch-state-badge-BcObk0ca.js +2 -0
- package/public/assets/{branch-state-badge-T6t16OU5.js.map → branch-state-badge-BcObk0ca.js.map} +1 -1
- package/public/assets/{button-Dvz6HZ1j.js → button-DWiw--lT.js} +2 -2
- package/public/assets/{button-Dvz6HZ1j.js.map → button-DWiw--lT.js.map} +1 -1
- package/public/assets/{card-xVEUTFuh.js → card-BeqvuYTT.js} +2 -2
- package/public/assets/{card-xVEUTFuh.js.map → card-BeqvuYTT.js.map} +1 -1
- package/public/assets/channels-B2bftzgH.js +2 -0
- package/public/assets/{channels-C0J-VHEa.js.map → channels-B2bftzgH.js.map} +1 -1
- package/public/assets/chat-Dcwua_5V.js +2 -0
- package/public/assets/chat-Dcwua_5V.js.map +1 -0
- package/public/assets/{connectors-P5V_DlvA.js → connectors-CJOJirYT.js} +2 -2
- package/public/assets/{connectors-P5V_DlvA.js.map → connectors-CJOJirYT.js.map} +1 -1
- package/public/assets/copy-button-CIXy8ks6.js +2 -0
- package/public/assets/{copy-button-gB8Wc3dh.js.map → copy-button-CIXy8ks6.js.map} +1 -1
- package/public/assets/display-DRiGi1zj.js.map +1 -1
- package/public/assets/{dist-DbJ0cYxd.js → dist-BQXmO19g.js} +2 -2
- package/public/assets/{dist-DbJ0cYxd.js.map → dist-BQXmO19g.js.map} +1 -1
- package/public/assets/{dist-CE9yg7LH.js → dist-BufB2Xy_.js} +2 -2
- package/public/assets/{dist-CE9yg7LH.js.map → dist-BufB2Xy_.js.map} +1 -1
- package/public/assets/dist-CXkmW1Od.js +2 -0
- package/public/assets/{dist-4Joy6mhT.js.map → dist-CXkmW1Od.js.map} +1 -1
- package/public/assets/{dist-DoHTwsqW.js → dist-CbxR2pzD.js} +2 -2
- package/public/assets/{dist-DoHTwsqW.js.map → dist-CbxR2pzD.js.map} +1 -1
- package/public/assets/{dist-Cu5eOAWz.js → dist-CtuS_3Jl.js} +2 -2
- package/public/assets/{dist-Cu5eOAWz.js.map → dist-CtuS_3Jl.js.map} +1 -1
- package/public/assets/{dist-CVWxY_y8.js → dist-Du_bcq-z.js} +2 -2
- package/public/assets/{dist-CVWxY_y8.js.map → dist-Du_bcq-z.js.map} +1 -1
- package/public/assets/{dist-BkHh9GoG.js → dist-KxiSP9h9.js} +2 -2
- package/public/assets/{dist-BkHh9GoG.js.map → dist-KxiSP9h9.js.map} +1 -1
- package/public/assets/dist-LFuRypZd.js +2 -0
- package/public/assets/{dist-4O7O9HEE.js.map → dist-LFuRypZd.js.map} +1 -1
- package/public/assets/dist-Q6OOS84U.js +2 -0
- package/public/assets/{dist-B2WymQRX.js.map → dist-Q6OOS84U.js.map} +1 -1
- package/public/assets/{dist-B5OjWLDL.js → dist-eG_93I3z.js} +2 -2
- package/public/assets/{dist-B5OjWLDL.js.map → dist-eG_93I3z.js.map} +1 -1
- package/public/assets/{dist-XUy-xPl6.js → dist-zTw85jD8.js} +2 -2
- package/public/assets/{dist-XUy-xPl6.js.map → dist-zTw85jD8.js.map} +1 -1
- package/public/assets/{es2015-Dv7v8EgR.js → es2015-ibwCE_JR.js} +2 -2
- package/public/assets/{es2015-Dv7v8EgR.js.map → es2015-ibwCE_JR.js.map} +1 -1
- package/public/assets/{formatted-body-impl-B8xoPLk0.js → formatted-body-impl-CGACmUqI.js} +2 -2
- package/public/assets/{formatted-body-impl-B8xoPLk0.js.map → formatted-body-impl-CGACmUqI.js.map} +1 -1
- package/public/assets/index-CKPsJqiW.css +2 -0
- package/public/assets/index-CwhhpGgX.js +23 -0
- package/public/assets/index-CwhhpGgX.js.map +1 -0
- package/public/assets/{input-CWYjJ4Bn.js → input-DUdtS3nG.js} +2 -2
- package/public/assets/{input-CWYjJ4Bn.js.map → input-DUdtS3nG.js.map} +1 -1
- package/public/assets/{insights-O02aG6Fa.js → insights-DqXjTYai.js} +2 -2
- package/public/assets/{insights-O02aG6Fa.js.map → insights-DqXjTYai.js.map} +1 -1
- package/public/assets/{integrations-COYT1FSR.js → integrations-DEgLatDv.js} +2 -2
- package/public/assets/{integrations-COYT1FSR.js.map → integrations-DEgLatDv.js.map} +1 -1
- package/public/assets/{lib-C6ShgLFg.js → lib-Gp69YB9e.js} +3 -3
- package/public/assets/{lib-C6ShgLFg.js.map → lib-Gp69YB9e.js.map} +1 -1
- package/public/assets/lucide-react-uFIMC7W7.js +9 -0
- package/public/assets/{lucide-react-BMjjWU36.js.map → lucide-react-uFIMC7W7.js.map} +1 -1
- package/public/assets/{maintenance-CsaxFb2K.js → maintenance-CcFJlNxt.js} +2 -2
- package/public/assets/{maintenance-CsaxFb2K.js.map → maintenance-CcFJlNxt.js.map} +1 -1
- package/public/assets/{managed-agents-BkMSa35M.js → managed-agents-CHR4Hx1O.js} +4 -4
- package/public/assets/{managed-agents-BkMSa35M.js.map → managed-agents-CHR4Hx1O.js.map} +1 -1
- package/public/assets/{markdown-preview-impl-CPUObdGL.js → markdown-preview-impl-BHaUcnfn.js} +2 -2
- package/public/assets/{markdown-preview-impl-CPUObdGL.js.map → markdown-preview-impl-BHaUcnfn.js.map} +1 -1
- package/public/assets/{memory-Bc9b5aFW.js → memory-Uk0VfqnC.js} +2 -2
- package/public/assets/{memory-Bc9b5aFW.js.map → memory-Uk0VfqnC.js.map} +1 -1
- package/public/assets/{messages-DDUpkDDo.js → messages-D_juCBfr.js} +2 -2
- package/public/assets/{messages-DDUpkDDo.js.map → messages-D_juCBfr.js.map} +1 -1
- package/public/assets/{orchestrators-CTiypI_B.js → orchestrators-8IrmgeHV.js} +2 -2
- package/public/assets/{orchestrators-CTiypI_B.js.map → orchestrators-8IrmgeHV.js.map} +1 -1
- package/public/assets/{overview-DT05JmLC.js → overview-D_DM0QHJ.js} +2 -2
- package/public/assets/{overview-DT05JmLC.js.map → overview-D_DM0QHJ.js.map} +1 -1
- package/public/assets/{pairs-VlxzegP3.js → pairs-jciDuPLn.js} +2 -2
- package/public/assets/{pairs-VlxzegP3.js.map → pairs-jciDuPLn.js.map} +1 -1
- package/public/assets/{projects-5xutbu4r.js → projects-C-QHyuMD.js} +2 -2
- package/public/assets/{projects-5xutbu4r.js.map → projects-C-QHyuMD.js.map} +1 -1
- package/public/assets/{react-dom-D1K8FBqJ.js → react-dom-DF2cuNaf.js} +2 -2
- package/public/assets/{react-dom-D1K8FBqJ.js.map → react-dom-DF2cuNaf.js.map} +1 -1
- package/public/assets/{registry-dClAc8d-.js → registry-D1EIvc8U.js} +2 -2
- package/public/assets/{registry-dClAc8d-.js.map → registry-D1EIvc8U.js.map} +1 -1
- package/public/assets/{security-sGs_RWhJ.js → security-C0_Df9yI.js} +2 -2
- package/public/assets/{security-sGs_RWhJ.js.map → security-C0_Df9yI.js.map} +1 -1
- package/public/assets/{select-AzzgLRfk.js → select-CXFXPZ7Z.js} +2 -2
- package/public/assets/{select-AzzgLRfk.js.map → select-CXFXPZ7Z.js.map} +1 -1
- package/public/assets/settings-DGPpdFoq.js +6 -0
- package/public/assets/{settings-A0LUC7z3.js.map → settings-DGPpdFoq.js.map} +1 -1
- package/public/assets/store-d-IbqTaD.js +9 -0
- package/public/assets/store-d-IbqTaD.js.map +1 -0
- package/public/assets/{tasks-QfihaEd7.js → tasks-B_epVa5b.js} +2 -2
- package/public/assets/{tasks-QfihaEd7.js.map → tasks-B_epVa5b.js.map} +1 -1
- package/public/assets/teams-D2hATpCD.js +2 -0
- package/public/assets/{teams-yi_-_mib.js.map → teams-D2hATpCD.js.map} +1 -1
- package/public/assets/{terminal-viewer-impl-BuXn1PG3.js → terminal-viewer-impl-CefeetWa.js} +3 -3
- package/public/assets/{terminal-viewer-impl-BuXn1PG3.js.map → terminal-viewer-impl-CefeetWa.js.map} +1 -1
- package/public/assets/types-Tv67voFu.js.map +1 -1
- package/public/assets/{use-keyboard-viewport-BAtKHKT6.js → use-keyboard-viewport-CeLM-PeW.js} +2 -2
- package/public/assets/{use-keyboard-viewport-BAtKHKT6.js.map → use-keyboard-viewport-CeLM-PeW.js.map} +1 -1
- package/public/assets/{user-avatar-D5hoY3pJ.js → user-avatar-BOGZ21O8.js} +2 -2
- package/public/assets/{user-avatar-D5hoY3pJ.js.map → user-avatar-BOGZ21O8.js.map} +1 -1
- package/public/assets/{work-queue-pZe5uRpJ.js → work-queue-C9wBOivX.js} +2 -2
- package/public/assets/{work-queue-pZe5uRpJ.js.map → work-queue-C9wBOivX.js.map} +1 -1
- package/public/assets/{workspaces-DVh1TmHX.js → workspaces-DKFmnOF8.js} +3 -3
- package/public/assets/{workspaces-DVh1TmHX.js.map → workspaces-DKFmnOF8.js.map} +1 -1
- package/public/index.html +21 -21
- package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/src/agent-busy-health.ts +12 -1
- package/src/codex-wham-quota.ts +4 -1
- package/src/config-store.ts +16 -5
- package/src/db/provider-quotas.ts +45 -15
- package/src/maintenance/jobs.ts +0 -1
- package/src/mcp/index.ts +22 -0
- package/src/notification-router.ts +4 -0
- package/src/notification-rules.ts +87 -6
- package/src/notification-types.ts +12 -0
- package/src/runtime-tokens.ts +3 -1
- package/public/assets/MessageBubble-g4NKZBDI.js +0 -3
- package/public/assets/branch-state-badge-T6t16OU5.js +0 -2
- package/public/assets/channels-C0J-VHEa.js +0 -2
- package/public/assets/chat-KKQrWEE_.js +0 -2
- package/public/assets/chat-KKQrWEE_.js.map +0 -1
- package/public/assets/copy-button-gB8Wc3dh.js +0 -2
- package/public/assets/dist-4Joy6mhT.js +0 -2
- package/public/assets/dist-4O7O9HEE.js +0 -2
- package/public/assets/dist-B2WymQRX.js +0 -2
- package/public/assets/index-D9oZL47o.js +0 -23
- package/public/assets/index-D9oZL47o.js.map +0 -1
- package/public/assets/index-DcyinRQU.css +0 -2
- package/public/assets/lucide-react-BMjjWU36.js +0 -9
- package/public/assets/settings-A0LUC7z3.js +0 -6
- package/public/assets/store-Bfl3XVmS.js +0 -9
- package/public/assets/store-Bfl3XVmS.js.map +0 -1
- package/public/assets/teams-yi_-_mib.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-A0LUC7z3.js","names":[],"sources":["../../dashboard/src/components/settings/schema-utils.ts","../../dashboard/src/components/settings/schema-form.tsx","../../dashboard/src/components/settings/browser-settings.tsx","../../dashboard/src/components/settings/model-catalog-settings.tsx","../../dashboard/src/components/settings/quota-settings.tsx","../../dashboard/src/components/views/settings.tsx"],"sourcesContent":["import { isRecord, type JSONSchema, type SettingEntry } from 'agent-relay-sdk/types'\n\nexport { hasScope } from 'agent-relay-sdk/types'\nexport type { SettingEntry }\n\ninterface SettingGroup {\n group: string\n slug: string\n settings: SettingEntry[]\n}\n\nexport type Path = Array<string | number>\n\nexport function settingId(setting: Pick<SettingEntry, 'namespace' | 'key'>): string {\n return `${setting.namespace}/${setting.key}`\n}\n\nexport function settingPath(setting: Pick<SettingEntry, 'namespace' | 'key'>): string {\n return `/settings/${encodeURIComponent(setting.namespace)}/${encodeURIComponent(setting.key)}`\n}\n\nexport function slugify(value: string): string {\n return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'settings'\n}\n\nexport function groupSettings(settings: SettingEntry[]): SettingGroup[] {\n const groups = new Map<string, SettingEntry[]>()\n for (const setting of settings.filter((entry) => entry.readable)) {\n const group = setting.display?.group?.trim() || setting.namespace\n groups.set(group, [...(groups.get(group) ?? []), setting])\n }\n return [...groups.entries()]\n .map(([group, items]) => ({\n group,\n slug: slugify(group),\n settings: items.sort(compareSettings),\n }))\n .sort((a, b) => groupOrder(a.settings) - groupOrder(b.settings) || a.group.localeCompare(b.group))\n}\n\nfunction compareSettings(a: SettingEntry, b: SettingEntry): number {\n return (a.display?.order ?? Number.MAX_SAFE_INTEGER) - (b.display?.order ?? Number.MAX_SAFE_INTEGER)\n || a.display?.label?.localeCompare(b.display?.label ?? '') || 0\n || settingId(a).localeCompare(settingId(b))\n}\n\nfunction groupOrder(settings: SettingEntry[]): number {\n return Math.min(...settings.map((setting) => setting.display?.order ?? Number.MAX_SAFE_INTEGER))\n}\n\nexport function schemaType(schema: JSONSchema): string | undefined {\n return Array.isArray(schema.type) ? schema.type.find((type) => type !== 'null') : schema.type\n}\n\nexport function valueAtPath(value: unknown, path: Path): unknown {\n let current = value\n for (const part of path) {\n if (typeof part === 'number') {\n if (!Array.isArray(current)) return undefined\n current = current[part]\n } else {\n if (!isRecord(current)) return undefined\n current = current[part]\n }\n }\n return current\n}\n\nexport function setValueAtPath(value: unknown, path: Path, next: unknown): unknown {\n if (!path.length) return next\n const [head, ...tail] = path\n if (head === undefined) return next\n if (typeof head === 'number') {\n const array = Array.isArray(value) ? [...value] : []\n array[head] = setValueAtPath(array[head], tail, next)\n return array\n }\n const record = isRecord(value) ? { ...value } : {}\n const updated = setValueAtPath(record[head], tail, next)\n if (updated === undefined) delete record[head]\n else record[head] = updated\n return record\n}\n\nexport function defaultValueForSchema(schema: JSONSchema): unknown {\n if (schema.default !== undefined) return schema.default\n if (schema.const !== undefined) return schema.const\n if (schema.enum?.length) return schema.enum[0]\n switch (schemaType(schema)) {\n case 'boolean': return false\n case 'integer':\n case 'number': return 0\n case 'array': return []\n case 'object': return {}\n case 'string': return ''\n default: return undefined\n }\n}\n\nexport function lines(value: string): string[] {\n return value.split(/\\r?\\n|,/).map((line) => line.trim()).filter(Boolean)\n}\n\nexport function arrayText(value: unknown): string {\n return Array.isArray(value) ? value.map((item) => String(item)).join('\\n') : ''\n}\n\nexport function recordText(value: unknown): string {\n if (!isRecord(value)) return ''\n return Object.entries(value).map(([key, item]) => `${key}=${String(item ?? '')}`).join('\\n')\n}\n\nexport function parseRecordText(value: string): Record<string, string> {\n return Object.fromEntries(value.split(/\\r?\\n/).map((raw) => raw.trim()).filter(Boolean).map((line) => {\n const idx = line.indexOf('=')\n return idx >= 0 ? [line.slice(0, idx).trim(), line.slice(idx + 1)] : [line, '']\n }))\n}\n\nexport { isRecord }\n","import { useState, type ReactNode } from 'react'\nimport type { JSONSchema, SettingTier } from 'agent-relay-sdk/types'\nimport { api, type ApiError } from '@/lib/api'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Textarea } from '@/components/ui/textarea'\nimport { Switch } from '@/components/ui/switch'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { Badge } from '@/components/ui/badge'\nimport { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport { AlertCircle, CheckCircle2, MonitorCog, Save, ServerCog } from 'lucide-react'\nimport {\n arrayText,\n defaultValueForSchema,\n isRecord,\n lines,\n parseRecordText,\n recordText,\n schemaType,\n setValueAtPath,\n settingId,\n settingPath,\n type Path,\n type SettingEntry,\n} from './schema-utils'\n\nexport const UNSET = '__unset__'\n\nfunction tierLabel(tier: SettingTier): string {\n if (tier === 'server-runtime') return 'Server runtime'\n if (tier === 'bootstrap') return 'Bootstrap'\n return 'Browser'\n}\n\nfunction tierDescription(tier: SettingTier): string {\n if (tier === 'server-runtime') return 'Stored by Relay and mutable while the server is running.'\n if (tier === 'bootstrap') return 'Read from startup configuration; restart or host config changes are required.'\n return 'Stored only in this browser profile.'\n}\n\nfunction tierIcon(tier: SettingTier) {\n if (tier === 'browser') return <MonitorCog className=\"size-3.5\" />\n return <ServerCog className=\"size-3.5\" />\n}\n\nexport function errorDetails(error: unknown): string[] {\n return (error as ApiError).details ?? []\n}\n\nexport function SchemaGroup({ group, settings, onSaved }: { group: string; settings: SettingEntry[]; onSaved: (setting: SettingEntry) => void }) {\n const tiers = [...new Set(settings.map((setting) => setting.tier))]\n return (\n <section className=\"space-y-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <h2 className=\"text-base font-semibold\">{group}</h2>\n <div className=\"flex flex-wrap gap-1\">\n {tiers.map((tier) => (\n <Badge key={tier} variant=\"outline\" className=\"gap-1\" title={tierDescription(tier)}>\n {tierIcon(tier)}\n {tierLabel(tier)}\n </Badge>\n ))}\n </div>\n </div>\n {settings.length === 0 ? (\n <Card size=\"sm\">\n <CardContent className=\"text-sm text-muted-foreground\">No settings in this group.</CardContent>\n </Card>\n ) : (\n <div className=\"space-y-3\">\n {settings.map((setting) => (\n <SettingCard key={settingId(setting)} setting={setting} onSaved={onSaved} />\n ))}\n </div>\n )}\n </section>\n )\n}\n\nfunction SettingCard({ setting, onSaved }: { setting: SettingEntry; onSaved: (setting: SettingEntry) => void }) {\n const [draft, setDraft] = useState<unknown>(() => setting.value ?? setting.defaults ?? defaultValueForSchema(setting.schema))\n const [saving, setSaving] = useState(false)\n const [status, setStatus] = useState('')\n const [errors, setErrors] = useState<string[]>([])\n const isWritable = setting.writable && setting.tier === 'server-runtime'\n\n function update(path: Path, value: unknown) {\n setDraft((current: unknown) => setValueAtPath(current, path, value))\n setErrors([])\n setStatus('')\n }\n\n async function save() {\n if (!isWritable) return\n setSaving(true)\n setErrors([])\n setStatus('')\n try {\n const saved = await api<SettingEntry>('PUT', settingPath(setting), { value: draft, updatedBy: 'dashboard' })\n setDraft(saved.value)\n onSaved(saved)\n setStatus('Saved')\n } catch (e) {\n const details = errorDetails(e)\n setErrors(details.length ? details : [(e as Error).message])\n } finally {\n setSaving(false)\n }\n }\n\n return (\n <Card size=\"sm\">\n <CardHeader>\n <CardTitle className=\"flex flex-wrap items-center gap-2 text-sm\">\n {setting.display.label}\n <Badge variant=\"outline\" className=\"gap-1\" title={tierDescription(setting.tier)}>{tierIcon(setting.tier)}{tierLabel(setting.tier)}</Badge>\n {!setting.writable && <Badge variant=\"secondary\">Read only</Badge>}\n </CardTitle>\n {setting.display.description && <CardDescription>{setting.display.description}</CardDescription>}\n <CardAction>\n <Button size=\"sm\" onClick={save} disabled={!isWritable || saving}>\n <Save className=\"size-4\" />\n {saving ? 'Saving' : 'Save'}\n </Button>\n </CardAction>\n </CardHeader>\n\n <CardContent className=\"space-y-3\">\n <SchemaField\n schema={setting.schema}\n value={draft}\n path={[]}\n label={setting.display.label}\n required\n disabled={!isWritable || saving}\n onChange={update}\n />\n\n <p className=\"flex flex-wrap items-center gap-x-2 text-[11px] text-muted-foreground\">\n <code className=\"rounded bg-muted px-1.5 py-0.5 font-mono\">{setting.namespace}/{setting.key}</code>\n <span>read <span className=\"text-foreground/70\">{setting.scope.read}</span></span>\n <span aria-hidden>·</span>\n <span>write <span className=\"text-foreground/70\">{setting.scope.write}</span></span>\n </p>\n\n {errors.length > 0 && (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">\n <div className=\"mb-1 flex items-center gap-2 font-medium\"><AlertCircle className=\"size-4\" />Save failed</div>\n <ul className=\"list-disc space-y-1 pl-5\">\n {errors.map((detail) => <li key={detail}>{detail}</li>)}\n </ul>\n </div>\n )}\n {status && <p className=\"flex items-center gap-1 text-sm text-emerald-500\"><CheckCircle2 className=\"size-4\" />{status}</p>}\n </CardContent>\n </Card>\n )\n}\n\nfunction SchemaField(props: {\n schema: JSONSchema\n value: unknown\n path: Path\n label: string\n required: boolean\n disabled: boolean\n onChange: (path: Path, value: unknown) => void\n}) {\n const { schema, value, path, label, required, disabled, onChange } = props\n const type = schemaType(schema)\n\n if (schema.enum?.length) {\n const current = value === undefined || value === null || value === '' ? UNSET : String(value)\n return (\n <Field label={label} description={schema.description}>\n <Select value={current} onValueChange={(next) => onChange(path, next === UNSET ? undefined : next)} disabled={disabled}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {!required && <SelectItem value={UNSET}>Not set</SelectItem>}\n {schema.enum.map((item) => <SelectItem key={String(item)} value={String(item)}>{String(item)}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n )\n }\n\n if (type === 'boolean') {\n return (\n <div className=\"flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3\">\n <div>\n <div className=\"text-sm font-medium\">{label}</div>\n {schema.description && <div className=\"text-xs text-muted-foreground\">{schema.description}</div>}\n </div>\n <Switch checked={Boolean(value)} onCheckedChange={(next) => onChange(path, next)} disabled={disabled} />\n </div>\n )\n }\n\n if (type === 'integer' || type === 'number') {\n return (\n <Field label={label} description={schema.description}>\n <Input\n type=\"number\"\n min={typeof schema.minimum === 'number' ? schema.minimum : undefined}\n max={typeof schema.maximum === 'number' ? schema.maximum : undefined}\n step={type === 'integer' ? 1 : 'any'}\n value={typeof value === 'number' ? value : ''}\n disabled={disabled}\n onChange={(e) => onChange(path, e.target.value === '' && !required ? undefined : Number(e.target.value))}\n />\n </Field>\n )\n }\n\n if (type === 'array') {\n return (\n <Field label={label} description={schema.description ?? 'One item per line.'}>\n <Textarea\n rows={Math.min(8, Math.max(3, Array.isArray(value) ? value.length + 1 : 3))}\n value={arrayText(value)}\n disabled={disabled}\n onChange={(e) => onChange(path, lines(e.target.value))}\n />\n </Field>\n )\n }\n\n if (type === 'object') {\n const properties = schema.properties ?? {}\n const requiredKeys = new Set(schema.required ?? [])\n if (Object.keys(properties).length === 0 && schema.additionalProperties) {\n return (\n <Field label={label} description={schema.description ?? 'KEY=value, one entry per line.'}>\n <Textarea rows={5} value={recordText(value)} disabled={disabled} onChange={(e) => onChange(path, parseRecordText(e.target.value))} />\n </Field>\n )\n }\n return (\n <div className=\"space-y-3\">\n {path.length > 0 && (\n <div>\n <div className=\"text-sm font-medium\">{label}</div>\n {schema.description && <div className=\"text-xs text-muted-foreground\">{schema.description}</div>}\n </div>\n )}\n <div className=\"grid gap-3 md:grid-cols-2\">\n {Object.entries(properties).map(([key, child]) => {\n const childValue = isRecord(value) ? value[key] : undefined\n return (\n <SchemaField\n key={key}\n schema={child}\n value={childValue === undefined && requiredKeys.has(key) ? defaultValueForSchema(child) : childValue}\n path={[...path, key]}\n label={child.title || labelForKey(key)}\n required={requiredKeys.has(key)}\n disabled={disabled}\n onChange={onChange}\n />\n )\n })}\n </div>\n </div>\n )\n }\n\n return (\n <Field label={label} description={schema.description}>\n <Input\n value={typeof value === 'string' ? value : value == null ? '' : String(value)}\n disabled={disabled}\n onChange={(e) => onChange(path, e.target.value === '' && !required ? undefined : e.target.value)}\n />\n </Field>\n )\n}\n\nexport function Field({ label, description, children }: { label: string; description?: string; children: ReactNode }) {\n return (\n <label className=\"block space-y-1.5 text-sm\">\n <span className=\"text-muted-foreground\">{label}</span>\n {children}\n {description && <span className=\"block text-xs text-muted-foreground\">{description}</span>}\n </label>\n )\n}\n\nfunction labelForKey(key: string): string {\n return key.replace(/([a-z0-9])([A-Z])/g, '$1 $2').replace(/[-_]+/g, ' ').replace(/^\\w/, (char) => char.toUpperCase())\n}\n","import { useEffect, useState } from 'react'\nimport { THEMES } from '@/lib/themes'\nimport { KOKORO_VOICES, availableSpeechVoices } from '@/lib/voice'\nimport { useRelayStore } from '@/store'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { Switch } from '@/components/ui/switch'\nimport { Badge } from '@/components/ui/badge'\nimport { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Brain, MonitorCog, Volume2 } from 'lucide-react'\nimport type { ThemeId } from '@/types'\nimport { Field, UNSET } from './schema-form'\n\nexport function BrowserSettings() {\n const theme = useRelayStore((s) => s.theme)\n const showReasoning = useRelayStore((s) => s.showReasoning)\n const set = useRelayStore((s) => s.set)\n return (\n <section className=\"space-y-4\">\n <div>\n <h2 className=\"text-base font-semibold\">Browser preferences</h2>\n <p className=\"text-sm text-muted-foreground\">These are stored in local dashboard state, not in Relay server config.</p>\n </div>\n <Card size=\"sm\">\n <CardHeader>\n <CardTitle className=\"text-sm\">Dashboard display</CardTitle>\n <CardDescription className=\"text-xs\">Browser tier · persisted in this browser profile.</CardDescription>\n <CardAction>\n <Badge variant=\"outline\" className=\"gap-1\"><MonitorCog className=\"size-3.5\" />Browser</Badge>\n </CardAction>\n </CardHeader>\n <CardContent className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Theme\">\n <Select value={theme} onValueChange={(value) => set({ theme: value as ThemeId })}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {THEMES.map((item) => <SelectItem key={item.id} value={item.id}>{item.label}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n <div className=\"flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3\">\n <div className=\"flex items-center gap-2\">\n <Brain className=\"size-4\" />\n <div>\n <div className=\"text-sm font-medium\">Show reasoning details</div>\n <div className=\"text-xs text-muted-foreground\">Display captured reasoning/tool steps in chat. Server capture is controlled separately by provider reasoningCapture.</div>\n </div>\n </div>\n <Switch checked={showReasoning} onCheckedChange={(value) => set({ showReasoning: value })} />\n </div>\n </CardContent>\n </Card>\n <VoiceSettings />\n </section>\n )\n}\n\nfunction VoiceSettings() {\n const voiceTtsEnabled = useRelayStore((s) => s.voiceTtsEnabled)\n const setVoiceTtsEnabled = useRelayStore((s) => s.setVoiceTtsEnabled)\n const voiceTtsMode = useRelayStore((s) => s.voiceTtsMode)\n const setVoiceTtsMode = useRelayStore((s) => s.setVoiceTtsMode)\n const voiceTtsKokoroVoice = useRelayStore((s) => s.voiceTtsKokoroVoice)\n const setVoiceTtsKokoroVoice = useRelayStore((s) => s.setVoiceTtsKokoroVoice)\n const voiceTtsBrowserVoice = useRelayStore((s) => s.voiceTtsBrowserVoice)\n const setVoiceTtsBrowserVoice = useRelayStore((s) => s.setVoiceTtsBrowserVoice)\n const voiceInputMode = useRelayStore((s) => s.voiceInputMode)\n const setVoiceInputMode = useRelayStore((s) => s.setVoiceInputMode)\n\n // External sync: the browser loads speech voices asynchronously.\n const [browserVoices, setBrowserVoices] = useState(() => availableSpeechVoices())\n useEffect(() => {\n if (typeof window === 'undefined' || !('speechSynthesis' in window)) return\n const refresh = () => setBrowserVoices(availableSpeechVoices())\n refresh()\n window.speechSynthesis.addEventListener?.('voiceschanged', refresh)\n return () => window.speechSynthesis.removeEventListener?.('voiceschanged', refresh)\n }, [])\n\n const kokoroOptions = KOKORO_VOICES.some((voice) => voice.id === voiceTtsKokoroVoice)\n ? KOKORO_VOICES\n : [...KOKORO_VOICES, { id: voiceTtsKokoroVoice, label: voiceTtsKokoroVoice }]\n\n return (\n <Card size=\"sm\">\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-sm\"><Volume2 className=\"size-4\" />Voice</CardTitle>\n <CardDescription className=\"text-xs\">Browser tier TTS and push-to-talk behavior.</CardDescription>\n <CardAction>\n <Switch checked={voiceTtsEnabled} onCheckedChange={setVoiceTtsEnabled} />\n </CardAction>\n </CardHeader>\n <CardContent className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Speech engine\">\n <Select value={voiceTtsMode} onValueChange={(value) => setVoiceTtsMode(value as 'kokoro' | 'browser')}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"kokoro\">Kokoro (server, fallback to browser)</SelectItem>\n <SelectItem value=\"browser\">Browser Web Speech API</SelectItem>\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Kokoro voice\">\n <Select value={voiceTtsKokoroVoice} onValueChange={setVoiceTtsKokoroVoice}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {kokoroOptions.map((voice) => <SelectItem key={voice.id} value={voice.id}>{voice.label}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Browser voice\">\n <Select value={voiceTtsBrowserVoice || UNSET} onValueChange={(value) => setVoiceTtsBrowserVoice(value === UNSET ? '' : value)}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value={UNSET}>System default</SelectItem>\n {browserVoices.map((voice) => <SelectItem key={voice.uri} value={voice.uri}>{voice.label}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Push-to-talk input\">\n <Select value={voiceInputMode} onValueChange={(value) => setVoiceInputMode(value as 'compose' | 'autosend' | 'handsfree')}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"compose\">Fill message box</SelectItem>\n <SelectItem value=\"autosend\">Send immediately</SelectItem>\n </SelectContent>\n </Select>\n </Field>\n </CardContent>\n </Card>\n )\n}\n","import { useState } from 'react'\nimport type { SpawnProvider } from 'agent-relay-sdk/types'\nimport { deriveContextThresholdFromWindowTokens, type ProviderCatalogEntry, type ProviderModelCatalogEntry } from 'agent-relay-sdk/provider-catalog'\nimport { api } from '@/lib/api'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Switch } from '@/components/ui/switch'\nimport { Badge } from '@/components/ui/badge'\nimport { Card, CardAction, CardContent, CardHeader, CardTitle } from '@/components/ui/card'\nimport { CheckCircle2, Eye, EyeOff, Pencil, Plus, ServerCog, SlidersHorizontal, Trash2 } from 'lucide-react'\nimport { errorDetails, Field } from './schema-form'\nimport { lines } from './schema-utils'\n\ninterface ProvidersResponse {\n catalog: ProviderCatalogEntry[]\n}\n\ninterface ModelForm {\n provider: SpawnProvider\n alias: string\n label: string\n providerModel: string\n efforts: string\n defaultEffort: string\n selfCompactUtilization: string\n warnUtilization: string\n hardBackstopUtilization: string\n disabled: boolean\n limits?: ProviderModelCatalogEntry['limits']\n capabilities?: ProviderModelCatalogEntry['capabilities']\n}\n\nexport function ModelCatalogSettings({\n catalog,\n error,\n canWrite,\n onCatalog,\n}: {\n catalog: ProviderCatalogEntry[]\n error: string\n canWrite: boolean\n onCatalog: (catalog: ProviderCatalogEntry[]) => void\n}) {\n const firstProvider = catalog[0]?.provider ?? 'codex'\n const [provider, setProvider] = useState<SpawnProvider>(firstProvider)\n const [form, setForm] = useState<ModelForm>(() => emptyModelForm(firstProvider))\n const [status, setStatus] = useState('')\n const [errors, setErrors] = useState<string[]>([])\n\n const selectedProvider = catalog.some((entry) => entry.provider === provider) ? provider : firstProvider\n const selectedCatalog = catalog.find((entry) => entry.provider === selectedProvider) ?? catalog[0]\n const providers = catalog.map((entry) => entry.provider)\n\n function updateForm(patch: Partial<ModelForm>) {\n setForm((current) => ({ ...current, ...patch }))\n setErrors([])\n setStatus('')\n }\n\n function switchProvider(next: SpawnProvider) {\n setProvider(next)\n setForm(emptyModelForm(next))\n setErrors([])\n setStatus('')\n }\n\n async function reloadCatalog() {\n const res = await api<ProvidersResponse>('GET', '/providers')\n onCatalog(res.catalog)\n }\n\n async function saveModel() {\n if (!canWrite) return\n setErrors([])\n setStatus('')\n try {\n await api('PUT', `/providers/${encodeURIComponent(form.provider)}/models/${encodeURIComponent(form.alias)}`, {\n label: form.label,\n providerModel: form.providerModel,\n efforts: lines(form.efforts),\n defaultEffort: form.defaultEffort.trim() || undefined,\n limits: form.limits,\n capabilities: form.capabilities,\n contextThreshold: contextThresholdFromForm(form),\n disabled: form.disabled,\n updatedBy: 'dashboard',\n })\n await reloadCatalog()\n setStatus(`${form.alias} saved`)\n setForm(emptyModelForm(form.provider))\n } catch (e) {\n const details = errorDetails(e)\n setErrors(details.length ? details : [(e as Error).message])\n }\n }\n\n async function setDisabled(model: ProviderModelCatalogEntry, disabled: boolean) {\n if (!canWrite) return\n setErrors([])\n setStatus('')\n try {\n await api('PATCH', `/providers/${encodeURIComponent(selectedProvider)}/models/${encodeURIComponent(model.alias)}`, { disabled, updatedBy: 'dashboard' })\n await reloadCatalog()\n setStatus(`${model.alias} ${disabled ? 'disabled' : 'enabled'}`)\n } catch (e) {\n const details = errorDetails(e)\n setErrors(details.length ? details : [(e as Error).message])\n }\n }\n\n async function removeModel(model: ProviderModelCatalogEntry) {\n if (!canWrite) return\n setErrors([])\n setStatus('')\n try {\n await api('DELETE', `/providers/${encodeURIComponent(selectedProvider)}/models/${encodeURIComponent(model.alias)}`)\n await reloadCatalog()\n setStatus(`${model.alias} removed`)\n } catch (e) {\n const details = errorDetails(e)\n setErrors(details.length ? details : [(e as Error).message])\n }\n }\n\n function editModel(model: ProviderModelCatalogEntry) {\n setForm({\n provider: selectedProvider,\n alias: model.alias,\n label: model.label,\n providerModel: model.providerModel,\n efforts: model.efforts.join(', '),\n defaultEffort: model.defaultEffort ?? '',\n selfCompactUtilization: model.contextThreshold?.selfCompactUtilization?.toString() ?? '',\n warnUtilization: model.contextThreshold?.warnUtilization?.toString() ?? '',\n hardBackstopUtilization: model.contextThreshold?.hardBackstopUtilization?.toString() ?? '',\n disabled: Boolean(model.disabled),\n limits: model.limits,\n capabilities: model.capabilities,\n })\n setErrors([])\n setStatus('')\n }\n\n if (error) {\n return (\n <Card size=\"sm\">\n <CardContent className=\"text-sm text-muted-foreground\">\n <div className=\"mb-1 flex items-center gap-2 font-medium text-foreground\"><SlidersHorizontal className=\"size-4\" />Model catalog</div>\n {error}\n </CardContent>\n </Card>\n )\n }\n\n return (\n <section className=\"space-y-4\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div>\n <h2 className=\"text-base font-semibold\">Model catalog</h2>\n <p className=\"text-sm text-muted-foreground\">Add override models, disable unavailable models, or remove custom entries from the provider catalog.</p>\n </div>\n {!canWrite && <Badge variant=\"secondary\">Read only: needs settings:write:provider</Badge>}\n </div>\n\n <div className=\"flex flex-wrap gap-2\">\n {providers.map((item) => (\n <Button key={item} variant={item === selectedProvider ? 'default' : 'outline'} size=\"sm\" onClick={() => switchProvider(item)}>\n {item}\n </Button>\n ))}\n </div>\n\n <Card size=\"sm\">\n <CardHeader>\n <CardTitle className=\"text-sm\">Add or edit model</CardTitle>\n <CardAction>\n <Badge variant=\"outline\" className=\"gap-1\"><ServerCog className=\"size-3.5\" />Server runtime</Badge>\n </CardAction>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <div className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Alias\">\n <Input value={form.alias} disabled={!canWrite} placeholder=\"nightly\" onChange={(e) => updateForm({ alias: e.target.value.trim() })} />\n </Field>\n <Field label=\"Label\">\n <Input value={form.label} disabled={!canWrite} placeholder=\"Nightly Codex\" onChange={(e) => updateForm({ label: e.target.value })} />\n </Field>\n <Field label=\"Provider model\">\n <Input value={form.providerModel} disabled={!canWrite} placeholder=\"codex-nightly\" onChange={(e) => updateForm({ providerModel: e.target.value })} />\n </Field>\n <Field label=\"Efforts\">\n <Input value={form.efforts} disabled={!canWrite} placeholder=\"low, medium, high\" onChange={(e) => updateForm({ efforts: e.target.value })} />\n </Field>\n <Field label=\"Default effort\">\n <Input value={form.defaultEffort} disabled={!canWrite} placeholder=\"medium\" onChange={(e) => updateForm({ defaultEffort: e.target.value })} />\n </Field>\n <Field label=\"Self compact utilization\">\n <Input value={form.selfCompactUtilization} disabled={!canWrite} placeholder=\"0.80\" inputMode=\"decimal\" onChange={(e) => updateForm({ selfCompactUtilization: e.target.value })} />\n </Field>\n <Field label=\"Warn utilization\">\n <Input value={form.warnUtilization} disabled={!canWrite} placeholder=\"default: self - 0.10\" inputMode=\"decimal\" onChange={(e) => updateForm({ warnUtilization: e.target.value })} />\n </Field>\n <Field label=\"Hard backstop utilization\">\n <Input value={form.hardBackstopUtilization} disabled={!canWrite} placeholder=\"0.90\" inputMode=\"decimal\" onChange={(e) => updateForm({ hardBackstopUtilization: e.target.value })} />\n </Field>\n <div className=\"flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3\">\n <div>\n <div className=\"text-sm font-medium\">Disabled</div>\n <div className=\"text-xs text-muted-foreground\">Keep visible but unavailable for new launches.</div>\n </div>\n <Switch checked={form.disabled} disabled={!canWrite} onCheckedChange={(disabled) => updateForm({ disabled })} />\n </div>\n </div>\n <Button onClick={saveModel} disabled={!canWrite || !form.alias || !form.label || !form.providerModel}>\n <Plus className=\"size-4\" />\n Save model\n </Button>\n </CardContent>\n </Card>\n\n <div className=\"space-y-2\">\n {selectedCatalog && selectedCatalog.models.length === 0 && (\n <Card size=\"sm\">\n <CardContent className=\"text-sm text-muted-foreground\">No models in this provider catalog yet.</CardContent>\n </Card>\n )}\n {selectedCatalog?.models.map((model) => (\n <Card key={model.alias} size=\"sm\">\n <CardContent className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-medium\">{model.label}</span>\n <code className=\"rounded bg-muted px-1.5 py-0.5 font-mono text-xs\">{model.alias}</code>\n {model.disabled && <Badge variant=\"secondary\">Disabled</Badge>}\n </div>\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {model.providerModel}\n {model.efforts.length > 0 ? ` · efforts ${model.efforts.join(', ')}` : ' · no effort levels'}\n {model.defaultEffort ? ` · default ${model.defaultEffort}` : ''}\n {` · context ${thresholdLabel(model)}`}\n </p>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => editModel(model)}>\n <Pencil className=\"size-4\" />\n Edit\n </Button>\n <Button variant=\"outline\" size=\"sm\" disabled={!canWrite} onClick={() => void setDisabled(model, !model.disabled)}>\n {model.disabled ? <Eye className=\"size-4\" /> : <EyeOff className=\"size-4\" />}\n {model.disabled ? 'Enable' : 'Disable'}\n </Button>\n <Button variant=\"outline\" size=\"sm\" disabled={!canWrite} onClick={() => void removeModel(model)}>\n <Trash2 className=\"size-4\" />\n Remove\n </Button>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n\n {errors.length > 0 && (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">\n <ul className=\"list-disc space-y-1 pl-5\">\n {errors.map((detail) => <li key={detail}>{detail}</li>)}\n </ul>\n </div>\n )}\n {status && <p className=\"flex items-center gap-1 text-sm text-emerald-500\"><CheckCircle2 className=\"size-4\" />{status}</p>}\n </section>\n )\n}\n\nfunction emptyModelForm(provider: SpawnProvider): ModelForm {\n return { provider, alias: '', label: '', providerModel: '', efforts: '', defaultEffort: '', selfCompactUtilization: '', warnUtilization: '', hardBackstopUtilization: '', disabled: false }\n}\n\nfunction contextThresholdFromForm(form: ModelForm): ProviderModelCatalogEntry['contextThreshold'] | undefined {\n const selfCompactUtilization = optionalNumber(form.selfCompactUtilization, 'Self compact utilization')\n const warnUtilization = optionalNumber(form.warnUtilization, 'Warn utilization')\n const hardBackstopUtilization = optionalNumber(form.hardBackstopUtilization, 'Hard backstop utilization')\n if (selfCompactUtilization === undefined && warnUtilization === undefined && hardBackstopUtilization === undefined) return undefined\n if (selfCompactUtilization === undefined) throw new Error('Self compact utilization is required when setting context thresholds')\n return {\n selfCompactUtilization,\n ...(warnUtilization !== undefined ? { warnUtilization } : {}),\n ...(hardBackstopUtilization !== undefined ? { hardBackstopUtilization } : {}),\n }\n}\n\nfunction optionalNumber(value: string, label: string): number | undefined {\n const trimmed = value.trim()\n if (!trimmed) return undefined\n const parsed = Number(trimmed)\n if (!Number.isFinite(parsed)) throw new Error(`${label} must be a number`)\n return parsed\n}\n\nfunction thresholdLabel(model: ProviderModelCatalogEntry): string {\n if (model.contextThreshold) {\n const self = percent(model.contextThreshold.selfCompactUtilization)\n const warn = percent(model.contextThreshold.warnUtilization ?? Math.max(0, model.contextThreshold.selfCompactUtilization - 0.1))\n return `self ${self}, warn ${warn}`\n }\n const derived = deriveContextThresholdFromWindowTokens(model.limits?.contextWindowTokens?.value)\n return `derived self ${percent(derived.selfCompactUtilization)}, warn ${percent(derived.warnUtilization)}`\n}\n\nfunction percent(value: number): string {\n return `${Math.round(value * 100)}%`\n}\n","import { useEffect, useState } from 'react'\nimport type { ProviderQuotaConfig, ProviderQuotaConfigMap } from 'agent-relay-sdk/types'\nimport { api } from '@/lib/api'\nimport { Switch } from '@/components/ui/switch'\nimport { Badge } from '@/components/ui/badge'\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport { AlertCircle, Gauge, Loader2 } from 'lucide-react'\n\n// Quota config block under Settings → Providers (#605). Per provider: enable\n// collection, poll cadence (5m–15m), and show-in-widget. enabled = collect,\n// showInWidget = display — disabling collection stops the orchestrator polling\n// that provider entirely; hiding only removes it from the dashboard widget.\nconst MIN_MINUTES = 5\nconst MAX_MINUTES = 15\n\nconst PROVIDER_LABELS: Record<string, string> = { claude: 'Claude', codex: 'Codex' }\n\nfunction minutesOf(pollIntervalMs: number): number {\n return Math.round(pollIntervalMs / 60_000)\n}\n\nfunction intervalLabel(pollIntervalMs: number): string {\n return `${minutesOf(pollIntervalMs)} min`\n}\n\nexport function QuotaSettings({ canWrite }: { canWrite: boolean }) {\n const [config, setConfig] = useState<ProviderQuotaConfigMap | null>(null)\n const [loadError, setLoadError] = useState('')\n const [saveError, setSaveError] = useState('')\n const [savingProvider, setSavingProvider] = useState<string | null>(null)\n\n // External data load on mount — mirrors the SettingsView reload() pattern.\n useEffect(() => {\n let cancelled = false\n void (async () => {\n try {\n const data = await api<ProviderQuotaConfigMap>('GET', '/providers/quota-config')\n if (!cancelled) setConfig(data)\n } catch (e) {\n if (!cancelled) setLoadError((e as Error).message)\n }\n })()\n return () => { cancelled = true }\n }, [])\n\n async function save(provider: string, next: ProviderQuotaConfig) {\n setConfig((current) => ({ ...(current ?? {}), [provider]: next }))\n setSaveError('')\n setSavingProvider(provider)\n try {\n const saved = await api<ProviderQuotaConfig>('PUT', `/providers/${provider}/quota-config`, next)\n setConfig((current) => ({ ...(current ?? {}), [provider]: saved }))\n } catch (e) {\n setSaveError(`${PROVIDER_LABELS[provider] ?? provider}: ${(e as Error).message}`)\n } finally {\n setSavingProvider(null)\n }\n }\n\n const providers = config ? Object.keys(config).sort() : []\n\n return (\n <section className=\"space-y-4\">\n <div>\n <h2 className=\"text-base font-semibold\">Quota</h2>\n <p className=\"text-sm text-muted-foreground\">\n Per-provider quota collection and display. <strong>Enabled</strong> governs collection (disabled stops polling — no API calls);\n <strong> Show in widget</strong> governs display only.\n </p>\n </div>\n\n {loadError && (\n <div className=\"flex items-start gap-2 rounded-lg border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">\n <AlertCircle className=\"mt-0.5 size-4\" />\n <span>{loadError}</span>\n </div>\n )}\n {saveError && (\n <div className=\"flex items-start gap-2 rounded-lg border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">\n <AlertCircle className=\"mt-0.5 size-4\" />\n <span>{saveError}</span>\n </div>\n )}\n\n {!config && !loadError && (\n <Card size=\"sm\"><CardContent className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Loader2 className=\"size-4 animate-spin\" />Loading quota config…\n </CardContent></Card>\n )}\n\n {providers.map((provider) => {\n const cfg = config![provider]!\n const disabled = !canWrite || savingProvider === provider\n return (\n <Card key={provider} size=\"sm\">\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-sm\">\n <Gauge className=\"size-4\" />\n {PROVIDER_LABELS[provider] ?? provider}\n {savingProvider === provider && <Loader2 className=\"size-3 animate-spin text-muted-foreground\" />}\n </CardTitle>\n <CardDescription className=\"text-xs\">\n {cfg.enabled ? `Polled every ${intervalLabel(cfg.pollIntervalMs)}` : 'Collection disabled'}\n {cfg.enabled && !cfg.showInWidget ? ' · hidden from widget' : ''}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3\">\n <div>\n <div className=\"text-sm font-medium\">Enabled</div>\n <div className=\"text-xs text-muted-foreground\">Collect quota for this provider. Off stops all polling (no API calls, no token spend).</div>\n </div>\n <Switch\n checked={cfg.enabled}\n disabled={disabled}\n onCheckedChange={(enabled) => void save(provider, { ...cfg, enabled })}\n />\n </div>\n\n <div className=\"rounded-md border bg-muted/20 p-3 space-y-2\">\n <div className=\"flex items-center justify-between\">\n <div className=\"text-sm font-medium\">Polling interval</div>\n <Badge variant=\"outline\" className=\"tabular-nums\">{intervalLabel(cfg.pollIntervalMs)}</Badge>\n </div>\n <input\n type=\"range\"\n min={MIN_MINUTES}\n max={MAX_MINUTES}\n step={1}\n value={minutesOf(cfg.pollIntervalMs)}\n disabled={disabled || !cfg.enabled}\n // Live label update while dragging; persist on pointer/key release.\n onChange={(e) => {\n const pollIntervalMs = Number(e.target.value) * 60_000\n setConfig((current) => ({ ...(current ?? {}), [provider]: { ...cfg, pollIntervalMs } }))\n }}\n onPointerUp={(e) => void save(provider, { ...cfg, pollIntervalMs: Number((e.target as HTMLInputElement).value) * 60_000 })}\n onKeyUp={(e) => void save(provider, { ...cfg, pollIntervalMs: Number((e.target as HTMLInputElement).value) * 60_000 })}\n className=\"w-full accent-primary disabled:opacity-50\"\n />\n <div className=\"flex justify-between text-[10px] text-muted-foreground\">\n <span>{MIN_MINUTES} min</span>\n <span>{MAX_MINUTES} min</span>\n </div>\n </div>\n\n <div className=\"flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3\">\n <div>\n <div className=\"text-sm font-medium\">Show in quota widget</div>\n <div className=\"text-xs text-muted-foreground\">Display only. Off hides this provider from the dashboard widget; collection continues if enabled.</div>\n </div>\n <Switch\n checked={cfg.showInWidget}\n disabled={disabled}\n onCheckedChange={(showInWidget) => void save(provider, { ...cfg, showInWidget })}\n />\n </div>\n </CardContent>\n </Card>\n )\n })}\n </section>\n )\n}\n","import { useEffect, useMemo, useRef, useState } from 'react'\nimport type { ProviderCatalogEntry } from 'agent-relay-sdk/provider-catalog'\nimport { api, apiUpload } from '@/lib/api'\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\nimport { Badge } from '@/components/ui/badge'\nimport { Card, CardContent } from '@/components/ui/card'\nimport { AlertCircle, Camera, Globe2, RefreshCw, Route, Save, Trash2, Upload } from 'lucide-react'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { Textarea } from '@/components/ui/textarea'\nimport { BrowserSettings } from '@/components/settings/browser-settings'\nimport { ModelCatalogSettings } from '@/components/settings/model-catalog-settings'\nimport { QuotaSettings } from '@/components/settings/quota-settings'\nimport { SchemaGroup } from '@/components/settings/schema-form'\nimport { UserAvatar } from '@/components/shared/user-avatar'\nimport { useRelayStore } from '@/store'\nimport {\n groupSettings,\n hasScope,\n settingId,\n type SettingEntry,\n} from '@/components/settings/schema-utils'\nimport type { Artifact, NotificationRoutingPreview, User } from '@/types'\n\ninterface SettingsResponse {\n settings: SettingEntry[]\n}\n\ninterface TokenMe {\n actor: string\n kind: string\n role?: string\n scopes: string[]\n}\n\ninterface ProvidersResponse {\n catalog: ProviderCatalogEntry[]\n}\n\ninterface NotificationPreviewResponse {\n preview: NotificationRoutingPreview\n}\n\nconst BROWSER_GROUP_SLUG = 'browser'\nconst MODELS_GROUP_SLUG = 'models'\nconst PROFILE_GROUP_SLUG = 'profile'\nconst NOTIFICATION_TYPES = [\n 'branch.landed',\n 'landed-failure',\n 'agent.ready',\n 'agent.exited',\n 'agent.spawn_failed',\n 'agent.context_threshold',\n 'agent.quota_threshold',\n 'workspace.steward_task',\n 'workspace.conflict',\n 'workspace.review_request',\n]\n\nfunction settingsHash(): string {\n if (typeof window === 'undefined') return ''\n const hash = window.location.hash.replace(/^#/, '')\n if (!hash.startsWith('settings/')) return ''\n return decodeURIComponent(hash.slice('settings/'.length))\n}\n\nfunction writeSettingsHash(slug: string): void {\n if (typeof window === 'undefined') return\n const url = new URL(window.location.href)\n url.hash = `settings/${encodeURIComponent(slug)}`\n window.history.pushState({}, '', url)\n}\n\nexport function SettingsView() {\n const [settings, setSettings] = useState<SettingEntry[]>([])\n const [token, setToken] = useState<TokenMe | null>(null)\n const [catalog, setCatalog] = useState<ProviderCatalogEntry[]>([])\n const [active, setActive] = useState(() => settingsHash())\n const [loading, setLoading] = useState(true)\n const [loadError, setLoadError] = useState('')\n const [catalogError, setCatalogError] = useState('')\n\n async function reload() {\n setLoading(true)\n setLoadError('')\n setCatalogError('')\n try {\n const [settingsRes, tokenRes, providersRes] = await Promise.all([\n api<SettingsResponse>('GET', '/settings'),\n api<TokenMe>('GET', '/tokens/me'),\n api<ProvidersResponse>('GET', '/providers').catch((e) => {\n setCatalogError((e as Error).message)\n return { catalog: [] }\n }),\n ])\n setSettings(settingsRes.settings)\n setToken(tokenRes)\n setCatalog(providersRes.catalog)\n } catch (e) {\n setLoadError((e as Error).message)\n } finally {\n setLoading(false)\n }\n }\n\n useEffect(() => {\n void reload()\n }, [])\n\n // External sync: keep the selected settings group aligned with browser history.\n useEffect(() => {\n const sync = () => setActive(settingsHash())\n window.addEventListener('hashchange', sync)\n window.addEventListener('popstate', sync)\n return () => {\n window.removeEventListener('hashchange', sync)\n window.removeEventListener('popstate', sync)\n }\n }, [])\n\n const descriptorGroups = useMemo(() => groupSettings(settings), [settings])\n const groups = useMemo(() => [\n ...descriptorGroups.map((group) => ({\n slug: group.slug,\n label: group.group,\n description: `${group.settings.length} schema setting${group.settings.length === 1 ? '' : 's'}`,\n kind: 'descriptors' as const,\n settings: group.settings,\n })),\n {\n slug: PROFILE_GROUP_SLUG,\n label: 'Profile',\n description: 'Display name and avatar',\n kind: 'profile' as const,\n settings: [],\n },\n {\n slug: BROWSER_GROUP_SLUG,\n label: 'Browser',\n description: 'Local dashboard preferences',\n kind: 'browser' as const,\n settings: [],\n },\n {\n slug: MODELS_GROUP_SLUG,\n label: 'Models',\n description: 'Provider model catalog',\n kind: 'models' as const,\n settings: [],\n },\n ], [descriptorGroups])\n\n const activeGroup = groups.find((group) => group.slug === active) ?? groups[0]\n\n function selectGroup(slug: string) {\n setActive(slug)\n writeSettingsHash(slug)\n }\n\n function replaceSetting(updated: SettingEntry) {\n setSettings((current) => current.map((entry) => settingId(entry) === settingId(updated) ? updated : entry))\n }\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div>\n <h1 className=\"text-lg font-semibold\">Settings</h1>\n <p className=\"text-sm text-muted-foreground\">Schema-driven Relay settings, browser preferences, and model catalog controls.</p>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n {token && (\n <Badge variant=\"outline\" className=\"gap-1\">\n <Globe2 className=\"size-3\" />\n {token.kind}:{token.actor}\n </Badge>\n )}\n <Button variant=\"outline\" size=\"sm\" onClick={() => void reload()} disabled={loading}>\n <RefreshCw className={cn('size-4', loading && 'animate-spin')} />\n Refresh\n </Button>\n </div>\n </div>\n\n {loadError && (\n <div className=\"flex items-start gap-2 rounded-lg border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">\n <AlertCircle className=\"mt-0.5 size-4\" />\n <span>{loadError}</span>\n </div>\n )}\n\n <div className=\"grid gap-4 lg:grid-cols-[230px_minmax(0,1fr)]\">\n <nav className=\"space-y-1 lg:sticky lg:top-4 lg:self-start\">\n {groups.map((group) => (\n <button\n key={group.slug}\n type=\"button\"\n className={cn(\n 'w-full rounded-md border px-3 py-2 text-left text-sm transition-colors',\n activeGroup?.slug === group.slug ? 'border-primary/50 bg-primary/10 text-foreground' : 'border-transparent hover:border-border hover:bg-accent',\n )}\n onClick={() => selectGroup(group.slug)}\n >\n <span className=\"block font-medium\">{group.label}</span>\n <span className=\"block truncate text-xs text-muted-foreground\">{group.description}</span>\n </button>\n ))}\n </nav>\n\n <div className=\"min-w-0 space-y-4\">\n {loading && !settings.length ? (\n <Card size=\"sm\">\n <CardContent className=\"text-sm text-muted-foreground\">Loading settings…</CardContent>\n </Card>\n ) : activeGroup?.kind === 'descriptors' ? (\n <>\n <SchemaGroup\n group={activeGroup.label}\n settings={activeGroup.settings}\n onSaved={replaceSetting}\n />\n {/* Quota config block lives under the Providers group (#605). */}\n {activeGroup.label === 'Providers' && (\n <QuotaSettings canWrite={hasScope(token?.scopes, 'settings:write:provider')} />\n )}\n {activeGroup.label === 'Notifications' && (\n <NotificationRoutingPreviewPanel />\n )}\n </>\n ) : activeGroup?.kind === 'profile' ? (\n <ProfileSettings />\n ) : activeGroup?.kind === 'browser' ? (\n <BrowserSettings />\n ) : (\n <ModelCatalogSettings\n catalog={catalog}\n error={catalogError}\n canWrite={hasScope(token?.scopes, 'settings:write:provider')}\n onCatalog={setCatalog}\n />\n )}\n </div>\n </div>\n </div>\n )\n}\n\nfunction NotificationRoutingPreviewPanel() {\n const [type, setType] = useState('branch.landed')\n const [scopeText, setScopeText] = useState('{\\n \"repoRoot\": \"/repo\"\\n}')\n const [preview, setPreview] = useState<NotificationRoutingPreview | null>(null)\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState('')\n\n async function runPreview() {\n setLoading(true)\n setError('')\n try {\n const scope = JSON.parse(scopeText) as unknown\n if (!scope || typeof scope !== 'object' || Array.isArray(scope)) throw new Error('Scope must be a JSON object')\n const result = await api<NotificationPreviewResponse>('POST', '/notifications/preview', { type, scope })\n setPreview(result.preview)\n } catch (e) {\n setPreview(null)\n setError((e as Error).message)\n } finally {\n setLoading(false)\n }\n }\n\n return (\n <Card size=\"sm\">\n <CardContent className=\"space-y-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <div>\n <h2 className=\"text-sm font-semibold\">Who gets what</h2>\n <p className=\"text-xs text-muted-foreground\">Dry-run notification routing without sending.</p>\n </div>\n <Button size=\"sm\" onClick={() => void runPreview()} disabled={loading}>\n <Route className=\"size-4\" />\n Preview\n </Button>\n </div>\n <div className=\"grid gap-3 md:grid-cols-[240px_minmax(0,1fr)]\">\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">Type</label>\n <Select value={type} onValueChange={setType}>\n <SelectTrigger className=\"w-full\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {NOTIFICATION_TYPES.map((item) => <SelectItem key={item} value={item}>{item}</SelectItem>)}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">Scope</label>\n <Textarea value={scopeText} onChange={(e) => setScopeText(e.target.value)} rows={4} className=\"font-mono text-xs\" />\n </div>\n </div>\n {error && (\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 p-2 text-xs text-destructive\">\n <AlertCircle className=\"mt-0.5 size-3.5\" />\n <span>{error}</span>\n </div>\n )}\n {preview && (\n <div className=\"overflow-hidden rounded-md border border-border\">\n {preview.recipients.length === 0 ? (\n <div className=\"px-3 py-4 text-center text-xs text-muted-foreground\">No recipients</div>\n ) : preview.recipients.map((recipient) => (\n <div key={`${recipient.recipient}-${recipient.matchedRule}`} className=\"grid gap-1 border-b border-border px-3 py-2 text-xs last:border-b-0 md:grid-cols-[minmax(0,180px)_minmax(0,160px)_minmax(0,1fr)]\">\n <span className=\"truncate font-medium\">{recipient.recipient}</span>\n <span className=\"truncate font-mono text-muted-foreground\">{recipient.matchedRule}</span>\n <span className=\"truncate text-muted-foreground\">{recipient.reason}</span>\n </div>\n ))}\n </div>\n )}\n </CardContent>\n </Card>\n )\n}\n\nfunction ProfileSettings() {\n const fetchUsers = useRelayStore((s) => s.fetchUsers)\n const fileRef = useRef<HTMLInputElement>(null)\n const [user, setUser] = useState<User | null>(null)\n const [displayName, setDisplayName] = useState('')\n const [loading, setLoading] = useState(true)\n const [saving, setSaving] = useState(false)\n const [error, setError] = useState('')\n\n async function loadProfile() {\n setLoading(true)\n setError('')\n try {\n const next = await api<User>('GET', '/users/me')\n setUser(next)\n setDisplayName(next.displayName || next.handle)\n } catch (e) {\n setError((e as Error).message)\n } finally {\n setLoading(false)\n }\n }\n\n useEffect(() => {\n void loadProfile()\n }, [])\n\n async function saveProfile() {\n setSaving(true)\n setError('')\n try {\n const next = await api<User>('PATCH', '/users/me', { displayName })\n setUser(next)\n setDisplayName(next.displayName || next.handle)\n await fetchUsers()\n } catch (e) {\n setError((e as Error).message)\n } finally {\n setSaving(false)\n }\n }\n\n async function uploadAvatar(file: File | undefined) {\n if (!file) return\n setSaving(true)\n setError('')\n try {\n const res = await apiUpload<{ user: User; artifact: Artifact }>('/users/me/avatar', file)\n setUser(res.user)\n setDisplayName(res.user.displayName || res.user.handle)\n await fetchUsers()\n } catch (e) {\n setError((e as Error).message)\n } finally {\n setSaving(false)\n if (fileRef.current) fileRef.current.value = ''\n }\n }\n\n async function removeAvatar() {\n setSaving(true)\n setError('')\n try {\n const next = await api<User>('DELETE', '/users/me/avatar')\n setUser(next)\n await fetchUsers()\n } catch (e) {\n setError((e as Error).message)\n } finally {\n setSaving(false)\n }\n }\n\n return (\n <Card size=\"sm\">\n <CardContent className=\"space-y-4\">\n {error && (\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">\n <AlertCircle className=\"mt-0.5 size-4\" />\n <span>{error}</span>\n </div>\n )}\n <div className=\"flex flex-wrap items-center gap-4\">\n <UserAvatar user={user ?? undefined} distinct className=\"size-16 text-lg\" />\n <div className=\"min-w-0 flex-1 space-y-2\">\n <label className=\"block text-xs font-medium text-muted-foreground\" htmlFor=\"profile-display-name\">Display name</label>\n <input\n id=\"profile-display-name\"\n className=\"h-9 w-full rounded-md border border-input bg-background px-3 text-sm\"\n value={displayName}\n onChange={(e) => setDisplayName(e.target.value)}\n disabled={loading || saving}\n maxLength={120}\n />\n </div>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button size=\"sm\" onClick={() => void saveProfile()} disabled={loading || saving || !displayName.trim()}>\n <Save className=\"size-4\" />\n Save\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={() => fileRef.current?.click()} disabled={loading || saving}>\n <Upload className=\"size-4\" />\n Upload\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={() => void removeAvatar()} disabled={loading || saving || !user?.avatarArtifactId}>\n <Trash2 className=\"size-4\" />\n Remove\n </Button>\n {saving && <Camera className=\"size-4 animate-pulse text-muted-foreground\" />}\n <input\n ref={fileRef}\n type=\"file\"\n accept=\"image/png,image/jpeg,image/gif,image/webp\"\n className=\"hidden\"\n onChange={(e) => void uploadAvatar(e.target.files?.[0])}\n />\n </div>\n </CardContent>\n </Card>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"settings-DGPpdFoq.js","names":[],"sources":["../../dashboard/src/components/settings/schema-utils.ts","../../dashboard/src/components/settings/schema-form.tsx","../../dashboard/src/components/settings/browser-settings.tsx","../../dashboard/src/components/settings/model-catalog-settings.tsx","../../dashboard/src/components/settings/quota-settings.tsx","../../dashboard/src/components/views/settings.tsx"],"sourcesContent":["import { isRecord, type JSONSchema, type SettingEntry } from 'agent-relay-sdk/types'\n\nexport { hasScope } from 'agent-relay-sdk/types'\nexport type { SettingEntry }\n\ninterface SettingGroup {\n group: string\n slug: string\n settings: SettingEntry[]\n}\n\nexport type Path = Array<string | number>\n\nexport function settingId(setting: Pick<SettingEntry, 'namespace' | 'key'>): string {\n return `${setting.namespace}/${setting.key}`\n}\n\nexport function settingPath(setting: Pick<SettingEntry, 'namespace' | 'key'>): string {\n return `/settings/${encodeURIComponent(setting.namespace)}/${encodeURIComponent(setting.key)}`\n}\n\nexport function slugify(value: string): string {\n return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'settings'\n}\n\nexport function groupSettings(settings: SettingEntry[]): SettingGroup[] {\n const groups = new Map<string, SettingEntry[]>()\n for (const setting of settings.filter((entry) => entry.readable)) {\n const group = setting.display?.group?.trim() || setting.namespace\n groups.set(group, [...(groups.get(group) ?? []), setting])\n }\n return [...groups.entries()]\n .map(([group, items]) => ({\n group,\n slug: slugify(group),\n settings: items.sort(compareSettings),\n }))\n .sort((a, b) => groupOrder(a.settings) - groupOrder(b.settings) || a.group.localeCompare(b.group))\n}\n\nfunction compareSettings(a: SettingEntry, b: SettingEntry): number {\n return (a.display?.order ?? Number.MAX_SAFE_INTEGER) - (b.display?.order ?? Number.MAX_SAFE_INTEGER)\n || a.display?.label?.localeCompare(b.display?.label ?? '') || 0\n || settingId(a).localeCompare(settingId(b))\n}\n\nfunction groupOrder(settings: SettingEntry[]): number {\n return Math.min(...settings.map((setting) => setting.display?.order ?? Number.MAX_SAFE_INTEGER))\n}\n\nexport function schemaType(schema: JSONSchema): string | undefined {\n return Array.isArray(schema.type) ? schema.type.find((type) => type !== 'null') : schema.type\n}\n\nexport function valueAtPath(value: unknown, path: Path): unknown {\n let current = value\n for (const part of path) {\n if (typeof part === 'number') {\n if (!Array.isArray(current)) return undefined\n current = current[part]\n } else {\n if (!isRecord(current)) return undefined\n current = current[part]\n }\n }\n return current\n}\n\nexport function setValueAtPath(value: unknown, path: Path, next: unknown): unknown {\n if (!path.length) return next\n const [head, ...tail] = path\n if (head === undefined) return next\n if (typeof head === 'number') {\n const array = Array.isArray(value) ? [...value] : []\n array[head] = setValueAtPath(array[head], tail, next)\n return array\n }\n const record = isRecord(value) ? { ...value } : {}\n const updated = setValueAtPath(record[head], tail, next)\n if (updated === undefined) delete record[head]\n else record[head] = updated\n return record\n}\n\nexport function defaultValueForSchema(schema: JSONSchema): unknown {\n if (schema.default !== undefined) return schema.default\n if (schema.const !== undefined) return schema.const\n if (schema.enum?.length) return schema.enum[0]\n switch (schemaType(schema)) {\n case 'boolean': return false\n case 'integer':\n case 'number': return 0\n case 'array': return []\n case 'object': return {}\n case 'string': return ''\n default: return undefined\n }\n}\n\nexport function lines(value: string): string[] {\n return value.split(/\\r?\\n|,/).map((line) => line.trim()).filter(Boolean)\n}\n\nexport function arrayText(value: unknown): string {\n return Array.isArray(value) ? value.map((item) => String(item)).join('\\n') : ''\n}\n\nexport function recordText(value: unknown): string {\n if (!isRecord(value)) return ''\n return Object.entries(value).map(([key, item]) => `${key}=${String(item ?? '')}`).join('\\n')\n}\n\nexport function parseRecordText(value: string): Record<string, string> {\n return Object.fromEntries(value.split(/\\r?\\n/).map((raw) => raw.trim()).filter(Boolean).map((line) => {\n const idx = line.indexOf('=')\n return idx >= 0 ? [line.slice(0, idx).trim(), line.slice(idx + 1)] : [line, '']\n }))\n}\n\nexport { isRecord }\n","import { useState, type ReactNode } from 'react'\nimport type { JSONSchema, SettingTier } from 'agent-relay-sdk/types'\nimport { api, type ApiError } from '@/lib/api'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Textarea } from '@/components/ui/textarea'\nimport { Switch } from '@/components/ui/switch'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { Badge } from '@/components/ui/badge'\nimport { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport { AlertCircle, CheckCircle2, MonitorCog, Save, ServerCog } from 'lucide-react'\nimport {\n arrayText,\n defaultValueForSchema,\n isRecord,\n lines,\n parseRecordText,\n recordText,\n schemaType,\n setValueAtPath,\n settingId,\n settingPath,\n type Path,\n type SettingEntry,\n} from './schema-utils'\n\nexport const UNSET = '__unset__'\n\nfunction tierLabel(tier: SettingTier): string {\n if (tier === 'server-runtime') return 'Server runtime'\n if (tier === 'bootstrap') return 'Bootstrap'\n return 'Browser'\n}\n\nfunction tierDescription(tier: SettingTier): string {\n if (tier === 'server-runtime') return 'Stored by Relay and mutable while the server is running.'\n if (tier === 'bootstrap') return 'Read from startup configuration; restart or host config changes are required.'\n return 'Stored only in this browser profile.'\n}\n\nfunction tierIcon(tier: SettingTier) {\n if (tier === 'browser') return <MonitorCog className=\"size-3.5\" />\n return <ServerCog className=\"size-3.5\" />\n}\n\nexport function errorDetails(error: unknown): string[] {\n return (error as ApiError).details ?? []\n}\n\nexport function SchemaGroup({ group, settings, onSaved }: { group: string; settings: SettingEntry[]; onSaved: (setting: SettingEntry) => void }) {\n const tiers = [...new Set(settings.map((setting) => setting.tier))]\n return (\n <section className=\"space-y-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <h2 className=\"text-base font-semibold\">{group}</h2>\n <div className=\"flex flex-wrap gap-1\">\n {tiers.map((tier) => (\n <Badge key={tier} variant=\"outline\" className=\"gap-1\" title={tierDescription(tier)}>\n {tierIcon(tier)}\n {tierLabel(tier)}\n </Badge>\n ))}\n </div>\n </div>\n {settings.length === 0 ? (\n <Card size=\"sm\">\n <CardContent className=\"text-sm text-muted-foreground\">No settings in this group.</CardContent>\n </Card>\n ) : (\n <div className=\"space-y-3\">\n {settings.map((setting) => (\n <SettingCard key={settingId(setting)} setting={setting} onSaved={onSaved} />\n ))}\n </div>\n )}\n </section>\n )\n}\n\nfunction SettingCard({ setting, onSaved }: { setting: SettingEntry; onSaved: (setting: SettingEntry) => void }) {\n const [draft, setDraft] = useState<unknown>(() => setting.value ?? setting.defaults ?? defaultValueForSchema(setting.schema))\n const [saving, setSaving] = useState(false)\n const [status, setStatus] = useState('')\n const [errors, setErrors] = useState<string[]>([])\n const isWritable = setting.writable && setting.tier === 'server-runtime'\n\n function update(path: Path, value: unknown) {\n setDraft((current: unknown) => setValueAtPath(current, path, value))\n setErrors([])\n setStatus('')\n }\n\n async function save() {\n if (!isWritable) return\n setSaving(true)\n setErrors([])\n setStatus('')\n try {\n const saved = await api<SettingEntry>('PUT', settingPath(setting), { value: draft, updatedBy: 'dashboard' })\n setDraft(saved.value)\n onSaved(saved)\n setStatus('Saved')\n } catch (e) {\n const details = errorDetails(e)\n setErrors(details.length ? details : [(e as Error).message])\n } finally {\n setSaving(false)\n }\n }\n\n return (\n <Card size=\"sm\">\n <CardHeader>\n <CardTitle className=\"flex flex-wrap items-center gap-2 text-sm\">\n {setting.display.label}\n <Badge variant=\"outline\" className=\"gap-1\" title={tierDescription(setting.tier)}>{tierIcon(setting.tier)}{tierLabel(setting.tier)}</Badge>\n {!setting.writable && <Badge variant=\"secondary\">Read only</Badge>}\n </CardTitle>\n {setting.display.description && <CardDescription>{setting.display.description}</CardDescription>}\n <CardAction>\n <Button size=\"sm\" onClick={save} disabled={!isWritable || saving}>\n <Save className=\"size-4\" />\n {saving ? 'Saving' : 'Save'}\n </Button>\n </CardAction>\n </CardHeader>\n\n <CardContent className=\"space-y-3\">\n <SchemaField\n schema={setting.schema}\n value={draft}\n path={[]}\n label={setting.display.label}\n required\n disabled={!isWritable || saving}\n onChange={update}\n />\n\n <p className=\"flex flex-wrap items-center gap-x-2 text-[11px] text-muted-foreground\">\n <code className=\"rounded bg-muted px-1.5 py-0.5 font-mono\">{setting.namespace}/{setting.key}</code>\n <span>read <span className=\"text-foreground/70\">{setting.scope.read}</span></span>\n <span aria-hidden>·</span>\n <span>write <span className=\"text-foreground/70\">{setting.scope.write}</span></span>\n </p>\n\n {errors.length > 0 && (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">\n <div className=\"mb-1 flex items-center gap-2 font-medium\"><AlertCircle className=\"size-4\" />Save failed</div>\n <ul className=\"list-disc space-y-1 pl-5\">\n {errors.map((detail) => <li key={detail}>{detail}</li>)}\n </ul>\n </div>\n )}\n {status && <p className=\"flex items-center gap-1 text-sm text-emerald-500\"><CheckCircle2 className=\"size-4\" />{status}</p>}\n </CardContent>\n </Card>\n )\n}\n\nfunction SchemaField(props: {\n schema: JSONSchema\n value: unknown\n path: Path\n label: string\n required: boolean\n disabled: boolean\n onChange: (path: Path, value: unknown) => void\n}) {\n const { schema, value, path, label, required, disabled, onChange } = props\n const type = schemaType(schema)\n\n if (schema.enum?.length) {\n const current = value === undefined || value === null || value === '' ? UNSET : String(value)\n return (\n <Field label={label} description={schema.description}>\n <Select value={current} onValueChange={(next) => onChange(path, next === UNSET ? undefined : next)} disabled={disabled}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {!required && <SelectItem value={UNSET}>Not set</SelectItem>}\n {schema.enum.map((item) => <SelectItem key={String(item)} value={String(item)}>{String(item)}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n )\n }\n\n if (type === 'boolean') {\n return (\n <div className=\"flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3\">\n <div>\n <div className=\"text-sm font-medium\">{label}</div>\n {schema.description && <div className=\"text-xs text-muted-foreground\">{schema.description}</div>}\n </div>\n <Switch checked={Boolean(value)} onCheckedChange={(next) => onChange(path, next)} disabled={disabled} />\n </div>\n )\n }\n\n if (type === 'integer' || type === 'number') {\n return (\n <Field label={label} description={schema.description}>\n <Input\n type=\"number\"\n min={typeof schema.minimum === 'number' ? schema.minimum : undefined}\n max={typeof schema.maximum === 'number' ? schema.maximum : undefined}\n step={type === 'integer' ? 1 : 'any'}\n value={typeof value === 'number' ? value : ''}\n disabled={disabled}\n onChange={(e) => onChange(path, e.target.value === '' && !required ? undefined : Number(e.target.value))}\n />\n </Field>\n )\n }\n\n if (type === 'array') {\n return (\n <Field label={label} description={schema.description ?? 'One item per line.'}>\n <Textarea\n rows={Math.min(8, Math.max(3, Array.isArray(value) ? value.length + 1 : 3))}\n value={arrayText(value)}\n disabled={disabled}\n onChange={(e) => onChange(path, lines(e.target.value))}\n />\n </Field>\n )\n }\n\n if (type === 'object') {\n const properties = schema.properties ?? {}\n const requiredKeys = new Set(schema.required ?? [])\n if (Object.keys(properties).length === 0 && schema.additionalProperties) {\n return (\n <Field label={label} description={schema.description ?? 'KEY=value, one entry per line.'}>\n <Textarea rows={5} value={recordText(value)} disabled={disabled} onChange={(e) => onChange(path, parseRecordText(e.target.value))} />\n </Field>\n )\n }\n return (\n <div className=\"space-y-3\">\n {path.length > 0 && (\n <div>\n <div className=\"text-sm font-medium\">{label}</div>\n {schema.description && <div className=\"text-xs text-muted-foreground\">{schema.description}</div>}\n </div>\n )}\n <div className=\"grid gap-3 md:grid-cols-2\">\n {Object.entries(properties).map(([key, child]) => {\n const childValue = isRecord(value) ? value[key] : undefined\n return (\n <SchemaField\n key={key}\n schema={child}\n value={childValue === undefined && requiredKeys.has(key) ? defaultValueForSchema(child) : childValue}\n path={[...path, key]}\n label={child.title || labelForKey(key)}\n required={requiredKeys.has(key)}\n disabled={disabled}\n onChange={onChange}\n />\n )\n })}\n </div>\n </div>\n )\n }\n\n return (\n <Field label={label} description={schema.description}>\n <Input\n value={typeof value === 'string' ? value : value == null ? '' : String(value)}\n disabled={disabled}\n onChange={(e) => onChange(path, e.target.value === '' && !required ? undefined : e.target.value)}\n />\n </Field>\n )\n}\n\nexport function Field({ label, description, children }: { label: string; description?: string; children: ReactNode }) {\n return (\n <label className=\"block space-y-1.5 text-sm\">\n <span className=\"text-muted-foreground\">{label}</span>\n {children}\n {description && <span className=\"block text-xs text-muted-foreground\">{description}</span>}\n </label>\n )\n}\n\nfunction labelForKey(key: string): string {\n return key.replace(/([a-z0-9])([A-Z])/g, '$1 $2').replace(/[-_]+/g, ' ').replace(/^\\w/, (char) => char.toUpperCase())\n}\n","import { useEffect, useState } from 'react'\nimport { THEMES } from '@/lib/themes'\nimport { KOKORO_VOICES, availableSpeechVoices } from '@/lib/voice'\nimport { useRelayStore } from '@/store'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { Switch } from '@/components/ui/switch'\nimport { Badge } from '@/components/ui/badge'\nimport { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Brain, MonitorCog, Volume2 } from 'lucide-react'\nimport type { ThemeId } from '@/types'\nimport { Field, UNSET } from './schema-form'\n\nexport function BrowserSettings() {\n const theme = useRelayStore((s) => s.theme)\n const showReasoning = useRelayStore((s) => s.showReasoning)\n const set = useRelayStore((s) => s.set)\n return (\n <section className=\"space-y-4\">\n <div>\n <h2 className=\"text-base font-semibold\">Browser preferences</h2>\n <p className=\"text-sm text-muted-foreground\">These are stored in local dashboard state, not in Relay server config.</p>\n </div>\n <Card size=\"sm\">\n <CardHeader>\n <CardTitle className=\"text-sm\">Dashboard display</CardTitle>\n <CardDescription className=\"text-xs\">Browser tier · persisted in this browser profile.</CardDescription>\n <CardAction>\n <Badge variant=\"outline\" className=\"gap-1\"><MonitorCog className=\"size-3.5\" />Browser</Badge>\n </CardAction>\n </CardHeader>\n <CardContent className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Theme\">\n <Select value={theme} onValueChange={(value) => set({ theme: value as ThemeId })}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {THEMES.map((item) => <SelectItem key={item.id} value={item.id}>{item.label}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n <div className=\"flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3\">\n <div className=\"flex items-center gap-2\">\n <Brain className=\"size-4\" />\n <div>\n <div className=\"text-sm font-medium\">Show reasoning details</div>\n <div className=\"text-xs text-muted-foreground\">Display captured reasoning/tool steps in chat. Server capture is controlled separately by provider reasoningCapture.</div>\n </div>\n </div>\n <Switch checked={showReasoning} onCheckedChange={(value) => set({ showReasoning: value })} />\n </div>\n </CardContent>\n </Card>\n <VoiceSettings />\n </section>\n )\n}\n\nfunction VoiceSettings() {\n const voiceTtsEnabled = useRelayStore((s) => s.voiceTtsEnabled)\n const setVoiceTtsEnabled = useRelayStore((s) => s.setVoiceTtsEnabled)\n const voiceTtsMode = useRelayStore((s) => s.voiceTtsMode)\n const setVoiceTtsMode = useRelayStore((s) => s.setVoiceTtsMode)\n const voiceTtsKokoroVoice = useRelayStore((s) => s.voiceTtsKokoroVoice)\n const setVoiceTtsKokoroVoice = useRelayStore((s) => s.setVoiceTtsKokoroVoice)\n const voiceTtsBrowserVoice = useRelayStore((s) => s.voiceTtsBrowserVoice)\n const setVoiceTtsBrowserVoice = useRelayStore((s) => s.setVoiceTtsBrowserVoice)\n const voiceInputMode = useRelayStore((s) => s.voiceInputMode)\n const setVoiceInputMode = useRelayStore((s) => s.setVoiceInputMode)\n\n // External sync: the browser loads speech voices asynchronously.\n const [browserVoices, setBrowserVoices] = useState(() => availableSpeechVoices())\n useEffect(() => {\n if (typeof window === 'undefined' || !('speechSynthesis' in window)) return\n const refresh = () => setBrowserVoices(availableSpeechVoices())\n refresh()\n window.speechSynthesis.addEventListener?.('voiceschanged', refresh)\n return () => window.speechSynthesis.removeEventListener?.('voiceschanged', refresh)\n }, [])\n\n const kokoroOptions = KOKORO_VOICES.some((voice) => voice.id === voiceTtsKokoroVoice)\n ? KOKORO_VOICES\n : [...KOKORO_VOICES, { id: voiceTtsKokoroVoice, label: voiceTtsKokoroVoice }]\n\n return (\n <Card size=\"sm\">\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-sm\"><Volume2 className=\"size-4\" />Voice</CardTitle>\n <CardDescription className=\"text-xs\">Browser tier TTS and push-to-talk behavior.</CardDescription>\n <CardAction>\n <Switch checked={voiceTtsEnabled} onCheckedChange={setVoiceTtsEnabled} />\n </CardAction>\n </CardHeader>\n <CardContent className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Speech engine\">\n <Select value={voiceTtsMode} onValueChange={(value) => setVoiceTtsMode(value as 'kokoro' | 'browser')}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"kokoro\">Kokoro (server, fallback to browser)</SelectItem>\n <SelectItem value=\"browser\">Browser Web Speech API</SelectItem>\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Kokoro voice\">\n <Select value={voiceTtsKokoroVoice} onValueChange={setVoiceTtsKokoroVoice}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {kokoroOptions.map((voice) => <SelectItem key={voice.id} value={voice.id}>{voice.label}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Browser voice\">\n <Select value={voiceTtsBrowserVoice || UNSET} onValueChange={(value) => setVoiceTtsBrowserVoice(value === UNSET ? '' : value)}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value={UNSET}>System default</SelectItem>\n {browserVoices.map((voice) => <SelectItem key={voice.uri} value={voice.uri}>{voice.label}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Push-to-talk input\">\n <Select value={voiceInputMode} onValueChange={(value) => setVoiceInputMode(value as 'compose' | 'autosend' | 'handsfree')}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"compose\">Fill message box</SelectItem>\n <SelectItem value=\"autosend\">Send immediately</SelectItem>\n </SelectContent>\n </Select>\n </Field>\n </CardContent>\n </Card>\n )\n}\n","import { useState } from 'react'\nimport type { SpawnProvider } from 'agent-relay-sdk/types'\nimport { deriveContextThresholdFromWindowTokens, type ProviderCatalogEntry, type ProviderModelCatalogEntry } from 'agent-relay-sdk/provider-catalog'\nimport { api } from '@/lib/api'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Switch } from '@/components/ui/switch'\nimport { Badge } from '@/components/ui/badge'\nimport { Card, CardAction, CardContent, CardHeader, CardTitle } from '@/components/ui/card'\nimport { CheckCircle2, Eye, EyeOff, Pencil, Plus, ServerCog, SlidersHorizontal, Trash2 } from 'lucide-react'\nimport { errorDetails, Field } from './schema-form'\nimport { lines } from './schema-utils'\n\ninterface ProvidersResponse {\n catalog: ProviderCatalogEntry[]\n}\n\ninterface ModelForm {\n provider: SpawnProvider\n alias: string\n label: string\n providerModel: string\n efforts: string\n defaultEffort: string\n selfCompactUtilization: string\n warnUtilization: string\n hardBackstopUtilization: string\n disabled: boolean\n limits?: ProviderModelCatalogEntry['limits']\n capabilities?: ProviderModelCatalogEntry['capabilities']\n}\n\nexport function ModelCatalogSettings({\n catalog,\n error,\n canWrite,\n onCatalog,\n}: {\n catalog: ProviderCatalogEntry[]\n error: string\n canWrite: boolean\n onCatalog: (catalog: ProviderCatalogEntry[]) => void\n}) {\n const firstProvider = catalog[0]?.provider ?? 'codex'\n const [provider, setProvider] = useState<SpawnProvider>(firstProvider)\n const [form, setForm] = useState<ModelForm>(() => emptyModelForm(firstProvider))\n const [status, setStatus] = useState('')\n const [errors, setErrors] = useState<string[]>([])\n\n const selectedProvider = catalog.some((entry) => entry.provider === provider) ? provider : firstProvider\n const selectedCatalog = catalog.find((entry) => entry.provider === selectedProvider) ?? catalog[0]\n const providers = catalog.map((entry) => entry.provider)\n\n function updateForm(patch: Partial<ModelForm>) {\n setForm((current) => ({ ...current, ...patch }))\n setErrors([])\n setStatus('')\n }\n\n function switchProvider(next: SpawnProvider) {\n setProvider(next)\n setForm(emptyModelForm(next))\n setErrors([])\n setStatus('')\n }\n\n async function reloadCatalog() {\n const res = await api<ProvidersResponse>('GET', '/providers')\n onCatalog(res.catalog)\n }\n\n async function saveModel() {\n if (!canWrite) return\n setErrors([])\n setStatus('')\n try {\n await api('PUT', `/providers/${encodeURIComponent(form.provider)}/models/${encodeURIComponent(form.alias)}`, {\n label: form.label,\n providerModel: form.providerModel,\n efforts: lines(form.efforts),\n defaultEffort: form.defaultEffort.trim() || undefined,\n limits: form.limits,\n capabilities: form.capabilities,\n contextThreshold: contextThresholdFromForm(form),\n disabled: form.disabled,\n updatedBy: 'dashboard',\n })\n await reloadCatalog()\n setStatus(`${form.alias} saved`)\n setForm(emptyModelForm(form.provider))\n } catch (e) {\n const details = errorDetails(e)\n setErrors(details.length ? details : [(e as Error).message])\n }\n }\n\n async function setDisabled(model: ProviderModelCatalogEntry, disabled: boolean) {\n if (!canWrite) return\n setErrors([])\n setStatus('')\n try {\n await api('PATCH', `/providers/${encodeURIComponent(selectedProvider)}/models/${encodeURIComponent(model.alias)}`, { disabled, updatedBy: 'dashboard' })\n await reloadCatalog()\n setStatus(`${model.alias} ${disabled ? 'disabled' : 'enabled'}`)\n } catch (e) {\n const details = errorDetails(e)\n setErrors(details.length ? details : [(e as Error).message])\n }\n }\n\n async function removeModel(model: ProviderModelCatalogEntry) {\n if (!canWrite) return\n setErrors([])\n setStatus('')\n try {\n await api('DELETE', `/providers/${encodeURIComponent(selectedProvider)}/models/${encodeURIComponent(model.alias)}`)\n await reloadCatalog()\n setStatus(`${model.alias} removed`)\n } catch (e) {\n const details = errorDetails(e)\n setErrors(details.length ? details : [(e as Error).message])\n }\n }\n\n function editModel(model: ProviderModelCatalogEntry) {\n setForm({\n provider: selectedProvider,\n alias: model.alias,\n label: model.label,\n providerModel: model.providerModel,\n efforts: model.efforts.join(', '),\n defaultEffort: model.defaultEffort ?? '',\n selfCompactUtilization: model.contextThreshold?.selfCompactUtilization?.toString() ?? '',\n warnUtilization: model.contextThreshold?.warnUtilization?.toString() ?? '',\n hardBackstopUtilization: model.contextThreshold?.hardBackstopUtilization?.toString() ?? '',\n disabled: Boolean(model.disabled),\n limits: model.limits,\n capabilities: model.capabilities,\n })\n setErrors([])\n setStatus('')\n }\n\n if (error) {\n return (\n <Card size=\"sm\">\n <CardContent className=\"text-sm text-muted-foreground\">\n <div className=\"mb-1 flex items-center gap-2 font-medium text-foreground\"><SlidersHorizontal className=\"size-4\" />Model catalog</div>\n {error}\n </CardContent>\n </Card>\n )\n }\n\n return (\n <section className=\"space-y-4\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div>\n <h2 className=\"text-base font-semibold\">Model catalog</h2>\n <p className=\"text-sm text-muted-foreground\">Add override models, disable unavailable models, or remove custom entries from the provider catalog.</p>\n </div>\n {!canWrite && <Badge variant=\"secondary\">Read only: needs settings:write:provider</Badge>}\n </div>\n\n <div className=\"flex flex-wrap gap-2\">\n {providers.map((item) => (\n <Button key={item} variant={item === selectedProvider ? 'default' : 'outline'} size=\"sm\" onClick={() => switchProvider(item)}>\n {item}\n </Button>\n ))}\n </div>\n\n <Card size=\"sm\">\n <CardHeader>\n <CardTitle className=\"text-sm\">Add or edit model</CardTitle>\n <CardAction>\n <Badge variant=\"outline\" className=\"gap-1\"><ServerCog className=\"size-3.5\" />Server runtime</Badge>\n </CardAction>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <div className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Alias\">\n <Input value={form.alias} disabled={!canWrite} placeholder=\"nightly\" onChange={(e) => updateForm({ alias: e.target.value.trim() })} />\n </Field>\n <Field label=\"Label\">\n <Input value={form.label} disabled={!canWrite} placeholder=\"Nightly Codex\" onChange={(e) => updateForm({ label: e.target.value })} />\n </Field>\n <Field label=\"Provider model\">\n <Input value={form.providerModel} disabled={!canWrite} placeholder=\"codex-nightly\" onChange={(e) => updateForm({ providerModel: e.target.value })} />\n </Field>\n <Field label=\"Efforts\">\n <Input value={form.efforts} disabled={!canWrite} placeholder=\"low, medium, high\" onChange={(e) => updateForm({ efforts: e.target.value })} />\n </Field>\n <Field label=\"Default effort\">\n <Input value={form.defaultEffort} disabled={!canWrite} placeholder=\"medium\" onChange={(e) => updateForm({ defaultEffort: e.target.value })} />\n </Field>\n <Field label=\"Self compact utilization\">\n <Input value={form.selfCompactUtilization} disabled={!canWrite} placeholder=\"0.80\" inputMode=\"decimal\" onChange={(e) => updateForm({ selfCompactUtilization: e.target.value })} />\n </Field>\n <Field label=\"Warn utilization\">\n <Input value={form.warnUtilization} disabled={!canWrite} placeholder=\"default: self - 0.10\" inputMode=\"decimal\" onChange={(e) => updateForm({ warnUtilization: e.target.value })} />\n </Field>\n <Field label=\"Hard backstop utilization\">\n <Input value={form.hardBackstopUtilization} disabled={!canWrite} placeholder=\"0.90\" inputMode=\"decimal\" onChange={(e) => updateForm({ hardBackstopUtilization: e.target.value })} />\n </Field>\n <div className=\"flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3\">\n <div>\n <div className=\"text-sm font-medium\">Disabled</div>\n <div className=\"text-xs text-muted-foreground\">Keep visible but unavailable for new launches.</div>\n </div>\n <Switch checked={form.disabled} disabled={!canWrite} onCheckedChange={(disabled) => updateForm({ disabled })} />\n </div>\n </div>\n <Button onClick={saveModel} disabled={!canWrite || !form.alias || !form.label || !form.providerModel}>\n <Plus className=\"size-4\" />\n Save model\n </Button>\n </CardContent>\n </Card>\n\n <div className=\"space-y-2\">\n {selectedCatalog && selectedCatalog.models.length === 0 && (\n <Card size=\"sm\">\n <CardContent className=\"text-sm text-muted-foreground\">No models in this provider catalog yet.</CardContent>\n </Card>\n )}\n {selectedCatalog?.models.map((model) => (\n <Card key={model.alias} size=\"sm\">\n <CardContent className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-medium\">{model.label}</span>\n <code className=\"rounded bg-muted px-1.5 py-0.5 font-mono text-xs\">{model.alias}</code>\n {model.disabled && <Badge variant=\"secondary\">Disabled</Badge>}\n </div>\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {model.providerModel}\n {model.efforts.length > 0 ? ` · efforts ${model.efforts.join(', ')}` : ' · no effort levels'}\n {model.defaultEffort ? ` · default ${model.defaultEffort}` : ''}\n {` · context ${thresholdLabel(model)}`}\n </p>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => editModel(model)}>\n <Pencil className=\"size-4\" />\n Edit\n </Button>\n <Button variant=\"outline\" size=\"sm\" disabled={!canWrite} onClick={() => void setDisabled(model, !model.disabled)}>\n {model.disabled ? <Eye className=\"size-4\" /> : <EyeOff className=\"size-4\" />}\n {model.disabled ? 'Enable' : 'Disable'}\n </Button>\n <Button variant=\"outline\" size=\"sm\" disabled={!canWrite} onClick={() => void removeModel(model)}>\n <Trash2 className=\"size-4\" />\n Remove\n </Button>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n\n {errors.length > 0 && (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">\n <ul className=\"list-disc space-y-1 pl-5\">\n {errors.map((detail) => <li key={detail}>{detail}</li>)}\n </ul>\n </div>\n )}\n {status && <p className=\"flex items-center gap-1 text-sm text-emerald-500\"><CheckCircle2 className=\"size-4\" />{status}</p>}\n </section>\n )\n}\n\nfunction emptyModelForm(provider: SpawnProvider): ModelForm {\n return { provider, alias: '', label: '', providerModel: '', efforts: '', defaultEffort: '', selfCompactUtilization: '', warnUtilization: '', hardBackstopUtilization: '', disabled: false }\n}\n\nfunction contextThresholdFromForm(form: ModelForm): ProviderModelCatalogEntry['contextThreshold'] | undefined {\n const selfCompactUtilization = optionalNumber(form.selfCompactUtilization, 'Self compact utilization')\n const warnUtilization = optionalNumber(form.warnUtilization, 'Warn utilization')\n const hardBackstopUtilization = optionalNumber(form.hardBackstopUtilization, 'Hard backstop utilization')\n if (selfCompactUtilization === undefined && warnUtilization === undefined && hardBackstopUtilization === undefined) return undefined\n if (selfCompactUtilization === undefined) throw new Error('Self compact utilization is required when setting context thresholds')\n return {\n selfCompactUtilization,\n ...(warnUtilization !== undefined ? { warnUtilization } : {}),\n ...(hardBackstopUtilization !== undefined ? { hardBackstopUtilization } : {}),\n }\n}\n\nfunction optionalNumber(value: string, label: string): number | undefined {\n const trimmed = value.trim()\n if (!trimmed) return undefined\n const parsed = Number(trimmed)\n if (!Number.isFinite(parsed)) throw new Error(`${label} must be a number`)\n return parsed\n}\n\nfunction thresholdLabel(model: ProviderModelCatalogEntry): string {\n if (model.contextThreshold) {\n const self = percent(model.contextThreshold.selfCompactUtilization)\n const warn = percent(model.contextThreshold.warnUtilization ?? Math.max(0, model.contextThreshold.selfCompactUtilization - 0.1))\n return `self ${self}, warn ${warn}`\n }\n const derived = deriveContextThresholdFromWindowTokens(model.limits?.contextWindowTokens?.value)\n return `derived self ${percent(derived.selfCompactUtilization)}, warn ${percent(derived.warnUtilization)}`\n}\n\nfunction percent(value: number): string {\n return `${Math.round(value * 100)}%`\n}\n","import { useEffect, useState } from 'react'\nimport type { ProviderQuotaConfig, ProviderQuotaConfigMap } from 'agent-relay-sdk/types'\nimport { api } from '@/lib/api'\nimport { Switch } from '@/components/ui/switch'\nimport { Badge } from '@/components/ui/badge'\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport { AlertCircle, Gauge, Loader2 } from 'lucide-react'\n\n// Quota config block under Settings → Providers (#605). Per provider: enable\n// collection, poll cadence (5m–15m), and show-in-widget. enabled = collect,\n// showInWidget = display — disabling collection stops the orchestrator polling\n// that provider entirely; hiding only removes it from the dashboard widget.\nconst MIN_MINUTES = 5\nconst MAX_MINUTES = 15\n\nconst PROVIDER_LABELS: Record<string, string> = { claude: 'Claude', codex: 'Codex' }\n\nfunction minutesOf(pollIntervalMs: number): number {\n return Math.round(pollIntervalMs / 60_000)\n}\n\nfunction intervalLabel(pollIntervalMs: number): string {\n return `${minutesOf(pollIntervalMs)} min`\n}\n\nexport function QuotaSettings({ canWrite }: { canWrite: boolean }) {\n const [config, setConfig] = useState<ProviderQuotaConfigMap | null>(null)\n const [loadError, setLoadError] = useState('')\n const [saveError, setSaveError] = useState('')\n const [savingProvider, setSavingProvider] = useState<string | null>(null)\n\n // External data load on mount — mirrors the SettingsView reload() pattern.\n useEffect(() => {\n let cancelled = false\n void (async () => {\n try {\n const data = await api<ProviderQuotaConfigMap>('GET', '/providers/quota-config')\n if (!cancelled) setConfig(data)\n } catch (e) {\n if (!cancelled) setLoadError((e as Error).message)\n }\n })()\n return () => { cancelled = true }\n }, [])\n\n async function save(provider: string, next: ProviderQuotaConfig) {\n setConfig((current) => ({ ...(current ?? {}), [provider]: next }))\n setSaveError('')\n setSavingProvider(provider)\n try {\n const saved = await api<ProviderQuotaConfig>('PUT', `/providers/${provider}/quota-config`, next)\n setConfig((current) => ({ ...(current ?? {}), [provider]: saved }))\n } catch (e) {\n setSaveError(`${PROVIDER_LABELS[provider] ?? provider}: ${(e as Error).message}`)\n } finally {\n setSavingProvider(null)\n }\n }\n\n const providers = config ? Object.keys(config).sort() : []\n\n return (\n <section className=\"space-y-4\">\n <div>\n <h2 className=\"text-base font-semibold\">Quota</h2>\n <p className=\"text-sm text-muted-foreground\">\n Per-provider quota collection and display. <strong>Enabled</strong> governs collection (disabled stops polling — no API calls);\n <strong> Show in widget</strong> governs display only.\n </p>\n </div>\n\n {loadError && (\n <div className=\"flex items-start gap-2 rounded-lg border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">\n <AlertCircle className=\"mt-0.5 size-4\" />\n <span>{loadError}</span>\n </div>\n )}\n {saveError && (\n <div className=\"flex items-start gap-2 rounded-lg border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">\n <AlertCircle className=\"mt-0.5 size-4\" />\n <span>{saveError}</span>\n </div>\n )}\n\n {!config && !loadError && (\n <Card size=\"sm\"><CardContent className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Loader2 className=\"size-4 animate-spin\" />Loading quota config…\n </CardContent></Card>\n )}\n\n {providers.map((provider) => {\n const cfg = config![provider]!\n const disabled = !canWrite || savingProvider === provider\n return (\n <Card key={provider} size=\"sm\">\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-sm\">\n <Gauge className=\"size-4\" />\n {PROVIDER_LABELS[provider] ?? provider}\n {savingProvider === provider && <Loader2 className=\"size-3 animate-spin text-muted-foreground\" />}\n </CardTitle>\n <CardDescription className=\"text-xs\">\n {cfg.enabled ? `Polled every ${intervalLabel(cfg.pollIntervalMs)}` : 'Collection disabled'}\n {cfg.enabled && !cfg.showInWidget ? ' · hidden from widget' : ''}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3\">\n <div>\n <div className=\"text-sm font-medium\">Enabled</div>\n <div className=\"text-xs text-muted-foreground\">Collect quota for this provider. Off stops all polling (no API calls, no token spend).</div>\n </div>\n <Switch\n checked={cfg.enabled}\n disabled={disabled}\n onCheckedChange={(enabled) => void save(provider, { ...cfg, enabled })}\n />\n </div>\n\n <div className=\"rounded-md border bg-muted/20 p-3 space-y-2\">\n <div className=\"flex items-center justify-between\">\n <div className=\"text-sm font-medium\">Polling interval</div>\n <Badge variant=\"outline\" className=\"tabular-nums\">{intervalLabel(cfg.pollIntervalMs)}</Badge>\n </div>\n <input\n type=\"range\"\n min={MIN_MINUTES}\n max={MAX_MINUTES}\n step={1}\n value={minutesOf(cfg.pollIntervalMs)}\n disabled={disabled || !cfg.enabled}\n // Live label update while dragging; persist on pointer/key release.\n onChange={(e) => {\n const pollIntervalMs = Number(e.target.value) * 60_000\n setConfig((current) => ({ ...(current ?? {}), [provider]: { ...cfg, pollIntervalMs } }))\n }}\n onPointerUp={(e) => void save(provider, { ...cfg, pollIntervalMs: Number((e.target as HTMLInputElement).value) * 60_000 })}\n onKeyUp={(e) => void save(provider, { ...cfg, pollIntervalMs: Number((e.target as HTMLInputElement).value) * 60_000 })}\n className=\"w-full accent-primary disabled:opacity-50\"\n />\n <div className=\"flex justify-between text-[10px] text-muted-foreground\">\n <span>{MIN_MINUTES} min</span>\n <span>{MAX_MINUTES} min</span>\n </div>\n </div>\n\n <div className=\"flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3\">\n <div>\n <div className=\"text-sm font-medium\">Show in quota widget</div>\n <div className=\"text-xs text-muted-foreground\">Display only. Off hides this provider from the dashboard widget; collection continues if enabled.</div>\n </div>\n <Switch\n checked={cfg.showInWidget}\n disabled={disabled}\n onCheckedChange={(showInWidget) => void save(provider, { ...cfg, showInWidget })}\n />\n </div>\n </CardContent>\n </Card>\n )\n })}\n </section>\n )\n}\n","import { useEffect, useMemo, useRef, useState } from 'react'\nimport type { ProviderCatalogEntry } from 'agent-relay-sdk/provider-catalog'\nimport { api, apiUpload } from '@/lib/api'\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\nimport { Badge } from '@/components/ui/badge'\nimport { Card, CardContent } from '@/components/ui/card'\nimport { AlertCircle, Camera, Globe2, RefreshCw, Route, Save, Trash2, Upload } from 'lucide-react'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { Textarea } from '@/components/ui/textarea'\nimport { BrowserSettings } from '@/components/settings/browser-settings'\nimport { ModelCatalogSettings } from '@/components/settings/model-catalog-settings'\nimport { QuotaSettings } from '@/components/settings/quota-settings'\nimport { SchemaGroup } from '@/components/settings/schema-form'\nimport { UserAvatar } from '@/components/shared/user-avatar'\nimport { useRelayStore } from '@/store'\nimport {\n groupSettings,\n hasScope,\n settingId,\n type SettingEntry,\n} from '@/components/settings/schema-utils'\nimport type { Artifact, NotificationRoutingPreview, User } from '@/types'\n\ninterface SettingsResponse {\n settings: SettingEntry[]\n}\n\ninterface TokenMe {\n actor: string\n kind: string\n role?: string\n scopes: string[]\n}\n\ninterface ProvidersResponse {\n catalog: ProviderCatalogEntry[]\n}\n\ninterface NotificationPreviewResponse {\n preview: NotificationRoutingPreview\n}\n\nconst BROWSER_GROUP_SLUG = 'browser'\nconst MODELS_GROUP_SLUG = 'models'\nconst PROFILE_GROUP_SLUG = 'profile'\nconst NOTIFICATION_TYPES = [\n 'branch.landed',\n 'landed-failure',\n 'agent.ready',\n 'agent.exited',\n 'agent.spawn_failed',\n 'agent.context_threshold',\n 'agent.quota_threshold',\n 'workspace.steward_task',\n 'workspace.conflict',\n 'workspace.review_request',\n]\n\nfunction settingsHash(): string {\n if (typeof window === 'undefined') return ''\n const hash = window.location.hash.replace(/^#/, '')\n if (!hash.startsWith('settings/')) return ''\n return decodeURIComponent(hash.slice('settings/'.length))\n}\n\nfunction writeSettingsHash(slug: string): void {\n if (typeof window === 'undefined') return\n const url = new URL(window.location.href)\n url.hash = `settings/${encodeURIComponent(slug)}`\n window.history.pushState({}, '', url)\n}\n\nexport function SettingsView() {\n const [settings, setSettings] = useState<SettingEntry[]>([])\n const [token, setToken] = useState<TokenMe | null>(null)\n const [catalog, setCatalog] = useState<ProviderCatalogEntry[]>([])\n const [active, setActive] = useState(() => settingsHash())\n const [loading, setLoading] = useState(true)\n const [loadError, setLoadError] = useState('')\n const [catalogError, setCatalogError] = useState('')\n\n async function reload() {\n setLoading(true)\n setLoadError('')\n setCatalogError('')\n try {\n const [settingsRes, tokenRes, providersRes] = await Promise.all([\n api<SettingsResponse>('GET', '/settings'),\n api<TokenMe>('GET', '/tokens/me'),\n api<ProvidersResponse>('GET', '/providers').catch((e) => {\n setCatalogError((e as Error).message)\n return { catalog: [] }\n }),\n ])\n setSettings(settingsRes.settings)\n setToken(tokenRes)\n setCatalog(providersRes.catalog)\n } catch (e) {\n setLoadError((e as Error).message)\n } finally {\n setLoading(false)\n }\n }\n\n useEffect(() => {\n void reload()\n }, [])\n\n // External sync: keep the selected settings group aligned with browser history.\n useEffect(() => {\n const sync = () => setActive(settingsHash())\n window.addEventListener('hashchange', sync)\n window.addEventListener('popstate', sync)\n return () => {\n window.removeEventListener('hashchange', sync)\n window.removeEventListener('popstate', sync)\n }\n }, [])\n\n const descriptorGroups = useMemo(() => groupSettings(settings), [settings])\n const groups = useMemo(() => [\n ...descriptorGroups.map((group) => ({\n slug: group.slug,\n label: group.group,\n description: `${group.settings.length} schema setting${group.settings.length === 1 ? '' : 's'}`,\n kind: 'descriptors' as const,\n settings: group.settings,\n })),\n {\n slug: PROFILE_GROUP_SLUG,\n label: 'Profile',\n description: 'Display name and avatar',\n kind: 'profile' as const,\n settings: [],\n },\n {\n slug: BROWSER_GROUP_SLUG,\n label: 'Browser',\n description: 'Local dashboard preferences',\n kind: 'browser' as const,\n settings: [],\n },\n {\n slug: MODELS_GROUP_SLUG,\n label: 'Models',\n description: 'Provider model catalog',\n kind: 'models' as const,\n settings: [],\n },\n ], [descriptorGroups])\n\n const activeGroup = groups.find((group) => group.slug === active) ?? groups[0]\n\n function selectGroup(slug: string) {\n setActive(slug)\n writeSettingsHash(slug)\n }\n\n function replaceSetting(updated: SettingEntry) {\n setSettings((current) => current.map((entry) => settingId(entry) === settingId(updated) ? updated : entry))\n }\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div>\n <h1 className=\"text-lg font-semibold\">Settings</h1>\n <p className=\"text-sm text-muted-foreground\">Schema-driven Relay settings, browser preferences, and model catalog controls.</p>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n {token && (\n <Badge variant=\"outline\" className=\"gap-1\">\n <Globe2 className=\"size-3\" />\n {token.kind}:{token.actor}\n </Badge>\n )}\n <Button variant=\"outline\" size=\"sm\" onClick={() => void reload()} disabled={loading}>\n <RefreshCw className={cn('size-4', loading && 'animate-spin')} />\n Refresh\n </Button>\n </div>\n </div>\n\n {loadError && (\n <div className=\"flex items-start gap-2 rounded-lg border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">\n <AlertCircle className=\"mt-0.5 size-4\" />\n <span>{loadError}</span>\n </div>\n )}\n\n <div className=\"grid gap-4 lg:grid-cols-[230px_minmax(0,1fr)]\">\n <nav className=\"space-y-1 lg:sticky lg:top-4 lg:self-start\">\n {groups.map((group) => (\n <button\n key={group.slug}\n type=\"button\"\n className={cn(\n 'w-full rounded-md border px-3 py-2 text-left text-sm transition-colors',\n activeGroup?.slug === group.slug ? 'border-primary/50 bg-primary/10 text-foreground' : 'border-transparent hover:border-border hover:bg-accent',\n )}\n onClick={() => selectGroup(group.slug)}\n >\n <span className=\"block font-medium\">{group.label}</span>\n <span className=\"block truncate text-xs text-muted-foreground\">{group.description}</span>\n </button>\n ))}\n </nav>\n\n <div className=\"min-w-0 space-y-4\">\n {loading && !settings.length ? (\n <Card size=\"sm\">\n <CardContent className=\"text-sm text-muted-foreground\">Loading settings…</CardContent>\n </Card>\n ) : activeGroup?.kind === 'descriptors' ? (\n <>\n <SchemaGroup\n group={activeGroup.label}\n settings={activeGroup.settings}\n onSaved={replaceSetting}\n />\n {/* Quota config block lives under the Providers group (#605). */}\n {activeGroup.label === 'Providers' && (\n <QuotaSettings canWrite={hasScope(token?.scopes, 'settings:write:provider')} />\n )}\n {activeGroup.label === 'Notifications' && (\n <NotificationRoutingPreviewPanel />\n )}\n </>\n ) : activeGroup?.kind === 'profile' ? (\n <ProfileSettings />\n ) : activeGroup?.kind === 'browser' ? (\n <BrowserSettings />\n ) : (\n <ModelCatalogSettings\n catalog={catalog}\n error={catalogError}\n canWrite={hasScope(token?.scopes, 'settings:write:provider')}\n onCatalog={setCatalog}\n />\n )}\n </div>\n </div>\n </div>\n )\n}\n\nfunction NotificationRoutingPreviewPanel() {\n const [type, setType] = useState('branch.landed')\n const [scopeText, setScopeText] = useState('{\\n \"repoRoot\": \"/repo\"\\n}')\n const [preview, setPreview] = useState<NotificationRoutingPreview | null>(null)\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState('')\n\n async function runPreview() {\n setLoading(true)\n setError('')\n try {\n const scope = JSON.parse(scopeText) as unknown\n if (!scope || typeof scope !== 'object' || Array.isArray(scope)) throw new Error('Scope must be a JSON object')\n const result = await api<NotificationPreviewResponse>('POST', '/notifications/preview', { type, scope })\n setPreview(result.preview)\n } catch (e) {\n setPreview(null)\n setError((e as Error).message)\n } finally {\n setLoading(false)\n }\n }\n\n return (\n <Card size=\"sm\">\n <CardContent className=\"space-y-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <div>\n <h2 className=\"text-sm font-semibold\">Who gets what</h2>\n <p className=\"text-xs text-muted-foreground\">Dry-run notification routing without sending.</p>\n </div>\n <Button size=\"sm\" onClick={() => void runPreview()} disabled={loading}>\n <Route className=\"size-4\" />\n Preview\n </Button>\n </div>\n <div className=\"grid gap-3 md:grid-cols-[240px_minmax(0,1fr)]\">\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">Type</label>\n <Select value={type} onValueChange={setType}>\n <SelectTrigger className=\"w-full\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {NOTIFICATION_TYPES.map((item) => <SelectItem key={item} value={item}>{item}</SelectItem>)}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">Scope</label>\n <Textarea value={scopeText} onChange={(e) => setScopeText(e.target.value)} rows={4} className=\"font-mono text-xs\" />\n </div>\n </div>\n {error && (\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 p-2 text-xs text-destructive\">\n <AlertCircle className=\"mt-0.5 size-3.5\" />\n <span>{error}</span>\n </div>\n )}\n {preview && (\n <div className=\"overflow-hidden rounded-md border border-border\">\n {preview.recipients.length === 0 ? (\n <div className=\"px-3 py-4 text-center text-xs text-muted-foreground\">No recipients</div>\n ) : preview.recipients.map((recipient) => (\n <div key={`${recipient.recipient}-${recipient.matchedRule}`} className=\"grid gap-1 border-b border-border px-3 py-2 text-xs last:border-b-0 md:grid-cols-[minmax(0,180px)_minmax(0,160px)_minmax(0,1fr)]\">\n <span className=\"truncate font-medium\">{recipient.recipient}</span>\n <span className=\"truncate font-mono text-muted-foreground\">{recipient.matchedRule}</span>\n <span className=\"truncate text-muted-foreground\">{recipient.reason}</span>\n </div>\n ))}\n </div>\n )}\n </CardContent>\n </Card>\n )\n}\n\nfunction ProfileSettings() {\n const fetchUsers = useRelayStore((s) => s.fetchUsers)\n const fileRef = useRef<HTMLInputElement>(null)\n const [user, setUser] = useState<User | null>(null)\n const [displayName, setDisplayName] = useState('')\n const [loading, setLoading] = useState(true)\n const [saving, setSaving] = useState(false)\n const [error, setError] = useState('')\n\n async function loadProfile() {\n setLoading(true)\n setError('')\n try {\n const next = await api<User>('GET', '/users/me')\n setUser(next)\n setDisplayName(next.displayName || next.handle)\n } catch (e) {\n setError((e as Error).message)\n } finally {\n setLoading(false)\n }\n }\n\n useEffect(() => {\n void loadProfile()\n }, [])\n\n async function saveProfile() {\n setSaving(true)\n setError('')\n try {\n const next = await api<User>('PATCH', '/users/me', { displayName })\n setUser(next)\n setDisplayName(next.displayName || next.handle)\n await fetchUsers()\n } catch (e) {\n setError((e as Error).message)\n } finally {\n setSaving(false)\n }\n }\n\n async function uploadAvatar(file: File | undefined) {\n if (!file) return\n setSaving(true)\n setError('')\n try {\n const res = await apiUpload<{ user: User; artifact: Artifact }>('/users/me/avatar', file)\n setUser(res.user)\n setDisplayName(res.user.displayName || res.user.handle)\n await fetchUsers()\n } catch (e) {\n setError((e as Error).message)\n } finally {\n setSaving(false)\n if (fileRef.current) fileRef.current.value = ''\n }\n }\n\n async function removeAvatar() {\n setSaving(true)\n setError('')\n try {\n const next = await api<User>('DELETE', '/users/me/avatar')\n setUser(next)\n await fetchUsers()\n } catch (e) {\n setError((e as Error).message)\n } finally {\n setSaving(false)\n }\n }\n\n return (\n <Card size=\"sm\">\n <CardContent className=\"space-y-4\">\n {error && (\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">\n <AlertCircle className=\"mt-0.5 size-4\" />\n <span>{error}</span>\n </div>\n )}\n <div className=\"flex flex-wrap items-center gap-4\">\n <UserAvatar user={user ?? undefined} distinct className=\"size-16 text-lg\" />\n <div className=\"min-w-0 flex-1 space-y-2\">\n <label className=\"block text-xs font-medium text-muted-foreground\" htmlFor=\"profile-display-name\">Display name</label>\n <input\n id=\"profile-display-name\"\n className=\"h-9 w-full rounded-md border border-input bg-background px-3 text-sm\"\n value={displayName}\n onChange={(e) => setDisplayName(e.target.value)}\n disabled={loading || saving}\n maxLength={120}\n />\n </div>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button size=\"sm\" onClick={() => void saveProfile()} disabled={loading || saving || !displayName.trim()}>\n <Save className=\"size-4\" />\n Save\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={() => fileRef.current?.click()} disabled={loading || saving}>\n <Upload className=\"size-4\" />\n Upload\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={() => void removeAvatar()} disabled={loading || saving || !user?.avatarArtifactId}>\n <Trash2 className=\"size-4\" />\n Remove\n </Button>\n {saving && <Camera className=\"size-4 animate-pulse text-muted-foreground\" />}\n <input\n ref={fileRef}\n type=\"file\"\n accept=\"image/png,image/jpeg,image/gif,image/webp\"\n className=\"hidden\"\n onChange={(e) => void uploadAvatar(e.target.files?.[0])}\n />\n </div>\n </CardContent>\n </Card>\n )\n}\n"],"mappings":"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"}
|