agent-relay-server 0.73.0 → 0.74.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.
Files changed (81) hide show
  1. package/docs/openapi.json +1 -1
  2. package/package.json +2 -2
  3. package/public/assets/{MessageBubble-BWdM9UCM.js → MessageBubble-CspI1qqW.js} +2 -2
  4. package/public/assets/MessageBubble-CspI1qqW.js.map +1 -0
  5. package/public/assets/{PlanGraphPanel-icESxd82.js → PlanGraphPanel-WjXyWbzZ.js} +2 -2
  6. package/public/assets/{PlanGraphPanel-icESxd82.js.map → PlanGraphPanel-WjXyWbzZ.js.map} +1 -1
  7. package/public/assets/{activity-BR9I23hc.js → activity-B9WoIWSe.js} +2 -2
  8. package/public/assets/{activity-BR9I23hc.js.map → activity-B9WoIWSe.js.map} +1 -1
  9. package/public/assets/{agent-profiles-BB0V-Tg1.js → agent-profiles-D1X5BBW_.js} +2 -2
  10. package/public/assets/{agent-profiles-BB0V-Tg1.js.map → agent-profiles-D1X5BBW_.js.map} +1 -1
  11. package/public/assets/{agents-Clkboz93.js → agents-D7th_n2N.js} +2 -2
  12. package/public/assets/{agents-Clkboz93.js.map → agents-D7th_n2N.js.map} +1 -1
  13. package/public/assets/{analytics-DRlHs5ho.js → analytics-e_HOZBPx.js} +2 -2
  14. package/public/assets/{analytics-DRlHs5ho.js.map → analytics-e_HOZBPx.js.map} +1 -1
  15. package/public/assets/{automation-DlnH_MPy.js → automation-wOEiCheJ.js} +2 -2
  16. package/public/assets/{automation-DlnH_MPy.js.map → automation-wOEiCheJ.js.map} +1 -1
  17. package/public/assets/{branch-state-badge-Dg1qnmF5.js → branch-state-badge-B7T81Oct.js} +2 -2
  18. package/public/assets/{branch-state-badge-Dg1qnmF5.js.map → branch-state-badge-B7T81Oct.js.map} +1 -1
  19. package/public/assets/{channels-BVYLrKUL.js → channels-BAD_kIo7.js} +2 -2
  20. package/public/assets/{channels-BVYLrKUL.js.map → channels-BAD_kIo7.js.map} +1 -1
  21. package/public/assets/{chat-ml_YzbK4.js → chat-Bj6R0vno.js} +2 -2
  22. package/public/assets/{chat-ml_YzbK4.js.map → chat-Bj6R0vno.js.map} +1 -1
  23. package/public/assets/{connectors-BOyk5hC3.js → connectors-Cdjtxly2.js} +2 -2
  24. package/public/assets/{connectors-BOyk5hC3.js.map → connectors-Cdjtxly2.js.map} +1 -1
  25. package/public/assets/display-DHgdn4vN.js +3 -0
  26. package/public/assets/{display-LAWaAboe.js.map → display-DHgdn4vN.js.map} +1 -1
  27. package/public/assets/{formatted-body-impl-D2F76gPY.js → formatted-body-impl-BXeoUw5r.js} +2 -2
  28. package/public/assets/{formatted-body-impl-D2F76gPY.js.map → formatted-body-impl-BXeoUw5r.js.map} +1 -1
  29. package/public/assets/{index-DYmgI4s4.js → index-DNQadbv0.js} +6 -6
  30. package/public/assets/{index-DYmgI4s4.js.map → index-DNQadbv0.js.map} +1 -1
  31. package/public/assets/{insights-DylYp2q4.js → insights-n-pd12FP.js} +2 -2
  32. package/public/assets/{insights-DylYp2q4.js.map → insights-n-pd12FP.js.map} +1 -1
  33. package/public/assets/{integrations-B9ViWoJy.js → integrations-DzRla8mj.js} +2 -2
  34. package/public/assets/{integrations-B9ViWoJy.js.map → integrations-DzRla8mj.js.map} +1 -1
  35. package/public/assets/{maintenance-inyZGLys.js → maintenance-DZI5exUu.js} +2 -2
  36. package/public/assets/{maintenance-inyZGLys.js.map → maintenance-DZI5exUu.js.map} +1 -1
  37. package/public/assets/{managed-agents-CEFvMPN-.js → managed-agents-Bh_vowgH.js} +2 -2
  38. package/public/assets/{managed-agents-CEFvMPN-.js.map → managed-agents-Bh_vowgH.js.map} +1 -1
  39. package/public/assets/{markdown-preview-impl-CniyG4_g.js → markdown-preview-impl-B-6jdhi0.js} +2 -2
  40. package/public/assets/{markdown-preview-impl-CniyG4_g.js.map → markdown-preview-impl-B-6jdhi0.js.map} +1 -1
  41. package/public/assets/{memory-DDYGuRzr.js → memory-B74VVg5K.js} +2 -2
  42. package/public/assets/{memory-DDYGuRzr.js.map → memory-B74VVg5K.js.map} +1 -1
  43. package/public/assets/{messages-BMFcsMMa.js → messages-D5n46hEh.js} +2 -2
  44. package/public/assets/{messages-BMFcsMMa.js.map → messages-D5n46hEh.js.map} +1 -1
  45. package/public/assets/{orchestrators-D5nL4a52.js → orchestrators-DBryzqq2.js} +2 -2
  46. package/public/assets/{orchestrators-D5nL4a52.js.map → orchestrators-DBryzqq2.js.map} +1 -1
  47. package/public/assets/{overview-DywDrPKE.js → overview-0xb4ATEH.js} +2 -2
  48. package/public/assets/{overview-DywDrPKE.js.map → overview-0xb4ATEH.js.map} +1 -1
  49. package/public/assets/{pairs-UvIyBk4w.js → pairs-CnKDSHJu.js} +2 -2
  50. package/public/assets/{pairs-UvIyBk4w.js.map → pairs-CnKDSHJu.js.map} +1 -1
  51. package/public/assets/{projects-DXBjwPU5.js → projects-DluLrkwe.js} +2 -2
  52. package/public/assets/{projects-DXBjwPU5.js.map → projects-DluLrkwe.js.map} +1 -1
  53. package/public/assets/{security-Boe7MEIz.js → security-C2t99jNP.js} +2 -2
  54. package/public/assets/{security-Boe7MEIz.js.map → security-C2t99jNP.js.map} +1 -1
  55. package/public/assets/{select-Dh5Q8rJ8.js → select-CCbQiEmS.js} +2 -2
  56. package/public/assets/{select-Dh5Q8rJ8.js.map → select-CCbQiEmS.js.map} +1 -1
  57. package/public/assets/{settings-Ch4jMDrE.js → settings-Ucd8p6KS.js} +2 -2
  58. package/public/assets/{settings-Ch4jMDrE.js.map → settings-Ucd8p6KS.js.map} +1 -1
  59. package/public/assets/{store-BRvMMH5T.js → store-D1K4_xId.js} +2 -2
  60. package/public/assets/{store-BRvMMH5T.js.map → store-D1K4_xId.js.map} +1 -1
  61. package/public/assets/{tasks-DrW8R52c.js → tasks-Bk8clApn.js} +2 -2
  62. package/public/assets/{tasks-DrW8R52c.js.map → tasks-Bk8clApn.js.map} +1 -1
  63. package/public/assets/{teams-CJqpAwmO.js → teams-BXkI8tvS.js} +2 -2
  64. package/public/assets/{teams-CJqpAwmO.js.map → teams-BXkI8tvS.js.map} +1 -1
  65. package/public/assets/{terminal-viewer-impl-1_7v8GfU.js → terminal-viewer-impl-BL-zWN1C.js} +2 -2
  66. package/public/assets/{terminal-viewer-impl-1_7v8GfU.js.map → terminal-viewer-impl-BL-zWN1C.js.map} +1 -1
  67. package/public/assets/{work-queue-BnIi7evb.js → work-queue-DqMKcH5G.js} +2 -2
  68. package/public/assets/{work-queue-BnIi7evb.js.map → work-queue-DqMKcH5G.js.map} +1 -1
  69. package/public/assets/{workspaces-u5j6mOlA.js → workspaces-B_nIm6Tw.js} +2 -2
  70. package/public/assets/{workspaces-u5j6mOlA.js.map → workspaces-B_nIm6Tw.js.map} +1 -1
  71. package/public/index.html +3 -3
  72. package/src/context-advisory.ts +2 -2
  73. package/src/db/continuations.ts +8 -2
  74. package/src/notification-router.ts +2 -0
  75. package/src/notification-types.ts +2 -0
  76. package/src/notify.ts +2 -0
  77. package/src/self-resume-config.ts +2 -0
  78. package/src/self-resume.ts +82 -13
  79. package/src/sse.ts +2 -6
  80. package/public/assets/MessageBubble-BWdM9UCM.js.map +0 -1
  81. package/public/assets/display-LAWaAboe.js +0 -3
