agent-relay-server 0.97.0 → 0.98.1

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 (80) hide show
  1. package/docs/openapi.json +55 -1
  2. package/package.json +2 -2
  3. package/public/assets/{MessageBubble-CIDyX8f7.js → MessageBubble-C4AeEHdz.js} +2 -2
  4. package/public/assets/{MessageBubble-CIDyX8f7.js.map → MessageBubble-C4AeEHdz.js.map} +1 -1
  5. package/public/assets/{PlanGraphPanel-BmWB81w_.js → PlanGraphPanel-cwPUGFXA.js} +2 -2
  6. package/public/assets/{PlanGraphPanel-BmWB81w_.js.map → PlanGraphPanel-cwPUGFXA.js.map} +1 -1
  7. package/public/assets/{activity-QQikHZe4.js → activity-BWGwnSg5.js} +2 -2
  8. package/public/assets/{activity-QQikHZe4.js.map → activity-BWGwnSg5.js.map} +1 -1
  9. package/public/assets/{agent-profiles-WvAN5cR_.js → agent-profiles-C6N9cTJg.js} +2 -2
  10. package/public/assets/{agent-profiles-WvAN5cR_.js.map → agent-profiles-C6N9cTJg.js.map} +1 -1
  11. package/public/assets/{agents-BsFfumLn.js → agents-FUBxhCEU.js} +2 -2
  12. package/public/assets/{agents-BsFfumLn.js.map → agents-FUBxhCEU.js.map} +1 -1
  13. package/public/assets/{automation-BTbpiINE.js → automation-CMketzfB.js} +2 -2
  14. package/public/assets/{automation-BTbpiINE.js.map → automation-CMketzfB.js.map} +1 -1
  15. package/public/assets/{chat-BlFUmD3r.js → chat-BV_pnRhk.js} +2 -2
  16. package/public/assets/{chat-BlFUmD3r.js.map → chat-BV_pnRhk.js.map} +1 -1
  17. package/public/assets/{formatted-body-impl-Dbjjdcu9.js → formatted-body-impl-DzHQTBmn.js} +2 -2
  18. package/public/assets/{formatted-body-impl-Dbjjdcu9.js.map → formatted-body-impl-DzHQTBmn.js.map} +1 -1
  19. package/public/assets/index-CYLrIuJT.css +2 -0
  20. package/public/assets/{index-CPXz74W5.js → index-CdEAo41I.js} +7 -7
  21. package/public/assets/index-CdEAo41I.js.map +1 -0
  22. package/public/assets/{insights-D1Oq25BL.js → insights-C_pJNcFD.js} +2 -2
  23. package/public/assets/{insights-D1Oq25BL.js.map → insights-C_pJNcFD.js.map} +1 -1
  24. package/public/assets/{maintenance-CgXJwFTo.js → maintenance-Ckz5BAor.js} +2 -2
  25. package/public/assets/{maintenance-CgXJwFTo.js.map → maintenance-Ckz5BAor.js.map} +1 -1
  26. package/public/assets/{managed-agents-CbuFHwWE.js → managed-agents-BbZclnqP.js} +2 -2
  27. package/public/assets/{managed-agents-CbuFHwWE.js.map → managed-agents-BbZclnqP.js.map} +1 -1
  28. package/public/assets/{markdown-preview-impl-B79bSsKK.js → markdown-preview-impl-CtuHw6Mm.js} +2 -2
  29. package/public/assets/{markdown-preview-impl-B79bSsKK.js.map → markdown-preview-impl-CtuHw6Mm.js.map} +1 -1
  30. package/public/assets/{memory-Box_rMj_.js → memory-C5DK3rhW.js} +2 -2
  31. package/public/assets/{memory-Box_rMj_.js.map → memory-C5DK3rhW.js.map} +1 -1
  32. package/public/assets/{messages-BXIHBaN2.js → messages-CsjtiFEb.js} +2 -2
  33. package/public/assets/{messages-BXIHBaN2.js.map → messages-CsjtiFEb.js.map} +1 -1
  34. package/public/assets/{orchestrators-MNj_mp3U.js → orchestrators-D9fMiBRy.js} +2 -2
  35. package/public/assets/{orchestrators-MNj_mp3U.js.map → orchestrators-D9fMiBRy.js.map} +1 -1
  36. package/public/assets/{overview-KfwJgCUa.js → overview-BLWoCnNQ.js} +2 -2
  37. package/public/assets/{overview-KfwJgCUa.js.map → overview-BLWoCnNQ.js.map} +1 -1
  38. package/public/assets/{pairs-DfrGWlgL.js → pairs-HnvpLz4C.js} +2 -2
  39. package/public/assets/{pairs-DfrGWlgL.js.map → pairs-HnvpLz4C.js.map} +1 -1
  40. package/public/assets/{registry-CiBC97sL.js → registry-BqAS3ADV.js} +2 -2
  41. package/public/assets/{registry-CiBC97sL.js.map → registry-BqAS3ADV.js.map} +1 -1
  42. package/public/assets/{security-BbU_vIdb.js → security-CWgtcQ2X.js} +2 -2
  43. package/public/assets/{security-BbU_vIdb.js.map → security-CWgtcQ2X.js.map} +1 -1
  44. package/public/assets/{select-CeQwmVTm.js → select-UdIYiKFs.js} +2 -2
  45. package/public/assets/{select-CeQwmVTm.js.map → select-UdIYiKFs.js.map} +1 -1
  46. package/public/assets/settings-ruDxPuza.js +6 -0
  47. package/public/assets/settings-ruDxPuza.js.map +1 -0
  48. package/public/assets/{tasks-za0RxIQw.js → tasks-DomQFwZP.js} +2 -2
  49. package/public/assets/{tasks-za0RxIQw.js.map → tasks-DomQFwZP.js.map} +1 -1
  50. package/public/assets/{teams-ByAqwLG9.js → teams-CXNp0U3B.js} +2 -2
  51. package/public/assets/{teams-ByAqwLG9.js.map → teams-CXNp0U3B.js.map} +1 -1
  52. package/public/assets/{terminal-viewer-impl-CkoWD5D_.js → terminal-viewer-impl-DiWBtzvZ.js} +2 -2
  53. package/public/assets/{terminal-viewer-impl-CkoWD5D_.js.map → terminal-viewer-impl-DiWBtzvZ.js.map} +1 -1
  54. package/public/assets/{user-avatar-Q_N6iHEn.js → user-avatar-DBs9Koqp.js} +2 -2
  55. package/public/assets/{user-avatar-Q_N6iHEn.js.map → user-avatar-DBs9Koqp.js.map} +1 -1
  56. package/public/assets/{work-queue-DfRo1B2P.js → work-queue-BD29QuLd.js} +2 -2
  57. package/public/assets/{work-queue-DfRo1B2P.js.map → work-queue-BD29QuLd.js.map} +1 -1
  58. package/public/index.html +2 -2
  59. package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
  60. package/runner/src/adapter.ts +9 -1
  61. package/src/agent-busy-health.ts +62 -63
  62. package/src/codex-wham-quota.ts +5 -76
  63. package/src/compaction-watch.ts +7 -6
  64. package/src/db/provider-quota-burn.ts +6 -18
  65. package/src/db/provider-quotas.ts +27 -12
  66. package/src/lifecycle-manager.ts +4 -2
  67. package/src/maintenance/jobs.ts +1 -1
  68. package/src/notification-types.ts +3 -1
  69. package/src/quota.ts +1 -1
  70. package/src/routes/index.ts +3 -0
  71. package/src/routes/routing-policy.ts +25 -0
  72. package/src/routing-policy-push.ts +82 -0
  73. package/src/routing-policy-store.ts +148 -0
  74. package/src/routing-rule-resolver.ts +87 -0
  75. package/src/security.ts +6 -0
  76. package/src/spawn-targets.ts +44 -12
  77. package/public/assets/index-CPWbr4sq.css +0 -2
  78. package/public/assets/index-CPXz74W5.js.map +0 -1
  79. package/public/assets/settings-DBsL3jb7.js +0 -6
  80. package/public/assets/settings-DBsL3jb7.js.map +0 -1
