agent-relay-server 0.106.0 → 0.107.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/openapi.json +29 -1
- package/package.json +5 -4
- package/public/assets/{MessageBubble-CPYQQLDI.js → MessageBubble-PEdvVh_m.js} +2 -2
- package/public/assets/{MessageBubble-CPYQQLDI.js.map → MessageBubble-PEdvVh_m.js.map} +1 -1
- package/public/assets/{PlanGraphPanel-B7xZt5DI.js → PlanGraphPanel-DSts7Rtq.js} +2 -2
- package/public/assets/{PlanGraphPanel-B7xZt5DI.js.map → PlanGraphPanel-DSts7Rtq.js.map} +1 -1
- package/public/assets/{activity-UKQrQ8_0.js → activity-BcYf8YNO.js} +2 -2
- package/public/assets/{activity-UKQrQ8_0.js.map → activity-BcYf8YNO.js.map} +1 -1
- package/public/assets/{agent-profiles-Zr_5nNEJ.js → agent-profiles-CuTQtmV6.js} +2 -2
- package/public/assets/{agent-profiles-Zr_5nNEJ.js.map → agent-profiles-CuTQtmV6.js.map} +1 -1
- package/public/assets/{agents-FdrfmJsj.js → agents-CgRFJyks.js} +2 -2
- package/public/assets/{agents-FdrfmJsj.js.map → agents-CgRFJyks.js.map} +1 -1
- package/public/assets/{analytics-VximqXQ9.js → analytics-C3OTFIXo.js} +18 -18
- package/public/assets/{analytics-VximqXQ9.js.map → analytics-C3OTFIXo.js.map} +1 -1
- package/public/assets/{automation-DlEcJvgu.js → automation-CH9YGYoE.js} +2 -2
- package/public/assets/{automation-DlEcJvgu.js.map → automation-CH9YGYoE.js.map} +1 -1
- package/public/assets/{chat-D1bunuI-.js → chat-BLcm2Aht.js} +2 -2
- package/public/assets/{chat-D1bunuI-.js.map → chat-BLcm2Aht.js.map} +1 -1
- package/public/assets/{formatted-body-impl-4v9SkUD1.js → formatted-body-impl-BJTthVHg.js} +2 -2
- package/public/assets/{formatted-body-impl-4v9SkUD1.js.map → formatted-body-impl-BJTthVHg.js.map} +1 -1
- package/public/assets/{index-Vmhw442d.js → index-3ydeNO0c.js} +6 -6
- package/public/assets/index-3ydeNO0c.js.map +1 -0
- package/public/assets/{insights-CntgHcTp.js → insights-DklrIhb6.js} +2 -2
- package/public/assets/{insights-CntgHcTp.js.map → insights-DklrIhb6.js.map} +1 -1
- package/public/assets/{maintenance-Dw7frQtu.js → maintenance-FAAMGpuZ.js} +2 -2
- package/public/assets/{maintenance-Dw7frQtu.js.map → maintenance-FAAMGpuZ.js.map} +1 -1
- package/public/assets/{managed-agents-Bj--bFmZ.js → managed-agents-CVca-s3t.js} +2 -2
- package/public/assets/{managed-agents-Bj--bFmZ.js.map → managed-agents-CVca-s3t.js.map} +1 -1
- package/public/assets/{markdown-preview-impl-DGLCocU8.js → markdown-preview-impl-BPW4OQo9.js} +2 -2
- package/public/assets/{markdown-preview-impl-DGLCocU8.js.map → markdown-preview-impl-BPW4OQo9.js.map} +1 -1
- package/public/assets/{memory-yj2MIxUA.js → memory-BzuDTHC5.js} +2 -2
- package/public/assets/{memory-yj2MIxUA.js.map → memory-BzuDTHC5.js.map} +1 -1
- package/public/assets/{messages-BT5mL7iz.js → messages-_W24PNvT.js} +2 -2
- package/public/assets/{messages-BT5mL7iz.js.map → messages-_W24PNvT.js.map} +1 -1
- package/public/assets/{orchestrators-BVDAhrPk.js → orchestrators-Du6I_n8i.js} +2 -2
- package/public/assets/{orchestrators-BVDAhrPk.js.map → orchestrators-Du6I_n8i.js.map} +1 -1
- package/public/assets/{overview-DlqJIqYK.js → overview-Dyvm1qpT.js} +2 -2
- package/public/assets/{overview-DlqJIqYK.js.map → overview-Dyvm1qpT.js.map} +1 -1
- package/public/assets/{pairs-DQ4tNCo3.js → pairs-B8x1RCNd.js} +2 -2
- package/public/assets/{pairs-DQ4tNCo3.js.map → pairs-B8x1RCNd.js.map} +1 -1
- package/public/assets/{prompt-settings-DlsqOP0C.js → prompt-settings-xVXmvxB5.js} +2 -2
- package/public/assets/{prompt-settings-DlsqOP0C.js.map → prompt-settings-xVXmvxB5.js.map} +1 -1
- package/public/assets/{registry-Cw2fdWrn.js → registry-ypiICauZ.js} +2 -2
- package/public/assets/{registry-Cw2fdWrn.js.map → registry-ypiICauZ.js.map} +1 -1
- package/public/assets/{security-ucr7IT1V.js → security-BfOQ6T5r.js} +2 -2
- package/public/assets/{security-ucr7IT1V.js.map → security-BfOQ6T5r.js.map} +1 -1
- package/public/assets/{select-D8UWCtYZ.js → select-Dx8Ro-A3.js} +2 -2
- package/public/assets/{select-D8UWCtYZ.js.map → select-Dx8Ro-A3.js.map} +1 -1
- package/public/assets/settings-87clTx4N.js +6 -0
- package/public/assets/settings-87clTx4N.js.map +1 -0
- package/public/assets/{tasks-jRUvxUd5.js → tasks-1Kvp53wh.js} +2 -2
- package/public/assets/{tasks-jRUvxUd5.js.map → tasks-1Kvp53wh.js.map} +1 -1
- package/public/assets/{teams-Dn0yggD-.js → teams-DJWp4AKi.js} +2 -2
- package/public/assets/{teams-Dn0yggD-.js.map → teams-DJWp4AKi.js.map} +1 -1
- package/public/assets/{terminal-viewer-impl-fLly20IP.js → terminal-viewer-impl-DgMuRAe_.js} +2 -2
- package/public/assets/{terminal-viewer-impl-fLly20IP.js.map → terminal-viewer-impl-DgMuRAe_.js.map} +1 -1
- package/public/assets/types-DorDDvEb.js.map +1 -1
- package/public/assets/{user-avatar-BWLUHt2e.js → user-avatar-CfAUS3PZ.js} +2 -2
- package/public/assets/{user-avatar-BWLUHt2e.js.map → user-avatar-CfAUS3PZ.js.map} +1 -1
- package/public/assets/{work-queue-BAnNY0xE.js → work-queue-D-Otxd9u.js} +2 -2
- package/public/assets/{work-queue-BAnNY0xE.js.map → work-queue-D-Otxd9u.js.map} +1 -1
- package/public/index.html +1 -1
- package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/src/branch-landed.ts +76 -1
- package/src/db/provider-quotas.ts +6 -0
- package/src/notification-types.ts +2 -0
- package/src/routes/commands.ts +17 -1
- package/src/routes/index.ts +2 -1
- package/src/routes/provider-quotas.ts +13 -1
- package/src/security.ts +2 -0
- package/src/services/transient-agent-reaper.ts +16 -1
- package/public/assets/index-Vmhw442d.js.map +0 -1
- package/public/assets/settings-Dvf_ps1B.js +0 -6
- package/public/assets/settings-Dvf_ps1B.js.map +0 -1
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./chunk-CilyBKbf.js";import{A as t,An as n,B as r,Bn as i,D as a,En as o,Gn as s,I as c,Kt as l,Qn as u,S as d,W as f,Yn as p,Z as m,Zn as h,Zt as g,_n as _,c as v,ft as y,h as b,hn as x,j as S,jt as C,nr as w,p as T,qt as E,ur as D,xn as ee,yn as te}from"./lucide-react-C4eXYCwx.js";import{g as ne,m as O,t as k,u as re}from"./store-DUfrGvOE.js";import{c as ie,o as ae,r as oe,u as A}from"./types-DorDDvEb.js";import{t as se}from"./themes-DjSwmAZN.js";import{a as j,i as M,n as N,r as P,t as F}from"./select-D8UWCtYZ.js";import{t as I}from"./badge-D8fABzMs.js";import{t as L}from"./button-KASZcscA.js";import{t as R}from"./input-CtHfLn1i.js";import{r as ce,z}from"./index-Vmhw442d.js";import{i as B,n as V,o as H,r as U,s as W,t as G}from"./card-Cds0MWME.js";import{t as le}from"./user-avatar-BWLUHt2e.js";var K=e(D(),1);function q(e){return`${e.namespace}/${e.key}`}function ue(e){return`/settings/${encodeURIComponent(e.namespace)}/${encodeURIComponent(e.key)}`}function de(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``)||`settings`}function fe(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:de(e),settings:t.sort(pe)})).sort((e,t)=>me(e.settings)-me(t.settings)||e.group.localeCompare(t.group))}function pe(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 me(e){return Math.min(...e.map(e=>e.display?.order??2**53-1))}function he(e){return Array.isArray(e.type)?e.type.find(e=>e!==`null`):e.type}function ge(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]=ge(t[r],i,n),t}let a=ae(e)?{...e}:{},o=ge(a[r],i,n);return o===void 0?delete a[r]:a[r]=o,a}function _e(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(he(e)){case`boolean`:return!1;case`integer`:case`number`:return 0;case`array`:return[];case`object`:return{};case`string`:return``;default:return}}function ve(e){return e.split(/\r?\n|,/).map(e=>e.trim()).filter(Boolean)}function ye(e){return Array.isArray(e)?e.map(e=>String(e)).join(`
|
|
2
|
-
`):``}function be(e){return ae(e)?Object.entries(e).map(([e,t])=>`${e}=${String(t??``)}`).join(`
|
|
3
|
-
`):``}function xe(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 J=h(),Se=`__unset__`;function Ce(e){return e===`server-runtime`?`Server runtime`:e===`bootstrap`?`Bootstrap`:`Browser`}function we(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 Te(e){return e===`browser`?(0,J.jsx)(m,{className:`size-3.5`}):(0,J.jsx)(a,{className:`size-3.5`})}function Ee(e){return e.details??[]}function De({group:e,settings:t,onSaved:n}){let r=[...new Set(t.map(e=>e.tier))];return(0,J.jsxs)(`section`,{className:`space-y-3`,children:[(0,J.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,J.jsx)(`h2`,{className:`text-base font-semibold`,children:e}),(0,J.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:r.map(e=>(0,J.jsxs)(I,{variant:`outline`,className:`gap-1`,title:we(e),children:[Te(e),Ce(e)]},e))})]}),t.length===0?(0,J.jsx)(G,{size:`sm`,children:(0,J.jsx)(U,{className:`text-sm text-muted-foreground`,children:`No settings in this group.`})}):(0,J.jsx)(`div`,{className:`space-y-3`,children:t.map(e=>(0,J.jsx)(Oe,{setting:e,onSaved:n},q(e)))})]})}function Oe({setting:e,onSaved:n}){let[r,i]=(0,K.useState)(()=>e.value??e.defaults??_e(e.schema)),[a,o]=(0,K.useState)(!1),[s,c]=(0,K.useState)(``),[l,d]=(0,K.useState)([]),f=e.writable&&e.tier===`server-runtime`;function p(e,t){i(n=>ge(n,e,t)),d([]),c(``)}async function m(){if(f){o(!0),d([]),c(``);try{let t=await u(`PUT`,ue(e),{value:r,updatedBy:`dashboard`});i(t.value),n(t),c(`Saved`)}catch(e){let t=Ee(e);d(t.length?t:[e.message])}finally{o(!1)}}}return(0,J.jsxs)(G,{size:`sm`,children:[(0,J.jsxs)(H,{children:[(0,J.jsxs)(W,{className:`flex flex-wrap items-center gap-2 text-sm`,children:[e.display.label,(0,J.jsxs)(I,{variant:`outline`,className:`gap-1`,title:we(e.tier),children:[Te(e.tier),Ce(e.tier)]}),!e.writable&&(0,J.jsx)(I,{variant:`secondary`,children:`Read only`})]}),e.display.description&&(0,J.jsx)(B,{children:e.display.description}),(0,J.jsx)(V,{children:(0,J.jsxs)(L,{size:`sm`,onClick:m,disabled:!f||a,children:[(0,J.jsx)(t,{className:`size-4`}),a?`Saving`:`Save`]})})]}),(0,J.jsxs)(U,{className:`space-y-3`,children:[(0,J.jsx)(ke,{schema:e.schema,value:r,path:[],label:e.display.label,required:!0,disabled:!f||a,onChange:p}),(0,J.jsxs)(`p`,{className:`flex flex-wrap items-center gap-x-2 text-[11px] text-muted-foreground`,children:[(0,J.jsxs)(`code`,{className:`rounded bg-muted px-1.5 py-0.5 font-mono`,children:[e.namespace,`/`,e.key]}),(0,J.jsxs)(`span`,{children:[`read `,(0,J.jsx)(`span`,{className:`text-foreground/70`,children:e.scope.read})]}),(0,J.jsx)(`span`,{"aria-hidden":!0,children:`·`}),(0,J.jsxs)(`span`,{children:[`write `,(0,J.jsx)(`span`,{className:`text-foreground/70`,children:e.scope.write})]})]}),l.length>0&&(0,J.jsxs)(`div`,{className:`rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive`,children:[(0,J.jsxs)(`div`,{className:`mb-1 flex items-center gap-2 font-medium`,children:[(0,J.jsx)(_,{className:`size-4`}),`Save failed`]}),(0,J.jsx)(`ul`,{className:`list-disc space-y-1 pl-5`,children:l.map(e=>(0,J.jsx)(`li`,{children:e},e))})]}),s&&(0,J.jsxs)(`p`,{className:`flex items-center gap-1 text-sm text-emerald-500`,children:[(0,J.jsx)(x,{className:`size-4`}),s]})]})]})}function ke(e){let{schema:t,value:n,path:r,label:i,required:a,disabled:o,onChange:s}=e,c=he(t);if(t.enum?.length){let e=n==null||n===``?Se:String(n);return(0,J.jsx)(Y,{label:i,description:t.description,children:(0,J.jsxs)(F,{value:e,onValueChange:e=>s(r,e===`__unset__`?void 0:e),disabled:o,children:[(0,J.jsx)(M,{children:(0,J.jsx)(j,{})}),(0,J.jsxs)(N,{children:[!a&&(0,J.jsx)(P,{value:`__unset__`,children:`Not set`}),t.enum.map(e=>(0,J.jsx)(P,{value:String(e),children:String(e)},String(e)))]})]})})}if(c===`boolean`)return(0,J.jsxs)(`div`,{className:`flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3`,children:[(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`div`,{className:`text-sm font-medium`,children:i}),t.description&&(0,J.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:t.description})]}),(0,J.jsx)(z,{checked:!!n,onCheckedChange:e=>s(r,e),disabled:o})]});if(c===`integer`||c===`number`)return(0,J.jsx)(Y,{label:i,description:t.description,children:(0,J.jsx)(R,{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,J.jsx)(Y,{label:i,description:t.description??`One item per line.`,children:(0,J.jsx)(ce,{rows:Math.min(8,Math.max(3,Array.isArray(n)?n.length+1:3)),value:ye(n),disabled:o,onChange:e=>s(r,ve(e.target.value))})});if(c===`object`){let e=t.properties??{},a=new Set(t.required??[]);return Object.keys(e).length===0&&t.additionalProperties?(0,J.jsx)(Y,{label:i,description:t.description??`KEY=value, one entry per line.`,children:(0,J.jsx)(ce,{rows:5,value:be(n),disabled:o,onChange:e=>s(r,xe(e.target.value))})}):(0,J.jsxs)(`div`,{className:`space-y-3`,children:[r.length>0&&(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`div`,{className:`text-sm font-medium`,children:i}),t.description&&(0,J.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:t.description})]}),(0,J.jsx)(`div`,{className:`grid gap-3 md:grid-cols-2`,children:Object.entries(e).map(([e,t])=>{let i=ae(n)?n[e]:void 0;return(0,J.jsx)(ke,{schema:t,value:i===void 0&&a.has(e)?_e(t):i,path:[...r,e],label:t.title||Ae(e),required:a.has(e),disabled:o,onChange:s},e)})})]})}return(0,J.jsx)(Y,{label:i,description:t.description,children:(0,J.jsx)(R,{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 Y({label:e,description:t,children:n}){return(0,J.jsxs)(`label`,{className:`block space-y-1.5 text-sm`,children:[(0,J.jsx)(`span`,{className:`text-muted-foreground`,children:e}),n,t&&(0,J.jsx)(`span`,{className:`block text-xs text-muted-foreground`,children:t})]})}function Ae(e){return e.replace(/([a-z0-9])([A-Z])/g,`$1 $2`).replace(/[-_]+/g,` `).replace(/^\w/,e=>e.toUpperCase())}function je(){let e=k(e=>e.theme),t=k(e=>e.showReasoning),r=k(e=>e.set);return(0,J.jsxs)(`section`,{className:`space-y-4`,children:[(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`h2`,{className:`text-base font-semibold`,children:`Browser preferences`}),(0,J.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`These are stored in local dashboard state, not in Relay server config.`})]}),(0,J.jsxs)(G,{size:`sm`,children:[(0,J.jsxs)(H,{children:[(0,J.jsx)(W,{className:`text-sm`,children:`Dashboard display`}),(0,J.jsx)(B,{className:`text-xs`,children:`Browser tier · persisted in this browser profile.`}),(0,J.jsx)(V,{children:(0,J.jsxs)(I,{variant:`outline`,className:`gap-1`,children:[(0,J.jsx)(m,{className:`size-3.5`}),`Browser`]})})]}),(0,J.jsxs)(U,{className:`grid gap-3 md:grid-cols-2`,children:[(0,J.jsx)(Y,{label:`Theme`,children:(0,J.jsxs)(F,{value:e,onValueChange:e=>r({theme:e}),children:[(0,J.jsx)(M,{children:(0,J.jsx)(j,{})}),(0,J.jsx)(N,{children:se.map(e=>(0,J.jsx)(P,{value:e.id,children:e.label},e.id))})]})}),(0,J.jsxs)(`div`,{className:`flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3`,children:[(0,J.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,J.jsx)(n,{className:`size-4`}),(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`div`,{className:`text-sm font-medium`,children:`Show reasoning details`}),(0,J.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,J.jsx)(z,{checked:t,onCheckedChange:e=>r({showReasoning:e})})]})]})]}),(0,J.jsx)(Me,{})]})}function Me(){let e=k(e=>e.voiceTtsEnabled),t=k(e=>e.setVoiceTtsEnabled),n=k(e=>e.voiceTtsMode),r=k(e=>e.setVoiceTtsMode),i=k(e=>e.voiceTtsKokoroVoice),a=k(e=>e.setVoiceTtsKokoroVoice),o=k(e=>e.voiceTtsBrowserVoice),s=k(e=>e.setVoiceTtsBrowserVoice),c=k(e=>e.voiceInputMode),l=k(e=>e.setVoiceInputMode),[u,d]=(0,K.useState)(()=>ne());(0,K.useEffect)(()=>{if(typeof window>`u`||!(`speechSynthesis`in window))return;let e=()=>d(ne());return e(),window.speechSynthesis.addEventListener?.(`voiceschanged`,e),()=>window.speechSynthesis.removeEventListener?.(`voiceschanged`,e)},[]);let f=O.some(e=>e.id===i)?O:[...O,{id:i,label:i}];return(0,J.jsxs)(G,{size:`sm`,children:[(0,J.jsxs)(H,{children:[(0,J.jsxs)(W,{className:`flex items-center gap-2 text-sm`,children:[(0,J.jsx)(v,{className:`size-4`}),`Voice`]}),(0,J.jsx)(B,{className:`text-xs`,children:`Browser tier TTS and push-to-talk behavior.`}),(0,J.jsx)(V,{children:(0,J.jsx)(z,{checked:e,onCheckedChange:t})})]}),(0,J.jsxs)(U,{className:`grid gap-3 md:grid-cols-2`,children:[(0,J.jsx)(Y,{label:`Speech engine`,children:(0,J.jsxs)(F,{value:n,onValueChange:e=>r(e),children:[(0,J.jsx)(M,{children:(0,J.jsx)(j,{})}),(0,J.jsxs)(N,{children:[(0,J.jsx)(P,{value:`kokoro`,children:`Kokoro (server, fallback to browser)`}),(0,J.jsx)(P,{value:`browser`,children:`Browser Web Speech API`})]})]})}),(0,J.jsx)(Y,{label:`Kokoro voice`,children:(0,J.jsxs)(F,{value:i,onValueChange:a,children:[(0,J.jsx)(M,{children:(0,J.jsx)(j,{})}),(0,J.jsx)(N,{children:f.map(e=>(0,J.jsx)(P,{value:e.id,children:e.label},e.id))})]})}),(0,J.jsx)(Y,{label:`Browser voice`,children:(0,J.jsxs)(F,{value:o||`__unset__`,onValueChange:e=>s(e===`__unset__`?``:e),children:[(0,J.jsx)(M,{children:(0,J.jsx)(j,{})}),(0,J.jsxs)(N,{children:[(0,J.jsx)(P,{value:Se,children:`System default`}),u.map(e=>(0,J.jsx)(P,{value:e.uri,children:e.label},e.uri))]})]})}),(0,J.jsx)(Y,{label:`Push-to-talk input`,children:(0,J.jsxs)(F,{value:c,onValueChange:e=>l(e),children:[(0,J.jsx)(M,{children:(0,J.jsx)(j,{})}),(0,J.jsxs)(N,{children:[(0,J.jsx)(P,{value:`compose`,children:`Fill message box`}),(0,J.jsx)(P,{value:`autosend`,children:`Send immediately`})]})]})})]})]})}function Ne({catalog:e,error:t,canWrite:n,onCatalog:i}){let o=e[0]?.provider??``,[s,c]=(0,K.useState)(o),[p,m]=(0,K.useState)(()=>Pe(o)),[h,g]=(0,K.useState)(``),[_,v]=(0,K.useState)([]),y=e.some(e=>e.provider===s)?s:o,S=e.find(e=>e.provider===y)??e[0],C=e.map(e=>e.provider);function w(e){m(t=>({...t,...e})),v([]),g(``)}function T(e){c(e),m(Pe(e)),v([]),g(``)}async function D(){i((await u(`GET`,`/providers`)).catalog)}async function ee(){if(n){v([]),g(``);try{await u(`PUT`,`/providers/${encodeURIComponent(p.provider)}/models/${encodeURIComponent(p.alias)}`,{label:p.label,providerModel:p.providerModel,efforts:ve(p.efforts),defaultEffort:p.defaultEffort.trim()||void 0,limits:p.limits,capabilities:p.capabilities,contextThreshold:Fe(p),disabled:p.disabled,updatedBy:`dashboard`}),await D(),g(`${p.alias} saved`),m(Pe(p.provider))}catch(e){let t=Ee(e);v(t.length?t:[e.message])}}}async function te(e,t){if(n){v([]),g(``);try{await u(`PATCH`,`/providers/${encodeURIComponent(y)}/models/${encodeURIComponent(e.alias)}`,{disabled:t,updatedBy:`dashboard`}),await D(),g(`${e.alias} ${t?`disabled`:`enabled`}`)}catch(e){let t=Ee(e);v(t.length?t:[e.message])}}}async function ne(e){if(n){v([]),g(``);try{await u(`DELETE`,`/providers/${encodeURIComponent(y)}/models/${encodeURIComponent(e.alias)}`),await D(),g(`${e.alias} removed`)}catch(e){let t=Ee(e);v(t.length?t:[e.message])}}}function O(e){m({provider:y,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 t?(0,J.jsx)(G,{size:`sm`,children:(0,J.jsxs)(U,{className:`text-sm text-muted-foreground`,children:[(0,J.jsxs)(`div`,{className:`mb-1 flex items-center gap-2 font-medium text-foreground`,children:[(0,J.jsx)(d,{className:`size-4`}),`Model catalog`]}),t]})}):(0,J.jsxs)(`section`,{className:`space-y-4`,children:[(0,J.jsxs)(`div`,{className:`flex flex-wrap items-start justify-between gap-3`,children:[(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`h2`,{className:`text-base font-semibold`,children:`Model catalog`}),(0,J.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Add override models, disable unavailable models, or remove custom entries from the provider catalog.`})]}),!n&&(0,J.jsx)(I,{variant:`secondary`,children:`Read only: needs settings:write:provider`})]}),(0,J.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:C.map(e=>(0,J.jsx)(L,{variant:e===y?`default`:`outline`,size:`sm`,onClick:()=>T(e),children:e},e))}),(0,J.jsxs)(G,{size:`sm`,children:[(0,J.jsxs)(H,{children:[(0,J.jsx)(W,{className:`text-sm`,children:`Add or edit model`}),(0,J.jsx)(V,{children:(0,J.jsxs)(I,{variant:`outline`,className:`gap-1`,children:[(0,J.jsx)(a,{className:`size-3.5`}),`Server runtime`]})})]}),(0,J.jsxs)(U,{className:`space-y-3`,children:[(0,J.jsxs)(`div`,{className:`grid gap-3 md:grid-cols-2`,children:[(0,J.jsx)(Y,{label:`Alias`,children:(0,J.jsx)(R,{value:p.alias,disabled:!n,placeholder:`nightly`,onChange:e=>w({alias:e.target.value.trim()})})}),(0,J.jsx)(Y,{label:`Label`,children:(0,J.jsx)(R,{value:p.label,disabled:!n,placeholder:`Nightly Codex`,onChange:e=>w({label:e.target.value})})}),(0,J.jsx)(Y,{label:`Provider model`,children:(0,J.jsx)(R,{value:p.providerModel,disabled:!n,placeholder:`codex-nightly`,onChange:e=>w({providerModel:e.target.value})})}),(0,J.jsx)(Y,{label:`Efforts`,children:(0,J.jsx)(R,{value:p.efforts,disabled:!n,placeholder:`low, medium, high`,onChange:e=>w({efforts:e.target.value})})}),(0,J.jsx)(Y,{label:`Default effort`,children:(0,J.jsx)(R,{value:p.defaultEffort,disabled:!n,placeholder:`medium`,onChange:e=>w({defaultEffort:e.target.value})})}),(0,J.jsx)(Y,{label:`Self compact utilization`,children:(0,J.jsx)(R,{value:p.selfCompactUtilization,disabled:!n,placeholder:`0.80`,inputMode:`decimal`,onChange:e=>w({selfCompactUtilization:e.target.value})})}),(0,J.jsx)(Y,{label:`Warn utilization`,children:(0,J.jsx)(R,{value:p.warnUtilization,disabled:!n,placeholder:`default: self - 0.10`,inputMode:`decimal`,onChange:e=>w({warnUtilization:e.target.value})})}),(0,J.jsx)(Y,{label:`Hard backstop utilization`,children:(0,J.jsx)(R,{value:p.hardBackstopUtilization,disabled:!n,placeholder:`0.90`,inputMode:`decimal`,onChange:e=>w({hardBackstopUtilization:e.target.value})})}),(0,J.jsxs)(`div`,{className:`flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3`,children:[(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`div`,{className:`text-sm font-medium`,children:`Disabled`}),(0,J.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:`Keep visible but unavailable for new launches.`})]}),(0,J.jsx)(z,{checked:p.disabled,disabled:!n,onCheckedChange:e=>w({disabled:e})})]})]}),(0,J.jsxs)(L,{onClick:ee,disabled:!n||!p.alias||!p.label||!p.providerModel,children:[(0,J.jsx)(r,{className:`size-4`}),`Save model`]})]})]}),(0,J.jsxs)(`div`,{className:`space-y-2`,children:[S&&S.models.length===0&&(0,J.jsx)(G,{size:`sm`,children:(0,J.jsx)(U,{className:`text-sm text-muted-foreground`,children:`No models in this provider catalog yet.`})}),S?.models.map(e=>(0,J.jsx)(G,{size:`sm`,children:(0,J.jsxs)(U,{className:`flex flex-wrap items-center justify-between gap-3`,children:[(0,J.jsxs)(`div`,{className:`min-w-0`,children:[(0,J.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,J.jsx)(`span`,{className:`font-medium`,children:e.label}),(0,J.jsx)(`code`,{className:`rounded bg-muted px-1.5 py-0.5 font-mono text-xs`,children:e.alias}),e.disabled&&(0,J.jsx)(I,{variant:`secondary`,children:`Disabled`})]}),(0,J.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 ${Le(e)}`]})]}),(0,J.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,J.jsxs)(L,{variant:`outline`,size:`sm`,onClick:()=>O(e),children:[(0,J.jsx)(f,{className:`size-4`}),`Edit`]}),(0,J.jsxs)(L,{variant:`outline`,size:`sm`,disabled:!n,onClick:()=>void te(e,!e.disabled),children:[e.disabled?(0,J.jsx)(l,{className:`size-4`}):(0,J.jsx)(E,{className:`size-4`}),e.disabled?`Enable`:`Disable`]}),(0,J.jsxs)(L,{variant:`outline`,size:`sm`,disabled:!n,onClick:()=>void ne(e),children:[(0,J.jsx)(b,{className:`size-4`}),`Remove`]})]})]})},e.alias))]}),_.length>0&&(0,J.jsx)(`div`,{className:`rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive`,children:(0,J.jsx)(`ul`,{className:`list-disc space-y-1 pl-5`,children:_.map(e=>(0,J.jsx)(`li`,{children:e},e))})}),h&&(0,J.jsxs)(`p`,{className:`flex items-center gap-1 text-sm text-emerald-500`,children:[(0,J.jsx)(x,{className:`size-4`}),h]})]})}function Pe(e){return{provider:e,alias:``,label:``,providerModel:``,efforts:``,defaultEffort:``,selfCompactUtilization:``,warnUtilization:``,hardBackstopUtilization:``,disabled:!1}}function Fe(e){let t=Ie(e.selfCompactUtilization,`Self compact utilization`),n=Ie(e.warnUtilization,`Warn utilization`),r=Ie(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 Ie(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 Le(e){if(e.contextThreshold)return`self ${Re(e.contextThreshold.selfCompactUtilization)}, warn ${Re(e.contextThreshold.warnUtilization??Math.max(0,e.contextThreshold.selfCompactUtilization-.1))}`;let t=re(e.limits?.contextWindowTokens?.value);return`derived self ${Re(t.selfCompactUtilization)}, warn ${Re(t.warnUtilization)}`}function Re(e){return`${Math.round(e*100)}%`}var ze=5,Be=15,Ve={claude:`Claude`,codex:`Codex`};function He(e){return Math.round(e/6e4)}function Ue(e){return`${He(e)} min`}function We({canWrite:e}){let[t,n]=(0,K.useState)(null),[r,i]=(0,K.useState)(``),[a,o]=(0,K.useState)(``),[s,c]=(0,K.useState)(null);(0,K.useEffect)(()=>{let e=!1;return(async()=>{try{let t=await u(`GET`,`/providers/quota-config`);e||n(t)}catch(t){e||i(t.message)}})(),()=>{e=!0}},[]);async function l(e,t){n(n=>({...n??{},[e]:t})),o(``),c(e);try{let r=await u(`PUT`,`/providers/${e}/quota-config`,t);n(t=>({...t??{},[e]:r}))}catch(t){o(`${Ve[e]??e}: ${t.message}`)}finally{c(null)}}let d=t?Object.keys(t).sort():[];return(0,J.jsxs)(`section`,{className:`space-y-4`,children:[(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`h2`,{className:`text-base font-semibold`,children:`Quota`}),(0,J.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[`Per-provider quota collection and display. `,(0,J.jsx)(`strong`,{children:`Enabled`}),` governs collection (disabled stops polling — no API calls);`,(0,J.jsx)(`strong`,{children:` Show in widget`}),` governs display only.`]})]}),r&&(0,J.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,J.jsx)(_,{className:`mt-0.5 size-4`}),(0,J.jsx)(`span`,{children:r})]}),a&&(0,J.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,J.jsx)(_,{className:`mt-0.5 size-4`}),(0,J.jsx)(`span`,{children:a})]}),!t&&!r&&(0,J.jsx)(G,{size:`sm`,children:(0,J.jsxs)(U,{className:`flex items-center gap-2 text-sm text-muted-foreground`,children:[(0,J.jsx)(y,{className:`size-4 animate-spin`}),`Loading quota config…`]})}),d.map(r=>{let i=t[r],a=!e||s===r;return(0,J.jsxs)(G,{size:`sm`,children:[(0,J.jsxs)(H,{children:[(0,J.jsxs)(W,{className:`flex items-center gap-2 text-sm`,children:[(0,J.jsx)(C,{className:`size-4`}),Ve[r]??r,s===r&&(0,J.jsx)(y,{className:`size-3 animate-spin text-muted-foreground`})]}),(0,J.jsxs)(B,{className:`text-xs`,children:[i.enabled?`Polled every ${Ue(i.pollIntervalMs)}`:`Collection disabled`,i.enabled&&!i.showInWidget?` · hidden from widget`:``]})]}),(0,J.jsxs)(U,{className:`space-y-4`,children:[(0,J.jsxs)(`div`,{className:`flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3`,children:[(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`div`,{className:`text-sm font-medium`,children:`Enabled`}),(0,J.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,J.jsx)(z,{checked:i.enabled,disabled:a,onCheckedChange:e=>void l(r,{...i,enabled:e})})]}),(0,J.jsxs)(`div`,{className:`rounded-md border bg-muted/20 p-3 space-y-2`,children:[(0,J.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,J.jsx)(`div`,{className:`text-sm font-medium`,children:`Polling interval`}),(0,J.jsx)(I,{variant:`outline`,className:`tabular-nums`,children:Ue(i.pollIntervalMs)})]}),(0,J.jsx)(`input`,{type:`range`,min:ze,max:Be,step:1,value:He(i.pollIntervalMs),disabled:a||!i.enabled,onChange:e=>{let t=Number(e.target.value)*6e4;n(e=>({...e??{},[r]:{...i,pollIntervalMs:t}}))},onPointerUp:e=>void l(r,{...i,pollIntervalMs:Number(e.target.value)*6e4}),onKeyUp:e=>void l(r,{...i,pollIntervalMs:Number(e.target.value)*6e4}),className:`w-full accent-primary disabled:opacity-50`}),(0,J.jsxs)(`div`,{className:`flex justify-between text-[10px] text-muted-foreground`,children:[(0,J.jsxs)(`span`,{children:[ze,` min`]}),(0,J.jsxs)(`span`,{children:[Be,` min`]})]})]}),(0,J.jsxs)(`div`,{className:`flex items-center justify-between gap-3 rounded-md border bg-muted/20 p-3`,children:[(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`div`,{className:`text-sm font-medium`,children:`Show in quota widget`}),(0,J.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:`Display only. Off hides this provider from the dashboard widget; collection continues if enabled.`})]}),(0,J.jsx)(z,{checked:i.showInWidget,disabled:a,onCheckedChange:e=>void l(r,{...i,showInWidget:e})})]})]})]},r)})]})}function Ge({message:e}){return(0,J.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,J.jsx)(_,{className:`mt-0.5 size-4 shrink-0`}),(0,J.jsx)(`span`,{children:e})]})}var Ke=ie(),X={cautionAt:.15,avoidLargeAt:.5,hardAvoidAt:1},qe=.99,Je=.5;function Z(e,t){return((e??t)*100).toFixed(0)}function Q(e){let t=Number(e);return!Number.isFinite(t)||t<0||t>100?null:t/100}function Ye({policy:e,canWrite:n,onPolicy:r}){let i=e.quotaBands,a=e.providerQuota??{},[o,s]=(0,K.useState)(Z(i?.cautionAt,X.cautionAt)),[c,l]=(0,K.useState)(Z(i?.avoidLargeAt,X.avoidLargeAt)),[d,f]=(0,K.useState)(Z(i?.hardAvoidAt,X.hardAvoidAt)),[p,m]=(0,K.useState)(()=>{let e={};for(let t of Ke){let n=a[t]??{};e[t]={backstop:Z(n.hardBackstopUtilization,qe),floor:Z(n.burnPenaltyUtilizationFloor,Je)}}return e}),[h,g]=(0,K.useState)(!1),[_,v]=(0,K.useState)(``),[b,x]=(0,K.useState)(!1),[S,C]=(0,K.useState)(``);async function w(){let t=Q(o),n=Q(c),i=Q(d);if(t===null){C(`Caution threshold must be 0–100%.`);return}if(n===null){C(`Avoid-large threshold must be 0–100%.`);return}if(i===null){C(`Hard-avoid threshold must be 0–100%.`);return}if(t>=n){C(`Caution must be less than avoid-large.`);return}if(n>=i){C(`Avoid-large must be less than hard-avoid.`);return}let a={};for(let e of Ke){let t=p[e],n=Q(t.backstop),r=Q(t.floor);if(n===null){C(`${A(e)}: hard-backstop must be 0–100%.`);return}if(r===null){C(`${A(e)}: burn-penalty floor must be 0–100%.`);return}a[e]={hardBackstopUtilization:n,burnPenaltyUtilizationFloor:r}}C(``),g(!0),v(``),x(!1);try{r(await u(`PUT`,`/routing-policy`,{...e,quotaBands:{cautionAt:t,avoidLargeAt:n,hardAvoidAt:i},providerQuota:a})),x(!0),setTimeout(()=>x(!1),2e3)}catch(e){v(e.message)}finally{g(!1)}}function T(e,t){m(n=>({...n,[e]:{...n[e],...t}})),C(``),x(!1)}function E(){C(``),x(!1)}return(0,J.jsxs)(G,{size:`sm`,children:[(0,J.jsxs)(H,{children:[(0,J.jsx)(W,{className:`text-sm`,children:`Quota thresholds`}),(0,J.jsx)(B,{className:`text-xs`,children:`Band cutoffs govern when the orchestrator starts penalising or blocking high-quota providers. Values are utilization percentages (0–100).`})]}),(0,J.jsxs)(U,{className:`space-y-4`,children:[(_||S)&&(0,J.jsx)(Ge,{message:_||S}),(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`div`,{className:`mb-2 text-xs font-medium text-muted-foreground uppercase tracking-wide`,children:`Band cutoffs`}),(0,J.jsx)(Xe,{caution:Number(o),avoidLarge:Number(c),hardAvoid:Number(d)}),(0,J.jsxs)(`div`,{className:`mt-3 grid gap-3 sm:grid-cols-3`,children:[(0,J.jsx)($,{label:`Caution at`,hint:`Default: ${(X.cautionAt*100).toFixed(0)}%`,value:o,disabled:!n||h,onChange:e=>{s(e),E()}}),(0,J.jsx)($,{label:`Avoid-large at`,hint:`Default: ${(X.avoidLargeAt*100).toFixed(0)}%`,value:c,disabled:!n||h,onChange:e=>{l(e),E()}}),(0,J.jsx)($,{label:`Hard-avoid at`,hint:`Default: ${(X.hardAvoidAt*100).toFixed(0)}%`,value:d,disabled:!n||h,onChange:e=>{f(e),E()}})]})]}),Ke.map(e=>{let t=p[e];return(0,J.jsxs)(`div`,{children:[(0,J.jsxs)(`div`,{className:`mb-2 text-xs font-medium text-muted-foreground uppercase tracking-wide`,children:[A(e),` overrides`]}),(0,J.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,J.jsx)($,{label:`Hard-backstop utilization`,hint:`Provider blocked above this. Default: ${(qe*100).toFixed(0)}%`,value:t.backstop,disabled:!n||h,onChange:t=>T(e,{backstop:t})}),(0,J.jsx)($,{label:`Burn-penalty floor`,hint:`Penalties suppressed below this. Default: ${(Je*100).toFixed(0)}%`,value:t.floor,disabled:!n||h,onChange:t=>T(e,{floor:t})})]})]},e)}),n&&(0,J.jsxs)(L,{size:`sm`,onClick:()=>void w(),disabled:h,children:[h?(0,J.jsx)(y,{className:`size-4 animate-spin`}):(0,J.jsx)(t,{className:`size-4`}),b?`Saved`:`Save thresholds`]})]})]})}function Xe({caution:e,avoidLarge:t,hardAvoid:n}){let r=e=>Math.max(0,Math.min(100,Number.isFinite(e)?e:0)),i=r(e),a=Math.max(i,r(t)),o=Math.max(a,r(n)),s=e=>`${e.toFixed(0)}%`,c=[{key:`normal`,label:`normal`,color:`bg-emerald-500`,from:0,to:i,range:`0–${s(i)}`},{key:`caution`,label:`caution`,color:`bg-amber-500`,from:i,to:a,range:`${s(i)}–${s(a)}`},{key:`avoid-large`,label:`avoid large`,color:`bg-orange-500`,from:a,to:o,range:`${s(a)}–${s(o)}`},{key:`hard-avoid`,label:`hard avoid`,color:`bg-red-500`,from:o,to:100,range:`≥ ${s(o)}`}];return(0,J.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,J.jsx)(`div`,{className:`flex h-2.5 overflow-hidden rounded-full bg-muted`,role:`img`,"aria-label":`Quota penalty bands from 0 to 100 percent`,children:c.map(e=>(0,J.jsx)(`div`,{className:p(e.color,`transition-[width] duration-300`),style:{width:`${e.to-e.from}%`},title:`${e.label} · ${e.range}`},e.key))}),(0,J.jsx)(`div`,{className:`flex flex-wrap gap-x-3 gap-y-1 text-[10px] text-muted-foreground`,children:c.map(e=>(0,J.jsxs)(`span`,{className:`flex items-center gap-1`,children:[(0,J.jsx)(`span`,{className:p(`size-2 shrink-0 rounded-full`,e.color)}),e.label,` `,(0,J.jsx)(`span`,{className:`tabular-nums text-foreground/70`,children:e.range})]},e.key))})]})}function $({label:e,hint:t,value:n,disabled:r,onChange:i}){return(0,J.jsxs)(`label`,{className:`space-y-1`,children:[(0,J.jsx)(`span`,{className:`text-[10px] font-medium text-muted-foreground`,children:e}),(0,J.jsxs)(`div`,{className:`relative`,children:[(0,J.jsx)(R,{value:n,onChange:e=>i(e.target.value),disabled:r,className:`h-8 pr-6 text-xs tabular-nums`}),(0,J.jsx)(`span`,{className:`pointer-events-none absolute inset-y-0 right-2.5 flex items-center text-xs text-muted-foreground`,children:`%`})]}),(0,J.jsx)(`span`,{className:`text-[10px] text-muted-foreground`,children:t})]})}function Ze(){let[e,t]=(0,K.useState)(null),[n,r]=(0,K.useState)(!1),[i,a]=(0,K.useState)(``),[o,s]=(0,K.useState)(!1),[d,f]=(0,K.useState)(!1);async function m(){if(!d){r(!0),a(``);try{let[e,n]=await Promise.all([u(`GET`,`/routing-policy`),u(`GET`,`/agent-profiles/coordinator`).catch(()=>null)]);t({policy:e,profile:n}),f(!0)}catch(e){a(e.message)}finally{r(!1)}}}async function h(){f(!1),r(!0),a(``);try{let[e,n]=await Promise.all([u(`GET`,`/routing-policy`),u(`GET`,`/agent-profiles/coordinator`).catch(()=>null)]);t({policy:e,profile:n}),f(!0)}catch(e){a(e.message)}finally{r(!1)}}function g(){let e=!o;s(e),e&&!d&&m()}return(0,J.jsx)(G,{size:`sm`,children:(0,J.jsxs)(U,{className:`space-y-3`,children:[(0,J.jsxs)(`button`,{type:`button`,className:`flex w-full items-center gap-2 text-left`,onClick:g,children:[(0,J.jsx)(l,{className:`size-4 text-muted-foreground`}),(0,J.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,J.jsx)(`div`,{className:`text-sm font-semibold`,children:`What your coordinator knows`}),(0,J.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:`Active routing policy + coordinator profile instructions (read-only)`})]}),o?(0,J.jsx)(ee,{className:`size-4 shrink-0 text-muted-foreground`}):(0,J.jsx)(te,{className:`size-4 shrink-0 text-muted-foreground`})]}),o&&(0,J.jsxs)(`div`,{className:`space-y-4 pt-1`,children:[(0,J.jsx)(`div`,{className:`flex justify-end`,children:(0,J.jsxs)(L,{variant:`outline`,size:`sm`,onClick:()=>void h(),disabled:n,children:[(0,J.jsx)(c,{className:p(`size-3.5`,n&&`animate-spin`)}),`Refresh`]})}),i&&(0,J.jsx)(Ge,{message:i}),n&&!e&&(0,J.jsxs)(`div`,{className:`flex items-center gap-2 text-xs text-muted-foreground py-2`,children:[(0,J.jsx)(y,{className:`size-3.5 animate-spin`}),`Loading…`]}),e&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(Qe,{policy:e.policy}),e.profile?(0,J.jsx)(et,{profile:e.profile}):(0,J.jsx)(`div`,{className:`text-xs text-muted-foreground italic`,children:`Coordinator profile not found.`})]})]})]})})}function Qe({policy:e}){let t=e.quotaBands,n=e.providerQuota??{};return(0,J.jsxs)(`div`,{className:`space-y-2`,children:[(0,J.jsx)(`div`,{className:`text-xs font-semibold text-muted-foreground uppercase tracking-wide`,children:`Active routing policy`}),e.rules.length===0?(0,J.jsx)(`div`,{className:`text-xs text-muted-foreground italic`,children:`No rules — coordinators use their own heuristics.`}):(0,J.jsxs)(`div`,{className:`overflow-hidden rounded-md border border-border text-xs`,children:[(0,J.jsxs)(`div`,{className:`grid grid-cols-[1.5rem_minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)] gap-px bg-border text-[10px] font-medium text-muted-foreground uppercase tracking-wide`,children:[(0,J.jsx)(`div`,{className:`bg-muted/40 px-2 py-1.5`,children:`#`}),(0,J.jsx)(`div`,{className:`bg-muted/40 px-2 py-1.5`,children:`Match`}),(0,J.jsx)(`div`,{className:`bg-muted/40 px-2 py-1.5`,children:`Target`}),(0,J.jsx)(`div`,{className:`bg-muted/40 px-2 py-1.5`,children:`Status`})]}),e.rules.map((e,t)=>(0,J.jsxs)(`div`,{className:p(`grid grid-cols-[1.5rem_minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)] gap-px bg-border`,e.enabled===!1&&`opacity-50`),children:[(0,J.jsx)(`div`,{className:`bg-card px-2 py-1.5 text-muted-foreground tabular-nums`,children:t+1}),(0,J.jsxs)(`div`,{className:`bg-card px-2 py-1.5`,children:[e.label&&(0,J.jsx)(`div`,{className:`font-medium`,children:e.label}),e.match.taskType&&(0,J.jsxs)(`div`,{className:`font-mono`,children:[`task: `,e.match.taskType]}),e.match.capability&&(0,J.jsxs)(`div`,{className:`font-mono`,children:[`cap: `,e.match.capability]})]}),(0,J.jsxs)(`div`,{className:`bg-card px-2 py-1.5`,children:[(0,J.jsx)(`span`,{className:`font-medium`,children:e.target.provider}),e.target.model&&(0,J.jsxs)(`span`,{className:`text-muted-foreground`,children:[` / `,e.target.model]}),e.target.effort&&(0,J.jsxs)(`span`,{className:`text-muted-foreground`,children:[` (`,e.target.effort,`)`]})]}),(0,J.jsx)(`div`,{className:`bg-card px-2 py-1.5`,children:e.enabled===!1?(0,J.jsx)(`span`,{className:`text-muted-foreground`,children:`disabled`}):(0,J.jsx)(`span`,{className:`text-emerald-500`,children:`active`})})]},t))]}),(t||Object.keys(n).length>0)&&(0,J.jsxs)(`div`,{className:`rounded-md border border-border bg-muted/10 px-3 py-2 text-xs space-y-1`,children:[t&&(0,J.jsxs)(`div`,{className:`flex flex-wrap gap-x-4 gap-y-0.5`,children:[t.cautionAt!==void 0&&(0,J.jsxs)(`span`,{children:[`caution ≥ `,(t.cautionAt*100).toFixed(0),`%`]}),t.avoidLargeAt!==void 0&&(0,J.jsxs)(`span`,{children:[`avoid-large ≥ `,(t.avoidLargeAt*100).toFixed(0),`%`]}),t.hardAvoidAt!==void 0&&(0,J.jsxs)(`span`,{children:[`hard-avoid ≥ `,(t.hardAvoidAt*100).toFixed(0),`%`]})]}),Object.entries(n).map(([e,t])=>(0,J.jsxs)(`div`,{className:`flex flex-wrap gap-x-4 gap-y-0.5 text-muted-foreground`,children:[(0,J.jsx)(`span`,{className:`font-medium text-foreground`,children:A(e)}),t?.hardBackstopUtilization!==void 0&&(0,J.jsxs)(`span`,{children:[`backstop: `,(t.hardBackstopUtilization*100).toFixed(0),`%`]}),t?.burnPenaltyUtilizationFloor!==void 0&&(0,J.jsxs)(`span`,{children:[`floor: `,(t.burnPenaltyUtilizationFloor*100).toFixed(0),`%`]})]},e))]})]})}function $e({text:e,index:t}){return(0,J.jsxs)(`div`,{className:`relative max-h-72 overflow-y-auto rounded-md border border-border bg-muted/20`,children:[t!==void 0&&(0,J.jsxs)(`span`,{className:`sticky top-0 float-right m-1.5 rounded bg-muted px-1.5 py-0.5 text-[9px] font-medium tabular-nums text-muted-foreground`,children:[`#`,t]}),(0,J.jsx)(`pre`,{className:`whitespace-pre-wrap break-words px-3 py-2.5 font-sans text-[11px] leading-relaxed text-foreground/90`,children:e})]})}function et({profile:e}){return(0,J.jsxs)(`div`,{className:`space-y-2`,children:[(0,J.jsxs)(`div`,{className:`text-xs font-semibold text-muted-foreground uppercase tracking-wide`,children:[`Coordinator profile instructions`,(0,J.jsx)(I,{variant:`secondary`,className:`ml-2 text-[10px]`,children:e.name}),e.builtIn&&(0,J.jsx)(I,{variant:`outline`,className:`ml-1 text-[10px]`,children:`built-in`})]}),e.description&&(0,J.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:e.description}),(0,J.jsxs)(`div`,{className:`flex flex-wrap gap-2 text-[10px]`,children:[(0,J.jsxs)(I,{variant:`outline`,children:[`base: `,e.base]}),(0,J.jsxs)(I,{variant:`outline`,children:[`repo: `,e.instructions.repoInstructions]}),(0,J.jsxs)(I,{variant:`outline`,children:[`global: `,e.instructions.globalInstructions]}),e.provider&&(0,J.jsxs)(I,{variant:`outline`,children:[`provider: `,e.provider]})]}),e.instructions.system&&(0,J.jsxs)(`div`,{className:`space-y-1`,children:[(0,J.jsx)(`div`,{className:`text-[10px] font-medium text-muted-foreground uppercase tracking-wide`,children:`System prompt`}),(0,J.jsx)($e,{text:e.instructions.system})]}),e.instructions.append.length>0&&(0,J.jsxs)(`div`,{className:`space-y-2`,children:[(0,J.jsxs)(`div`,{className:`text-[10px] font-medium text-muted-foreground uppercase tracking-wide`,children:[`Appended instructions (`,e.instructions.append.length,`)`]}),e.instructions.append.map((e,t)=>(0,J.jsx)($e,{text:e,index:t+1},t))]}),e.instructions.append.length===0&&!e.instructions.system&&(0,J.jsx)(`div`,{className:`text-xs text-muted-foreground italic`,children:`No instruction blocks defined.`})]})}var tt=ie();function nt(){return{label:``,matchTaskType:``,matchCapability:``,targetProvider:tt[0]??``,targetModel:``,targetEffort:``,enabled:!0}}function rt(e){return{label:e.label??``,matchTaskType:e.match.taskType??``,matchCapability:e.match.capability??``,targetProvider:e.target.provider,targetModel:e.target.model??``,targetEffort:e.target.effort??``,enabled:e.enabled!==!1}}function it(e){return{...e.label.trim()?{label:e.label.trim()}:{},match:{...e.matchTaskType.trim()?{taskType:e.matchTaskType.trim()}:{},...e.matchCapability.trim()?{capability:e.matchCapability.trim()}:{}},target:{provider:e.targetProvider,...e.targetModel.trim()?{model:e.targetModel.trim()}:{},...e.targetEffort.trim()?{effort:e.targetEffort.trim()}:{}},enabled:e.enabled}}function at(e){return!e.matchTaskType.trim()&&!e.matchCapability.trim()?`At least one match criterion (task type or capability) is required.`:null}function ot({message:e}){return(0,J.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,J.jsx)(_,{className:`mt-0.5 size-4 shrink-0`}),(0,J.jsx)(`span`,{children:e})]})}function st({canWrite:e}){let[t,n]=(0,K.useState)(null),[r,i]=(0,K.useState)(!1),[a,o]=(0,K.useState)(``),[s,l]=(0,K.useState)(!1);!s&&!r&&!a&&(i(!0),(async()=>{try{n(await u(`GET`,`/routing-policy`)),l(!0)}catch(e){o(e.message)}finally{i(!1)}})());async function d(){i(!0),o(``);try{n(await u(`GET`,`/routing-policy`)),l(!0)}catch(e){o(e.message)}finally{i(!1)}}return(0,J.jsxs)(`div`,{className:`space-y-6`,children:[(0,J.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`h2`,{className:`text-base font-semibold`,children:`Routing`}),(0,J.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Declarative rules mapping task types and capabilities to providers. Rules are advisory — coordinators apply them; explicit per-spawn arguments always take precedence.`})]}),(0,J.jsxs)(L,{variant:`outline`,size:`sm`,onClick:()=>void d(),disabled:r,children:[(0,J.jsx)(c,{className:p(`size-4`,r&&`animate-spin`)}),`Refresh`]})]}),a&&(0,J.jsx)(ot,{message:a}),r&&!t&&(0,J.jsx)(G,{size:`sm`,children:(0,J.jsxs)(U,{className:`flex items-center gap-2 text-sm text-muted-foreground`,children:[(0,J.jsx)(y,{className:`size-4 animate-spin`}),`Loading routing policy…`]})}),t&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(ct,{policy:t,canWrite:e,onPolicy:n}),(0,J.jsx)(Ye,{policy:t,canWrite:e,onPolicy:n})]}),(0,J.jsx)(Ze,{})]})}function ct({policy:e,canWrite:t,onPolicy:n}){let[i,a]=(0,K.useState)(!1),[o,s]=(0,K.useState)(``),[c,l]=(0,K.useState)(!1),[d,f]=(0,K.useState)(nt),[p,m]=(0,K.useState)(``),[h,g]=(0,K.useState)(null),[_,v]=(0,K.useState)(nt),[b,x]=(0,K.useState)(``);async function C(e){a(!0),s(``);try{n(await u(`PUT`,`/routing-policy`,e))}catch(e){s(e.message)}finally{a(!1)}}function w(t,n){let r=[...e.rules],i=t+n;i<0||i>=r.length||([r[t],r[i]]=[r[i],r[t]],C({...e,rules:r}))}function T(t){let n=e.rules.map((e,n)=>n===t?{...e,enabled:e.enabled===!1}:e);C({...e,rules:n})}function E(t){C({...e,rules:e.rules.filter((e,n)=>n!==t)})}function D(){f(nt()),m(``),l(!0)}function ee(){l(!1),m(``)}function te(){let t=at(d);if(t){m(t);return}l(!1),C({...e,rules:[...e.rules,it(d)]})}function ne(t){g(t),v(rt(e.rules[t])),x(``)}function O(){g(null),x(``)}function k(){if(h===null)return;let t=at(_);if(t){x(t);return}let n=e.rules.map((e,t)=>t===h?it(_):e);g(null),C({...e,rules:n})}return(0,J.jsxs)(G,{size:`sm`,children:[(0,J.jsxs)(H,{children:[(0,J.jsxs)(W,{className:`flex items-center gap-2 text-sm`,children:[(0,J.jsx)(S,{className:`size-4`}),`Rules`,(0,J.jsxs)(I,{variant:`outline`,className:`ml-auto text-[10px]`,children:[e.rules.length,` rule`,e.rules.length===1?``:`s`]}),i&&(0,J.jsx)(y,{className:`size-3 animate-spin text-muted-foreground`})]}),(0,J.jsx)(B,{className:`text-xs`,children:`Evaluated in order — first matching enabled rule wins. Rules are advisory; explicit spawn arguments override them.`})]}),(0,J.jsxs)(U,{className:`space-y-2`,children:[o&&(0,J.jsx)(ot,{message:o}),e.rules.length===0&&!c&&(0,J.jsx)(`div`,{className:`rounded-md border border-dashed border-border py-6 text-center text-xs text-muted-foreground`,children:`No rules — coordinators fall back to their own heuristics.`}),e.rules.map((n,r)=>h===r?(0,J.jsx)(ut,{form:_,error:b,onChange:v,onSave:k,onCancel:O},r):(0,J.jsx)(lt,{rule:n,idx:r,total:e.rules.length,canWrite:t,saving:i,onMoveUp:()=>w(r,-1),onMoveDown:()=>w(r,1),onToggle:()=>T(r),onEdit:()=>ne(r),onRemove:()=>E(r)},r)),c&&(0,J.jsx)(ut,{form:d,error:p,onChange:f,onSave:te,onCancel:ee,isNew:!0}),t&&!c&&h===null&&(0,J.jsxs)(L,{variant:`outline`,size:`sm`,className:`w-full gap-1`,onClick:D,disabled:i,children:[(0,J.jsx)(r,{className:`size-4`}),`Add rule`]})]})]})}function lt({rule:e,idx:t,total:n,canWrite:r,saving:a,onMoveUp:o,onMoveDown:c,onToggle:l,onEdit:u,onRemove:d}){return(0,J.jsxs)(`div`,{className:p(`group flex items-start gap-3 rounded-md border bg-muted/20 p-3`,e.enabled===!1&&`opacity-60`),children:[(0,J.jsxs)(`div`,{className:`flex flex-col items-center gap-0.5 pt-0.5`,children:[(0,J.jsx)(`button`,{type:`button`,title:`Move up`,onClick:o,disabled:!r||a||t===0,className:`rounded p-0.5 text-muted-foreground hover:bg-accent hover:text-foreground disabled:pointer-events-none disabled:opacity-30`,children:(0,J.jsx)(i,{className:`size-3.5`})}),(0,J.jsx)(`button`,{type:`button`,title:`Move down`,onClick:c,disabled:!r||a||t===n-1,className:`rounded p-0.5 text-muted-foreground hover:bg-accent hover:text-foreground disabled:pointer-events-none disabled:opacity-30`,children:(0,J.jsx)(s,{className:`size-3.5`})})]}),(0,J.jsxs)(`div`,{className:`min-w-0 flex-1 space-y-1`,children:[(0,J.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,J.jsxs)(`span`,{className:`text-[10px] tabular-nums text-muted-foreground`,children:[`#`,t+1]}),e.label&&(0,J.jsx)(`span`,{className:`text-xs font-medium`,children:e.label}),(0,J.jsx)(I,{variant:`outline`,className:`text-[10px]`,children:e.target.provider}),e.target.model&&(0,J.jsx)(I,{variant:`outline`,className:`text-[10px] font-mono`,children:e.target.model}),e.target.effort&&(0,J.jsx)(I,{variant:`outline`,className:`text-[10px]`,children:e.target.effort})]}),(0,J.jsxs)(`div`,{className:`flex flex-wrap gap-x-3 gap-y-0.5 text-[10px] text-muted-foreground`,children:[e.match.taskType&&(0,J.jsxs)(`span`,{children:[`task-type: `,(0,J.jsx)(`span`,{className:`font-mono text-foreground`,children:e.match.taskType})]}),e.match.capability&&(0,J.jsxs)(`span`,{children:[`capability: `,(0,J.jsx)(`span`,{className:`font-mono text-foreground`,children:e.match.capability})]})]})]}),(0,J.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1 opacity-70 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100`,children:[(0,J.jsx)(z,{checked:e.enabled!==!1,disabled:!r||a,onCheckedChange:l,title:e.enabled===!1?`Enable rule`:`Disable rule`}),r&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`button`,{type:`button`,title:`Edit`,onClick:u,disabled:a,className:`rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground disabled:pointer-events-none`,children:(0,J.jsxs)(`svg`,{className:`size-3.5`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:2,children:[(0,J.jsx)(`path`,{d:`M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7`}),(0,J.jsx)(`path`,{d:`M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z`})]})}),(0,J.jsx)(`button`,{type:`button`,title:`Remove`,onClick:d,disabled:a,className:`rounded p-1 text-destructive hover:bg-destructive/10 disabled:pointer-events-none`,children:(0,J.jsx)(b,{className:`size-3.5`})})]})]})]})}function ut({form:e,error:n,onChange:r,onSave:i,onCancel:a,isNew:o}){function s(t){r({...e,...t})}return(0,J.jsxs)(`div`,{className:`rounded-md border border-primary/30 bg-primary/5 p-3 space-y-3`,children:[(0,J.jsx)(`div`,{className:`text-xs font-semibold text-muted-foreground uppercase tracking-wide`,children:o?`New rule`:`Edit rule`}),(0,J.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,J.jsxs)(`label`,{className:`space-y-1`,children:[(0,J.jsx)(`span`,{className:`text-[10px] font-medium text-muted-foreground`,children:`Label (optional)`}),(0,J.jsx)(R,{value:e.label,onChange:e=>s({label:e.target.value}),placeholder:`e.g. Route GUI tasks to Claude`,className:`h-8 text-xs`})]}),(0,J.jsxs)(`label`,{className:`space-y-1`,children:[(0,J.jsx)(`span`,{className:`text-[10px] font-medium text-muted-foreground`,children:`Target provider`}),(0,J.jsxs)(F,{value:e.targetProvider,onValueChange:e=>s({targetProvider:e}),children:[(0,J.jsx)(M,{className:`h-8 text-xs`,children:(0,J.jsx)(j,{})}),(0,J.jsx)(N,{children:tt.map(e=>(0,J.jsx)(P,{value:e,className:`text-xs`,children:A(e)},e))})]})]})]}),(0,J.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,J.jsxs)(`label`,{className:`space-y-1`,children:[(0,J.jsx)(`span`,{className:`text-[10px] font-medium text-muted-foreground`,children:`Match task-type (prefix)`}),(0,J.jsx)(R,{value:e.matchTaskType,onChange:e=>s({matchTaskType:e.target.value}),placeholder:`e.g. gui, backend, mechanical`,className:`h-8 font-mono text-xs`}),(0,J.jsxs)(`span`,{className:`block text-[10px] leading-snug text-muted-foreground`,children:[`Prefix match — `,(0,J.jsx)(`span`,{className:`font-mono text-foreground`,children:`gui`}),` matches `,(0,J.jsx)(`span`,{className:`font-mono text-foreground`,children:`gui/ux`}),`, `,(0,J.jsx)(`span`,{className:`font-mono text-foreground`,children:`gui/layout`}),`.`]})]}),(0,J.jsxs)(`label`,{className:`space-y-1`,children:[(0,J.jsx)(`span`,{className:`text-[10px] font-medium text-muted-foreground`,children:`Match capability (exact)`}),(0,J.jsx)(R,{value:e.matchCapability,onChange:e=>s({matchCapability:e.target.value}),placeholder:`e.g. code, research, bounded`,className:`h-8 font-mono text-xs`}),(0,J.jsx)(`span`,{className:`block text-[10px] leading-snug text-muted-foreground`,children:`Exact match against the agent's capability tag. Both fields are AND-ed.`})]})]}),(0,J.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,J.jsxs)(`label`,{className:`space-y-1`,children:[(0,J.jsx)(`span`,{className:`text-[10px] font-medium text-muted-foreground`,children:`Model alias (optional)`}),(0,J.jsx)(R,{value:e.targetModel,onChange:e=>s({targetModel:e.target.value}),placeholder:`e.g. opus, gpt-5.4`,className:`h-8 font-mono text-xs`})]}),(0,J.jsxs)(`label`,{className:`space-y-1`,children:[(0,J.jsx)(`span`,{className:`text-[10px] font-medium text-muted-foreground`,children:`Effort (optional)`}),(0,J.jsx)(R,{value:e.targetEffort,onChange:e=>s({targetEffort:e.target.value}),placeholder:`e.g. high, low`,className:`h-8 text-xs`})]})]}),(0,J.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,J.jsx)(z,{checked:e.enabled,onCheckedChange:e=>s({enabled:e})}),(0,J.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`Enabled`})]}),n&&(0,J.jsx)(ot,{message:n}),(0,J.jsxs)(`div`,{className:`flex gap-2`,children:[(0,J.jsxs)(L,{size:`sm`,onClick:i,children:[(0,J.jsx)(t,{className:`size-4`}),o?`Add`:`Save`]}),(0,J.jsx)(L,{size:`sm`,variant:`outline`,onClick:a,children:`Cancel`})]})]})}var dt=`browser`,ft=`models`,pt=`profile`,mt=`routing`,ht=[`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 gt(){if(typeof window>`u`)return``;let e=window.location.hash.replace(/^#/,``);return e.startsWith(`settings/`)?decodeURIComponent(e.slice(9)):``}function _t(e){if(typeof window>`u`)return;let t=new URL(window.location.href);t.hash=`settings/${encodeURIComponent(e)}`,window.history.pushState({},``,t)}function vt(){let[e,t]=(0,K.useState)([]),[n,r]=(0,K.useState)(null),[i,a]=(0,K.useState)([]),[o,s]=(0,K.useState)(()=>gt()),[l,d]=(0,K.useState)(!0),[f,m]=(0,K.useState)(``),[h,v]=(0,K.useState)(``);async function y(){d(!0),m(``),v(``);try{let[e,n,i]=await Promise.all([u(`GET`,`/settings`),u(`GET`,`/tokens/me`),u(`GET`,`/providers`).catch(e=>(v(e.message),{catalog:[]}))]);t(e.settings),r(n),a(i.catalog)}catch(e){m(e.message)}finally{d(!1)}}(0,K.useEffect)(()=>{y()},[]),(0,K.useEffect)(()=>{let e=()=>s(gt());return window.addEventListener(`hashchange`,e),window.addEventListener(`popstate`,e),()=>{window.removeEventListener(`hashchange`,e),window.removeEventListener(`popstate`,e)}},[]);let b=(0,K.useMemo)(()=>fe(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:mt,label:`Routing`,description:`Rules, quota thresholds, coordinator view`,kind:`routing`,settings:[]},{slug:pt,label:`Profile`,description:`Display name and avatar`,kind:`profile`,settings:[]},{slug:dt,label:`Browser`,description:`Local dashboard preferences`,kind:`browser`,settings:[]},{slug:ft,label:`Models`,description:`Provider model catalog`,kind:`models`,settings:[]}],[b]),S=x.find(e=>e.slug===o)??x[0];function C(e){s(e),_t(e)}function w(e){t(t=>t.map(t=>q(t)===q(e)?e:t))}return(0,J.jsxs)(`div`,{className:`space-y-4`,children:[(0,J.jsxs)(`div`,{className:`flex flex-wrap items-start justify-between gap-3`,children:[(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`h1`,{className:`text-lg font-semibold`,children:`Settings`}),(0,J.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Schema-driven Relay settings, browser preferences, and model catalog controls.`})]}),(0,J.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[n&&(0,J.jsxs)(I,{variant:`outline`,className:`gap-1`,children:[(0,J.jsx)(g,{className:`size-3`}),n.kind,`:`,n.actor]}),(0,J.jsxs)(L,{variant:`outline`,size:`sm`,onClick:()=>void y(),disabled:l,children:[(0,J.jsx)(c,{className:p(`size-4`,l&&`animate-spin`)}),`Refresh`]})]})]}),f&&(0,J.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,J.jsx)(_,{className:`mt-0.5 size-4`}),(0,J.jsx)(`span`,{children:f})]}),(0,J.jsxs)(`div`,{className:`grid gap-4 lg:grid-cols-[230px_minmax(0,1fr)]`,children:[(0,J.jsx)(`nav`,{className:`space-y-1 lg:sticky lg:top-4 lg:self-start`,children:x.map(e=>(0,J.jsxs)(`button`,{type:`button`,className:p(`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,J.jsx)(`span`,{className:`block font-medium`,children:e.label}),(0,J.jsx)(`span`,{className:`block truncate text-xs text-muted-foreground`,children:e.description})]},e.slug))}),(0,J.jsx)(`div`,{className:`min-w-0 space-y-4`,children:l&&!e.length?(0,J.jsx)(G,{size:`sm`,children:(0,J.jsx)(U,{className:`text-sm text-muted-foreground`,children:`Loading settings…`})}):S?.kind===`routing`?(0,J.jsx)(st,{canWrite:oe(n?.scopes,`settings:write:routing`)}):S?.kind===`descriptors`?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(De,{group:S.label,settings:S.settings,onSaved:w}),S.label===`Providers`&&(0,J.jsx)(We,{canWrite:oe(n?.scopes,`settings:write:provider`)}),S.label===`Notifications`&&(0,J.jsx)(yt,{})]}):S?.kind===`profile`?(0,J.jsx)(bt,{}):S?.kind===`browser`?(0,J.jsx)(je,{}):(0,J.jsx)(Ne,{catalog:i,error:h,canWrite:oe(n?.scopes,`settings:write:provider`),onCatalog:a})})]})]})}function yt(){let[e,t]=(0,K.useState)(`branch.landed`),[n,r]=(0,K.useState)(`{
|
|
4
|
-
"repoRoot": "/repo"
|
|
5
|
-
}`),[i,a]=(0,K.useState)(null),[o,s]=(0,K.useState)(!1),[c,l]=(0,K.useState)(``);async function d(){s(!0),l(``);try{let t=JSON.parse(n);if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`Scope must be a JSON object`);a((await u(`POST`,`/notifications/preview`,{type:e,scope:t})).preview)}catch(e){a(null),l(e.message)}finally{s(!1)}}return(0,J.jsx)(G,{size:`sm`,children:(0,J.jsxs)(U,{className:`space-y-3`,children:[(0,J.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`h2`,{className:`text-sm font-semibold`,children:`Who gets what`}),(0,J.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Dry-run notification routing without sending.`})]}),(0,J.jsxs)(L,{size:`sm`,onClick:()=>void d(),disabled:o,children:[(0,J.jsx)(S,{className:`size-4`}),`Preview`]})]}),(0,J.jsxs)(`div`,{className:`grid gap-3 md:grid-cols-[240px_minmax(0,1fr)]`,children:[(0,J.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,J.jsx)(`label`,{className:`text-xs font-medium text-muted-foreground`,children:`Type`}),(0,J.jsxs)(F,{value:e,onValueChange:t,children:[(0,J.jsx)(M,{className:`w-full`,children:(0,J.jsx)(j,{})}),(0,J.jsx)(N,{children:ht.map(e=>(0,J.jsx)(P,{value:e,children:e},e))})]})]}),(0,J.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,J.jsx)(`label`,{className:`text-xs font-medium text-muted-foreground`,children:`Scope`}),(0,J.jsx)(ce,{value:n,onChange:e=>r(e.target.value),rows:4,className:`font-mono text-xs`})]})]}),c&&(0,J.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,J.jsx)(_,{className:`mt-0.5 size-3.5`}),(0,J.jsx)(`span`,{children:c})]}),i&&(0,J.jsx)(`div`,{className:`overflow-hidden rounded-md border border-border`,children:i.recipients.length===0?(0,J.jsx)(`div`,{className:`px-3 py-4 text-center text-xs text-muted-foreground`,children:`No recipients`}):i.recipients.map(e=>(0,J.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,J.jsx)(`span`,{className:`truncate font-medium`,children:e.recipient}),(0,J.jsx)(`span`,{className:`truncate font-mono text-muted-foreground`,children:e.matchedRule}),(0,J.jsx)(`span`,{className:`truncate text-muted-foreground`,children:e.reason})]},`${e.recipient}-${e.matchedRule}`))})]})})}function bt(){let e=k(e=>e.fetchUsers),n=(0,K.useRef)(null),[r,i]=(0,K.useState)(null),[a,s]=(0,K.useState)(``),[c,l]=(0,K.useState)(!0),[d,f]=(0,K.useState)(!1),[p,m]=(0,K.useState)(``);async function h(){l(!0),m(``);try{let e=await u(`GET`,`/users/me`);i(e),s(e.displayName||e.handle)}catch(e){m(e.message)}finally{l(!1)}}(0,K.useEffect)(()=>{h()},[]);async function g(){f(!0),m(``);try{let t=await u(`PATCH`,`/users/me`,{displayName:a});i(t),s(t.displayName||t.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);i(n.user),s(n.user.displayName||n.user.handle),await e()}catch(e){m(e.message)}finally{f(!1),n.current&&(n.current.value=``)}}}async function y(){f(!0),m(``);try{i(await u(`DELETE`,`/users/me/avatar`)),await e()}catch(e){m(e.message)}finally{f(!1)}}return(0,J.jsx)(G,{size:`sm`,children:(0,J.jsxs)(U,{className:`space-y-4`,children:[p&&(0,J.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,J.jsx)(_,{className:`mt-0.5 size-4`}),(0,J.jsx)(`span`,{children:p})]}),(0,J.jsxs)(`div`,{className:`flex flex-wrap items-center gap-4`,children:[(0,J.jsx)(le,{user:r??void 0,distinct:!0,className:`size-16 text-lg`}),(0,J.jsxs)(`div`,{className:`min-w-0 flex-1 space-y-2`,children:[(0,J.jsx)(`label`,{className:`block text-xs font-medium text-muted-foreground`,htmlFor:`profile-display-name`,children:`Display name`}),(0,J.jsx)(`input`,{id:`profile-display-name`,className:`h-9 w-full rounded-md border border-input bg-background px-3 text-sm`,value:a,onChange:e=>s(e.target.value),disabled:c||d,maxLength:120})]})]}),(0,J.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,J.jsxs)(L,{size:`sm`,onClick:()=>void g(),disabled:c||d||!a.trim(),children:[(0,J.jsx)(t,{className:`size-4`}),`Save`]}),(0,J.jsxs)(L,{size:`sm`,variant:`outline`,onClick:()=>n.current?.click(),disabled:c||d,children:[(0,J.jsx)(T,{className:`size-4`}),`Upload`]}),(0,J.jsxs)(L,{size:`sm`,variant:`outline`,onClick:()=>void y(),disabled:c||d||!r?.avatarArtifactId,children:[(0,J.jsx)(b,{className:`size-4`}),`Remove`]}),d&&(0,J.jsx)(o,{className:`size-4 animate-pulse text-muted-foreground`}),(0,J.jsx)(`input`,{ref:n,type:`file`,accept:`image/png,image/jpeg,image/gif,image/webp`,className:`hidden`,onChange:e=>void v(e.target.files?.[0])})]})]})})}export{vt as SettingsView};
|
|
6
|
-
//# sourceMappingURL=settings-Dvf_ps1B.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"settings-Dvf_ps1B.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/settings/routing-coordinator-panel.tsx","../../dashboard/src/components/settings/routing-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 ?? ''\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 { useState } from 'react'\nimport type { ProviderQuotaRoutingConfig, QuotaBandThresholds, RoutingPolicy } from 'agent-relay-sdk/types'\nimport type { AgentProfile } from '@/types'\nimport { api } from '@/lib/api'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Badge } from '@/components/ui/badge'\nimport { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'\nimport { AlertCircle, ChevronDown, ChevronRight, Eye, Loader2, RefreshCw, Save } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { getKnownProviderIds, getProviderLabel } from '@/lib/provider-display'\n\nfunction ErrorBanner({ message }: { message: string }) {\n return (\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 shrink-0\" />\n <span>{message}</span>\n </div>\n )\n}\n\nconst PROVIDERS = getKnownProviderIds()\n\nconst BAND_DEFAULTS = { cautionAt: 0.15, avoidLargeAt: 0.5, hardAvoidAt: 1.0 }\nconst BACKSTOP_DEFAULT = 0.99\nconst FLOOR_DEFAULT = 0.5\n\nfunction pctStr(v: number | undefined, def: number) {\n return ((v ?? def) * 100).toFixed(0)\n}\n\nfunction parseFraction(s: string): number | null {\n const n = Number(s)\n if (!Number.isFinite(n) || n < 0 || n > 100) return null\n return n / 100\n}\n\n// ─── QuotaThresholdsEditor ────────────────────────────────────────────────────\n\nexport function QuotaThresholdsEditor({\n policy,\n canWrite,\n onPolicy,\n}: {\n policy: RoutingPolicy\n canWrite: boolean\n onPolicy: (p: RoutingPolicy) => void\n}) {\n const bands = policy.quotaBands\n const providerQuota = policy.providerQuota ?? {}\n\n const [cautionPct, setCautionPct] = useState(pctStr(bands?.cautionAt, BAND_DEFAULTS.cautionAt))\n const [avoidLargePct, setAvoidLargePct] = useState(pctStr(bands?.avoidLargeAt, BAND_DEFAULTS.avoidLargeAt))\n const [hardAvoidPct, setHardAvoidPct] = useState(pctStr(bands?.hardAvoidAt, BAND_DEFAULTS.hardAvoidAt))\n\n const [providerForms, setProviderForms] = useState<Record<string, { backstop: string; floor: string }>>(() => {\n const out: Record<string, { backstop: string; floor: string }> = {}\n for (const p of PROVIDERS) {\n const cfg = providerQuota[p] ?? {}\n out[p] = {\n backstop: pctStr(cfg.hardBackstopUtilization, BACKSTOP_DEFAULT),\n floor: pctStr(cfg.burnPenaltyUtilizationFloor, FLOOR_DEFAULT),\n }\n }\n return out\n })\n\n const [saving, setSaving] = useState(false)\n const [saveError, setSaveError] = useState('')\n const [saveOk, setSaveOk] = useState(false)\n const [validationError, setValidationError] = useState('')\n\n async function save() {\n const caution = parseFraction(cautionPct)\n const avoidLarge = parseFraction(avoidLargePct)\n const hardAvoid = parseFraction(hardAvoidPct)\n\n if (caution === null) { setValidationError('Caution threshold must be 0–100%.'); return }\n if (avoidLarge === null) { setValidationError('Avoid-large threshold must be 0–100%.'); return }\n if (hardAvoid === null) { setValidationError('Hard-avoid threshold must be 0–100%.'); return }\n if (caution >= avoidLarge) { setValidationError('Caution must be less than avoid-large.'); return }\n if (avoidLarge >= hardAvoid) { setValidationError('Avoid-large must be less than hard-avoid.'); return }\n\n const nextProviderQuota: Partial<Record<string, ProviderQuotaRoutingConfig>> = {}\n for (const p of PROVIDERS) {\n const f = providerForms[p]!\n const backstop = parseFraction(f.backstop)\n const floor = parseFraction(f.floor)\n if (backstop === null) { setValidationError(`${getProviderLabel(p)}: hard-backstop must be 0–100%.`); return }\n if (floor === null) { setValidationError(`${getProviderLabel(p)}: burn-penalty floor must be 0–100%.`); return }\n nextProviderQuota[p] = { hardBackstopUtilization: backstop, burnPenaltyUtilizationFloor: floor }\n }\n\n setValidationError('')\n setSaving(true)\n setSaveError('')\n setSaveOk(false)\n try {\n const saved = await api<RoutingPolicy>('PUT', '/routing-policy', {\n ...policy,\n quotaBands: { cautionAt: caution, avoidLargeAt: avoidLarge, hardAvoidAt: hardAvoid } satisfies QuotaBandThresholds,\n providerQuota: nextProviderQuota,\n })\n onPolicy(saved)\n setSaveOk(true)\n setTimeout(() => setSaveOk(false), 2000)\n } catch (e) {\n setSaveError((e as Error).message)\n } finally {\n setSaving(false)\n }\n }\n\n function patchProvider(provider: string, patch: { backstop?: string; floor?: string }) {\n setProviderForms((cur) => ({ ...cur, [provider]: { ...cur[provider]!, ...patch } }))\n setValidationError('')\n setSaveOk(false)\n }\n\n function markDirty() { setValidationError(''); setSaveOk(false) }\n\n return (\n <Card size=\"sm\">\n <CardHeader>\n <CardTitle className=\"text-sm\">Quota thresholds</CardTitle>\n <CardDescription className=\"text-xs\">\n Band cutoffs govern when the orchestrator starts penalising or blocking high-quota providers. Values are utilization percentages (0–100).\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {(saveError || validationError) && <ErrorBanner message={saveError || validationError} />}\n\n <div>\n <div className=\"mb-2 text-xs font-medium text-muted-foreground uppercase tracking-wide\">Band cutoffs</div>\n <QuotaBandDiagram caution={Number(cautionPct)} avoidLarge={Number(avoidLargePct)} hardAvoid={Number(hardAvoidPct)} />\n <div className=\"mt-3 grid gap-3 sm:grid-cols-3\">\n <FractionField label=\"Caution at\" hint={`Default: ${(BAND_DEFAULTS.cautionAt * 100).toFixed(0)}%`}\n value={cautionPct} disabled={!canWrite || saving} onChange={(v) => { setCautionPct(v); markDirty() }} />\n <FractionField label=\"Avoid-large at\" hint={`Default: ${(BAND_DEFAULTS.avoidLargeAt * 100).toFixed(0)}%`}\n value={avoidLargePct} disabled={!canWrite || saving} onChange={(v) => { setAvoidLargePct(v); markDirty() }} />\n <FractionField label=\"Hard-avoid at\" hint={`Default: ${(BAND_DEFAULTS.hardAvoidAt * 100).toFixed(0)}%`}\n value={hardAvoidPct} disabled={!canWrite || saving} onChange={(v) => { setHardAvoidPct(v); markDirty() }} />\n </div>\n </div>\n\n {PROVIDERS.map((p) => {\n const f = providerForms[p]!\n return (\n <div key={p}>\n <div className=\"mb-2 text-xs font-medium text-muted-foreground uppercase tracking-wide\">{getProviderLabel(p)} overrides</div>\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <FractionField label=\"Hard-backstop utilization\"\n hint={`Provider blocked above this. Default: ${(BACKSTOP_DEFAULT * 100).toFixed(0)}%`}\n value={f.backstop} disabled={!canWrite || saving}\n onChange={(v) => patchProvider(p, { backstop: v })} />\n <FractionField label=\"Burn-penalty floor\"\n hint={`Penalties suppressed below this. Default: ${(FLOOR_DEFAULT * 100).toFixed(0)}%`}\n value={f.floor} disabled={!canWrite || saving}\n onChange={(v) => patchProvider(p, { floor: v })} />\n </div>\n </div>\n )\n })}\n\n {canWrite && (\n <Button size=\"sm\" onClick={() => void save()} disabled={saving}>\n {saving ? <Loader2 className=\"size-4 animate-spin\" /> : <Save className=\"size-4\" />}\n {saveOk ? 'Saved' : 'Save thresholds'}\n </Button>\n )}\n </CardContent>\n </Card>\n )\n}\n\n// Linear band diagram (#731): renders the four quota zones as proportional segments\n// on a 0–100% axis so the relationship between the three cutoffs is legible at a glance.\n// Driven live by the current input values — it reshapes as you edit the fields below.\nfunction QuotaBandDiagram({ caution, avoidLarge, hardAvoid }: { caution: number; avoidLarge: number; hardAvoid: number }) {\n const clamp = (n: number) => Math.max(0, Math.min(100, Number.isFinite(n) ? n : 0))\n const c = clamp(caution)\n // Keep boundaries monotonic for display even while a half-typed value is out of order.\n const a = Math.max(c, clamp(avoidLarge))\n const h = Math.max(a, clamp(hardAvoid))\n const fmt = (n: number) => `${n.toFixed(0)}%`\n const zones = [\n { key: 'normal', label: 'normal', color: 'bg-emerald-500', from: 0, to: c, range: `0–${fmt(c)}` },\n { key: 'caution', label: 'caution', color: 'bg-amber-500', from: c, to: a, range: `${fmt(c)}–${fmt(a)}` },\n { key: 'avoid-large', label: 'avoid large', color: 'bg-orange-500', from: a, to: h, range: `${fmt(a)}–${fmt(h)}` },\n { key: 'hard-avoid', label: 'hard avoid', color: 'bg-red-500', from: h, to: 100, range: `≥ ${fmt(h)}` },\n ]\n return (\n <div className=\"space-y-1.5\">\n <div className=\"flex h-2.5 overflow-hidden rounded-full bg-muted\" role=\"img\" aria-label=\"Quota penalty bands from 0 to 100 percent\">\n {zones.map((z) => (\n <div key={z.key} className={cn(z.color, 'transition-[width] duration-300')} style={{ width: `${z.to - z.from}%` }} title={`${z.label} · ${z.range}`} />\n ))}\n </div>\n <div className=\"flex flex-wrap gap-x-3 gap-y-1 text-[10px] text-muted-foreground\">\n {zones.map((z) => (\n <span key={z.key} className=\"flex items-center gap-1\">\n <span className={cn('size-2 shrink-0 rounded-full', z.color)} />\n {z.label} <span className=\"tabular-nums text-foreground/70\">{z.range}</span>\n </span>\n ))}\n </div>\n </div>\n )\n}\n\nfunction FractionField({ label, hint, value, disabled, onChange }: {\n label: string; hint: string; value: string; disabled: boolean; onChange: (v: string) => void\n}) {\n return (\n <label className=\"space-y-1\">\n <span className=\"text-[10px] font-medium text-muted-foreground\">{label}</span>\n <div className=\"relative\">\n <Input value={value} onChange={(e) => onChange(e.target.value)} disabled={disabled}\n className=\"h-8 pr-6 text-xs tabular-nums\" />\n <span className=\"pointer-events-none absolute inset-y-0 right-2.5 flex items-center text-xs text-muted-foreground\">%</span>\n </div>\n <span className=\"text-[10px] text-muted-foreground\">{hint}</span>\n </label>\n )\n}\n\n// ─── CoordinatorVisibilityPanel ───────────────────────────────────────────────\n\ninterface VisibilityData {\n policy: RoutingPolicy\n profile: AgentProfile | null\n}\n\nexport function CoordinatorVisibilityPanel() {\n const [data, setData] = useState<VisibilityData | null>(null)\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState('')\n const [open, setOpen] = useState(false)\n const [loaded, setLoaded] = useState(false)\n\n async function load() {\n if (loaded) return\n setLoading(true)\n setError('')\n try {\n const [policy, profile] = await Promise.all([\n api<RoutingPolicy>('GET', '/routing-policy'),\n api<AgentProfile>('GET', '/agent-profiles/coordinator').catch(() => null),\n ])\n setData({ policy, profile })\n setLoaded(true)\n } catch (e) {\n setError((e as Error).message)\n } finally {\n setLoading(false)\n }\n }\n\n async function reload() {\n setLoaded(false)\n setLoading(true)\n setError('')\n try {\n const [policy, profile] = await Promise.all([\n api<RoutingPolicy>('GET', '/routing-policy'),\n api<AgentProfile>('GET', '/agent-profiles/coordinator').catch(() => null),\n ])\n setData({ policy, profile })\n setLoaded(true)\n } catch (e) {\n setError((e as Error).message)\n } finally {\n setLoading(false)\n }\n }\n\n function toggle() {\n const next = !open\n setOpen(next)\n if (next && !loaded) void load()\n }\n\n return (\n <Card size=\"sm\">\n <CardContent className=\"space-y-3\">\n <button type=\"button\" className=\"flex w-full items-center gap-2 text-left\" onClick={toggle}>\n <Eye className=\"size-4 text-muted-foreground\" />\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm font-semibold\">What your coordinator knows</div>\n <div className=\"text-xs text-muted-foreground\">Active routing policy + coordinator profile instructions (read-only)</div>\n </div>\n {open ? <ChevronDown className=\"size-4 shrink-0 text-muted-foreground\" /> : <ChevronRight className=\"size-4 shrink-0 text-muted-foreground\" />}\n </button>\n\n {open && (\n <div className=\"space-y-4 pt-1\">\n <div className=\"flex justify-end\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => void reload()} disabled={loading}>\n <RefreshCw className={cn('size-3.5', loading && 'animate-spin')} />\n Refresh\n </Button>\n </div>\n\n {error && <ErrorBanner message={error} />}\n\n {loading && !data && (\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground py-2\">\n <Loader2 className=\"size-3.5 animate-spin\" />Loading…\n </div>\n )}\n\n {data && (\n <>\n <ActivePolicyDisplay policy={data.policy} />\n {data.profile\n ? <CoordinatorProfileDisplay profile={data.profile} />\n : <div className=\"text-xs text-muted-foreground italic\">Coordinator profile not found.</div>\n }\n </>\n )}\n </div>\n )}\n </CardContent>\n </Card>\n )\n}\n\nfunction ActivePolicyDisplay({ policy }: { policy: RoutingPolicy }) {\n const bands = policy.quotaBands\n const providerQuota = policy.providerQuota ?? {}\n\n return (\n <div className=\"space-y-2\">\n <div className=\"text-xs font-semibold text-muted-foreground uppercase tracking-wide\">Active routing policy</div>\n\n {policy.rules.length === 0 ? (\n <div className=\"text-xs text-muted-foreground italic\">No rules — coordinators use their own heuristics.</div>\n ) : (\n <div className=\"overflow-hidden rounded-md border border-border text-xs\">\n <div className=\"grid grid-cols-[1.5rem_minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)] gap-px bg-border text-[10px] font-medium text-muted-foreground uppercase tracking-wide\">\n <div className=\"bg-muted/40 px-2 py-1.5\">#</div>\n <div className=\"bg-muted/40 px-2 py-1.5\">Match</div>\n <div className=\"bg-muted/40 px-2 py-1.5\">Target</div>\n <div className=\"bg-muted/40 px-2 py-1.5\">Status</div>\n </div>\n {policy.rules.map((rule, idx) => (\n <div key={idx}\n className={cn('grid grid-cols-[1.5rem_minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)] gap-px bg-border', rule.enabled === false && 'opacity-50')}>\n <div className=\"bg-card px-2 py-1.5 text-muted-foreground tabular-nums\">{idx + 1}</div>\n <div className=\"bg-card px-2 py-1.5\">\n {rule.label && <div className=\"font-medium\">{rule.label}</div>}\n {rule.match.taskType && <div className=\"font-mono\">task: {rule.match.taskType}</div>}\n {rule.match.capability && <div className=\"font-mono\">cap: {rule.match.capability}</div>}\n </div>\n <div className=\"bg-card px-2 py-1.5\">\n <span className=\"font-medium\">{rule.target.provider}</span>\n {rule.target.model && <span className=\"text-muted-foreground\"> / {rule.target.model}</span>}\n {rule.target.effort && <span className=\"text-muted-foreground\"> ({rule.target.effort})</span>}\n </div>\n <div className=\"bg-card px-2 py-1.5\">\n {rule.enabled === false ? <span className=\"text-muted-foreground\">disabled</span> : <span className=\"text-emerald-500\">active</span>}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {(bands || Object.keys(providerQuota).length > 0) && (\n <div className=\"rounded-md border border-border bg-muted/10 px-3 py-2 text-xs space-y-1\">\n {bands && (\n <div className=\"flex flex-wrap gap-x-4 gap-y-0.5\">\n {bands.cautionAt !== undefined && <span>caution ≥ {(bands.cautionAt * 100).toFixed(0)}%</span>}\n {bands.avoidLargeAt !== undefined && <span>avoid-large ≥ {(bands.avoidLargeAt * 100).toFixed(0)}%</span>}\n {bands.hardAvoidAt !== undefined && <span>hard-avoid ≥ {(bands.hardAvoidAt * 100).toFixed(0)}%</span>}\n </div>\n )}\n {Object.entries(providerQuota).map(([provider, cfg]) => (\n <div key={provider} className=\"flex flex-wrap gap-x-4 gap-y-0.5 text-muted-foreground\">\n <span className=\"font-medium text-foreground\">{getProviderLabel(provider)}</span>\n {cfg?.hardBackstopUtilization !== undefined && <span>backstop: {(cfg.hardBackstopUtilization * 100).toFixed(0)}%</span>}\n {cfg?.burnPenaltyUtilizationFloor !== undefined && <span>floor: {(cfg.burnPenaltyUtilizationFloor * 100).toFixed(0)}%</span>}\n </div>\n ))}\n </div>\n )}\n </div>\n )\n}\n\n// Instruction text is prose (markdown), not code — render it in the prose font with\n// relaxed line-height so it reads as prose, while `whitespace-pre-wrap` preserves the\n// author's exact line breaks. A capped, scrollable height keeps a long system prompt\n// from running the whole panel off-screen (#731).\nfunction InstructionBlock({ text, index }: { text: string; index?: number }) {\n return (\n <div className=\"relative max-h-72 overflow-y-auto rounded-md border border-border bg-muted/20\">\n {index !== undefined && (\n <span className=\"sticky top-0 float-right m-1.5 rounded bg-muted px-1.5 py-0.5 text-[9px] font-medium tabular-nums text-muted-foreground\">\n #{index}\n </span>\n )}\n <pre className=\"whitespace-pre-wrap break-words px-3 py-2.5 font-sans text-[11px] leading-relaxed text-foreground/90\">\n {text}\n </pre>\n </div>\n )\n}\n\nfunction CoordinatorProfileDisplay({ profile }: { profile: AgentProfile }) {\n return (\n <div className=\"space-y-2\">\n <div className=\"text-xs font-semibold text-muted-foreground uppercase tracking-wide\">\n Coordinator profile instructions\n <Badge variant=\"secondary\" className=\"ml-2 text-[10px]\">{profile.name}</Badge>\n {profile.builtIn && <Badge variant=\"outline\" className=\"ml-1 text-[10px]\">built-in</Badge>}\n </div>\n\n {profile.description && <p className=\"text-xs text-muted-foreground\">{profile.description}</p>}\n\n <div className=\"flex flex-wrap gap-2 text-[10px]\">\n <Badge variant=\"outline\">base: {profile.base}</Badge>\n <Badge variant=\"outline\">repo: {profile.instructions.repoInstructions}</Badge>\n <Badge variant=\"outline\">global: {profile.instructions.globalInstructions}</Badge>\n {profile.provider && <Badge variant=\"outline\">provider: {profile.provider}</Badge>}\n </div>\n\n {profile.instructions.system && (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] font-medium text-muted-foreground uppercase tracking-wide\">System prompt</div>\n <InstructionBlock text={profile.instructions.system} />\n </div>\n )}\n\n {profile.instructions.append.length > 0 && (\n <div className=\"space-y-2\">\n <div className=\"text-[10px] font-medium text-muted-foreground uppercase tracking-wide\">\n Appended instructions ({profile.instructions.append.length})\n </div>\n {profile.instructions.append.map((block, i) => (\n <InstructionBlock key={i} text={block} index={i + 1} />\n ))}\n </div>\n )}\n\n {profile.instructions.append.length === 0 && !profile.instructions.system && (\n <div className=\"text-xs text-muted-foreground italic\">No instruction blocks defined.</div>\n )}\n </div>\n )\n}\n","import { useState } from 'react'\nimport type { RoutingPolicy, RoutingRule } from 'agent-relay-sdk/types'\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, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport {\n AlertCircle,\n ArrowDown,\n ArrowUp,\n Loader2,\n Plus,\n RefreshCw,\n Route,\n Save,\n Trash2,\n} from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { getKnownProviderIds, getProviderLabel } from '@/lib/provider-display'\nimport { QuotaThresholdsEditor, CoordinatorVisibilityPanel } from './routing-coordinator-panel'\n\nconst PROVIDERS = getKnownProviderIds()\n\n// ─── types ───────────────────────────────────────────────────────────────────\n\ninterface RuleForm {\n label: string\n matchTaskType: string\n matchCapability: string\n targetProvider: string\n targetModel: string\n targetEffort: string\n enabled: boolean\n}\n\nfunction emptyRuleForm(): RuleForm {\n return { label: '', matchTaskType: '', matchCapability: '', targetProvider: PROVIDERS[0] ?? '', targetModel: '', targetEffort: '', enabled: true }\n}\n\nfunction ruleToForm(rule: RoutingRule): RuleForm {\n return {\n label: rule.label ?? '',\n matchTaskType: rule.match.taskType ?? '',\n matchCapability: rule.match.capability ?? '',\n targetProvider: rule.target.provider,\n targetModel: rule.target.model ?? '',\n targetEffort: rule.target.effort ?? '',\n enabled: rule.enabled !== false,\n }\n}\n\nfunction formToRule(form: RuleForm): RoutingRule {\n return {\n ...(form.label.trim() ? { label: form.label.trim() } : {}),\n match: {\n ...(form.matchTaskType.trim() ? { taskType: form.matchTaskType.trim() } : {}),\n ...(form.matchCapability.trim() ? { capability: form.matchCapability.trim() } : {}),\n },\n target: {\n provider: form.targetProvider,\n ...(form.targetModel.trim() ? { model: form.targetModel.trim() } : {}),\n ...(form.targetEffort.trim() ? { effort: form.targetEffort.trim() } : {}),\n },\n enabled: form.enabled,\n }\n}\n\nfunction validateRuleForm(form: RuleForm): string | null {\n if (!form.matchTaskType.trim() && !form.matchCapability.trim()) {\n return 'At least one match criterion (task type or capability) is required.'\n }\n return null\n}\n\nfunction ErrorBanner({ message }: { message: string }) {\n return (\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 shrink-0\" />\n <span>{message}</span>\n </div>\n )\n}\n\n// ─── RoutingSettings (root) ───────────────────────────────────────────────────\n\nexport function RoutingSettings({ canWrite }: { canWrite: boolean }) {\n const [policy, setPolicy] = useState<RoutingPolicy | null>(null)\n const [loading, setLoading] = useState(false)\n const [loadError, setLoadError] = useState('')\n const [loaded, setLoaded] = useState(false)\n\n if (!loaded && !loading && !loadError) {\n setLoading(true)\n void (async () => {\n try {\n const data = await api<RoutingPolicy>('GET', '/routing-policy')\n setPolicy(data)\n setLoaded(true)\n } catch (e) {\n setLoadError((e as Error).message)\n } finally {\n setLoading(false)\n }\n })()\n }\n\n async function reload() {\n setLoading(true)\n setLoadError('')\n try {\n const data = await api<RoutingPolicy>('GET', '/routing-policy')\n setPolicy(data)\n setLoaded(true)\n } catch (e) {\n setLoadError((e as Error).message)\n } finally {\n setLoading(false)\n }\n }\n\n return (\n <div className=\"space-y-6\">\n <div className=\"flex items-center justify-between gap-3\">\n <div>\n <h2 className=\"text-base font-semibold\">Routing</h2>\n <p className=\"text-sm text-muted-foreground\">\n Declarative rules mapping task types and capabilities to providers. Rules are advisory — coordinators apply\n them; explicit per-spawn arguments always take precedence.\n </p>\n </div>\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\n {loadError && <ErrorBanner message={loadError} />}\n\n {loading && !policy && (\n <Card size=\"sm\">\n <CardContent className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Loader2 className=\"size-4 animate-spin\" />\n Loading routing policy…\n </CardContent>\n </Card>\n )}\n\n {policy && (\n <>\n <RoutingRulesEditor policy={policy} canWrite={canWrite} onPolicy={setPolicy} />\n <QuotaThresholdsEditor policy={policy} canWrite={canWrite} onPolicy={setPolicy} />\n </>\n )}\n\n <CoordinatorVisibilityPanel />\n </div>\n )\n}\n\n// ─── RoutingRulesEditor ───────────────────────────────────────────────────────\n\nfunction RoutingRulesEditor({\n policy,\n canWrite,\n onPolicy,\n}: {\n policy: RoutingPolicy\n canWrite: boolean\n onPolicy: (p: RoutingPolicy) => void\n}) {\n const [saving, setSaving] = useState(false)\n const [saveError, setSaveError] = useState('')\n const [addOpen, setAddOpen] = useState(false)\n const [addForm, setAddForm] = useState<RuleForm>(emptyRuleForm)\n const [addError, setAddError] = useState('')\n const [editIdx, setEditIdx] = useState<number | null>(null)\n const [editForm, setEditForm] = useState<RuleForm>(emptyRuleForm)\n const [editError, setEditError] = useState('')\n\n async function putPolicy(next: RoutingPolicy) {\n setSaving(true)\n setSaveError('')\n try {\n const saved = await api<RoutingPolicy>('PUT', '/routing-policy', next)\n onPolicy(saved)\n } catch (e) {\n setSaveError((e as Error).message)\n } finally {\n setSaving(false)\n }\n }\n\n function move(idx: number, dir: -1 | 1) {\n const rules = [...policy.rules]\n const target = idx + dir\n if (target < 0 || target >= rules.length) return\n ;[rules[idx], rules[target]] = [rules[target]!, rules[idx]!]\n void putPolicy({ ...policy, rules })\n }\n\n function toggleEnabled(idx: number) {\n const rules = policy.rules.map((r, i) => (i === idx ? { ...r, enabled: r.enabled === false ? true : false } : r))\n void putPolicy({ ...policy, rules })\n }\n\n function removeRule(idx: number) {\n void putPolicy({ ...policy, rules: policy.rules.filter((_, i) => i !== idx) })\n }\n\n function startAdd() { setAddForm(emptyRuleForm()); setAddError(''); setAddOpen(true) }\n function cancelAdd() { setAddOpen(false); setAddError('') }\n\n function commitAdd() {\n const err = validateRuleForm(addForm)\n if (err) { setAddError(err); return }\n setAddOpen(false)\n void putPolicy({ ...policy, rules: [...policy.rules, formToRule(addForm)] })\n }\n\n function startEdit(idx: number) {\n setEditIdx(idx); setEditForm(ruleToForm(policy.rules[idx]!)); setEditError('')\n }\n\n function cancelEdit() { setEditIdx(null); setEditError('') }\n\n function commitEdit() {\n if (editIdx === null) return\n const err = validateRuleForm(editForm)\n if (err) { setEditError(err); return }\n const rules = policy.rules.map((r, i) => (i === editIdx ? formToRule(editForm) : r))\n setEditIdx(null)\n void putPolicy({ ...policy, rules })\n }\n\n return (\n <Card size=\"sm\">\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-sm\">\n <Route className=\"size-4\" />\n Rules\n <Badge variant=\"outline\" className=\"ml-auto text-[10px]\">\n {policy.rules.length} rule{policy.rules.length === 1 ? '' : 's'}\n </Badge>\n {saving && <Loader2 className=\"size-3 animate-spin text-muted-foreground\" />}\n </CardTitle>\n <CardDescription className=\"text-xs\">\n Evaluated in order — first matching enabled rule wins. Rules are advisory; explicit spawn arguments override them.\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n {saveError && <ErrorBanner message={saveError} />}\n\n {policy.rules.length === 0 && !addOpen && (\n <div className=\"rounded-md border border-dashed border-border py-6 text-center text-xs text-muted-foreground\">\n No rules — coordinators fall back to their own heuristics.\n </div>\n )}\n\n {policy.rules.map((rule, idx) =>\n editIdx === idx ? (\n <RuleEditForm key={idx} form={editForm} error={editError} onChange={setEditForm} onSave={commitEdit} onCancel={cancelEdit} />\n ) : (\n <RuleRow\n key={idx}\n rule={rule}\n idx={idx}\n total={policy.rules.length}\n canWrite={canWrite}\n saving={saving}\n onMoveUp={() => move(idx, -1)}\n onMoveDown={() => move(idx, 1)}\n onToggle={() => toggleEnabled(idx)}\n onEdit={() => startEdit(idx)}\n onRemove={() => removeRule(idx)}\n />\n ),\n )}\n\n {addOpen && (\n <RuleEditForm form={addForm} error={addError} onChange={setAddForm} onSave={commitAdd} onCancel={cancelAdd} isNew />\n )}\n\n {canWrite && !addOpen && editIdx === null && (\n <Button variant=\"outline\" size=\"sm\" className=\"w-full gap-1\" onClick={startAdd} disabled={saving}>\n <Plus className=\"size-4\" />\n Add rule\n </Button>\n )}\n </CardContent>\n </Card>\n )\n}\n\nfunction RuleRow({\n rule, idx, total, canWrite, saving,\n onMoveUp, onMoveDown, onToggle, onEdit, onRemove,\n}: {\n rule: RoutingRule\n idx: number\n total: number\n canWrite: boolean\n saving: boolean\n onMoveUp: () => void\n onMoveDown: () => void\n onToggle: () => void\n onEdit: () => void\n onRemove: () => void\n}) {\n const disabled = rule.enabled === false\n return (\n <div className={cn('group flex items-start gap-3 rounded-md border bg-muted/20 p-3', disabled && 'opacity-60')}>\n <div className=\"flex flex-col items-center gap-0.5 pt-0.5\">\n <button type=\"button\" title=\"Move up\" onClick={onMoveUp} disabled={!canWrite || saving || idx === 0}\n className=\"rounded p-0.5 text-muted-foreground hover:bg-accent hover:text-foreground disabled:pointer-events-none disabled:opacity-30\">\n <ArrowUp className=\"size-3.5\" />\n </button>\n <button type=\"button\" title=\"Move down\" onClick={onMoveDown} disabled={!canWrite || saving || idx === total - 1}\n className=\"rounded p-0.5 text-muted-foreground hover:bg-accent hover:text-foreground disabled:pointer-events-none disabled:opacity-30\">\n <ArrowDown className=\"size-3.5\" />\n </button>\n </div>\n\n <div className=\"min-w-0 flex-1 space-y-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-[10px] tabular-nums text-muted-foreground\">#{idx + 1}</span>\n {rule.label && <span className=\"text-xs font-medium\">{rule.label}</span>}\n <Badge variant=\"outline\" className=\"text-[10px]\">{rule.target.provider}</Badge>\n {rule.target.model && <Badge variant=\"outline\" className=\"text-[10px] font-mono\">{rule.target.model}</Badge>}\n {rule.target.effort && <Badge variant=\"outline\" className=\"text-[10px]\">{rule.target.effort}</Badge>}\n </div>\n <div className=\"flex flex-wrap gap-x-3 gap-y-0.5 text-[10px] text-muted-foreground\">\n {rule.match.taskType && <span>task-type: <span className=\"font-mono text-foreground\">{rule.match.taskType}</span></span>}\n {rule.match.capability && <span>capability: <span className=\"font-mono text-foreground\">{rule.match.capability}</span></span>}\n </div>\n </div>\n\n <div className=\"flex shrink-0 items-center gap-1 opacity-70 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100\">\n <Switch checked={rule.enabled !== false} disabled={!canWrite || saving} onCheckedChange={onToggle}\n title={rule.enabled === false ? 'Enable rule' : 'Disable rule'} />\n {canWrite && (\n <>\n <button type=\"button\" title=\"Edit\" onClick={onEdit} disabled={saving}\n className=\"rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground disabled:pointer-events-none\">\n <svg className=\"size-3.5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2}>\n <path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\" />\n <path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\" />\n </svg>\n </button>\n <button type=\"button\" title=\"Remove\" onClick={onRemove} disabled={saving}\n className=\"rounded p-1 text-destructive hover:bg-destructive/10 disabled:pointer-events-none\">\n <Trash2 className=\"size-3.5\" />\n </button>\n </>\n )}\n </div>\n </div>\n )\n}\n\nfunction RuleEditForm({\n form, error, onChange, onSave, onCancel, isNew,\n}: {\n form: RuleForm\n error: string\n onChange: (f: RuleForm) => void\n onSave: () => void\n onCancel: () => void\n isNew?: boolean\n}) {\n function patch(p: Partial<RuleForm>) { onChange({ ...form, ...p }) }\n return (\n <div className=\"rounded-md border border-primary/30 bg-primary/5 p-3 space-y-3\">\n <div className=\"text-xs font-semibold text-muted-foreground uppercase tracking-wide\">{isNew ? 'New rule' : 'Edit rule'}</div>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <label className=\"space-y-1\">\n <span className=\"text-[10px] font-medium text-muted-foreground\">Label (optional)</span>\n <Input value={form.label} onChange={(e) => patch({ label: e.target.value })}\n placeholder=\"e.g. Route GUI tasks to Claude\" className=\"h-8 text-xs\" />\n </label>\n <label className=\"space-y-1\">\n <span className=\"text-[10px] font-medium text-muted-foreground\">Target provider</span>\n <Select value={form.targetProvider} onValueChange={(v) => patch({ targetProvider: v })}>\n <SelectTrigger className=\"h-8 text-xs\"><SelectValue /></SelectTrigger>\n <SelectContent>\n {PROVIDERS.map((p) => <SelectItem key={p} value={p} className=\"text-xs\">{getProviderLabel(p)}</SelectItem>)}\n </SelectContent>\n </Select>\n </label>\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <label className=\"space-y-1\">\n <span className=\"text-[10px] font-medium text-muted-foreground\">Match task-type (prefix)</span>\n <Input value={form.matchTaskType} onChange={(e) => patch({ matchTaskType: e.target.value })}\n placeholder=\"e.g. gui, backend, mechanical\" className=\"h-8 font-mono text-xs\" />\n <span className=\"block text-[10px] leading-snug text-muted-foreground\">\n Prefix match — <span className=\"font-mono text-foreground\">gui</span> matches <span className=\"font-mono text-foreground\">gui/ux</span>, <span className=\"font-mono text-foreground\">gui/layout</span>.\n </span>\n </label>\n <label className=\"space-y-1\">\n <span className=\"text-[10px] font-medium text-muted-foreground\">Match capability (exact)</span>\n <Input value={form.matchCapability} onChange={(e) => patch({ matchCapability: e.target.value })}\n placeholder=\"e.g. code, research, bounded\" className=\"h-8 font-mono text-xs\" />\n <span className=\"block text-[10px] leading-snug text-muted-foreground\">\n Exact match against the agent's capability tag. Both fields are AND-ed.\n </span>\n </label>\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <label className=\"space-y-1\">\n <span className=\"text-[10px] font-medium text-muted-foreground\">Model alias (optional)</span>\n <Input value={form.targetModel} onChange={(e) => patch({ targetModel: e.target.value })}\n placeholder=\"e.g. opus, gpt-5.4\" className=\"h-8 font-mono text-xs\" />\n </label>\n <label className=\"space-y-1\">\n <span className=\"text-[10px] font-medium text-muted-foreground\">Effort (optional)</span>\n <Input value={form.targetEffort} onChange={(e) => patch({ targetEffort: e.target.value })}\n placeholder=\"e.g. high, low\" className=\"h-8 text-xs\" />\n </label>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <Switch checked={form.enabled} onCheckedChange={(enabled) => patch({ enabled })} />\n <span className=\"text-xs text-muted-foreground\">Enabled</span>\n </div>\n\n {error && <ErrorBanner message={error} />}\n\n <div className=\"flex gap-2\">\n <Button size=\"sm\" onClick={onSave}>\n <Save className=\"size-4\" />\n {isNew ? 'Add' : 'Save'}\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={onCancel}>Cancel</Button>\n </div>\n </div>\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 { RoutingSettings } from '@/components/settings/routing-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 ROUTING_GROUP_SLUG = 'routing'\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: ROUTING_GROUP_SLUG,\n label: 'Routing',\n description: 'Rules, quota thresholds, coordinator view',\n kind: 'routing' as const,\n 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 === 'routing' ? (\n <RoutingSettings canWrite={hasScope(token?.scopes, 'settings:write:routing')} />\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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"}
|