@@ -1 +1 @@
1
- {"version":3,"file":"settings-Ch4jMDrE.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/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, useMemo, useState } from 'react'\nimport type { ProviderCatalogEntry } from 'agent-relay-sdk/provider-catalog'\nimport { api } 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, Globe2, RefreshCw } from 'lucide-react'\nimport { BrowserSettings } from '@/components/settings/browser-settings'\nimport { ModelCatalogSettings } from '@/components/settings/model-catalog-settings'\nimport { SchemaGroup } from '@/components/settings/schema-form'\nimport {\n groupSettings,\n hasScope,\n settingId,\n type SettingEntry,\n} from '@/components/settings/schema-utils'\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\nconst BROWSER_GROUP_SLUG = 'browser'\nconst MODELS_GROUP_SLUG = 'models'\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: 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 <SchemaGroup\n group={activeGroup.label}\n settings={activeGroup.settings}\n onSaved={replaceSetting}\n />\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"],"mappings":"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"}
1
+ {"version":3,"file":"settings-Ucd8p6KS.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/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, useMemo, useState } from 'react'\nimport type { ProviderCatalogEntry } from 'agent-relay-sdk/provider-catalog'\nimport { api } 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, Globe2, RefreshCw } from 'lucide-react'\nimport { BrowserSettings } from '@/components/settings/browser-settings'\nimport { ModelCatalogSettings } from '@/components/settings/model-catalog-settings'\nimport { SchemaGroup } from '@/components/settings/schema-form'\nimport {\n groupSettings,\n hasScope,\n settingId,\n type SettingEntry,\n} from '@/components/settings/schema-utils'\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\nconst BROWSER_GROUP_SLUG = 'browser'\nconst MODELS_GROUP_SLUG = 'models'\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: 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 <SchemaGroup\n group={activeGroup.label}\n settings={activeGroup.settings}\n onSaved={replaceSetting}\n />\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"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{Qn as t,Un as n,Vn as r,Wn as i,Xn as a,Yn as o,Zn as s,qn as c}from"./lucide-react-DI8kTavp.js";import{B as l,C as u,D as d,I as f,O as p,Q as m,W as h,X as g,Z as ee,_,at as v,b as y,d as te,it as b,j as x,nt as S,ot as C,p as w,rt as T,st as E,tt as D,w as ne}from"./display-LAWaAboe.js";var O=e(t(),1),re=e=>{let t,n=new Set,r=(e,r)=>{let i=typeof e==`function`?e(t):e;if(!Object.is(i,t)){let e=t;t=r??(typeof i!=`object`||!i)?i:Object.assign({},t,i),n.forEach(n=>n(t,e))}},i=()=>t,a={setState:r,getState:i,getInitialState:()=>o,subscribe:e=>(n.add(e),()=>n.delete(e))},o=t=e(r,i,a);return a},ie=(e=>e?re(e):re),ae=e=>e;function oe(e,t=ae){let n=O.useSyncExternalStore(e.subscribe,O.useCallback(()=>t(e.getState()),[e,t]),O.useCallback(()=>t(e.getInitialState()),[e,t]));return O.useDebugValue(n),n}var se=e=>{let t=ie(e),n=e=>oe(t,e);return Object.assign(n,t),n},ce=(e=>e?se(e):se);function le(e,t){let n;try{n=e()}catch{return}return{getItem:e=>{let r=e=>e===null?null:JSON.parse(e,t?.reviver),i=n.getItem(e)??null;return i instanceof Promise?i.then(r):r(i)},setItem:(e,r)=>n.setItem(e,JSON.stringify(r,t?.replacer)),removeItem:e=>n.removeItem(e)}}var ue=e=>t=>{try{let n=e(t);return n instanceof Promise?n:{then(e){return ue(e)(n)},catch(e){return this}}}catch(e){return{then(e){return this},catch(t){return ue(t)(e)}}}},de=(e,t)=>(n,r,i)=>{let a={storage:le(()=>window.localStorage),partialize:e=>e,version:0,merge:(e,t)=>({...t,...e}),...t},o=!1,s=0,c=new Set,l=new Set,u=a.storage;if(!u)return e((...e)=>{console.warn(`[zustand persist middleware] Unable to update item '${a.name}', the given storage is currently unavailable.`),n(...e)},r,i);let d=()=>{let e=a.partialize({...r()});return u.setItem(a.name,{state:e,version:a.version})},f=i.setState;i.setState=(e,t)=>(f(e,t),d());let p=e((...e)=>(n(...e),d()),r,i);i.getInitialState=()=>p;let m,h=()=>{if(!u)return;let e=++s;o=!1,c.forEach(e=>e(r()??p));let t=a.onRehydrateStorage?.call(a,r()??p)||void 0;return ue(u.getItem.bind(u))(a.name).then(e=>{if(e)if(typeof e.version==`number`&&e.version!==a.version){if(a.migrate){let t=a.migrate(e.state,e.version);return t instanceof Promise?t.then(e=>[!0,e]):[!0,t]}console.error(`State loaded from storage couldn't be migrated since no migrate function was provided`)}else return[!1,e.state];return[!1,void 0]}).then(t=>{if(e!==s)return;let[i,o]=t;if(m=a.merge(o,r()??p),n(m,!0),i)return d()}).then(()=>{e===s&&(t?.(r(),void 0),m=r(),o=!0,l.forEach(e=>e(m)))}).catch(n=>{e===s&&t?.(void 0,n)})};return i.persist={setOptions:e=>{a={...a,...e},e.storage&&(u=e.storage)},clearStorage:()=>{u?.removeItem(a.name)},getOptions:()=>a,rehydrate:()=>h(),hasHydrated:()=>o,onHydrate:e=>(c.add(e),()=>{c.delete(e)}),onFinishHydration:e=>(l.add(e),()=>{l.delete(e)})},a.skipHydration||h(),m||p};function fe(e){if(!e)return``;let t=e.replace(/\r\n/g,`
1
+ import{r as e}from"./chunk-CilyBKbf.js";import{Qn as t,Un as n,Vn as r,Wn as i,Xn as a,Yn as o,Zn as s,qn as c}from"./lucide-react-DI8kTavp.js";import{B as l,C as u,D as d,I as f,O as p,Q as m,W as h,X as g,Z as ee,_,at as v,b as y,d as te,it as b,j as x,nt as S,ot as C,p as w,rt as T,st as E,tt as D,w as ne}from"./display-DHgdn4vN.js";var O=e(t(),1),re=e=>{let t,n=new Set,r=(e,r)=>{let i=typeof e==`function`?e(t):e;if(!Object.is(i,t)){let e=t;t=r??(typeof i!=`object`||!i)?i:Object.assign({},t,i),n.forEach(n=>n(t,e))}},i=()=>t,a={setState:r,getState:i,getInitialState:()=>o,subscribe:e=>(n.add(e),()=>n.delete(e))},o=t=e(r,i,a);return a},ie=(e=>e?re(e):re),ae=e=>e;function oe(e,t=ae){let n=O.useSyncExternalStore(e.subscribe,O.useCallback(()=>t(e.getState()),[e,t]),O.useCallback(()=>t(e.getInitialState()),[e,t]));return O.useDebugValue(n),n}var se=e=>{let t=ie(e),n=e=>oe(t,e);return Object.assign(n,t),n},ce=(e=>e?se(e):se);function le(e,t){let n;try{n=e()}catch{return}return{getItem:e=>{let r=e=>e===null?null:JSON.parse(e,t?.reviver),i=n.getItem(e)??null;return i instanceof Promise?i.then(r):r(i)},setItem:(e,r)=>n.setItem(e,JSON.stringify(r,t?.replacer)),removeItem:e=>n.removeItem(e)}}var ue=e=>t=>{try{let n=e(t);return n instanceof Promise?n:{then(e){return ue(e)(n)},catch(e){return this}}}catch(e){return{then(e){return this},catch(t){return ue(t)(e)}}}},de=(e,t)=>(n,r,i)=>{let a={storage:le(()=>window.localStorage),partialize:e=>e,version:0,merge:(e,t)=>({...t,...e}),...t},o=!1,s=0,c=new Set,l=new Set,u=a.storage;if(!u)return e((...e)=>{console.warn(`[zustand persist middleware] Unable to update item '${a.name}', the given storage is currently unavailable.`),n(...e)},r,i);let d=()=>{let e=a.partialize({...r()});return u.setItem(a.name,{state:e,version:a.version})},f=i.setState;i.setState=(e,t)=>(f(e,t),d());let p=e((...e)=>(n(...e),d()),r,i);i.getInitialState=()=>p;let m,h=()=>{if(!u)return;let e=++s;o=!1,c.forEach(e=>e(r()??p));let t=a.onRehydrateStorage?.call(a,r()??p)||void 0;return ue(u.getItem.bind(u))(a.name).then(e=>{if(e)if(typeof e.version==`number`&&e.version!==a.version){if(a.migrate){let t=a.migrate(e.state,e.version);return t instanceof Promise?t.then(e=>[!0,e]):[!0,t]}console.error(`State loaded from storage couldn't be migrated since no migrate function was provided`)}else return[!1,e.state];return[!1,void 0]}).then(t=>{if(e!==s)return;let[i,o]=t;if(m=a.merge(o,r()??p),n(m,!0),i)return d()}).then(()=>{e===s&&(t?.(r(),void 0),m=r(),o=!0,l.forEach(e=>e(m)))}).catch(n=>{e===s&&t?.(void 0,n)})};return i.persist={setOptions:e=>{a={...a,...e},e.storage&&(u=e.storage)},clearStorage:()=>{u?.removeItem(a.name)},getOptions:()=>a,rehydrate:()=>h(),hasHydrated:()=>o,onHydrate:e=>(c.add(e),()=>{c.delete(e)}),onFinishHydration:e=>(l.add(e),()=>{l.delete(e)})},a.skipHydration||h(),m||p};function fe(e){if(!e)return``;let t=e.replace(/\r\n/g,`
2
2
  `);return t=t.replace(/```[^\n]*\n([\s\S]*?)```/g,(e,t)=>{let n=t.replace(/\n+$/,``).split(`
3
3
  `).length;return` code block, ${n} ${n===1?`line`:`lines`}. `}),t=t.replace(/```[^\n]*/g,` code block. `),t=ge(t),t=t.replace(/^#{1,6}\s+/gm,``),t=t.replace(/^\s*[-*+]\s+/gm,`. `),t=t.replace(/^\s*\d+\.\s+/gm,`. `),t=t.replace(/`([^`]+)`/g,`$1`),t=t.replace(/\[([^\]]+)\]\([^)]+\)/g,`$1`),t=t.replace(/(\*\*|__|\*|_)(.*?)\1/g,`$2`),t=t.replace(/[ \t]+/g,` `),t=t.replace(/\n{2,}/g,`. `),t=t.replace(/\s*\.\s*\.\s*(\.\s*)+/g,`. `),t.trim()}function pe(e){return/\|/.test(e)&&e.trim().length>0}function me(e){return/^\s*\|?\s*:?-{2,}:?\s*(\|\s*:?-{2,}:?\s*)+\|?\s*$/.test(e)}function he(e){return e.trim().replace(/^\||\|$/g,``).split(`|`).map(e=>e.trim()).filter(e=>e.length>0)}function ge(e){let t=e.split(`
4
4
  `),n=[],r=0;for(;r<t.length;){if(pe(t[r])&&r+1<t.length&&me(t[r+1])){let e=he(t[r]),i=r+2,a=0;for(;i<t.length&&pe(t[i])&&!me(t[i]);)a++,i++;let o=e.length?`with columns ${e.join(`, `)}`:``,s=`${a} ${a===1?`row`:`rows`}`;n.push(`table ${o?`${o}, `:``}${s}.`.replace(/\s+/g,` `).trim()),r=i;continue}n.push(t[r]),r++}return n.join(`
@@ -6,4 +6,4 @@ import{r as e}from"./chunk-CilyBKbf.js";import{Qn as t,Un as n,Vn as r,Wn as i,X
6
6
  `),E=14e3,D=`You are continuing work from a previous agent session (${C}). Below is the conversation history. Treat it as context for your work, not as your own actions.\n\n${T.length>E?`...
7
7
  `+T.slice(T.length-E):T}`,ne=r.filter(e=>typeof e.id==`number`&&e.id>0).map(e=>e.id);e({spawnOrchId:S.id,spawnProvider:c||V(S),spawnModel:u||H(c||V(S)),spawnEffort:p,spawnProfile:i.spawnProfile||`default-relay`,spawnCwd:_||S.baseDir||``,spawnLabel:x,spawnApproval:b,spawnWorkspaceMode:y,spawnPrompt:`Continue from this previous session.`,spawnSystemPromptAppend:D,spawnCount:1,pendingForkImport:{sourcePeerId:a.id,sourceAgentId:a.id,sourceThreadId:a.id,sourceAgentLabel:C,messageIds:ne},orchestratorSpawnOpen:!0})},openOrchestratorInstall(){e({orchestratorInstallOpen:!0})},openOrchestratorSpawnFor(n){let r=t(),i=r.orchestrators.find(e=>e.id===n),a=V(i),o=H(a,r.providerCatalog),s=r.spawnProvider===a&&r.spawnModel===o?r.spawnEffort:``,c=r.spawnCwd&&f(r.spawnCwd,i?.baseDir)?r.spawnCwd:i?.baseDir||``;e({spawnOrchId:n,spawnProvider:a,spawnModel:o,spawnEffort:s,spawnProfile:r.spawnProfile||`default-relay`,spawnCwd:c,spawnLabel:``,spawnWorkspaceMode:`inherit`,spawnPrompt:``,spawnSystemPromptAppend:``,spawnCount:1,pendingForkImport:null,orchestratorSpawnOpen:!0})},selectSpawnHistory(n,r){let i=t(),a=i.orchestrators.find(e=>e.id===n&&e.status===`online`);if(!a){t().showError(`Unavailable`,`That orchestrator is no longer online.`);return}if(n===i.spawnOrchId){e({spawnCwd:r});return}let o=i.spawnProvider&&a.providers.includes(i.spawnProvider)?i.spawnProvider:V(a),s=i.spawnProvider===o&&i.spawnModel&&Ue(o,i.providerCatalog).some(e=>e.alias===i.spawnModel)?i.spawnModel:H(o,i.providerCatalog);e({spawnOrchId:n,spawnProvider:o,spawnModel:s,spawnEffort:i.spawnProvider===o&&i.spawnModel===s?i.spawnEffort:``,spawnCwd:r})},async submitOrchestratorSpawn(){let n=t();if(n.isSpawning)return;if(!n.spawnOrchId){t().showError(`Validation`,`Select an orchestrator.`);return}let i=n.orchestrators.find(e=>e.id===n.spawnOrchId);if(!i){t().showError(`Validation`,`Selected orchestrator is not available.`);return}let a=n.spawnCwd.trim();if(!a){t().showError(`Validation`,`Select a working directory.`);return}if(!f(a,i.baseDir)){t().showError(`Validation`,`Working directory must be under ${i.baseDir}.`);return}let o=n.pendingForkImport,s=o?1:Math.max(1,Math.min(10,Math.round(n.spawnCount)||1));e({isSpawning:!0});try{for(let e=0;e<s;e++){let t={provider:n.spawnProvider,orchestratorId:n.spawnOrchId,approvalMode:n.spawnApproval,workspaceMode:n.spawnWorkspaceMode||`inherit`};n.spawnModel&&(t.model=n.spawnModel),n.spawnEffort&&(t.effort=n.spawnEffort),n.spawnProfile&&(t.profile=n.spawnProfile),t.cwd=a,n.spawnLabel&&(t.label=s>1?`${n.spawnLabel} ${e+1}`:n.spawnLabel),n.spawnPrompt&&(t.prompt=n.spawnPrompt),n.spawnSystemPromptAppend&&(t.systemPromptAppend=n.spawnSystemPromptAppend);let i=(await r(`POST`,`/agents/spawn`,t)).command?.params?.spawnRequestId;o&&i&&o.messageIds.length>0&&await r(`POST`,`/chat/history-imports`,{targetSpawnRequestId:i,sourcePeerId:o.sourcePeerId,sourceAgentId:o.sourceAgentId,sourceThreadId:o.sourceThreadId,sourceAgentLabel:o.sourceAgentLabel,importedBy:C,messageIds:o.messageIds})}e({orchestratorSpawnOpen:!1,pendingForkImport:null,isSpawning:!1,spawnCwdHistory:[{orchId:n.spawnOrchId,cwd:a},...n.spawnCwdHistory.filter(e=>!(e.orchId===n.spawnOrchId&&e.cwd===a))].slice(0,5)}),await Promise.all([t().fetchAgents(),t().fetchOrchestrators(),t().fetchActivityEvents(),t().fetchChatHistoryImports()])}catch(n){e({isSpawning:!1}),t().showError(`Spawn Failed`,n.message)}},orchestratorAction(e,n,i,a){let o=n===`restart`?`Restart`:`Shutdown`,s=i?`agent "${i}"`:`all agents`;t().openConfirm(`${o} Agent`,`${o} ${s} on orchestrator "${e}"?`,async()=>{try{await r(`POST`,`/orchestrators/`+encodeURIComponent(e)+`/actions`,{action:n,agentId:i,...a?{surface:{component:a}}:{}}),await Promise.all([t().fetchOrchestrators(),t().fetchActivityEvents()])}catch(e){t().showError(`${o} Failed`,e.message)}})},upgradeOrchestrator(e,n){let i=n?` to v${n}`:` to match the relay`;t().openConfirm(`Upgrade Orchestrator`,`Upgrade "${e}"${i}? It will install the new version and restart itself.`,async()=>{try{await r(`POST`,`/orchestrators/`+encodeURIComponent(e)+`/actions`,{action:`upgrade`,...n?{targetVersion:n}:{}}),await Promise.all([t().fetchOrchestrators(),t().fetchActivityEvents()])}catch(e){t().showError(`Upgrade Failed`,e.message)}})},deleteOrchestrator(e){t().openConfirm(`Remove Orchestrator`,`Remove orchestrator "${e}"?`,async()=>{try{await r(`DELETE`,`/orchestrators/`+encodeURIComponent(e)),await Promise.all([t().fetchOrchestrators(),t().fetchActivityEvents()])}catch(e){t().showError(`Delete Failed`,e.message)}})},async browseSpawnDirectory(n){let i=t().spawnOrchId;if(!i)return;let a=t().spawnDirBrowser;e({spawnDirBrowser:{...a,loading:!0,error:``}});try{let a=n?`?path=`+encodeURIComponent(n):``,o=await r(`GET`,`/orchestrators/`+encodeURIComponent(i)+`/directories`+a);e({spawnDirBrowser:{open:!0,loading:!1,path:o.path||``,parent:o.parent||``,baseDir:o.baseDir||``,entries:o.entries||[],error:``},spawnCwd:o.path||t().spawnCwd})}catch(n){e({spawnDirBrowser:{...t().spawnDirBrowser,loading:!1,error:n.message}})}},selectSpawnDirectory(n){e({spawnCwd:n||t().spawnDirBrowser.path,spawnDirBrowser:{...t().spawnDirBrowser,open:!1}})}}),zt=(e,t)=>({managedPolicies:[],policyModal:{open:!1,editing:``,name:``,description:``,orchestratorId:``,cwd:``,enabled:void 0,provider:`claude`,rig:``,model:H(`claude`),effort:``,profile:`default-relay`,providerArgs:``,prompt:``,tags:``,capabilities:``,label:``,mode:`always-on`,permissionMode:`guarded`,restartOnUpdate:!0,scheduledDailyRestart:!1,keepaliveSeconds:`300`,backoffSchedule:`5,15,60,300`,backoffResetAfterSeconds:`600`,channelId:``},policyDirBrowser:{open:!1,loading:!1,path:``,parent:``,baseDir:``,entries:[],error:``},agentProfiles:[],profileModal:{open:!1,mode:`create`,profile:{name:``,description:``,provider:`any`,base:`host`,instructions:{system:``,append:[],repoInstructions:`allow`,globalInstructions:`allow`},relay:{context:!0,skills:!0,plugins:!0,statusLine:!0,mcp:!0},skills:[],plugins:[],mcp:{mode:`host`},hooks:{mode:`host`},permissions:{filesystem:`host`},env:{},providerOptions:{}}},async fetchManagedPolicies(){try{e({managedPolicies:await r(`GET`,`/spawn-policies/health`)})}catch{}},async fetchAgentProfiles(){try{e({agentProfiles:(await r(`GET`,`/agent-profiles`)).map(e=>e.value)})}catch{}},openPolicyCreate(){let n=t().orchestrators.filter(e=>e.status===`online`);if(!n.length){t().showError(`No Orchestrators`,`No orchestrators are currently online.`);return}t().fetchProviderCatalog(),e({policyModal:{open:!0,editing:``,name:``,description:``,orchestratorId:n[0].id,cwd:``,enabled:void 0,provider:V(n[0]),rig:``,model:H(V(n[0]),t().providerCatalog),effort:``,profile:`default-relay`,providerArgs:``,prompt:``,tags:``,capabilities:``,label:``,mode:`always-on`,permissionMode:`guarded`,restartOnUpdate:!0,scheduledDailyRestart:!1,keepaliveSeconds:`300`,backoffSchedule:`5,15,60,300`,backoffResetAfterSeconds:`600`,channelId:``},policyDirBrowser:{open:!1,loading:!1,path:``,parent:``,baseDir:``,entries:[],error:``}})},openPolicyEdit(n){t().fetchProviderCatalog(),e({policyModal:{open:!0,editing:n.name,name:n.name,enabled:n.enabled,description:n.description||``,orchestratorId:n.orchestratorId,cwd:n.cwd,provider:n.provider,rig:n.rig||``,model:n.model||H(n.provider,t().providerCatalog),effort:n.effort||``,profile:n.profile||`default-relay`,providerArgs:(n.providerArgs||[]).join(` `),prompt:n.prompt||``,tags:(n.tags||[]).join(`, `),capabilities:(n.capabilities||[]).join(`, `),label:n.label||``,mode:n.mode,permissionMode:n.permissionMode,restartOnUpdate:n.restartOnUpdate,scheduledDailyRestart:n.scheduledDailyRestart,keepaliveSeconds:String(n.onDemand?.keepaliveSeconds??300),backoffSchedule:(n.backoff?.schedule||[5,15,60,300]).join(`, `),backoffResetAfterSeconds:String(n.backoff?.resetAfterSeconds??600),channelId:n.binding?.channelId||``},policyDirBrowser:{open:!1,loading:!1,path:``,parent:``,baseDir:``,entries:[],error:``}})},async submitPolicy(){let n=t().policyModal;if(!n.name.trim()){t().showError(`Validation`,`Policy name is required.`);return}if(!n.orchestratorId){t().showError(`Validation`,`Select an orchestrator.`);return}if(!n.cwd.trim()){t().showError(`Validation`,`Working directory is required.`);return}let i=e=>e.split(/[,\s]+/).map(e=>e.trim()).filter(Boolean),a={name:n.name.trim(),...n.description.trim()?{description:n.description.trim()}:{},...n.enabled===void 0?{}:{enabled:n.enabled},orchestratorId:n.orchestratorId,cwd:n.cwd.trim(),provider:n.provider,...n.rig.trim()?{rig:n.rig.trim()}:{},...n.model?{model:n.model}:{},...n.effort?{effort:n.effort}:{},...n.profile?{profile:n.profile}:{},providerArgs:n.providerArgs.trim()?n.providerArgs.trim().split(/\s+/):[],...n.prompt.trim()?{prompt:n.prompt.trim()}:{},tags:i(n.tags),capabilities:i(n.capabilities),...n.label.trim()?{label:n.label.trim()}:{},mode:n.mode,permissionMode:n.permissionMode,restartOnUpdate:n.restartOnUpdate,scheduledDailyRestart:n.scheduledDailyRestart,...n.mode===`on-demand`?{onDemand:{keepaliveSeconds:Number(n.keepaliveSeconds)||300,idleDefinition:`no-activity`}}:{},backoff:{schedule:i(n.backoffSchedule).map(Number).filter(e=>e>0),resetAfterSeconds:Number(n.backoffResetAfterSeconds)||600},...n.channelId.trim()?{binding:{type:`channel`,channelId:n.channelId.trim()}}:{}};a.backoff.schedule.length||(a.backoff.schedule=[5,15,60,300]);try{await r(`PUT`,`/spawn-policy/`+encodeURIComponent(a.name),a),e({policyModal:{...n,open:!1}}),await t().fetchManagedPolicies()}catch(e){t().showError(`Save Failed`,e.message)}},deletePolicy(e){t().openConfirm(`Delete Policy`,`Delete managed agent policy "${e}"? This will stop any running agent.`,async()=>{try{await r(`DELETE`,`/spawn-policy/`+encodeURIComponent(e)),await t().fetchManagedPolicies()}catch(e){t().showError(`Delete Failed`,e.message)}})},async browsePolicyDirectory(n){let i=t().policyModal.orchestratorId;if(!i)return;let a=t().policyDirBrowser;e({policyDirBrowser:{...a,loading:!0,error:``}});try{let a=n?`?path=`+encodeURIComponent(n):``,o=await r(`GET`,`/orchestrators/`+encodeURIComponent(i)+`/directories`+a);e({policyDirBrowser:{open:!0,loading:!1,path:o.path||``,parent:o.parent||``,baseDir:o.baseDir||``,entries:o.entries||[],error:``},policyModal:{...t().policyModal,cwd:o.path||t().policyModal.cwd}})}catch(n){e({policyDirBrowser:{...t().policyDirBrowser,loading:!1,error:n.message}})}},selectPolicyDirectory(n){e({policyModal:{...t().policyModal,cwd:n||t().policyDirBrowser.path},policyDirBrowser:{...t().policyDirBrowser,open:!1}})},openProfileModal(t,n){let r={name:``,description:``,provider:`any`,base:`host`,instructions:{system:``,append:[],repoInstructions:`allow`,globalInstructions:`allow`},relay:{context:!0,skills:!0,plugins:!0,statusLine:!0,mcp:!0},skills:[],plugins:[],mcp:{mode:`host`},hooks:{mode:`host`},permissions:{filesystem:`host`},env:{},providerOptions:{}},i;n&&t===`duplicate`?(i=JSON.parse(JSON.stringify(n)),i.name=n.name+`-copy`,delete i.builtIn):i=n&&(t===`edit`||t===`view`)?JSON.parse(JSON.stringify(n)):r,e({profileModal:{open:!0,mode:t,profile:i}})},closeProfileModal(){e({profileModal:{...t().profileModal,open:!1}})},updateProfileModal(n){let r=t().profileModal.profile;e({profileModal:{...t().profileModal,profile:{...r,...n}}})},async saveProfile(){let{mode:n,profile:i}=t().profileModal;if(!i.name.trim()){t().showError(`Validation`,`Profile name is required.`);return}if(n!==`view`)try{await r(`PUT`,`/agent-profiles/`+encodeURIComponent(i.name.trim()),i),e({profileModal:{...t().profileModal,open:!1}}),await t().fetchAgentProfiles(),t().showNotification(`Profile "${i.name}" saved`)}catch(e){t().showError(`Save Failed`,e.message)}},deleteProfile(e){t().openConfirm(`Delete Profile`,`Delete agent profile "${e}"?`,async()=>{try{await r(`DELETE`,`/agent-profiles/`+encodeURIComponent(e)),await t().fetchAgentProfiles(),t().showNotification(`Profile "${e}" deleted`)}catch(e){t().showError(`Delete Failed`,e.message)}})}}),Bt=(e,t)=>({operatorActivity:[],recordOperatorActivity(n){let i={id:Date.now(),kind:`operator`,title:n.title||`Activity`,body:n.body,meta:n.meta,icon:n.icon,view:n.view,peer:n.peer,messageId:n.messageId,pairId:n.pairId,taskId:n.taskId,agentId:n.agentId,ts:Date.now(),clientId:`op-`+Date.now(),createdAt:Date.now()};e({operatorActivity:[i,...t().operatorActivity.slice(0,79)]}),r(`POST`,`/activity`,{operatorId:C,clientId:i.clientId,kind:i.kind,title:i.title,body:i.body,meta:i.meta,icon:i.icon,view:i.view,peer:i.peer,messageId:i.messageId,pairId:i.pairId,taskId:i.taskId,agentId:i.agentId}).catch(()=>{})},async openActivityItem(e){if(e.view&&await t().switchView(e.view===`inbox`?`chat`:e.view),e.peer&&t().openInboxThread(e.peer),e.agentId){let n=t().agentsById[e.agentId];n&&t().openAgentDetail(n)}if(e.taskId){let n=t().tasks.find(t=>t.id===e.taskId);n&&await t().openTaskEvents(n)}}});function Q(e){return h(e.createdAt??e.ts)}function Vt(e,t){let n=[`# Agent Relay Timeline`,``,`Exported: ${t}`,`Events: ${e.length}`,``];for(let t of e){let e=new Date(Q(t)).toISOString();n.push(`## ${t.title||t.kind||`Event`}`),n.push(`- When: ${e}`),t.kind&&n.push(`- Kind: ${t.kind}`),t.agentId&&n.push(`- Agent: ${t.agentId}`),t.peer&&n.push(`- Peer: ${t.peer}`),t.body&&n.push(``,t.body),n.push(``)}return n.join(`
8
8
  `)}var Ht=(e,t)=>({activityEvents:[],activityFilter:``,async fetchActivityEvents(){try{e({activityEvents:await r(`GET`,`/activity?limit=200`)})}catch{}},exportActivity(e){let n=t(),r=[...n.operatorActivity,...n.activityEvents].sort((e,t)=>Q(t)-Q(e)),i=new Date().toISOString(),a=`agent-relay-timeline-${i.slice(0,10)}.${e===`json`?`json`:`md`}`;e===`json`?w(a,JSON.stringify({title:`Agent Relay Timeline`,exportedAt:i,events:r},null,2),`application/json`):w(a,Vt(r,i),`text/markdown`)},exportThread(e,t){let n=`agent-relay-thread-${l(e.peer)}.${t===`json`?`json`:`md`}`,r={title:`Thread: `+e.peer,importedHistory:e.importedHistory||[],messages:e.messages,exportedAt:new Date().toISOString()};w(n,JSON.stringify(r,null,2),t===`json`?`application/json`:`text/markdown`)},exportPair(e,t){let n=`agent-relay-pair-${l(e.id)}.${t===`json`?`json`:`md`}`,r={title:`Pair: `+e.id,pair:e,exportedAt:new Date().toISOString()};w(n,JSON.stringify(r,null,2),t===`json`?`application/json`:`text/markdown`)},async exportTask(n,i){let a=t().taskEventCache[n.id]||[];if(!a.length)try{a=await r(`GET`,`/tasks/`+n.id+`/events`),e({taskEventCache:{...t().taskEventCache,[n.id]:a}})}catch{}let o=`agent-relay-task-${n.id}.${i===`json`?`json`:`md`}`,s={title:`Task: `+(n.title||`#`+n.id),task:n,events:a,exportedAt:new Date().toISOString()};w(o,JSON.stringify(s,null,2),i===`json`?`application/json`:`text/markdown`)}}),Ut=(e,t)=>({channels:[],connectors:[],integrations:[],automations:[],automationRuns:[],health:null,maintenanceJobs:[],analyticsPeriod:`24h`,analyticsData:null,async fetchChannels(){try{e({channels:await r(`GET`,`/channels`)})}catch{}},async fetchConnectors(){try{e({connectors:await r(`GET`,`/connectors`)})}catch{}},async fetchIntegrations(){try{e({integrations:await r(`GET`,`/integrations`)})}catch{}},async fetchAutomations(){try{e({automations:await r(`GET`,`/automations`)})}catch{}},async fetchAutomationRuns(t){try{let n=new URLSearchParams({limit:`100`});t&&n.set(`automationId`,t),e({automationRuns:await r(`GET`,`/automation-runs?`+n.toString())})}catch{}},async fetchHealth(){try{e({health:await r(`GET`,`/health`)})}catch{}},async fetchMaintenanceJobs(){try{e({maintenanceJobs:await r(`GET`,`/maintenance/jobs`)})}catch{}},async runMaintenanceJob(n){try{let i=await r(`POST`,`/maintenance/jobs/`+encodeURIComponent(n)+`/run`,{});return e({maintenanceJobs:i.jobs}),t().showNotification(i.run.status===`succeeded`?`Maintenance job completed`:`Maintenance job skipped`),i.run}catch(e){return t().showError(`Maintenance Job Failed`,e.message),await t().fetchMaintenanceJobs(),null}},async runHealthAction(n){if(n.preset&&e({agentPresetFilter:n.preset,showOffline:!0}),n.api&&n.path&&(await r(n.api,n.path),await t().refreshLiveData()),n.view&&await t().switchView(n.view),n.copy)try{await navigator.clipboard?.writeText(n.copy)}catch{}},async runConnectorAction(e,n){try{let i=await r(`POST`,`/connectors/`+encodeURIComponent(e)+`/actions`,{action:n});if(await t().fetchConnectors(),!i.ok)throw Error(i.stderr||`${n} failed`);return i}catch(e){throw t().showError(`Connector Action Failed`,e.message),e}},async fetchAnalytics(){try{e({analyticsData:await r(`GET`,`/stats/analytics?period=`+t().analyticsPeriod)})}catch{}},setAnalyticsPeriod(n){e({analyticsPeriod:n}),t().fetchAnalytics()}}),Wt=(e,t)=>({workspaces:[],workspaceFocusId:null,workspaceGitState:{},workspaceMergePreview:{},workspaceDiff:{},workspaceOrphans:[],async openWorkspaceFocus(n){e({workspaceFocusId:n}),await t().switchView(`workspaces`)},async fetchWorkspaces(){try{e({workspaces:await r(`GET`,`/workspaces`)})}catch{}},async fetchWorkspaceGitState(t){try{let n=await r(`GET`,`/workspaces/`+encodeURIComponent(t)+`/git-state`);e(e=>({workspaceGitState:{...e.workspaceGitState,[t]:n}}))}catch(n){e(e=>({workspaceGitState:{...e.workspaceGitState,[t]:{available:!1,reason:n.message}}}))}},async fetchWorkspaceMergePreview(t){try{let n=await r(`GET`,`/workspaces/`+encodeURIComponent(t)+`/merge-preview`);e(e=>({workspaceMergePreview:{...e.workspaceMergePreview,[t]:n}}))}catch(n){e(e=>({workspaceMergePreview:{...e.workspaceMergePreview,[t]:{available:!1,reason:n.message}}}))}},async fetchWorkspaceDiff(t){try{let n=await r(`GET`,`/workspaces/`+encodeURIComponent(t)+`/diff`);e(e=>({workspaceDiff:{...e.workspaceDiff,[t]:n}}))}catch(n){e(e=>({workspaceDiff:{...e.workspaceDiff,[t]:{available:!1,reason:n.message}}}))}},async fetchWorkspaceOrphans(){try{e({workspaceOrphans:(await r(`GET`,`/workspaces/orphans`)).orphans??[]})}catch{}},async reclaimWorkspaceOrphan(e){t().openConfirm(`Reclaim Orphan Worktree`,`Remove the orphaned worktree "${e.branch||e.worktreePath}" from disk? It has no live agent.`,async()=>{try{await r(`POST`,`/workspaces/orphans/reclaim`,{worktreePath:e.worktreePath,repoRoot:e.repoRoot,branch:e.branch}),t().showNotification(`Orphan reclaim dispatched`),await Promise.all([t().fetchWorkspaceOrphans(),t().fetchActivityEvents()])}catch(e){t().showError(`Reclaim Failed`,e.message)}})},async workspaceAction(e,n){let i=n===`ready`?`Mark ready`:n===`request-review`?`Request review`:n===`merge-plan`?`Mark merge planned`:n===`merge`?`Merge`:n===`abandon`?`Abandon`:`Cleanup`,a=async()=>{try{await r(`POST`,`/workspaces/`+encodeURIComponent(e)+`/actions`,{action:n}),t().showNotification(n===`cleanup`?`Workspace cleanup requested`:n===`merge`?`Workspace merge dispatched`:`Workspace updated: ${i}`),await Promise.all([t().fetchWorkspaces(),t().fetchOrchestrators(),t().fetchActivityEvents()])}catch(e){t().showError(`Workspace Action Failed`,e.message)}};if(n===`cleanup`||n===`abandon`||n===`merge`){let r=t().workspaces.find(t=>t.id===e),i=r?.branch||r?.worktreePath||e;if(n===`merge`){let n=t().workspaceMergePreview[e],r=n&&n.available!==!1?` — ${n.strategy===`pr`?`opens a PR`:`rebases & fast-forwards into ${n.baseRef||`base`}, then deletes the branch`}.`:` — lands the work and deletes the branch.`;t().openConfirm(`Merge Workspace`,`Merge workspace "${i}"?${r}`,a);return}if(n===`cleanup`){await t().fetchWorkspaceGitState(e);let n=t().workspaceGitState[e],r=``;if(n&&n.available!==!1&&!n.missing){let e=n.ahead??0,t=n.dirtyCount??0;(e>0||t>0)&&(r=` ⚠ This destroys ${[e>0?`${e} unmerged commit(s)`:``,t>0?`${t} uncommitted change(s)`:``].filter(Boolean).join(` and `)}.`)}t().openConfirm(`Cleanup Workspace`,`Remove the worktree for "${i}" on the host?${r}`,a);return}t().openConfirm(`Abandon Workspace`,`Abandon workspace "${i}"?`,a);return}await a()},async purgeWorkspace(e){let n=t().workspaces.find(t=>t.id===e),i=n?.branch||n?.worktreePath||e;t().openConfirm(`Purge Workspace Record`,`Permanently remove the record for "${i}"? This only clears the dashboard row — it does not touch disk.`,async()=>{try{await r(`DELETE`,`/workspaces/`+encodeURIComponent(e)),t().showNotification(`Workspace record purged`),await Promise.all([t().fetchWorkspaces(),t().fetchActivityEvents()])}catch(e){t().showError(`Purge Failed`,e.message)}})}}),Gt=(e,t)=>({memories:[],memoryTotal:0,memoryBrokerInfo:null,memoryStats:null,memoryFilters:{search:``,type:``,scope:``,tags:``,visibility:``,minRelevance:`0`},selectedMemoryId:``,memoryLoading:!1,async refreshMemory(){await Promise.all([t().fetchMemoryBroker(),t().fetchMemoryStats(),t().fetchMemories()])},async fetchMemoryBroker(){try{e({memoryBrokerInfo:await r(`GET`,`/memories/broker`)})}catch(e){t().showError(`Memory Broker Failed`,e.message)}},async fetchMemoryStats(){try{e({memoryStats:await r(`GET`,`/memories/stats`)})}catch{}},async fetchMemories(){let n=t().memoryFilters,i={limit:100};if(n.type&&(i.type=n.type),n.scope.trim()&&(i.scope=n.scope.trim()),n.visibility&&(i.visibility=n.visibility),n.tags.trim()&&(i.tags=n.tags.split(`,`).map(e=>e.trim()).filter(Boolean)),n.minRelevance.trim()!==``){let e=Number(n.minRelevance);Number.isFinite(e)&&(i.minRelevance=Math.max(0,Math.min(1,e)))}e({memoryLoading:!0});try{let n=await r(`POST`,`/memories/search`,i),a=n.memories.some(e=>e.id===t().selectedMemoryId)?t().selectedMemoryId:n.memories[0]?.id||``;e({memories:n.memories,memoryTotal:n.total,selectedMemoryId:a})}catch(e){t().showError(`Memory Search Failed`,e.message)}finally{e({memoryLoading:!1})}},async saveMemory(n,i){try{e({selectedMemoryId:(i?await r(`PATCH`,`/memories/`+encodeURIComponent(i),n):await r(`POST`,`/memories`,n)).id}),await Promise.all([t().fetchMemories(),t().fetchMemoryStats()]),t().showNotification(i?`Memory updated`:`Memory created`)}catch(e){t().showError(`Memory Save Failed`,e.message)}},deleteMemory(n){t().openConfirm(`Delete Memory`,`Delete memory "${n}"?`,async()=>{try{await r(`DELETE`,`/memories/`+encodeURIComponent(n)),e({selectedMemoryId:``}),await Promise.all([t().fetchMemories(),t().fetchMemoryStats()]),t().showNotification(`Memory deleted`)}catch(e){t().showError(`Delete Failed`,e.message)}})},async injectMemory(e){try{let n=await r(`POST`,`/memories/inject`,e);return t().showNotification(`Memory inject command sent to ${e.agentId}`),n}catch(e){return t().showError(`Memory Inject Failed`,e.message),null}}}),Kt=(e,t)=>({projectFocusId:null,projectByCwd:{},async openProjectFocus(n){e({projectFocusId:n}),await t().switchView(`projects`)},consumeProjectFocus(){t().projectFocusId!==null&&e({projectFocusId:null})},async fetchProjectForCwd(n){if(!(!n||n in t().projectByCwd))try{let t=await r(`GET`,`/projects/resolve?cwd=`+encodeURIComponent(n));e(e=>({projectByCwd:{...e.projectByCwd,[n]:t.project??null}}))}catch{}}});function qt(){return $.persist.hasHydrated()?Promise.resolve():new Promise(e=>{let t=$.persist.onFinishHydration(()=>{t(),e()})})}var $=ce()(de((...e)=>({...vt({waitForHydration:qt})(...e),...yt(...e),...Dt(...e),...Mt(...e),...Nt(...e),...It(...e),...Lt(...e),...Rt(...e),...zt(...e),...mt(...e),...Bt(...e),...Ht(...e),...ht(...e),...Ut(...e),...Wt(...e),...Gt(...e),...Kt(...e)}),{name:`agent-relay-dashboard`,partialize:e=>({theme:e.theme,view:e.view,showOffline:e.showOffline,showBuiltIns:e.showBuiltIns,showReasoning:e.showReasoning,autoRefresh:e.autoRefresh,voiceTtsEnabled:e.voiceTtsEnabled,voiceTtsLang:e.voiceTtsLang,voiceTtsMode:e.voiceTtsMode,voiceTtsKokoroVoice:e.voiceTtsKokoroVoice,voiceTtsBrowserVoice:e.voiceTtsBrowserVoice,voiceInputMode:e.voiceInputMode,agentSort:e.agentSort,agentSortDir:e.agentSortDir,agentPresetFilter:e.agentPresetFilter,agentStatusFilter:e.agentStatusFilter,agentTagFilter:e.agentTagFilter,agentHostFilter:e.agentHostFilter,pairStatusFilter:e.pairStatusFilter,inboxSort:e.inboxSort,inboxSortDir:e.inboxSortDir,inboxShowArchived:e.inboxShowArchived,chatAgentProviderFilter:e.chatAgentProviderFilter,chatAgentStatusFilter:e.chatAgentStatusFilter,chatAgentTagFilter:e.chatAgentTagFilter,chatAgentCapFilter:e.chatAgentCapFilter,chatAgentHostFilter:e.chatAgentHostFilter,chatAgentSort:e.chatAgentSort,chatAgentSortDir:e.chatAgentSortDir,chatAgentGroupBy:e.chatAgentGroupBy,chatAgentFiltersCollapsed:e.chatAgentFiltersCollapsed,planCollapsed:e.planCollapsed,activityFilter:e.activityFilter,analyticsPeriod:e.analyticsPeriod,memoryFilters:e.memoryFilters,authToken:e.authToken,inboxReadCursors:e.inboxReadCursors,inboxArchivedThreads:e.inboxArchivedThreads,inboxDrafts:e.inboxDrafts,chatStatusEvents:e.chatStatusEvents,operatorActivity:e.operatorActivity,notifications:e.notifications,notificationUnread:e.notificationUnread,notificationSettings:e.notificationSettings,spawnOrchId:e.spawnOrchId,spawnProvider:e.spawnProvider,spawnModel:e.spawnModel,spawnEffort:e.spawnEffort,spawnProfile:e.spawnProfile,spawnCwd:e.spawnCwd,spawnApproval:e.spawnApproval,spawnWorkspaceMode:e.spawnWorkspaceMode,spawnCwdHistory:e.spawnCwdHistory})}));$.subscribe(_t);export{Ue as a,N as c,Se as d,De as f,M as g,Oe as h,X as i,ke as l,Te as m,Pt as n,H as o,we as p,Y as r,Re as s,$ as t,Ae as u};
9
- //# sourceMappingURL=store-BRvMMH5T.js.map
9
+ //# sourceMappingURL=store-D1K4_xId.js.map