@@ -1,6 +0,0 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{$n as t,A as n,An as r,B as i,D as a,En as o,I as s,Kt as c,Qn as l,S as u,W as d,Xn as f,Z as p,Zt as m,_n as h,c as g,dr as _,ft as v,h as y,hn as b,j as x,jt as S,p as C,qt as ee,rr as w}from"./lucide-react-BYZuAhQs.js";import{d as T,p as E,s as te,t as D}from"./store-pKbf_WYd.js";import{o as O,r as k}from"./types-Tv67voFu.js";import{t as ne}from"./themes-DjSwmAZN.js";import{a as A,i as j,n as M,r as N,t as P}from"./select-CeQwmVTm.js";import{t as F}from"./badge-BLar6FjP.js";import{t as I}from"./button-BrIB69qd.js";import{t as L}from"./input-B_fUHtLD.js";import{r as R,z}from"./index-CPXz74W5.js";import{a as B,i as V,n as H,o as U,r as W,t as G}from"./card-lhnFnBoz.js";import{t as re}from"./user-avatar-Q_N6iHEn.js";var K=e(_(),1);function q(e){return`${e.namespace}/${e.key}`}function ie(e){return`/settings/${encodeURIComponent(e.namespace)}/${encodeURIComponent(e.key)}`}function ae(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``)||`settings`}function oe(e){let t=new Map;for(let n of e.filter(e=>e.readable)){let e=n.display?.group?.trim()||n.namespace;t.set(e,[...t.get(e)??[],n])}return[...t.entries()].map(([e,t])=>({group:e,slug:ae(e),settings:t.sort(se)})).sort((e,t)=>ce(e.settings)-ce(t.settings)||e.group.localeCompare(t.group))}function se(e,t){return(e.display?.order??2**53-1)-(t.display?.order??2**53-1)||e.display?.label?.localeCompare(t.display?.label??``)||q(e).localeCompare(q(t))}function ce(e){return Math.min(...e.map(e=>e.display?.order??2**53-1))}function le(e){return Array.isArray(e.type)?e.type.find(e=>e!==`null`):e.type}function J(e,t,n){if(!t.length)return n;let[r,...i]=t;if(r===void 0)return n;if(typeof r==`number`){let t=Array.isArray(e)?[...e]:[];return t[r]=J(t[r],i,n),t}let a=O(e)?{...e}:{},o=J(a[r],i,n);return o===void 0?delete a[r]:a[r]=o,a}function ue(e){if(e.default!==void 0)return e.default;if(e.const!==void 0)return e.const;if(e.enum?.length)return e.enum[0];switch(le(e)){case`boolean`:return!1;case`integer`:case`number`:return 0;case`array`:return[];case`object`:return{};case`string`:return``;default:return}}function de(e){return e.split(/\r?\n|,/).map(e=>e.trim()).filter(Boolean)}function fe(e){return Array.isArray(e)?e.map(e=>String(e)).join(`
2
- `):``}function pe(e){return O(e)?Object.entries(e).map(([e,t])=>`${e}=${String(t??``)}`).join(`
3
- `):``}function me(e){return Object.fromEntries(e.split(/\r?\n/).map(e=>e.trim()).filter(Boolean).map(e=>{let t=e.indexOf(`=`);return t>=0?[e.slice(0,t).trim(),e.slice(t+1)]:[e,``]}))}var Y=l(),he=`__unset__`;function ge(e){return e===`server-runtime`?`Server runtime`:e===`bootstrap`?`Bootstrap`:`Browser`}function _e(e){return e===`server-runtime`?`Stored by Relay and mutable while the server is running.`:e===`bootstrap`?`Read from startup configuration; restart or host config changes are required.`:`Stored only in this browser profile.`}function ve(e){return e===`browser`?(0,Y.jsx)(p,{className:`size-3.5`}):(0,Y.jsx)(a,{className:`size-3.5`})}function X(e){return e.details??[]}function ye({group:e,settings:t,onSaved:n}){let r=[...new Set(t.map(e=>e.tier))];return(0,Y.jsxs)(`section`,{className:`space-y-3`,children:[(0,Y.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,Y.jsx)(`h2`,{className:`text-base font-semibold`,children:e}),(0,Y.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:r.map(e=>(0,Y.jsxs)(F,{variant:`outline`,className:`gap-1`,title:_e(e),children:[ve(e),ge(e)]},e))})]}),t.length===0?(0,Y.jsx)(G,{size:`sm`,children:(0,Y.jsx)(W,{className:`text-sm text-muted-foreground`,children:`No settings in this group.`})}):(0,Y.jsx)(`div`,{className:`space-y-3`,children:t.map(e=>(0,Y.jsx)(be,{setting:e,onSaved:n},q(e)))})]})}function be({setting:e,onSaved:r}){let[i,a]=(0,K.useState)(()=>e.value??e.defaults??ue(e.schema)),[o,s]=(0,K.useState)(!1),[c,l]=(0,K.useState)(``),[u,d]=(0,K.useState)([]),f=e.writable&&e.tier===`server-runtime`;function p(e,t){a(n=>J(n,e,t)),d([]),l(``)}async function m(){if(f){s(!0),d([]),l(``);try{let n=await t(`PUT`,ie(e),{value:i,updatedBy:`dashboard`});a(n.value),r(n),l(`Saved`)}catch(e){let t=X(e);d(t.length?t:[e.message])}finally{s(!1)}}}return(0,Y.jsxs)(G,{size:`sm`,children:[(0,Y.jsxs)(B,{children:[(0,Y.jsxs)(U,{className:`flex flex-wrap items-center gap-2 text-sm`,children:[e.display.label,(0,Y.jsxs)(F,{variant:`outline`,className:`gap-1`,title:_e(e.tier),children:[ve(e.tier),ge(e.tier)]}),!e.writable&&(0,Y.jsx)(F,{variant:`secondary`,children:`Read only`})]}),e.display.description&&(0,Y.jsx)(V,{children:e.display.description}),(0,Y.jsx)(H,{children:(0,Y.jsxs)(I,{size:`sm`,onClick:m,disabled:!f||o,children:[(0,Y.jsx)(n,{className:`size-4`}),o?`Saving`:`Save`]})})]}),(0,Y.jsxs)(W,{className:`space-y-3`,children:[(0,Y.jsx)(xe,{schema:e.schema,value:i,path:[],label:e.display.label,required:!0,disabled:!f||o,onChange:p}),(0,Y.jsxs)(`p`,{className:`flex flex-wrap items-center gap-x-2 text-[11px] text-muted-foreground`,children:[(0,Y.jsxs)(`code`,{className:`rounded bg-muted px-1.5 py-0.5 font-mono`,children:[e.namespace,`/`,e.key]}),(0,Y.jsxs)(`span`,{children:[`read `,(0,Y.jsx)(`span`,{className:`text-foreground/70`,children:e.scope.read})]}),(0,Y.jsx)(`span`,{"aria-hidden":!0,children:`·`}),(0,Y.jsxs)(`span`,{children:[`write `,(0,Y.jsx)(`span`,{className:`text-foreground/70`,children:e.scope.write})]})]}),u.length>0&&(0,Y.jsxs)(`div`,{className:`rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive`,children:[(0,Y.jsxs)(`div`,{className:`mb-1 flex items-center gap-2 font-medium`,children:[(0,Y.jsx)(h,{className:`size-4`}),`Save failed`]}),(0,Y.jsx)(`ul`,{className:`list-disc space-y-1 pl-5`,children:u.map(e=>(0,Y.jsx)(`li`,{children:e},e))})]}),c&&(0,Y.jsxs)(`p`,{className:`flex items-center gap-1 text-sm text-emerald-500`,children:[(0,Y.jsx)(b,{className:`size-4`}),c]})]})]})}function xe(e){let{schema:t,value:n,path:r,label:i,required:a,disabled:o,onChange:s}=e,c=le(t);if(t.enum?.length){let e=n==null||n===``?he:String(n);return(0,Y.jsx)(Z,{label:i,description:t.description,children:(0,Y.jsxs)(P,{value:e,onValueChange:e=>s(r,e===`__unset__`?void 0:e),disabled:o,children:[(0,Y.jsx)(j,{children:(0,Y.jsx)(A,{})}),(0,Y.jsxs)(M,{children:[!a&&(0,Y.jsx)(N,{value:`__unset__`,children:`Not set`}),t.enum.map(e=>(0,Y.jsx)(N,{value:String(e),children:String(e)},String(e)))]})]})})}if(c===`boolean`)return(0,Y.jsxs)(`div`,{className:`flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3`,children:[(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`div`,{className:`text-sm font-medium`,children:i}),t.description&&(0,Y.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:t.description})]}),(0,Y.jsx)(z,{checked:!!n,onCheckedChange:e=>s(r,e),disabled:o})]});if(c===`integer`||c===`number`)return(0,Y.jsx)(Z,{label:i,description:t.description,children:(0,Y.jsx)(L,{type:`number`,min:typeof t.minimum==`number`?t.minimum:void 0,max:typeof t.maximum==`number`?t.maximum:void 0,step:c===`integer`?1:`any`,value:typeof n==`number`?n:``,disabled:o,onChange:e=>s(r,e.target.value===``&&!a?void 0:Number(e.target.value))})});if(c===`array`)return(0,Y.jsx)(Z,{label:i,description:t.description??`One item per line.`,children:(0,Y.jsx)(R,{rows:Math.min(8,Math.max(3,Array.isArray(n)?n.length+1:3)),value:fe(n),disabled:o,onChange:e=>s(r,de(e.target.value))})});if(c===`object`){let e=t.properties??{},a=new Set(t.required??[]);return Object.keys(e).length===0&&t.additionalProperties?(0,Y.jsx)(Z,{label:i,description:t.description??`KEY=value, one entry per line.`,children:(0,Y.jsx)(R,{rows:5,value:pe(n),disabled:o,onChange:e=>s(r,me(e.target.value))})}):(0,Y.jsxs)(`div`,{className:`space-y-3`,children:[r.length>0&&(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`div`,{className:`text-sm font-medium`,children:i}),t.description&&(0,Y.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:t.description})]}),(0,Y.jsx)(`div`,{className:`grid gap-3 md:grid-cols-2`,children:Object.entries(e).map(([e,t])=>{let i=O(n)?n[e]:void 0;return(0,Y.jsx)(xe,{schema:t,value:i===void 0&&a.has(e)?ue(t):i,path:[...r,e],label:t.title||Se(e),required:a.has(e),disabled:o,onChange:s},e)})})]})}return(0,Y.jsx)(Z,{label:i,description:t.description,children:(0,Y.jsx)(L,{value:typeof n==`string`?n:n==null?``:String(n),disabled:o,onChange:e=>s(r,e.target.value===``&&!a?void 0:e.target.value)})})}function Z({label:e,description:t,children:n}){return(0,Y.jsxs)(`label`,{className:`block space-y-1.5 text-sm`,children:[(0,Y.jsx)(`span`,{className:`text-muted-foreground`,children:e}),n,t&&(0,Y.jsx)(`span`,{className:`block text-xs text-muted-foreground`,children:t})]})}function Se(e){return e.replace(/([a-z0-9])([A-Z])/g,`$1 $2`).replace(/[-_]+/g,` `).replace(/^\w/,e=>e.toUpperCase())}function Ce(){let e=D(e=>e.theme),t=D(e=>e.showReasoning),n=D(e=>e.set);return(0,Y.jsxs)(`section`,{className:`space-y-4`,children:[(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`h2`,{className:`text-base font-semibold`,children:`Browser preferences`}),(0,Y.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`These are stored in local dashboard state, not in Relay server config.`})]}),(0,Y.jsxs)(G,{size:`sm`,children:[(0,Y.jsxs)(B,{children:[(0,Y.jsx)(U,{className:`text-sm`,children:`Dashboard display`}),(0,Y.jsx)(V,{className:`text-xs`,children:`Browser tier · persisted in this browser profile.`}),(0,Y.jsx)(H,{children:(0,Y.jsxs)(F,{variant:`outline`,className:`gap-1`,children:[(0,Y.jsx)(p,{className:`size-3.5`}),`Browser`]})})]}),(0,Y.jsxs)(W,{className:`grid gap-3 md:grid-cols-2`,children:[(0,Y.jsx)(Z,{label:`Theme`,children:(0,Y.jsxs)(P,{value:e,onValueChange:e=>n({theme:e}),children:[(0,Y.jsx)(j,{children:(0,Y.jsx)(A,{})}),(0,Y.jsx)(M,{children:ne.map(e=>(0,Y.jsx)(N,{value:e.id,children:e.label},e.id))})]})}),(0,Y.jsxs)(`div`,{className:`flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3`,children:[(0,Y.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Y.jsx)(r,{className:`size-4`}),(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`div`,{className:`text-sm font-medium`,children:`Show reasoning details`}),(0,Y.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:`Display captured reasoning/tool steps in chat. Server capture is controlled separately by provider reasoningCapture.`})]})]}),(0,Y.jsx)(z,{checked:t,onCheckedChange:e=>n({showReasoning:e})})]})]})]}),(0,Y.jsx)(we,{})]})}function we(){let e=D(e=>e.voiceTtsEnabled),t=D(e=>e.setVoiceTtsEnabled),n=D(e=>e.voiceTtsMode),r=D(e=>e.setVoiceTtsMode),i=D(e=>e.voiceTtsKokoroVoice),a=D(e=>e.setVoiceTtsKokoroVoice),o=D(e=>e.voiceTtsBrowserVoice),s=D(e=>e.setVoiceTtsBrowserVoice),c=D(e=>e.voiceInputMode),l=D(e=>e.setVoiceInputMode),[u,d]=(0,K.useState)(()=>E());(0,K.useEffect)(()=>{if(typeof window>`u`||!(`speechSynthesis`in window))return;let e=()=>d(E());return e(),window.speechSynthesis.addEventListener?.(`voiceschanged`,e),()=>window.speechSynthesis.removeEventListener?.(`voiceschanged`,e)},[]);let f=T.some(e=>e.id===i)?T:[...T,{id:i,label:i}];return(0,Y.jsxs)(G,{size:`sm`,children:[(0,Y.jsxs)(B,{children:[(0,Y.jsxs)(U,{className:`flex items-center gap-2 text-sm`,children:[(0,Y.jsx)(g,{className:`size-4`}),`Voice`]}),(0,Y.jsx)(V,{className:`text-xs`,children:`Browser tier TTS and push-to-talk behavior.`}),(0,Y.jsx)(H,{children:(0,Y.jsx)(z,{checked:e,onCheckedChange:t})})]}),(0,Y.jsxs)(W,{className:`grid gap-3 md:grid-cols-2`,children:[(0,Y.jsx)(Z,{label:`Speech engine`,children:(0,Y.jsxs)(P,{value:n,onValueChange:e=>r(e),children:[(0,Y.jsx)(j,{children:(0,Y.jsx)(A,{})}),(0,Y.jsxs)(M,{children:[(0,Y.jsx)(N,{value:`kokoro`,children:`Kokoro (server, fallback to browser)`}),(0,Y.jsx)(N,{value:`browser`,children:`Browser Web Speech API`})]})]})}),(0,Y.jsx)(Z,{label:`Kokoro voice`,children:(0,Y.jsxs)(P,{value:i,onValueChange:a,children:[(0,Y.jsx)(j,{children:(0,Y.jsx)(A,{})}),(0,Y.jsx)(M,{children:f.map(e=>(0,Y.jsx)(N,{value:e.id,children:e.label},e.id))})]})}),(0,Y.jsx)(Z,{label:`Browser voice`,children:(0,Y.jsxs)(P,{value:o||`__unset__`,onValueChange:e=>s(e===`__unset__`?``:e),children:[(0,Y.jsx)(j,{children:(0,Y.jsx)(A,{})}),(0,Y.jsxs)(M,{children:[(0,Y.jsx)(N,{value:he,children:`System default`}),u.map(e=>(0,Y.jsx)(N,{value:e.uri,children:e.label},e.uri))]})]})}),(0,Y.jsx)(Z,{label:`Push-to-talk input`,children:(0,Y.jsxs)(P,{value:c,onValueChange:e=>l(e),children:[(0,Y.jsx)(j,{children:(0,Y.jsx)(A,{})}),(0,Y.jsxs)(M,{children:[(0,Y.jsx)(N,{value:`compose`,children:`Fill message box`}),(0,Y.jsx)(N,{value:`autosend`,children:`Send immediately`})]})]})})]})]})}function Te({catalog:e,error:n,canWrite:r,onCatalog:o}){let s=e[0]?.provider??`codex`,[l,f]=(0,K.useState)(s),[p,m]=(0,K.useState)(()=>Q(s)),[h,g]=(0,K.useState)(``),[_,v]=(0,K.useState)([]),x=e.some(e=>e.provider===l)?l:s,S=e.find(e=>e.provider===x)??e[0],C=e.map(e=>e.provider);function w(e){m(t=>({...t,...e})),v([]),g(``)}function T(e){f(e),m(Q(e)),v([]),g(``)}async function E(){o((await t(`GET`,`/providers`)).catalog)}async function te(){if(r){v([]),g(``);try{await t(`PUT`,`/providers/${encodeURIComponent(p.provider)}/models/${encodeURIComponent(p.alias)}`,{label:p.label,providerModel:p.providerModel,efforts:de(p.efforts),defaultEffort:p.defaultEffort.trim()||void 0,limits:p.limits,capabilities:p.capabilities,contextThreshold:Ee(p),disabled:p.disabled,updatedBy:`dashboard`}),await E(),g(`${p.alias} saved`),m(Q(p.provider))}catch(e){let t=X(e);v(t.length?t:[e.message])}}}async function D(e,n){if(r){v([]),g(``);try{await t(`PATCH`,`/providers/${encodeURIComponent(x)}/models/${encodeURIComponent(e.alias)}`,{disabled:n,updatedBy:`dashboard`}),await E(),g(`${e.alias} ${n?`disabled`:`enabled`}`)}catch(e){let t=X(e);v(t.length?t:[e.message])}}}async function O(e){if(r){v([]),g(``);try{await t(`DELETE`,`/providers/${encodeURIComponent(x)}/models/${encodeURIComponent(e.alias)}`),await E(),g(`${e.alias} removed`)}catch(e){let t=X(e);v(t.length?t:[e.message])}}}function k(e){m({provider:x,alias:e.alias,label:e.label,providerModel:e.providerModel,efforts:e.efforts.join(`, `),defaultEffort:e.defaultEffort??``,selfCompactUtilization:e.contextThreshold?.selfCompactUtilization?.toString()??``,warnUtilization:e.contextThreshold?.warnUtilization?.toString()??``,hardBackstopUtilization:e.contextThreshold?.hardBackstopUtilization?.toString()??``,disabled:!!e.disabled,limits:e.limits,capabilities:e.capabilities}),v([]),g(``)}return n?(0,Y.jsx)(G,{size:`sm`,children:(0,Y.jsxs)(W,{className:`text-sm text-muted-foreground`,children:[(0,Y.jsxs)(`div`,{className:`mb-1 flex items-center gap-2 font-medium text-foreground`,children:[(0,Y.jsx)(u,{className:`size-4`}),`Model catalog`]}),n]})}):(0,Y.jsxs)(`section`,{className:`space-y-4`,children:[(0,Y.jsxs)(`div`,{className:`flex flex-wrap items-start justify-between gap-3`,children:[(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`h2`,{className:`text-base font-semibold`,children:`Model catalog`}),(0,Y.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Add override models, disable unavailable models, or remove custom entries from the provider catalog.`})]}),!r&&(0,Y.jsx)(F,{variant:`secondary`,children:`Read only: needs settings:write:provider`})]}),(0,Y.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:C.map(e=>(0,Y.jsx)(I,{variant:e===x?`default`:`outline`,size:`sm`,onClick:()=>T(e),children:e},e))}),(0,Y.jsxs)(G,{size:`sm`,children:[(0,Y.jsxs)(B,{children:[(0,Y.jsx)(U,{className:`text-sm`,children:`Add or edit model`}),(0,Y.jsx)(H,{children:(0,Y.jsxs)(F,{variant:`outline`,className:`gap-1`,children:[(0,Y.jsx)(a,{className:`size-3.5`}),`Server runtime`]})})]}),(0,Y.jsxs)(W,{className:`space-y-3`,children:[(0,Y.jsxs)(`div`,{className:`grid gap-3 md:grid-cols-2`,children:[(0,Y.jsx)(Z,{label:`Alias`,children:(0,Y.jsx)(L,{value:p.alias,disabled:!r,placeholder:`nightly`,onChange:e=>w({alias:e.target.value.trim()})})}),(0,Y.jsx)(Z,{label:`Label`,children:(0,Y.jsx)(L,{value:p.label,disabled:!r,placeholder:`Nightly Codex`,onChange:e=>w({label:e.target.value})})}),(0,Y.jsx)(Z,{label:`Provider model`,children:(0,Y.jsx)(L,{value:p.providerModel,disabled:!r,placeholder:`codex-nightly`,onChange:e=>w({providerModel:e.target.value})})}),(0,Y.jsx)(Z,{label:`Efforts`,children:(0,Y.jsx)(L,{value:p.efforts,disabled:!r,placeholder:`low, medium, high`,onChange:e=>w({efforts:e.target.value})})}),(0,Y.jsx)(Z,{label:`Default effort`,children:(0,Y.jsx)(L,{value:p.defaultEffort,disabled:!r,placeholder:`medium`,onChange:e=>w({defaultEffort:e.target.value})})}),(0,Y.jsx)(Z,{label:`Self compact utilization`,children:(0,Y.jsx)(L,{value:p.selfCompactUtilization,disabled:!r,placeholder:`0.80`,inputMode:`decimal`,onChange:e=>w({selfCompactUtilization:e.target.value})})}),(0,Y.jsx)(Z,{label:`Warn utilization`,children:(0,Y.jsx)(L,{value:p.warnUtilization,disabled:!r,placeholder:`default: self - 0.10`,inputMode:`decimal`,onChange:e=>w({warnUtilization:e.target.value})})}),(0,Y.jsx)(Z,{label:`Hard backstop utilization`,children:(0,Y.jsx)(L,{value:p.hardBackstopUtilization,disabled:!r,placeholder:`0.90`,inputMode:`decimal`,onChange:e=>w({hardBackstopUtilization:e.target.value})})}),(0,Y.jsxs)(`div`,{className:`flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3`,children:[(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`div`,{className:`text-sm font-medium`,children:`Disabled`}),(0,Y.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:`Keep visible but unavailable for new launches.`})]}),(0,Y.jsx)(z,{checked:p.disabled,disabled:!r,onCheckedChange:e=>w({disabled:e})})]})]}),(0,Y.jsxs)(I,{onClick:te,disabled:!r||!p.alias||!p.label||!p.providerModel,children:[(0,Y.jsx)(i,{className:`size-4`}),`Save model`]})]})]}),(0,Y.jsxs)(`div`,{className:`space-y-2`,children:[S&&S.models.length===0&&(0,Y.jsx)(G,{size:`sm`,children:(0,Y.jsx)(W,{className:`text-sm text-muted-foreground`,children:`No models in this provider catalog yet.`})}),S?.models.map(e=>(0,Y.jsx)(G,{size:`sm`,children:(0,Y.jsxs)(W,{className:`flex flex-wrap items-center justify-between gap-3`,children:[(0,Y.jsxs)(`div`,{className:`min-w-0`,children:[(0,Y.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,Y.jsx)(`span`,{className:`font-medium`,children:e.label}),(0,Y.jsx)(`code`,{className:`rounded bg-muted px-1.5 py-0.5 font-mono text-xs`,children:e.alias}),e.disabled&&(0,Y.jsx)(F,{variant:`secondary`,children:`Disabled`})]}),(0,Y.jsxs)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:[e.providerModel,e.efforts.length>0?` · efforts ${e.efforts.join(`, `)}`:` · no effort levels`,e.defaultEffort?` · default ${e.defaultEffort}`:``,` · context ${Oe(e)}`]})]}),(0,Y.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,Y.jsxs)(I,{variant:`outline`,size:`sm`,onClick:()=>k(e),children:[(0,Y.jsx)(d,{className:`size-4`}),`Edit`]}),(0,Y.jsxs)(I,{variant:`outline`,size:`sm`,disabled:!r,onClick:()=>void D(e,!e.disabled),children:[e.disabled?(0,Y.jsx)(c,{className:`size-4`}):(0,Y.jsx)(ee,{className:`size-4`}),e.disabled?`Enable`:`Disable`]}),(0,Y.jsxs)(I,{variant:`outline`,size:`sm`,disabled:!r,onClick:()=>void O(e),children:[(0,Y.jsx)(y,{className:`size-4`}),`Remove`]})]})]})},e.alias))]}),_.length>0&&(0,Y.jsx)(`div`,{className:`rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive`,children:(0,Y.jsx)(`ul`,{className:`list-disc space-y-1 pl-5`,children:_.map(e=>(0,Y.jsx)(`li`,{children:e},e))})}),h&&(0,Y.jsxs)(`p`,{className:`flex items-center gap-1 text-sm text-emerald-500`,children:[(0,Y.jsx)(b,{className:`size-4`}),h]})]})}function Q(e){return{provider:e,alias:``,label:``,providerModel:``,efforts:``,defaultEffort:``,selfCompactUtilization:``,warnUtilization:``,hardBackstopUtilization:``,disabled:!1}}function Ee(e){let t=De(e.selfCompactUtilization,`Self compact utilization`),n=De(e.warnUtilization,`Warn utilization`),r=De(e.hardBackstopUtilization,`Hard backstop utilization`);if(!(t===void 0&&n===void 0&&r===void 0)){if(t===void 0)throw Error(`Self compact utilization is required when setting context thresholds`);return{selfCompactUtilization:t,...n===void 0?{}:{warnUtilization:n},...r===void 0?{}:{hardBackstopUtilization:r}}}}function De(e,t){let n=e.trim();if(!n)return;let r=Number(n);if(!Number.isFinite(r))throw Error(`${t} must be a number`);return r}function Oe(e){if(e.contextThreshold)return`self ${$(e.contextThreshold.selfCompactUtilization)}, warn ${$(e.contextThreshold.warnUtilization??Math.max(0,e.contextThreshold.selfCompactUtilization-.1))}`;let t=te(e.limits?.contextWindowTokens?.value);return`derived self ${$(t.selfCompactUtilization)}, warn ${$(t.warnUtilization)}`}function $(e){return`${Math.round(e*100)}%`}var ke=5,Ae=15,je={claude:`Claude`,codex:`Codex`};function Me(e){return Math.round(e/6e4)}function Ne(e){return`${Me(e)} min`}function Pe({canWrite:e}){let[n,r]=(0,K.useState)(null),[i,a]=(0,K.useState)(``),[o,s]=(0,K.useState)(``),[c,l]=(0,K.useState)(null);(0,K.useEffect)(()=>{let e=!1;return(async()=>{try{let n=await t(`GET`,`/providers/quota-config`);e||r(n)}catch(t){e||a(t.message)}})(),()=>{e=!0}},[]);async function u(e,n){r(t=>({...t??{},[e]:n})),s(``),l(e);try{let i=await t(`PUT`,`/providers/${e}/quota-config`,n);r(t=>({...t??{},[e]:i}))}catch(t){s(`${je[e]??e}: ${t.message}`)}finally{l(null)}}let d=n?Object.keys(n).sort():[];return(0,Y.jsxs)(`section`,{className:`space-y-4`,children:[(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`h2`,{className:`text-base font-semibold`,children:`Quota`}),(0,Y.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[`Per-provider quota collection and display. `,(0,Y.jsx)(`strong`,{children:`Enabled`}),` governs collection (disabled stops polling — no API calls);`,(0,Y.jsx)(`strong`,{children:` Show in widget`}),` governs display only.`]})]}),i&&(0,Y.jsxs)(`div`,{className:`flex items-start gap-2 rounded-lg border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive`,children:[(0,Y.jsx)(h,{className:`mt-0.5 size-4`}),(0,Y.jsx)(`span`,{children:i})]}),o&&(0,Y.jsxs)(`div`,{className:`flex items-start gap-2 rounded-lg border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive`,children:[(0,Y.jsx)(h,{className:`mt-0.5 size-4`}),(0,Y.jsx)(`span`,{children:o})]}),!n&&!i&&(0,Y.jsx)(G,{size:`sm`,children:(0,Y.jsxs)(W,{className:`flex items-center gap-2 text-sm text-muted-foreground`,children:[(0,Y.jsx)(v,{className:`size-4 animate-spin`}),`Loading quota config…`]})}),d.map(t=>{let i=n[t],a=!e||c===t;return(0,Y.jsxs)(G,{size:`sm`,children:[(0,Y.jsxs)(B,{children:[(0,Y.jsxs)(U,{className:`flex items-center gap-2 text-sm`,children:[(0,Y.jsx)(S,{className:`size-4`}),je[t]??t,c===t&&(0,Y.jsx)(v,{className:`size-3 animate-spin text-muted-foreground`})]}),(0,Y.jsxs)(V,{className:`text-xs`,children:[i.enabled?`Polled every ${Ne(i.pollIntervalMs)}`:`Collection disabled`,i.enabled&&!i.showInWidget?` · hidden from widget`:``]})]}),(0,Y.jsxs)(W,{className:`space-y-4`,children:[(0,Y.jsxs)(`div`,{className:`flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3`,children:[(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`div`,{className:`text-sm font-medium`,children:`Enabled`}),(0,Y.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:`Collect quota for this provider. Off stops all polling (no API calls, no token spend).`})]}),(0,Y.jsx)(z,{checked:i.enabled,disabled:a,onCheckedChange:e=>void u(t,{...i,enabled:e})})]}),(0,Y.jsxs)(`div`,{className:`rounded-md border bg-muted/20 p-3 space-y-2`,children:[(0,Y.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,Y.jsx)(`div`,{className:`text-sm font-medium`,children:`Polling interval`}),(0,Y.jsx)(F,{variant:`outline`,className:`tabular-nums`,children:Ne(i.pollIntervalMs)})]}),(0,Y.jsx)(`input`,{type:`range`,min:ke,max:Ae,step:1,value:Me(i.pollIntervalMs),disabled:a||!i.enabled,onChange:e=>{let n=Number(e.target.value)*6e4;r(e=>({...e??{},[t]:{...i,pollIntervalMs:n}}))},onPointerUp:e=>void u(t,{...i,pollIntervalMs:Number(e.target.value)*6e4}),onKeyUp:e=>void u(t,{...i,pollIntervalMs:Number(e.target.value)*6e4}),className:`w-full accent-primary disabled:opacity-50`}),(0,Y.jsxs)(`div`,{className:`flex justify-between text-[10px] text-muted-foreground`,children:[(0,Y.jsxs)(`span`,{children:[ke,` min`]}),(0,Y.jsxs)(`span`,{children:[Ae,` min`]})]})]}),(0,Y.jsxs)(`div`,{className:`flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3`,children:[(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`div`,{className:`text-sm font-medium`,children:`Show in quota widget`}),(0,Y.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:`Display only. Off hides this provider from the dashboard widget; collection continues if enabled.`})]}),(0,Y.jsx)(z,{checked:i.showInWidget,disabled:a,onCheckedChange:e=>void u(t,{...i,showInWidget:e})})]})]})]},t)})]})}var Fe=`browser`,Ie=`models`,Le=`profile`,Re=[`branch.landed`,`landed-failure`,`agent.ready`,`agent.exited`,`agent.spawn_failed`,`agent.context_threshold`,`agent.quota_threshold`,`workspace.steward_task`,`workspace.conflict`,`workspace.review_request`];function ze(){if(typeof window>`u`)return``;let e=window.location.hash.replace(/^#/,``);return e.startsWith(`settings/`)?decodeURIComponent(e.slice(9)):``}function Be(e){if(typeof window>`u`)return;let t=new URL(window.location.href);t.hash=`settings/${encodeURIComponent(e)}`,window.history.pushState({},``,t)}function Ve(){let[e,n]=(0,K.useState)([]),[r,i]=(0,K.useState)(null),[a,o]=(0,K.useState)([]),[c,l]=(0,K.useState)(()=>ze()),[u,d]=(0,K.useState)(!0),[p,g]=(0,K.useState)(``),[_,v]=(0,K.useState)(``);async function y(){d(!0),g(``),v(``);try{let[e,r,a]=await Promise.all([t(`GET`,`/settings`),t(`GET`,`/tokens/me`),t(`GET`,`/providers`).catch(e=>(v(e.message),{catalog:[]}))]);n(e.settings),i(r),o(a.catalog)}catch(e){g(e.message)}finally{d(!1)}}(0,K.useEffect)(()=>{y()},[]),(0,K.useEffect)(()=>{let e=()=>l(ze());return window.addEventListener(`hashchange`,e),window.addEventListener(`popstate`,e),()=>{window.removeEventListener(`hashchange`,e),window.removeEventListener(`popstate`,e)}},[]);let b=(0,K.useMemo)(()=>oe(e),[e]),x=(0,K.useMemo)(()=>[...b.map(e=>({slug:e.slug,label:e.group,description:`${e.settings.length} schema setting${e.settings.length===1?``:`s`}`,kind:`descriptors`,settings:e.settings})),{slug:Le,label:`Profile`,description:`Display name and avatar`,kind:`profile`,settings:[]},{slug:Fe,label:`Browser`,description:`Local dashboard preferences`,kind:`browser`,settings:[]},{slug:Ie,label:`Models`,description:`Provider model catalog`,kind:`models`,settings:[]}],[b]),S=x.find(e=>e.slug===c)??x[0];function C(e){l(e),Be(e)}function ee(e){n(t=>t.map(t=>q(t)===q(e)?e:t))}return(0,Y.jsxs)(`div`,{className:`space-y-4`,children:[(0,Y.jsxs)(`div`,{className:`flex flex-wrap items-start justify-between gap-3`,children:[(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`h1`,{className:`text-lg font-semibold`,children:`Settings`}),(0,Y.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Schema-driven Relay settings, browser preferences, and model catalog controls.`})]}),(0,Y.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[r&&(0,Y.jsxs)(F,{variant:`outline`,className:`gap-1`,children:[(0,Y.jsx)(m,{className:`size-3`}),r.kind,`:`,r.actor]}),(0,Y.jsxs)(I,{variant:`outline`,size:`sm`,onClick:()=>void y(),disabled:u,children:[(0,Y.jsx)(s,{className:f(`size-4`,u&&`animate-spin`)}),`Refresh`]})]})]}),p&&(0,Y.jsxs)(`div`,{className:`flex items-start gap-2 rounded-lg border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive`,children:[(0,Y.jsx)(h,{className:`mt-0.5 size-4`}),(0,Y.jsx)(`span`,{children:p})]}),(0,Y.jsxs)(`div`,{className:`grid gap-4 lg:grid-cols-[230px_minmax(0,1fr)]`,children:[(0,Y.jsx)(`nav`,{className:`space-y-1 lg:sticky lg:top-4 lg:self-start`,children:x.map(e=>(0,Y.jsxs)(`button`,{type:`button`,className:f(`w-full rounded-md border px-3 py-2 text-left text-sm transition-colors`,S?.slug===e.slug?`border-primary/50 bg-primary/10 text-foreground`:`border-transparent hover:border-border hover:bg-accent`),onClick:()=>C(e.slug),children:[(0,Y.jsx)(`span`,{className:`block font-medium`,children:e.label}),(0,Y.jsx)(`span`,{className:`block truncate text-xs text-muted-foreground`,children:e.description})]},e.slug))}),(0,Y.jsx)(`div`,{className:`min-w-0 space-y-4`,children:u&&!e.length?(0,Y.jsx)(G,{size:`sm`,children:(0,Y.jsx)(W,{className:`text-sm text-muted-foreground`,children:`Loading settings…`})}):S?.kind===`descriptors`?(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(ye,{group:S.label,settings:S.settings,onSaved:ee}),S.label===`Providers`&&(0,Y.jsx)(Pe,{canWrite:k(r?.scopes,`settings:write:provider`)}),S.label===`Notifications`&&(0,Y.jsx)(He,{})]}):S?.kind===`profile`?(0,Y.jsx)(Ue,{}):S?.kind===`browser`?(0,Y.jsx)(Ce,{}):(0,Y.jsx)(Te,{catalog:a,error:_,canWrite:k(r?.scopes,`settings:write:provider`),onCatalog:o})})]})]})}function He(){let[e,n]=(0,K.useState)(`branch.landed`),[r,i]=(0,K.useState)(`{
4
- "repoRoot": "/repo"
5
- }`),[a,o]=(0,K.useState)(null),[s,c]=(0,K.useState)(!1),[l,u]=(0,K.useState)(``);async function d(){c(!0),u(``);try{let n=JSON.parse(r);if(!n||typeof n!=`object`||Array.isArray(n))throw Error(`Scope must be a JSON object`);o((await t(`POST`,`/notifications/preview`,{type:e,scope:n})).preview)}catch(e){o(null),u(e.message)}finally{c(!1)}}return(0,Y.jsx)(G,{size:`sm`,children:(0,Y.jsxs)(W,{className:`space-y-3`,children:[(0,Y.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`h2`,{className:`text-sm font-semibold`,children:`Who gets what`}),(0,Y.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Dry-run notification routing without sending.`})]}),(0,Y.jsxs)(I,{size:`sm`,onClick:()=>void d(),disabled:s,children:[(0,Y.jsx)(x,{className:`size-4`}),`Preview`]})]}),(0,Y.jsxs)(`div`,{className:`grid gap-3 md:grid-cols-[240px_minmax(0,1fr)]`,children:[(0,Y.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,Y.jsx)(`label`,{className:`text-xs font-medium text-muted-foreground`,children:`Type`}),(0,Y.jsxs)(P,{value:e,onValueChange:n,children:[(0,Y.jsx)(j,{className:`w-full`,children:(0,Y.jsx)(A,{})}),(0,Y.jsx)(M,{children:Re.map(e=>(0,Y.jsx)(N,{value:e,children:e},e))})]})]}),(0,Y.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,Y.jsx)(`label`,{className:`text-xs font-medium text-muted-foreground`,children:`Scope`}),(0,Y.jsx)(R,{value:r,onChange:e=>i(e.target.value),rows:4,className:`font-mono text-xs`})]})]}),l&&(0,Y.jsxs)(`div`,{className:`flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 p-2 text-xs text-destructive`,children:[(0,Y.jsx)(h,{className:`mt-0.5 size-3.5`}),(0,Y.jsx)(`span`,{children:l})]}),a&&(0,Y.jsx)(`div`,{className:`overflow-hidden rounded-md border border-border`,children:a.recipients.length===0?(0,Y.jsx)(`div`,{className:`px-3 py-4 text-center text-xs text-muted-foreground`,children:`No recipients`}):a.recipients.map(e=>(0,Y.jsxs)(`div`,{className:`grid gap-1 border-b border-border px-3 py-2 text-xs last:border-b-0 md:grid-cols-[minmax(0,180px)_minmax(0,160px)_minmax(0,1fr)]`,children:[(0,Y.jsx)(`span`,{className:`truncate font-medium`,children:e.recipient}),(0,Y.jsx)(`span`,{className:`truncate font-mono text-muted-foreground`,children:e.matchedRule}),(0,Y.jsx)(`span`,{className:`truncate text-muted-foreground`,children:e.reason})]},`${e.recipient}-${e.matchedRule}`))})]})})}function Ue(){let e=D(e=>e.fetchUsers),r=(0,K.useRef)(null),[i,a]=(0,K.useState)(null),[s,c]=(0,K.useState)(``),[l,u]=(0,K.useState)(!0),[d,f]=(0,K.useState)(!1),[p,m]=(0,K.useState)(``);async function g(){u(!0),m(``);try{let e=await t(`GET`,`/users/me`);a(e),c(e.displayName||e.handle)}catch(e){m(e.message)}finally{u(!1)}}(0,K.useEffect)(()=>{g()},[]);async function _(){f(!0),m(``);try{let n=await t(`PATCH`,`/users/me`,{displayName:s});a(n),c(n.displayName||n.handle),await e()}catch(e){m(e.message)}finally{f(!1)}}async function v(t){if(t){f(!0),m(``);try{let n=await w(`/users/me/avatar`,t);a(n.user),c(n.user.displayName||n.user.handle),await e()}catch(e){m(e.message)}finally{f(!1),r.current&&(r.current.value=``)}}}async function b(){f(!0),m(``);try{a(await t(`DELETE`,`/users/me/avatar`)),await e()}catch(e){m(e.message)}finally{f(!1)}}return(0,Y.jsx)(G,{size:`sm`,children:(0,Y.jsxs)(W,{className:`space-y-4`,children:[p&&(0,Y.jsxs)(`div`,{className:`flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive`,children:[(0,Y.jsx)(h,{className:`mt-0.5 size-4`}),(0,Y.jsx)(`span`,{children:p})]}),(0,Y.jsxs)(`div`,{className:`flex flex-wrap items-center gap-4`,children:[(0,Y.jsx)(re,{user:i??void 0,distinct:!0,className:`size-16 text-lg`}),(0,Y.jsxs)(`div`,{className:`min-w-0 flex-1 space-y-2`,children:[(0,Y.jsx)(`label`,{className:`block text-xs font-medium text-muted-foreground`,htmlFor:`profile-display-name`,children:`Display name`}),(0,Y.jsx)(`input`,{id:`profile-display-name`,className:`h-9 w-full rounded-md border border-input bg-background px-3 text-sm`,value:s,onChange:e=>c(e.target.value),disabled:l||d,maxLength:120})]})]}),(0,Y.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,Y.jsxs)(I,{size:`sm`,onClick:()=>void _(),disabled:l||d||!s.trim(),children:[(0,Y.jsx)(n,{className:`size-4`}),`Save`]}),(0,Y.jsxs)(I,{size:`sm`,variant:`outline`,onClick:()=>r.current?.click(),disabled:l||d,children:[(0,Y.jsx)(C,{className:`size-4`}),`Upload`]}),(0,Y.jsxs)(I,{size:`sm`,variant:`outline`,onClick:()=>void b(),disabled:l||d||!i?.avatarArtifactId,children:[(0,Y.jsx)(y,{className:`size-4`}),`Remove`]}),d&&(0,Y.jsx)(o,{className:`size-4 animate-pulse text-muted-foreground`}),(0,Y.jsx)(`input`,{ref:r,type:`file`,accept:`image/png,image/jpeg,image/gif,image/webp`,className:`hidden`,onChange:e=>void v(e.target.files?.[0])})]})]})})}export{Ve as SettingsView};
6
- //# sourceMappingURL=settings-DBsL3jb7.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"settings-DBsL3jb7.js","names":[],"sources":["../../dashboard/src/components/settings/schema-utils.ts","../../dashboard/src/components/settings/schema-form.tsx","../../dashboard/src/components/settings/browser-settings.tsx","../../dashboard/src/components/settings/model-catalog-settings.tsx","../../dashboard/src/components/settings/quota-settings.tsx","../../dashboard/src/components/views/settings.tsx"],"sourcesContent":["import { isRecord, type JSONSchema, type SettingEntry } from 'agent-relay-sdk/types'\n\nexport { hasScope } from 'agent-relay-sdk/types'\nexport type { SettingEntry }\n\ninterface SettingGroup {\n group: string\n slug: string\n settings: SettingEntry[]\n}\n\nexport type Path = Array<string | number>\n\nexport function settingId(setting: Pick<SettingEntry, 'namespace' | 'key'>): string {\n return `${setting.namespace}/${setting.key}`\n}\n\nexport function settingPath(setting: Pick<SettingEntry, 'namespace' | 'key'>): string {\n return `/settings/${encodeURIComponent(setting.namespace)}/${encodeURIComponent(setting.key)}`\n}\n\nexport function slugify(value: string): string {\n return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'settings'\n}\n\nexport function groupSettings(settings: SettingEntry[]): SettingGroup[] {\n const groups = new Map<string, SettingEntry[]>()\n for (const setting of settings.filter((entry) => entry.readable)) {\n const group = setting.display?.group?.trim() || setting.namespace\n groups.set(group, [...(groups.get(group) ?? []), setting])\n }\n return [...groups.entries()]\n .map(([group, items]) => ({\n group,\n slug: slugify(group),\n settings: items.sort(compareSettings),\n }))\n .sort((a, b) => groupOrder(a.settings) - groupOrder(b.settings) || a.group.localeCompare(b.group))\n}\n\nfunction compareSettings(a: SettingEntry, b: SettingEntry): number {\n return (a.display?.order ?? Number.MAX_SAFE_INTEGER) - (b.display?.order ?? Number.MAX_SAFE_INTEGER)\n || a.display?.label?.localeCompare(b.display?.label ?? '') || 0\n || settingId(a).localeCompare(settingId(b))\n}\n\nfunction groupOrder(settings: SettingEntry[]): number {\n return Math.min(...settings.map((setting) => setting.display?.order ?? Number.MAX_SAFE_INTEGER))\n}\n\nexport function schemaType(schema: JSONSchema): string | undefined {\n return Array.isArray(schema.type) ? schema.type.find((type) => type !== 'null') : schema.type\n}\n\nexport function valueAtPath(value: unknown, path: Path): unknown {\n let current = value\n for (const part of path) {\n if (typeof part === 'number') {\n if (!Array.isArray(current)) return undefined\n current = current[part]\n } else {\n if (!isRecord(current)) return undefined\n current = current[part]\n }\n }\n return current\n}\n\nexport function setValueAtPath(value: unknown, path: Path, next: unknown): unknown {\n if (!path.length) return next\n const [head, ...tail] = path\n if (head === undefined) return next\n if (typeof head === 'number') {\n const array = Array.isArray(value) ? [...value] : []\n array[head] = setValueAtPath(array[head], tail, next)\n return array\n }\n const record = isRecord(value) ? { ...value } : {}\n const updated = setValueAtPath(record[head], tail, next)\n if (updated === undefined) delete record[head]\n else record[head] = updated\n return record\n}\n\nexport function defaultValueForSchema(schema: JSONSchema): unknown {\n if (schema.default !== undefined) return schema.default\n if (schema.const !== undefined) return schema.const\n if (schema.enum?.length) return schema.enum[0]\n switch (schemaType(schema)) {\n case 'boolean': return false\n case 'integer':\n case 'number': return 0\n case 'array': return []\n case 'object': return {}\n case 'string': return ''\n default: return undefined\n }\n}\n\nexport function lines(value: string): string[] {\n return value.split(/\\r?\\n|,/).map((line) => line.trim()).filter(Boolean)\n}\n\nexport function arrayText(value: unknown): string {\n return Array.isArray(value) ? value.map((item) => String(item)).join('\\n') : ''\n}\n\nexport function recordText(value: unknown): string {\n if (!isRecord(value)) return ''\n return Object.entries(value).map(([key, item]) => `${key}=${String(item ?? '')}`).join('\\n')\n}\n\nexport function parseRecordText(value: string): Record<string, string> {\n return Object.fromEntries(value.split(/\\r?\\n/).map((raw) => raw.trim()).filter(Boolean).map((line) => {\n const idx = line.indexOf('=')\n return idx >= 0 ? [line.slice(0, idx).trim(), line.slice(idx + 1)] : [line, '']\n }))\n}\n\nexport { isRecord }\n","import { useState, type ReactNode } from 'react'\nimport type { JSONSchema, SettingTier } from 'agent-relay-sdk/types'\nimport { api, type ApiError } from '@/lib/api'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Textarea } from '@/components/ui/textarea'\nimport { Switch } from '@/components/ui/switch'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { Badge } from '@/components/ui/badge'\nimport { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport { AlertCircle, CheckCircle2, MonitorCog, Save, ServerCog } from 'lucide-react'\nimport {\n arrayText,\n defaultValueForSchema,\n isRecord,\n lines,\n parseRecordText,\n recordText,\n schemaType,\n setValueAtPath,\n settingId,\n settingPath,\n type Path,\n type SettingEntry,\n} from './schema-utils'\n\nexport const UNSET = '__unset__'\n\nfunction tierLabel(tier: SettingTier): string {\n if (tier === 'server-runtime') return 'Server runtime'\n if (tier === 'bootstrap') return 'Bootstrap'\n return 'Browser'\n}\n\nfunction tierDescription(tier: SettingTier): string {\n if (tier === 'server-runtime') return 'Stored by Relay and mutable while the server is running.'\n if (tier === 'bootstrap') return 'Read from startup configuration; restart or host config changes are required.'\n return 'Stored only in this browser profile.'\n}\n\nfunction tierIcon(tier: SettingTier) {\n if (tier === 'browser') return <MonitorCog className=\"size-3.5\" />\n return <ServerCog className=\"size-3.5\" />\n}\n\nexport function errorDetails(error: unknown): string[] {\n return (error as ApiError).details ?? []\n}\n\nexport function SchemaGroup({ group, settings, onSaved }: { group: string; settings: SettingEntry[]; onSaved: (setting: SettingEntry) => void }) {\n const tiers = [...new Set(settings.map((setting) => setting.tier))]\n return (\n <section className=\"space-y-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <h2 className=\"text-base font-semibold\">{group}</h2>\n <div className=\"flex flex-wrap gap-1\">\n {tiers.map((tier) => (\n <Badge key={tier} variant=\"outline\" className=\"gap-1\" title={tierDescription(tier)}>\n {tierIcon(tier)}\n {tierLabel(tier)}\n </Badge>\n ))}\n </div>\n </div>\n {settings.length === 0 ? (\n <Card size=\"sm\">\n <CardContent className=\"text-sm text-muted-foreground\">No settings in this group.</CardContent>\n </Card>\n ) : (\n <div className=\"space-y-3\">\n {settings.map((setting) => (\n <SettingCard key={settingId(setting)} setting={setting} onSaved={onSaved} />\n ))}\n </div>\n )}\n </section>\n )\n}\n\nfunction SettingCard({ setting, onSaved }: { setting: SettingEntry; onSaved: (setting: SettingEntry) => void }) {\n const [draft, setDraft] = useState<unknown>(() => setting.value ?? setting.defaults ?? defaultValueForSchema(setting.schema))\n const [saving, setSaving] = useState(false)\n const [status, setStatus] = useState('')\n const [errors, setErrors] = useState<string[]>([])\n const isWritable = setting.writable && setting.tier === 'server-runtime'\n\n function update(path: Path, value: unknown) {\n setDraft((current: unknown) => setValueAtPath(current, path, value))\n setErrors([])\n setStatus('')\n }\n\n async function save() {\n if (!isWritable) return\n setSaving(true)\n setErrors([])\n setStatus('')\n try {\n const saved = await api<SettingEntry>('PUT', settingPath(setting), { value: draft, updatedBy: 'dashboard' })\n setDraft(saved.value)\n onSaved(saved)\n setStatus('Saved')\n } catch (e) {\n const details = errorDetails(e)\n setErrors(details.length ? details : [(e as Error).message])\n } finally {\n setSaving(false)\n }\n }\n\n return (\n <Card size=\"sm\">\n <CardHeader>\n <CardTitle className=\"flex flex-wrap items-center gap-2 text-sm\">\n {setting.display.label}\n <Badge variant=\"outline\" className=\"gap-1\" title={tierDescription(setting.tier)}>{tierIcon(setting.tier)}{tierLabel(setting.tier)}</Badge>\n {!setting.writable && <Badge variant=\"secondary\">Read only</Badge>}\n </CardTitle>\n {setting.display.description && <CardDescription>{setting.display.description}</CardDescription>}\n <CardAction>\n <Button size=\"sm\" onClick={save} disabled={!isWritable || saving}>\n <Save className=\"size-4\" />\n {saving ? 'Saving' : 'Save'}\n </Button>\n </CardAction>\n </CardHeader>\n\n <CardContent className=\"space-y-3\">\n <SchemaField\n schema={setting.schema}\n value={draft}\n path={[]}\n label={setting.display.label}\n required\n disabled={!isWritable || saving}\n onChange={update}\n />\n\n <p className=\"flex flex-wrap items-center gap-x-2 text-[11px] text-muted-foreground\">\n <code className=\"rounded bg-muted px-1.5 py-0.5 font-mono\">{setting.namespace}/{setting.key}</code>\n <span>read <span className=\"text-foreground/70\">{setting.scope.read}</span></span>\n <span aria-hidden>·</span>\n <span>write <span className=\"text-foreground/70\">{setting.scope.write}</span></span>\n </p>\n\n {errors.length > 0 && (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">\n <div className=\"mb-1 flex items-center gap-2 font-medium\"><AlertCircle className=\"size-4\" />Save failed</div>\n <ul className=\"list-disc space-y-1 pl-5\">\n {errors.map((detail) => <li key={detail}>{detail}</li>)}\n </ul>\n </div>\n )}\n {status && <p className=\"flex items-center gap-1 text-sm text-emerald-500\"><CheckCircle2 className=\"size-4\" />{status}</p>}\n </CardContent>\n </Card>\n )\n}\n\nfunction SchemaField(props: {\n schema: JSONSchema\n value: unknown\n path: Path\n label: string\n required: boolean\n disabled: boolean\n onChange: (path: Path, value: unknown) => void\n}) {\n const { schema, value, path, label, required, disabled, onChange } = props\n const type = schemaType(schema)\n\n if (schema.enum?.length) {\n const current = value === undefined || value === null || value === '' ? UNSET : String(value)\n return (\n <Field label={label} description={schema.description}>\n <Select value={current} onValueChange={(next) => onChange(path, next === UNSET ? undefined : next)} disabled={disabled}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {!required && <SelectItem value={UNSET}>Not set</SelectItem>}\n {schema.enum.map((item) => <SelectItem key={String(item)} value={String(item)}>{String(item)}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n )\n }\n\n if (type === 'boolean') {\n return (\n <div className=\"flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3\">\n <div>\n <div className=\"text-sm font-medium\">{label}</div>\n {schema.description && <div className=\"text-xs text-muted-foreground\">{schema.description}</div>}\n </div>\n <Switch checked={Boolean(value)} onCheckedChange={(next) => onChange(path, next)} disabled={disabled} />\n </div>\n )\n }\n\n if (type === 'integer' || type === 'number') {\n return (\n <Field label={label} description={schema.description}>\n <Input\n type=\"number\"\n min={typeof schema.minimum === 'number' ? schema.minimum : undefined}\n max={typeof schema.maximum === 'number' ? schema.maximum : undefined}\n step={type === 'integer' ? 1 : 'any'}\n value={typeof value === 'number' ? value : ''}\n disabled={disabled}\n onChange={(e) => onChange(path, e.target.value === '' && !required ? undefined : Number(e.target.value))}\n />\n </Field>\n )\n }\n\n if (type === 'array') {\n return (\n <Field label={label} description={schema.description ?? 'One item per line.'}>\n <Textarea\n rows={Math.min(8, Math.max(3, Array.isArray(value) ? value.length + 1 : 3))}\n value={arrayText(value)}\n disabled={disabled}\n onChange={(e) => onChange(path, lines(e.target.value))}\n />\n </Field>\n )\n }\n\n if (type === 'object') {\n const properties = schema.properties ?? {}\n const requiredKeys = new Set(schema.required ?? [])\n if (Object.keys(properties).length === 0 && schema.additionalProperties) {\n return (\n <Field label={label} description={schema.description ?? 'KEY=value, one entry per line.'}>\n <Textarea rows={5} value={recordText(value)} disabled={disabled} onChange={(e) => onChange(path, parseRecordText(e.target.value))} />\n </Field>\n )\n }\n return (\n <div className=\"space-y-3\">\n {path.length > 0 && (\n <div>\n <div className=\"text-sm font-medium\">{label}</div>\n {schema.description && <div className=\"text-xs text-muted-foreground\">{schema.description}</div>}\n </div>\n )}\n <div className=\"grid gap-3 md:grid-cols-2\">\n {Object.entries(properties).map(([key, child]) => {\n const childValue = isRecord(value) ? value[key] : undefined\n return (\n <SchemaField\n key={key}\n schema={child}\n value={childValue === undefined && requiredKeys.has(key) ? defaultValueForSchema(child) : childValue}\n path={[...path, key]}\n label={child.title || labelForKey(key)}\n required={requiredKeys.has(key)}\n disabled={disabled}\n onChange={onChange}\n />\n )\n })}\n </div>\n </div>\n )\n }\n\n return (\n <Field label={label} description={schema.description}>\n <Input\n value={typeof value === 'string' ? value : value == null ? '' : String(value)}\n disabled={disabled}\n onChange={(e) => onChange(path, e.target.value === '' && !required ? undefined : e.target.value)}\n />\n </Field>\n )\n}\n\nexport function Field({ label, description, children }: { label: string; description?: string; children: ReactNode }) {\n return (\n <label className=\"block space-y-1.5 text-sm\">\n <span className=\"text-muted-foreground\">{label}</span>\n {children}\n {description && <span className=\"block text-xs text-muted-foreground\">{description}</span>}\n </label>\n )\n}\n\nfunction labelForKey(key: string): string {\n return key.replace(/([a-z0-9])([A-Z])/g, '$1 $2').replace(/[-_]+/g, ' ').replace(/^\\w/, (char) => char.toUpperCase())\n}\n","import { useEffect, useState } from 'react'\nimport { THEMES } from '@/lib/themes'\nimport { KOKORO_VOICES, availableSpeechVoices } from '@/lib/voice'\nimport { useRelayStore } from '@/store'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { Switch } from '@/components/ui/switch'\nimport { Badge } from '@/components/ui/badge'\nimport { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Brain, MonitorCog, Volume2 } from 'lucide-react'\nimport type { ThemeId } from '@/types'\nimport { Field, UNSET } from './schema-form'\n\nexport function BrowserSettings() {\n const theme = useRelayStore((s) => s.theme)\n const showReasoning = useRelayStore((s) => s.showReasoning)\n const set = useRelayStore((s) => s.set)\n return (\n <section className=\"space-y-4\">\n <div>\n <h2 className=\"text-base font-semibold\">Browser preferences</h2>\n <p className=\"text-sm text-muted-foreground\">These are stored in local dashboard state, not in Relay server config.</p>\n </div>\n <Card size=\"sm\">\n <CardHeader>\n <CardTitle className=\"text-sm\">Dashboard display</CardTitle>\n <CardDescription className=\"text-xs\">Browser tier · persisted in this browser profile.</CardDescription>\n <CardAction>\n <Badge variant=\"outline\" className=\"gap-1\"><MonitorCog className=\"size-3.5\" />Browser</Badge>\n </CardAction>\n </CardHeader>\n <CardContent className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Theme\">\n <Select value={theme} onValueChange={(value) => set({ theme: value as ThemeId })}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {THEMES.map((item) => <SelectItem key={item.id} value={item.id}>{item.label}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n <div className=\"flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3\">\n <div className=\"flex items-center gap-2\">\n <Brain className=\"size-4\" />\n <div>\n <div className=\"text-sm font-medium\">Show reasoning details</div>\n <div className=\"text-xs text-muted-foreground\">Display captured reasoning/tool steps in chat. Server capture is controlled separately by provider reasoningCapture.</div>\n </div>\n </div>\n <Switch checked={showReasoning} onCheckedChange={(value) => set({ showReasoning: value })} />\n </div>\n </CardContent>\n </Card>\n <VoiceSettings />\n </section>\n )\n}\n\nfunction VoiceSettings() {\n const voiceTtsEnabled = useRelayStore((s) => s.voiceTtsEnabled)\n const setVoiceTtsEnabled = useRelayStore((s) => s.setVoiceTtsEnabled)\n const voiceTtsMode = useRelayStore((s) => s.voiceTtsMode)\n const setVoiceTtsMode = useRelayStore((s) => s.setVoiceTtsMode)\n const voiceTtsKokoroVoice = useRelayStore((s) => s.voiceTtsKokoroVoice)\n const setVoiceTtsKokoroVoice = useRelayStore((s) => s.setVoiceTtsKokoroVoice)\n const voiceTtsBrowserVoice = useRelayStore((s) => s.voiceTtsBrowserVoice)\n const setVoiceTtsBrowserVoice = useRelayStore((s) => s.setVoiceTtsBrowserVoice)\n const voiceInputMode = useRelayStore((s) => s.voiceInputMode)\n const setVoiceInputMode = useRelayStore((s) => s.setVoiceInputMode)\n\n // External sync: the browser loads speech voices asynchronously.\n const [browserVoices, setBrowserVoices] = useState(() => availableSpeechVoices())\n useEffect(() => {\n if (typeof window === 'undefined' || !('speechSynthesis' in window)) return\n const refresh = () => setBrowserVoices(availableSpeechVoices())\n refresh()\n window.speechSynthesis.addEventListener?.('voiceschanged', refresh)\n return () => window.speechSynthesis.removeEventListener?.('voiceschanged', refresh)\n }, [])\n\n const kokoroOptions = KOKORO_VOICES.some((voice) => voice.id === voiceTtsKokoroVoice)\n ? KOKORO_VOICES\n : [...KOKORO_VOICES, { id: voiceTtsKokoroVoice, label: voiceTtsKokoroVoice }]\n\n return (\n <Card size=\"sm\">\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-sm\"><Volume2 className=\"size-4\" />Voice</CardTitle>\n <CardDescription className=\"text-xs\">Browser tier TTS and push-to-talk behavior.</CardDescription>\n <CardAction>\n <Switch checked={voiceTtsEnabled} onCheckedChange={setVoiceTtsEnabled} />\n </CardAction>\n </CardHeader>\n <CardContent className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Speech engine\">\n <Select value={voiceTtsMode} onValueChange={(value) => setVoiceTtsMode(value as 'kokoro' | 'browser')}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"kokoro\">Kokoro (server, fallback to browser)</SelectItem>\n <SelectItem value=\"browser\">Browser Web Speech API</SelectItem>\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Kokoro voice\">\n <Select value={voiceTtsKokoroVoice} onValueChange={setVoiceTtsKokoroVoice}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {kokoroOptions.map((voice) => <SelectItem key={voice.id} value={voice.id}>{voice.label}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Browser voice\">\n <Select value={voiceTtsBrowserVoice || UNSET} onValueChange={(value) => setVoiceTtsBrowserVoice(value === UNSET ? '' : value)}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value={UNSET}>System default</SelectItem>\n {browserVoices.map((voice) => <SelectItem key={voice.uri} value={voice.uri}>{voice.label}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Push-to-talk input\">\n <Select value={voiceInputMode} onValueChange={(value) => setVoiceInputMode(value as 'compose' | 'autosend' | 'handsfree')}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"compose\">Fill message box</SelectItem>\n <SelectItem value=\"autosend\">Send immediately</SelectItem>\n </SelectContent>\n </Select>\n </Field>\n </CardContent>\n </Card>\n )\n}\n","import { useState } from 'react'\nimport type { SpawnProvider } from 'agent-relay-sdk/types'\nimport { deriveContextThresholdFromWindowTokens, type ProviderCatalogEntry, type ProviderModelCatalogEntry } from 'agent-relay-sdk/provider-catalog'\nimport { api } from '@/lib/api'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Switch } from '@/components/ui/switch'\nimport { Badge } from '@/components/ui/badge'\nimport { Card, CardAction, CardContent, CardHeader, CardTitle } from '@/components/ui/card'\nimport { CheckCircle2, Eye, EyeOff, Pencil, Plus, ServerCog, SlidersHorizontal, Trash2 } from 'lucide-react'\nimport { errorDetails, Field } from './schema-form'\nimport { lines } from './schema-utils'\n\ninterface ProvidersResponse {\n catalog: ProviderCatalogEntry[]\n}\n\ninterface ModelForm {\n provider: SpawnProvider\n alias: string\n label: string\n providerModel: string\n efforts: string\n defaultEffort: string\n selfCompactUtilization: string\n warnUtilization: string\n hardBackstopUtilization: string\n disabled: boolean\n limits?: ProviderModelCatalogEntry['limits']\n capabilities?: ProviderModelCatalogEntry['capabilities']\n}\n\nexport function ModelCatalogSettings({\n catalog,\n error,\n canWrite,\n onCatalog,\n}: {\n catalog: ProviderCatalogEntry[]\n error: string\n canWrite: boolean\n onCatalog: (catalog: ProviderCatalogEntry[]) => void\n}) {\n const firstProvider = catalog[0]?.provider ?? 'codex'\n const [provider, setProvider] = useState<SpawnProvider>(firstProvider)\n const [form, setForm] = useState<ModelForm>(() => emptyModelForm(firstProvider))\n const [status, setStatus] = useState('')\n const [errors, setErrors] = useState<string[]>([])\n\n const selectedProvider = catalog.some((entry) => entry.provider === provider) ? provider : firstProvider\n const selectedCatalog = catalog.find((entry) => entry.provider === selectedProvider) ?? catalog[0]\n const providers = catalog.map((entry) => entry.provider)\n\n function updateForm(patch: Partial<ModelForm>) {\n setForm((current) => ({ ...current, ...patch }))\n setErrors([])\n setStatus('')\n }\n\n function switchProvider(next: SpawnProvider) {\n setProvider(next)\n setForm(emptyModelForm(next))\n setErrors([])\n setStatus('')\n }\n\n async function reloadCatalog() {\n const res = await api<ProvidersResponse>('GET', '/providers')\n onCatalog(res.catalog)\n }\n\n async function saveModel() {\n if (!canWrite) return\n setErrors([])\n setStatus('')\n try {\n await api('PUT', `/providers/${encodeURIComponent(form.provider)}/models/${encodeURIComponent(form.alias)}`, {\n label: form.label,\n providerModel: form.providerModel,\n efforts: lines(form.efforts),\n defaultEffort: form.defaultEffort.trim() || undefined,\n limits: form.limits,\n capabilities: form.capabilities,\n contextThreshold: contextThresholdFromForm(form),\n disabled: form.disabled,\n updatedBy: 'dashboard',\n })\n await reloadCatalog()\n setStatus(`${form.alias} saved`)\n setForm(emptyModelForm(form.provider))\n } catch (e) {\n const details = errorDetails(e)\n setErrors(details.length ? details : [(e as Error).message])\n }\n }\n\n async function setDisabled(model: ProviderModelCatalogEntry, disabled: boolean) {\n if (!canWrite) return\n setErrors([])\n setStatus('')\n try {\n await api('PATCH', `/providers/${encodeURIComponent(selectedProvider)}/models/${encodeURIComponent(model.alias)}`, { disabled, updatedBy: 'dashboard' })\n await reloadCatalog()\n setStatus(`${model.alias} ${disabled ? 'disabled' : 'enabled'}`)\n } catch (e) {\n const details = errorDetails(e)\n setErrors(details.length ? details : [(e as Error).message])\n }\n }\n\n async function removeModel(model: ProviderModelCatalogEntry) {\n if (!canWrite) return\n setErrors([])\n setStatus('')\n try {\n await api('DELETE', `/providers/${encodeURIComponent(selectedProvider)}/models/${encodeURIComponent(model.alias)}`)\n await reloadCatalog()\n setStatus(`${model.alias} removed`)\n } catch (e) {\n const details = errorDetails(e)\n setErrors(details.length ? details : [(e as Error).message])\n }\n }\n\n function editModel(model: ProviderModelCatalogEntry) {\n setForm({\n provider: selectedProvider,\n alias: model.alias,\n label: model.label,\n providerModel: model.providerModel,\n efforts: model.efforts.join(', '),\n defaultEffort: model.defaultEffort ?? '',\n selfCompactUtilization: model.contextThreshold?.selfCompactUtilization?.toString() ?? '',\n warnUtilization: model.contextThreshold?.warnUtilization?.toString() ?? '',\n hardBackstopUtilization: model.contextThreshold?.hardBackstopUtilization?.toString() ?? '',\n disabled: Boolean(model.disabled),\n limits: model.limits,\n capabilities: model.capabilities,\n })\n setErrors([])\n setStatus('')\n }\n\n if (error) {\n return (\n <Card size=\"sm\">\n <CardContent className=\"text-sm text-muted-foreground\">\n <div className=\"mb-1 flex items-center gap-2 font-medium text-foreground\"><SlidersHorizontal className=\"size-4\" />Model catalog</div>\n {error}\n </CardContent>\n </Card>\n )\n }\n\n return (\n <section className=\"space-y-4\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div>\n <h2 className=\"text-base font-semibold\">Model catalog</h2>\n <p className=\"text-sm text-muted-foreground\">Add override models, disable unavailable models, or remove custom entries from the provider catalog.</p>\n </div>\n {!canWrite && <Badge variant=\"secondary\">Read only: needs settings:write:provider</Badge>}\n </div>\n\n <div className=\"flex flex-wrap gap-2\">\n {providers.map((item) => (\n <Button key={item} variant={item === selectedProvider ? 'default' : 'outline'} size=\"sm\" onClick={() => switchProvider(item)}>\n {item}\n </Button>\n ))}\n </div>\n\n <Card size=\"sm\">\n <CardHeader>\n <CardTitle className=\"text-sm\">Add or edit model</CardTitle>\n <CardAction>\n <Badge variant=\"outline\" className=\"gap-1\"><ServerCog className=\"size-3.5\" />Server runtime</Badge>\n </CardAction>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <div className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Alias\">\n <Input value={form.alias} disabled={!canWrite} placeholder=\"nightly\" onChange={(e) => updateForm({ alias: e.target.value.trim() })} />\n </Field>\n <Field label=\"Label\">\n <Input value={form.label} disabled={!canWrite} placeholder=\"Nightly Codex\" onChange={(e) => updateForm({ label: e.target.value })} />\n </Field>\n <Field label=\"Provider model\">\n <Input value={form.providerModel} disabled={!canWrite} placeholder=\"codex-nightly\" onChange={(e) => updateForm({ providerModel: e.target.value })} />\n </Field>\n <Field label=\"Efforts\">\n <Input value={form.efforts} disabled={!canWrite} placeholder=\"low, medium, high\" onChange={(e) => updateForm({ efforts: e.target.value })} />\n </Field>\n <Field label=\"Default effort\">\n <Input value={form.defaultEffort} disabled={!canWrite} placeholder=\"medium\" onChange={(e) => updateForm({ defaultEffort: e.target.value })} />\n </Field>\n <Field label=\"Self compact utilization\">\n <Input value={form.selfCompactUtilization} disabled={!canWrite} placeholder=\"0.80\" inputMode=\"decimal\" onChange={(e) => updateForm({ selfCompactUtilization: e.target.value })} />\n </Field>\n <Field label=\"Warn utilization\">\n <Input value={form.warnUtilization} disabled={!canWrite} placeholder=\"default: self - 0.10\" inputMode=\"decimal\" onChange={(e) => updateForm({ warnUtilization: e.target.value })} />\n </Field>\n <Field label=\"Hard backstop utilization\">\n <Input value={form.hardBackstopUtilization} disabled={!canWrite} placeholder=\"0.90\" inputMode=\"decimal\" onChange={(e) => updateForm({ hardBackstopUtilization: e.target.value })} />\n </Field>\n <div className=\"flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3\">\n <div>\n <div className=\"text-sm font-medium\">Disabled</div>\n <div className=\"text-xs text-muted-foreground\">Keep visible but unavailable for new launches.</div>\n </div>\n <Switch checked={form.disabled} disabled={!canWrite} onCheckedChange={(disabled) => updateForm({ disabled })} />\n </div>\n </div>\n <Button onClick={saveModel} disabled={!canWrite || !form.alias || !form.label || !form.providerModel}>\n <Plus className=\"size-4\" />\n Save model\n </Button>\n </CardContent>\n </Card>\n\n <div className=\"space-y-2\">\n {selectedCatalog && selectedCatalog.models.length === 0 && (\n <Card size=\"sm\">\n <CardContent className=\"text-sm text-muted-foreground\">No models in this provider catalog yet.</CardContent>\n </Card>\n )}\n {selectedCatalog?.models.map((model) => (\n <Card key={model.alias} size=\"sm\">\n <CardContent className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-medium\">{model.label}</span>\n <code className=\"rounded bg-muted px-1.5 py-0.5 font-mono text-xs\">{model.alias}</code>\n {model.disabled && <Badge variant=\"secondary\">Disabled</Badge>}\n </div>\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {model.providerModel}\n {model.efforts.length > 0 ? ` · efforts ${model.efforts.join(', ')}` : ' · no effort levels'}\n {model.defaultEffort ? ` · default ${model.defaultEffort}` : ''}\n {` · context ${thresholdLabel(model)}`}\n </p>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => editModel(model)}>\n <Pencil className=\"size-4\" />\n Edit\n </Button>\n <Button variant=\"outline\" size=\"sm\" disabled={!canWrite} onClick={() => void setDisabled(model, !model.disabled)}>\n {model.disabled ? <Eye className=\"size-4\" /> : <EyeOff className=\"size-4\" />}\n {model.disabled ? 'Enable' : 'Disable'}\n </Button>\n <Button variant=\"outline\" size=\"sm\" disabled={!canWrite} onClick={() => void removeModel(model)}>\n <Trash2 className=\"size-4\" />\n Remove\n </Button>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n\n {errors.length > 0 && (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">\n <ul className=\"list-disc space-y-1 pl-5\">\n {errors.map((detail) => <li key={detail}>{detail}</li>)}\n </ul>\n </div>\n )}\n {status && <p className=\"flex items-center gap-1 text-sm text-emerald-500\"><CheckCircle2 className=\"size-4\" />{status}</p>}\n </section>\n )\n}\n\nfunction emptyModelForm(provider: SpawnProvider): ModelForm {\n return { provider, alias: '', label: '', providerModel: '', efforts: '', defaultEffort: '', selfCompactUtilization: '', warnUtilization: '', hardBackstopUtilization: '', disabled: false }\n}\n\nfunction contextThresholdFromForm(form: ModelForm): ProviderModelCatalogEntry['contextThreshold'] | undefined {\n const selfCompactUtilization = optionalNumber(form.selfCompactUtilization, 'Self compact utilization')\n const warnUtilization = optionalNumber(form.warnUtilization, 'Warn utilization')\n const hardBackstopUtilization = optionalNumber(form.hardBackstopUtilization, 'Hard backstop utilization')\n if (selfCompactUtilization === undefined && warnUtilization === undefined && hardBackstopUtilization === undefined) return undefined\n if (selfCompactUtilization === undefined) throw new Error('Self compact utilization is required when setting context thresholds')\n return {\n selfCompactUtilization,\n ...(warnUtilization !== undefined ? { warnUtilization } : {}),\n ...(hardBackstopUtilization !== undefined ? { hardBackstopUtilization } : {}),\n }\n}\n\nfunction optionalNumber(value: string, label: string): number | undefined {\n const trimmed = value.trim()\n if (!trimmed) return undefined\n const parsed = Number(trimmed)\n if (!Number.isFinite(parsed)) throw new Error(`${label} must be a number`)\n return parsed\n}\n\nfunction thresholdLabel(model: ProviderModelCatalogEntry): string {\n if (model.contextThreshold) {\n const self = percent(model.contextThreshold.selfCompactUtilization)\n const warn = percent(model.contextThreshold.warnUtilization ?? Math.max(0, model.contextThreshold.selfCompactUtilization - 0.1))\n return `self ${self}, warn ${warn}`\n }\n const derived = deriveContextThresholdFromWindowTokens(model.limits?.contextWindowTokens?.value)\n return `derived self ${percent(derived.selfCompactUtilization)}, warn ${percent(derived.warnUtilization)}`\n}\n\nfunction percent(value: number): string {\n return `${Math.round(value * 100)}%`\n}\n","import { useEffect, useState } from 'react'\nimport type { ProviderQuotaConfig, ProviderQuotaConfigMap } from 'agent-relay-sdk/types'\nimport { api } from '@/lib/api'\nimport { Switch } from '@/components/ui/switch'\nimport { Badge } from '@/components/ui/badge'\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport { AlertCircle, Gauge, Loader2 } from 'lucide-react'\n\n// Quota config block under Settings → Providers (#605). Per provider: enable\n// collection, poll cadence (5m–15m), and show-in-widget. enabled = collect,\n// showInWidget = display — disabling collection stops the orchestrator polling\n// that provider entirely; hiding only removes it from the dashboard widget.\nconst MIN_MINUTES = 5\nconst MAX_MINUTES = 15\n\nconst PROVIDER_LABELS: Record<string, string> = { claude: 'Claude', codex: 'Codex' }\n\nfunction minutesOf(pollIntervalMs: number): number {\n return Math.round(pollIntervalMs / 60_000)\n}\n\nfunction intervalLabel(pollIntervalMs: number): string {\n return `${minutesOf(pollIntervalMs)} min`\n}\n\nexport function QuotaSettings({ canWrite }: { canWrite: boolean }) {\n const [config, setConfig] = useState<ProviderQuotaConfigMap | null>(null)\n const [loadError, setLoadError] = useState('')\n const [saveError, setSaveError] = useState('')\n const [savingProvider, setSavingProvider] = useState<string | null>(null)\n\n // External data load on mount — mirrors the SettingsView reload() pattern.\n useEffect(() => {\n let cancelled = false\n void (async () => {\n try {\n const data = await api<ProviderQuotaConfigMap>('GET', '/providers/quota-config')\n if (!cancelled) setConfig(data)\n } catch (e) {\n if (!cancelled) setLoadError((e as Error).message)\n }\n })()\n return () => { cancelled = true }\n }, [])\n\n async function save(provider: string, next: ProviderQuotaConfig) {\n setConfig((current) => ({ ...(current ?? {}), [provider]: next }))\n setSaveError('')\n setSavingProvider(provider)\n try {\n const saved = await api<ProviderQuotaConfig>('PUT', `/providers/${provider}/quota-config`, next)\n setConfig((current) => ({ ...(current ?? {}), [provider]: saved }))\n } catch (e) {\n setSaveError(`${PROVIDER_LABELS[provider] ?? provider}: ${(e as Error).message}`)\n } finally {\n setSavingProvider(null)\n }\n }\n\n const providers = config ? Object.keys(config).sort() : []\n\n return (\n <section className=\"space-y-4\">\n <div>\n <h2 className=\"text-base font-semibold\">Quota</h2>\n <p className=\"text-sm text-muted-foreground\">\n Per-provider quota collection and display. <strong>Enabled</strong> governs collection (disabled stops polling — no API calls);\n <strong> Show in widget</strong> governs display only.\n </p>\n </div>\n\n {loadError && (\n <div className=\"flex items-start gap-2 rounded-lg border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">\n <AlertCircle className=\"mt-0.5 size-4\" />\n <span>{loadError}</span>\n </div>\n )}\n {saveError && (\n <div className=\"flex items-start gap-2 rounded-lg border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">\n <AlertCircle className=\"mt-0.5 size-4\" />\n <span>{saveError}</span>\n </div>\n )}\n\n {!config && !loadError && (\n <Card size=\"sm\"><CardContent className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Loader2 className=\"size-4 animate-spin\" />Loading quota config…\n </CardContent></Card>\n )}\n\n {providers.map((provider) => {\n const cfg = config![provider]!\n const disabled = !canWrite || savingProvider === provider\n return (\n <Card key={provider} size=\"sm\">\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-sm\">\n <Gauge className=\"size-4\" />\n {PROVIDER_LABELS[provider] ?? provider}\n {savingProvider === provider && <Loader2 className=\"size-3 animate-spin text-muted-foreground\" />}\n </CardTitle>\n <CardDescription className=\"text-xs\">\n {cfg.enabled ? `Polled every ${intervalLabel(cfg.pollIntervalMs)}` : 'Collection disabled'}\n {cfg.enabled && !cfg.showInWidget ? ' · hidden from widget' : ''}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3\">\n <div>\n <div className=\"text-sm font-medium\">Enabled</div>\n <div className=\"text-xs text-muted-foreground\">Collect quota for this provider. Off stops all polling (no API calls, no token spend).</div>\n </div>\n <Switch\n checked={cfg.enabled}\n disabled={disabled}\n onCheckedChange={(enabled) => void save(provider, { ...cfg, enabled })}\n />\n </div>\n\n <div className=\"rounded-md border bg-muted/20 p-3 space-y-2\">\n <div className=\"flex items-center justify-between\">\n <div className=\"text-sm font-medium\">Polling interval</div>\n <Badge variant=\"outline\" className=\"tabular-nums\">{intervalLabel(cfg.pollIntervalMs)}</Badge>\n </div>\n <input\n type=\"range\"\n min={MIN_MINUTES}\n max={MAX_MINUTES}\n step={1}\n value={minutesOf(cfg.pollIntervalMs)}\n disabled={disabled || !cfg.enabled}\n // Live label update while dragging; persist on pointer/key release.\n onChange={(e) => {\n const pollIntervalMs = Number(e.target.value) * 60_000\n setConfig((current) => ({ ...(current ?? {}), [provider]: { ...cfg, pollIntervalMs } }))\n }}\n onPointerUp={(e) => void save(provider, { ...cfg, pollIntervalMs: Number((e.target as HTMLInputElement).value) * 60_000 })}\n onKeyUp={(e) => void save(provider, { ...cfg, pollIntervalMs: Number((e.target as HTMLInputElement).value) * 60_000 })}\n className=\"w-full accent-primary disabled:opacity-50\"\n />\n <div className=\"flex justify-between text-[10px] text-muted-foreground\">\n <span>{MIN_MINUTES} min</span>\n <span>{MAX_MINUTES} min</span>\n </div>\n </div>\n\n <div className=\"flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3\">\n <div>\n <div className=\"text-sm font-medium\">Show in quota widget</div>\n <div className=\"text-xs text-muted-foreground\">Display only. Off hides this provider from the dashboard widget; collection continues if enabled.</div>\n </div>\n <Switch\n checked={cfg.showInWidget}\n disabled={disabled}\n onCheckedChange={(showInWidget) => void save(provider, { ...cfg, showInWidget })}\n />\n </div>\n </CardContent>\n </Card>\n )\n })}\n </section>\n )\n}\n","import { useEffect, useMemo, useRef, useState } from 'react'\nimport type { ProviderCatalogEntry } from 'agent-relay-sdk/provider-catalog'\nimport { api, apiUpload } from '@/lib/api'\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\nimport { Badge } from '@/components/ui/badge'\nimport { Card, CardContent } from '@/components/ui/card'\nimport { AlertCircle, Camera, Globe2, RefreshCw, Route, Save, Trash2, Upload } from 'lucide-react'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { Textarea } from '@/components/ui/textarea'\nimport { BrowserSettings } from '@/components/settings/browser-settings'\nimport { ModelCatalogSettings } from '@/components/settings/model-catalog-settings'\nimport { QuotaSettings } from '@/components/settings/quota-settings'\nimport { SchemaGroup } from '@/components/settings/schema-form'\nimport { UserAvatar } from '@/components/shared/user-avatar'\nimport { useRelayStore } from '@/store'\nimport {\n groupSettings,\n hasScope,\n settingId,\n type SettingEntry,\n} from '@/components/settings/schema-utils'\nimport type { Artifact, NotificationRoutingPreview, User } from '@/types'\n\ninterface SettingsResponse {\n settings: SettingEntry[]\n}\n\ninterface TokenMe {\n actor: string\n kind: string\n role?: string\n scopes: string[]\n}\n\ninterface ProvidersResponse {\n catalog: ProviderCatalogEntry[]\n}\n\ninterface NotificationPreviewResponse {\n preview: NotificationRoutingPreview\n}\n\nconst BROWSER_GROUP_SLUG = 'browser'\nconst MODELS_GROUP_SLUG = 'models'\nconst PROFILE_GROUP_SLUG = 'profile'\nconst NOTIFICATION_TYPES = [\n 'branch.landed',\n 'landed-failure',\n 'agent.ready',\n 'agent.exited',\n 'agent.spawn_failed',\n 'agent.context_threshold',\n 'agent.quota_threshold',\n 'workspace.steward_task',\n 'workspace.conflict',\n 'workspace.review_request',\n]\n\nfunction settingsHash(): string {\n if (typeof window === 'undefined') return ''\n const hash = window.location.hash.replace(/^#/, '')\n if (!hash.startsWith('settings/')) return ''\n return decodeURIComponent(hash.slice('settings/'.length))\n}\n\nfunction writeSettingsHash(slug: string): void {\n if (typeof window === 'undefined') return\n const url = new URL(window.location.href)\n url.hash = `settings/${encodeURIComponent(slug)}`\n window.history.pushState({}, '', url)\n}\n\nexport function SettingsView() {\n const [settings, setSettings] = useState<SettingEntry[]>([])\n const [token, setToken] = useState<TokenMe | null>(null)\n const [catalog, setCatalog] = useState<ProviderCatalogEntry[]>([])\n const [active, setActive] = useState(() => settingsHash())\n const [loading, setLoading] = useState(true)\n const [loadError, setLoadError] = useState('')\n const [catalogError, setCatalogError] = useState('')\n\n async function reload() {\n setLoading(true)\n setLoadError('')\n setCatalogError('')\n try {\n const [settingsRes, tokenRes, providersRes] = await Promise.all([\n api<SettingsResponse>('GET', '/settings'),\n api<TokenMe>('GET', '/tokens/me'),\n api<ProvidersResponse>('GET', '/providers').catch((e) => {\n setCatalogError((e as Error).message)\n return { catalog: [] }\n }),\n ])\n setSettings(settingsRes.settings)\n setToken(tokenRes)\n setCatalog(providersRes.catalog)\n } catch (e) {\n setLoadError((e as Error).message)\n } finally {\n setLoading(false)\n }\n }\n\n useEffect(() => {\n void reload()\n }, [])\n\n // External sync: keep the selected settings group aligned with browser history.\n useEffect(() => {\n const sync = () => setActive(settingsHash())\n window.addEventListener('hashchange', sync)\n window.addEventListener('popstate', sync)\n return () => {\n window.removeEventListener('hashchange', sync)\n window.removeEventListener('popstate', sync)\n }\n }, [])\n\n const descriptorGroups = useMemo(() => groupSettings(settings), [settings])\n const groups = useMemo(() => [\n ...descriptorGroups.map((group) => ({\n slug: group.slug,\n label: group.group,\n description: `${group.settings.length} schema setting${group.settings.length === 1 ? '' : 's'}`,\n kind: 'descriptors' as const,\n settings: group.settings,\n })),\n {\n slug: PROFILE_GROUP_SLUG,\n label: 'Profile',\n description: 'Display name and avatar',\n kind: 'profile' as const,\n settings: [],\n },\n {\n slug: BROWSER_GROUP_SLUG,\n label: 'Browser',\n description: 'Local dashboard preferences',\n kind: 'browser' as const,\n settings: [],\n },\n {\n slug: MODELS_GROUP_SLUG,\n label: 'Models',\n description: 'Provider model catalog',\n kind: 'models' as const,\n settings: [],\n },\n ], [descriptorGroups])\n\n const activeGroup = groups.find((group) => group.slug === active) ?? groups[0]\n\n function selectGroup(slug: string) {\n setActive(slug)\n writeSettingsHash(slug)\n }\n\n function replaceSetting(updated: SettingEntry) {\n setSettings((current) => current.map((entry) => settingId(entry) === settingId(updated) ? updated : entry))\n }\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div>\n <h1 className=\"text-lg font-semibold\">Settings</h1>\n <p className=\"text-sm text-muted-foreground\">Schema-driven Relay settings, browser preferences, and model catalog controls.</p>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n {token && (\n <Badge variant=\"outline\" className=\"gap-1\">\n <Globe2 className=\"size-3\" />\n {token.kind}:{token.actor}\n </Badge>\n )}\n <Button variant=\"outline\" size=\"sm\" onClick={() => void reload()} disabled={loading}>\n <RefreshCw className={cn('size-4', loading && 'animate-spin')} />\n Refresh\n </Button>\n </div>\n </div>\n\n {loadError && (\n <div className=\"flex items-start gap-2 rounded-lg border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">\n <AlertCircle className=\"mt-0.5 size-4\" />\n <span>{loadError}</span>\n </div>\n )}\n\n <div className=\"grid gap-4 lg:grid-cols-[230px_minmax(0,1fr)]\">\n <nav className=\"space-y-1 lg:sticky lg:top-4 lg:self-start\">\n {groups.map((group) => (\n <button\n key={group.slug}\n type=\"button\"\n className={cn(\n 'w-full rounded-md border px-3 py-2 text-left text-sm transition-colors',\n activeGroup?.slug === group.slug ? 'border-primary/50 bg-primary/10 text-foreground' : 'border-transparent hover:border-border hover:bg-accent',\n )}\n onClick={() => selectGroup(group.slug)}\n >\n <span className=\"block font-medium\">{group.label}</span>\n <span className=\"block truncate text-xs text-muted-foreground\">{group.description}</span>\n </button>\n ))}\n </nav>\n\n <div className=\"min-w-0 space-y-4\">\n {loading && !settings.length ? (\n <Card size=\"sm\">\n <CardContent className=\"text-sm text-muted-foreground\">Loading settings…</CardContent>\n </Card>\n ) : activeGroup?.kind === 'descriptors' ? (\n <>\n <SchemaGroup\n group={activeGroup.label}\n settings={activeGroup.settings}\n onSaved={replaceSetting}\n />\n {/* Quota config block lives under the Providers group (#605). */}\n {activeGroup.label === 'Providers' && (\n <QuotaSettings canWrite={hasScope(token?.scopes, 'settings:write:provider')} />\n )}\n {activeGroup.label === 'Notifications' && (\n <NotificationRoutingPreviewPanel />\n )}\n </>\n ) : activeGroup?.kind === 'profile' ? (\n <ProfileSettings />\n ) : activeGroup?.kind === 'browser' ? (\n <BrowserSettings />\n ) : (\n <ModelCatalogSettings\n catalog={catalog}\n error={catalogError}\n canWrite={hasScope(token?.scopes, 'settings:write:provider')}\n onCatalog={setCatalog}\n />\n )}\n </div>\n </div>\n </div>\n )\n}\n\nfunction NotificationRoutingPreviewPanel() {\n const [type, setType] = useState('branch.landed')\n const [scopeText, setScopeText] = useState('{\\n \"repoRoot\": \"/repo\"\\n}')\n const [preview, setPreview] = useState<NotificationRoutingPreview | null>(null)\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState('')\n\n async function runPreview() {\n setLoading(true)\n setError('')\n try {\n const scope = JSON.parse(scopeText) as unknown\n if (!scope || typeof scope !== 'object' || Array.isArray(scope)) throw new Error('Scope must be a JSON object')\n const result = await api<NotificationPreviewResponse>('POST', '/notifications/preview', { type, scope })\n setPreview(result.preview)\n } catch (e) {\n setPreview(null)\n setError((e as Error).message)\n } finally {\n setLoading(false)\n }\n }\n\n return (\n <Card size=\"sm\">\n <CardContent className=\"space-y-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <div>\n <h2 className=\"text-sm font-semibold\">Who gets what</h2>\n <p className=\"text-xs text-muted-foreground\">Dry-run notification routing without sending.</p>\n </div>\n <Button size=\"sm\" onClick={() => void runPreview()} disabled={loading}>\n <Route className=\"size-4\" />\n Preview\n </Button>\n </div>\n <div className=\"grid gap-3 md:grid-cols-[240px_minmax(0,1fr)]\">\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">Type</label>\n <Select value={type} onValueChange={setType}>\n <SelectTrigger className=\"w-full\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {NOTIFICATION_TYPES.map((item) => <SelectItem key={item} value={item}>{item}</SelectItem>)}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">Scope</label>\n <Textarea value={scopeText} onChange={(e) => setScopeText(e.target.value)} rows={4} className=\"font-mono text-xs\" />\n </div>\n </div>\n {error && (\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 p-2 text-xs text-destructive\">\n <AlertCircle className=\"mt-0.5 size-3.5\" />\n <span>{error}</span>\n </div>\n )}\n {preview && (\n <div className=\"overflow-hidden rounded-md border border-border\">\n {preview.recipients.length === 0 ? (\n <div className=\"px-3 py-4 text-center text-xs text-muted-foreground\">No recipients</div>\n ) : preview.recipients.map((recipient) => (\n <div key={`${recipient.recipient}-${recipient.matchedRule}`} className=\"grid gap-1 border-b border-border px-3 py-2 text-xs last:border-b-0 md:grid-cols-[minmax(0,180px)_minmax(0,160px)_minmax(0,1fr)]\">\n <span className=\"truncate font-medium\">{recipient.recipient}</span>\n <span className=\"truncate font-mono text-muted-foreground\">{recipient.matchedRule}</span>\n <span className=\"truncate text-muted-foreground\">{recipient.reason}</span>\n </div>\n ))}\n </div>\n )}\n </CardContent>\n </Card>\n )\n}\n\nfunction ProfileSettings() {\n const fetchUsers = useRelayStore((s) => s.fetchUsers)\n const fileRef = useRef<HTMLInputElement>(null)\n const [user, setUser] = useState<User | null>(null)\n const [displayName, setDisplayName] = useState('')\n const [loading, setLoading] = useState(true)\n const [saving, setSaving] = useState(false)\n const [error, setError] = useState('')\n\n async function loadProfile() {\n setLoading(true)\n setError('')\n try {\n const next = await api<User>('GET', '/users/me')\n setUser(next)\n setDisplayName(next.displayName || next.handle)\n } catch (e) {\n setError((e as Error).message)\n } finally {\n setLoading(false)\n }\n }\n\n useEffect(() => {\n void loadProfile()\n }, [])\n\n async function saveProfile() {\n setSaving(true)\n setError('')\n try {\n const next = await api<User>('PATCH', '/users/me', { displayName })\n setUser(next)\n setDisplayName(next.displayName || next.handle)\n await fetchUsers()\n } catch (e) {\n setError((e as Error).message)\n } finally {\n setSaving(false)\n }\n }\n\n async function uploadAvatar(file: File | undefined) {\n if (!file) return\n setSaving(true)\n setError('')\n try {\n const res = await apiUpload<{ user: User; artifact: Artifact }>('/users/me/avatar', file)\n setUser(res.user)\n setDisplayName(res.user.displayName || res.user.handle)\n await fetchUsers()\n } catch (e) {\n setError((e as Error).message)\n } finally {\n setSaving(false)\n if (fileRef.current) fileRef.current.value = ''\n }\n }\n\n async function removeAvatar() {\n setSaving(true)\n setError('')\n try {\n const next = await api<User>('DELETE', '/users/me/avatar')\n setUser(next)\n await fetchUsers()\n } catch (e) {\n setError((e as Error).message)\n } finally {\n setSaving(false)\n }\n }\n\n return (\n <Card size=\"sm\">\n <CardContent className=\"space-y-4\">\n {error && (\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">\n <AlertCircle className=\"mt-0.5 size-4\" />\n <span>{error}</span>\n </div>\n )}\n <div className=\"flex flex-wrap items-center gap-4\">\n <UserAvatar user={user ?? undefined} distinct className=\"size-16 text-lg\" />\n <div className=\"min-w-0 flex-1 space-y-2\">\n <label className=\"block text-xs font-medium text-muted-foreground\" htmlFor=\"profile-display-name\">Display name</label>\n <input\n id=\"profile-display-name\"\n className=\"h-9 w-full rounded-md border border-input bg-background px-3 text-sm\"\n value={displayName}\n onChange={(e) => setDisplayName(e.target.value)}\n disabled={loading || saving}\n maxLength={120}\n />\n </div>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button size=\"sm\" onClick={() => void saveProfile()} disabled={loading || saving || !displayName.trim()}>\n <Save className=\"size-4\" />\n Save\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={() => fileRef.current?.click()} disabled={loading || saving}>\n <Upload className=\"size-4\" />\n Upload\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={() => void removeAvatar()} disabled={loading || saving || !user?.avatarArtifactId}>\n <Trash2 className=\"size-4\" />\n Remove\n </Button>\n {saving && <Camera className=\"size-4 animate-pulse text-muted-foreground\" />}\n <input\n ref={fileRef}\n type=\"file\"\n accept=\"image/png,image/jpeg,image/gif,image/webp\"\n className=\"hidden\"\n onChange={(e) => void uploadAvatar(e.target.files?.[0])}\n />\n </div>\n </CardContent>\n </Card>\n )\n}\n"],"mappings":"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"}