diff --git a/docs/dashboard.md b/docs/dashboard.md index c4a20fe1..3ca727cb 100644 --- a/docs/dashboard.md +++ b/docs/dashboard.md @@ -21,7 +21,7 @@ straight. | **Purpose** | Signs in to the dashboard and authorizes every management API call | Encrypts provider API keys stored through the dashboard (encryption at rest) | | **Set via** | `OTARI_MASTER_KEY` (or `master_key` in `config.yml`); generated on first run if unset | `OTARI_SECRET_KEY` only; never generated for you | | **Format** | Any string you choose, or a generated `otari-mk-…` value | A Fernet key (generate with `otari gen-secret-key`) | -| **Where it lives** | Only its SHA-256 hash is stored; in the browser it is held in the tab's session storage | Supplied out of band at runtime; never written to the database | +| **Where it lives** | Only its SHA-256 hash is stored; the browser never keeps the key itself, just the session cookie it is exchanged for | Supplied out of band at runtime; never written to the database | | **If you lose it** | Rotate or reset it; nothing else is affected | Every provider key stored in the dashboard becomes undecryptable | A few consequences worth internalizing: @@ -95,11 +95,16 @@ can skip this step if all your providers live in `config.yml`. ### 4. Open the dashboard and sign in Browse to the gateway root, for example `http://localhost:8000/`. You land on a -sign-in screen. Paste your master key and select **Sign in**. The key is held -only in this browser tab's session storage and sent directly to this gateway; it -is never persisted to disk by the browser and is cleared when you sign out. If -you are on a fresh install and are not sure where your key is, the "First run? -Where to find your key" hint on the sign-in screen points you back at the logs. +sign-in screen. Paste your master key and select **Sign in**. The key is sent +once to this gateway and exchanged for a session cookie; the browser never stores +the key itself, so it cannot be read back out of the page. The sign-in lasts +`dashboard_session_ttl_hours` (a week by default) and survives closing the tab, +so you normally sign in once and not again. It survives restarting the gateway +too, as long as the gateway's database does: sessions are rows in it, so a +container running the default SQLite file with no mounted volume starts every run +signed out. If you are on a fresh install and are not sure where your key is, the +"First run? Where to find your key" hint on the sign-in screen points you back at +the logs. ### 5. Add a provider @@ -206,10 +211,18 @@ put it behind HTTPS, as the security notes below describe. authorizes every management request and must never travel over cleartext HTTP, so put the gateway behind HTTPS or a trusted reverse proxy before signing in from another host. -- **Session storage, not local storage.** The dashboard keeps the master key in - the browser tab's session storage, so it does not persist across tabs or - survive closing the tab, and signing out clears it along with any cached admin - data. +- **A session cookie, not a stored key.** The dashboard trades your master key + for an HttpOnly cookie (`SameSite=Strict`, and `Secure` whenever the request + arrives over HTTPS), so the key itself is never kept in the browser and script + on the page cannot read the cookie. Signing out revokes the session on the + server, expires the cookie, and clears any cached admin data. Rotating the + master key revokes every session and re-mints the one you are using, so other + signed-in browsers are logged out. +- **Sign out on a machine you share.** A session runs for its full + `dashboard_session_ttl_hours` with no idle timeout, so an unattended browser + stays signed in until the cookie expires. Use **Sign out** when you are done on + a shared or public machine, or shorten `dashboard_session_ttl_hours`. Rotating + the master key is the way to revoke a session you can no longer reach. - **Provider keys are write-only over the API.** Once stored, the plaintext is never returned; the UI shows only the last four characters. Losing `OTARI_SECRET_KEY` makes stored keys undecryptable, so back it up separately diff --git a/src/gateway/static/dashboard/assets/ActivityPage-lcRQhBAw.js b/src/gateway/static/dashboard/assets/ActivityPage-BngVFI4f.js similarity index 98% rename from src/gateway/static/dashboard/assets/ActivityPage-lcRQhBAw.js rename to src/gateway/static/dashboard/assets/ActivityPage-BngVFI4f.js index d90af543..fecfac82 100644 --- a/src/gateway/static/dashboard/assets/ActivityPage-lcRQhBAw.js +++ b/src/gateway/static/dashboard/assets/ActivityPage-BngVFI4f.js @@ -1 +1 @@ -import{j as s}from"./tanstack-query-1t81HyiD.js";import{u as ze,r as n}from"./react-dgEcD0HR.js";import{u as We,a as Ye,b as Ge,c as he,d as xe,e as He,f as Ve,P as Ze,E as Je,R as Qe,F as be,g as W}from"./index-JlWCttWt.js";import{f as O,b as Xe,A as et,C as ve,a as N,F as tt,c as G,i as st}from"./FilterChips-DZjxf-ot.js";import{u as at,r as rt,B as lt}from"./tableSelection-9hV37uhu.js";import{C as nt}from"./ConfirmDialog-DXR8OubG.js";import{D as ot}from"./DataTable-Bmn_eYSV.js";import{T as it,S as ct,P as dt}from"./TablePagination-CfsjgA8s.js";import{B as Y}from"./heroui-BI50yK5B.js";import"./recharts-C4kRDmvS.js";function ut(t){const[l,i]=ze(),a=n.useCallback(h=>l.get(h)??t[h],[l,t]),o=n.useCallback(h=>{const m=Number.parseInt(l.get(h)??"",10);if(!Number.isNaN(m))return m;const c=Number.parseInt(t[h],10);return Number.isNaN(c)?0:c},[l,t]),S=n.useCallback(h=>{i(m=>{const c=new URLSearchParams(m);for(const[p,x]of Object.entries(h)){const f=String(x);f===""||f===t[p]?c.delete(p):c.set(p,f)}return c},{replace:!0})},[i,t]);return{get:a,getNumber:o,patch:S}}const mt=new Intl.NumberFormat(void 0,{style:"currency",currency:"USD",maximumFractionDigits:4});function I(t){return t===null?"—":mt.format(t)}function _(t){return t===null?"—":t.toLocaleString()}function ke(t){return t===null?"—":t<1e3?`${t} ms`:`${(t/1e3).toFixed(t<1e4?2:1)} s`}function pt(t){const l=new Date(t);return Number.isNaN(l.getTime())?t:l.toLocaleString()}function gt(t){const l=new Date(t).getTime();if(Number.isNaN(l))return t;const i=Math.max(0,Math.round((Date.now()-l)/1e3));if(i<60)return`${i}s ago`;const a=Math.round(i/60);if(a<60)return`${a}m ago`;const o=Math.round(a/60);return o<24?`${o}h ago`:`${Math.round(o/24)}d ago`}const ht=t=>t.id,xt=t=>t.status==="error"?"bg-red-50":void 0,fe=[{label:"All",value:""},{label:"Success",value:"success"},{label:"Error",value:"error"}],_e=[{label:"All",value:""},{label:"Priced",value:"true"},{label:"Unpriced",value:"false"}],bt=50,ft={range:G,start_date:"",end_date:"",status:"",model:"",user_id:"",api_key_id:"",priced:"",page:"0",size:String(bt)};function y(t,l,i){if(l||i)return{start:l||void 0,end:i||void 0};if(t===ve)return{};const a=O(N,t)??O(N,G),o=(a==null?void 0:a.seconds)??null;return{start:o==null?void 0:st(o),end:void 0}}function _t({status:t}){const l=t==="error"?"border-red-200 bg-red-50 text-red-700":"border-[var(--otari-line)] bg-[var(--otari-brand-tint)] text-[var(--otari-brand-dark)]";return s.jsx("span",{className:`inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium ${l}`,children:t})}const vt={gateway:"Gateway",claude_code:"Claude Code",codex:"Codex"};function kt(t){return vt[t]??t}function u({label:t,children:l}){return s.jsxs("div",{className:"flex flex-col gap-0.5",children:[s.jsx("span",{className:"text-[11px] font-medium uppercase tracking-wide text-[var(--otari-muted)]",children:t}),s.jsx("span",{className:"text-sm text-[var(--otari-ink)] break-all",children:l})]})}function St({entry:t}){var l;return s.jsxs("div",{className:"flex flex-col gap-4 px-4 py-4",children:[t.error_message?s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx("span",{className:"text-[11px] font-medium uppercase tracking-wide text-[var(--otari-muted)]",children:"Error"}),s.jsx("pre",{className:"max-h-48 overflow-auto rounded-lg border border-red-200 bg-red-50 p-3 text-xs whitespace-pre-wrap break-all text-red-700",children:"The provider returned an error. Inspect gateway logs for details."})]}):null,s.jsxs("div",{className:"grid gap-4 sm:grid-cols-2 lg:grid-cols-4",children:[s.jsx(u,{label:"Provider",children:t.provider??"—"}),s.jsx(u,{label:"Endpoint",children:t.endpoint}),s.jsx(u,{label:"Source",children:kt(t.source)}),t.source_label?s.jsx(u,{label:"Session",children:t.source_label}):null,s.jsx(u,{label:"User",children:t.user_id??"—"}),s.jsx(u,{label:"API key",children:t.api_key_id??"—"}),s.jsx(u,{label:"Prompt tokens",children:_(t.prompt_tokens)}),s.jsx(u,{label:"Completion tokens",children:_(t.completion_tokens)}),s.jsx(u,{label:"Total tokens",children:_(t.total_tokens)}),s.jsx(u,{label:"Cost",children:I(t.cost)}),s.jsx(u,{label:"Cache read tokens",children:_(t.cache_read_tokens)}),s.jsx(u,{label:"Cache write tokens",children:_(t.cache_write_tokens)}),s.jsx(u,{label:"1h cache writes",children:_(t.cache_write_1h_tokens??null)}),s.jsx(u,{label:"Total time",children:ke(t.latency_ms)}),s.jsx(u,{label:"Request ID",children:t.id})]}),(l=t.pricing_breakdown)!=null&&l.length?s.jsxs("div",{className:"flex flex-col gap-2",children:[s.jsx("span",{className:"text-[11px] font-medium uppercase tracking-wide text-[var(--otari-muted)]",children:"Billed meters"}),s.jsx("div",{className:"grid gap-2 sm:grid-cols-2 lg:grid-cols-3",children:t.pricing_breakdown.map(i=>s.jsxs(u,{label:i.meter.replaceAll("_"," "),children:[_(i.units)," at ",I(i.rate_per_million)," / 1M, ",I(i.cost)]},i.meter))})]}):null]})}function It(){var ce,de,ue,me,pe;const t=We(),l=Ye(),i=n.useMemo(()=>{const e=new Map;for(const r of l.data??[])e.set(r.id,r.key_name??`${r.id.slice(0,8)}…`);return e},[l.data]),a=ut(ft),o=a.get("range"),S=a.get("start_date"),h=a.get("end_date"),m=a.get("status"),c=a.get("model"),p=a.get("user_id"),x=a.get("api_key_id"),f=a.get("priced"),H=Math.max(0,a.getNumber("page")),V=a.getNumber("size"),U=dt.reduce((e,r)=>Math.abs(r-V)y(o,S,h));n.useEffect(()=>{Z(y(o,S,h))},[o,S,h]);const[A,J]=n.useState(()=>y(o,"",""));n.useEffect(()=>{J(y(o,"",""))},[o]);const Se=!!(d.start||d.end),E=f==="true"?!0:f==="false"?!1:void 0,b=n.useMemo(()=>({start_date:d.start,end_date:d.end,status:m||void 0,model:c.trim()||void 0,user_id:p||void 0,api_key_id:x||void 0,priced:E}),[d,m,c,p,x,E]),g=at(),F=JSON.stringify(b),Q=n.useRef(F);n.useEffect(()=>{Q.current!==F&&(Q.current=F,a.patch({page:0}),g.clear())},[F,a,g]);const v=Ge(b,H,U),j=he(b),ye=n.useMemo(()=>({start_date:d.start,end_date:d.end,status:m||void 0,user_id:p||void 0,api_key_id:x||void 0}),[d,m,p,x]),X=xe(ye,"day"),L=((de=(ce=X.data)==null?void 0:ce.by_model)==null?void 0:de.filter(e=>!e.is_other&&e.key!==null).map(e=>e.key))??[],ee=(l.data??[]).map(e=>({value:e.id,label:e.key_name??`${e.id.slice(0,8)}…`})),w=O(N,o)??O(N,G),C=!!(d.start&&A.start&&new Date(d.start).getTime()({start_date:C?d.start:A.start,end_date:C?d.end:void 0,status:m||void 0,model:c.trim()||void 0,user_id:p||void 0,api_key_id:x||void 0,priced:E}),[C,d,A,m,c,p,x,E]),R=xe(we,te),Ce=(((ue=R.data)==null?void 0:ue.series)??[]).map(e=>({bucketStart:e.bucket_start,requests:e.requests})),k=v.data??[],Pe=j.isSuccess&&!j.isPlaceholderData?((me=j.data)==null?void 0:me.total)??0:null,Ne=!!(m||c.trim()||p||x||f||Se),M=(e,r)=>{var ge;return((ge=e.find(qe=>qe.value===r))==null?void 0:ge.label)??r},se=(t.data??[]).map(e=>({value:e.user_id,label:e.alias?`${e.alias} (${e.user_id})`:e.user_id})),Ae=()=>a.patch({status:"",priced:"",model:"",user_id:"",api_key_id:""}),Ee=[...m?[{key:"status",label:"Status",value:M(fe,m),onClear:()=>a.patch({status:""})}]:[],...f?[{key:"priced",label:"Priced",value:M(_e,f),onClear:()=>a.patch({priced:""})}]:[],...p?[{key:"user",label:"User",value:M(se,p),onClear:()=>a.patch({user_id:""})}]:[],...c.trim()?[{key:"model",label:"Model",value:c.trim(),onClear:()=>a.patch({model:""})}]:[],...x?[{key:"key",label:"API key",value:M(ee,x),onClear:()=>a.patch({api_key_id:""})}]:[]],K=n.useMemo(()=>k.filter(e=>!e.counts_toward_budget).map(e=>e.id),[k]),Fe=n.useMemo(()=>k.filter(e=>e.counts_toward_budget).map(e=>e.id),[k]),ae=rt(g.selectedKeys,K),P=ae.length,re=g.allMatching||P>0,Me=n.useMemo(()=>({...b,counts_toward_budget:!1}),[b]),le=he(Me,re),T=le.isSuccess?((pe=le.data)==null?void 0:pe.total)??null:null,Te=K.length>0&&P===K.length&&T!=null&&T>P,D=g.allMatching?T??P:P,B=He(),$=Ve(),[De,q]=n.useState(!1),[Ie,z]=n.useState(!1),[Oe,ne]=n.useState(null),Ue=n.useCallback(e=>s.jsxs("div",{children:[s.jsxs("div",{className:"flex items-center justify-between border-b border-[var(--otari-line)] px-4 py-2",children:[s.jsx("span",{className:"text-sm font-medium text-[var(--otari-ink)]",children:"Request detail"}),s.jsx(Y,{size:"sm",variant:"ghost",onPress:()=>ne(null),children:"Close"})]}),s.jsx(St,{entry:e})]}),[]),oe=()=>g.allMatching?{by_filter:!0,model:b.model,user_id:b.user_id,api_key_id:b.api_key_id,status:b.status,start_date:b.start_date,end_date:b.end_date,priced:b.priced}:{ids:ae},Le=()=>{B.mutate(oe(),{onSuccess:()=>{q(!1),g.clear()}})},Re=e=>{$.mutate({...oe(),...e},{onSuccess:()=>{z(!1),g.clear()}})},Ke=()=>{Z(y(o,S,h)),J(y(o,"","")),v.refetch(),j.refetch(),R.refetch(),X.refetch()},ie=e=>a.patch({range:e.key,start_date:"",end_date:""}),Be=(e,r)=>a.patch({start_date:e,end_date:r}),$e=n.useMemo(()=>{const e=r=>r===null?"—":i.get(r)??`${r.slice(0,8)}…`;return[{id:"time",header:"Time",cell:r=>s.jsx("span",{title:pt(r.timestamp),className:"text-[var(--otari-muted)]",children:gt(r.timestamp)})},{id:"user",header:"User",cell:r=>r.user_id??"—"},{id:"model",header:"Model",isRowHeader:!0,cell:r=>r.model},{id:"api_key",header:"API key",cell:r=>s.jsx("span",{className:"text-[var(--otari-muted)]",children:e(r.api_key_id)})},{id:"tokens",header:"Tokens",align:"end",cell:r=>_(r.total_tokens)},{id:"cost",header:"Cost",align:"end",cell:r=>I(r.cost)},{id:"latency",header:"Total time",align:"end",cell:r=>ke(r.latency_ms)},{id:"status",header:"Status",cell:r=>s.jsx(_t,{status:r.status})}]},[i]);return s.jsxs("div",{className:"flex flex-col gap-6",children:[s.jsx(Ze,{title:"Activity",description:"A per-request log of what the gateway served: tokens, cost, latency, and failures. No request or response content is stored."}),s.jsx(Je,{error:v.error??j.error}),s.jsxs("div",{className:"flex flex-col gap-3",children:[s.jsx(et,{presets:N,extentKey:je,onPreset:ie,onSelectRange:Be,onSelectFull:()=>w?ie(w):void 0,series:Ce,bucket:te,windowStart:d.start,windowEnd:d.end,loading:R.isLoading,ariaLabel:"Activity request volume over the selected window",action:s.jsx(Qe,{onRefresh:Ke,isFetching:v.isFetching,updatedAt:v.dataUpdatedAt})}),s.jsxs(tt,{chips:Ee,onClearAll:Ae,children:[s.jsx(be,{id:"filter-status",label:"Status",value:m,onChange:e=>a.patch({status:e}),children:fe.map(e=>s.jsx("option",{value:e.value,children:e.label},e.value))}),s.jsx(be,{id:"filter-priced",label:"Priced?",value:f,onChange:e=>a.patch({priced:e}),children:_e.map(e=>s.jsx("option",{value:e.value,children:e.label},e.value))}),s.jsx(W,{label:"API key",value:x,onChange:e=>a.patch({api_key_id:e}),placeholder:"All keys",options:ee}),s.jsx(W,{label:"User",value:p,onChange:e=>a.patch({user_id:e}),placeholder:"All users",options:se}),s.jsx(W,{label:"Model",value:c,onChange:e=>a.patch({model:e}),allowsCustom:!0,placeholder:"Any model",options:(c&&!L.includes(c)?[c,...L]:L).map(e=>({value:e,label:e}))})]})]}),re?s.jsxs(lt,{selectedCount:D,allMatching:g.allMatching,matchingTotal:T,canSelectAllMatching:Te,onSelectAllMatching:g.enableAllMatching,onClear:g.clear,children:[s.jsx(Y,{size:"sm",variant:"primary",onPress:()=>z(!0),children:"Set price"}),s.jsx(Y,{size:"sm",variant:"danger",onPress:()=>q(!0),children:"Delete"})]}):null,s.jsx(ot,{ariaLabel:"Activity log",columns:$e,rows:k,getRowKey:ht,isLoading:v.isLoading,emptyContent:Ne?"No requests match these filters.":"No requests recorded yet.",selectionMode:"multiple",selectedKeys:g.selectedKeys,onSelectionChange:g.onSelectionChange,disabledKeys:Fe,onRowAction:e=>ne(r=>r===e?null:e),rowClassName:xt,detailKey:Oe,renderDetail:Ue}),s.jsx(it,{page:H,pageSize:U,total:Pe,rowsOnPage:k.length,onPageChange:e=>a.patch({page:e}),onPageSizeChange:e=>a.patch({size:e,page:0}),isFetching:v.isFetching,hasNextFallback:k.length===U}),s.jsx(nt,{isOpen:De,onOpenChange:q,heading:"Delete usage rows",body:`Delete ${D.toLocaleString()} imported ${D===1?"row":"rows"}? Only imported rows are removed, and this cannot be undone.`,confirmLabel:"Delete",isPending:B.isPending,error:B.error,onConfirm:Le}),s.jsx(ct,{isOpen:Ie,onOpenChange:z,targetCount:D,isPending:$.isPending,error:$.error,onSubmit:Re})]})}export{It as ActivityPage}; +import{j as s}from"./tanstack-query-1t81HyiD.js";import{u as ze,r as n}from"./react-dgEcD0HR.js";import{u as We,a as Ye,b as Ge,c as he,d as xe,e as He,f as Ve,P as Ze,E as Je,R as Qe,F as be,g as W}from"./index-BP-wLuMr.js";import{f as O,b as Xe,A as et,C as ve,a as N,F as tt,c as G,i as st}from"./FilterChips-DZjxf-ot.js";import{u as at,r as rt,B as lt}from"./tableSelection-9hV37uhu.js";import{C as nt}from"./ConfirmDialog-BFS2k4X_.js";import{D as ot}from"./DataTable-Bmn_eYSV.js";import{T as it,S as ct,P as dt}from"./TablePagination-BtDO5gaH.js";import{B as Y}from"./heroui-BI50yK5B.js";import"./recharts-C4kRDmvS.js";function ut(t){const[l,i]=ze(),a=n.useCallback(h=>l.get(h)??t[h],[l,t]),o=n.useCallback(h=>{const m=Number.parseInt(l.get(h)??"",10);if(!Number.isNaN(m))return m;const c=Number.parseInt(t[h],10);return Number.isNaN(c)?0:c},[l,t]),S=n.useCallback(h=>{i(m=>{const c=new URLSearchParams(m);for(const[p,x]of Object.entries(h)){const f=String(x);f===""||f===t[p]?c.delete(p):c.set(p,f)}return c},{replace:!0})},[i,t]);return{get:a,getNumber:o,patch:S}}const mt=new Intl.NumberFormat(void 0,{style:"currency",currency:"USD",maximumFractionDigits:4});function I(t){return t===null?"—":mt.format(t)}function _(t){return t===null?"—":t.toLocaleString()}function ke(t){return t===null?"—":t<1e3?`${t} ms`:`${(t/1e3).toFixed(t<1e4?2:1)} s`}function pt(t){const l=new Date(t);return Number.isNaN(l.getTime())?t:l.toLocaleString()}function gt(t){const l=new Date(t).getTime();if(Number.isNaN(l))return t;const i=Math.max(0,Math.round((Date.now()-l)/1e3));if(i<60)return`${i}s ago`;const a=Math.round(i/60);if(a<60)return`${a}m ago`;const o=Math.round(a/60);return o<24?`${o}h ago`:`${Math.round(o/24)}d ago`}const ht=t=>t.id,xt=t=>t.status==="error"?"bg-red-50":void 0,fe=[{label:"All",value:""},{label:"Success",value:"success"},{label:"Error",value:"error"}],_e=[{label:"All",value:""},{label:"Priced",value:"true"},{label:"Unpriced",value:"false"}],bt=50,ft={range:G,start_date:"",end_date:"",status:"",model:"",user_id:"",api_key_id:"",priced:"",page:"0",size:String(bt)};function y(t,l,i){if(l||i)return{start:l||void 0,end:i||void 0};if(t===ve)return{};const a=O(N,t)??O(N,G),o=(a==null?void 0:a.seconds)??null;return{start:o==null?void 0:st(o),end:void 0}}function _t({status:t}){const l=t==="error"?"border-red-200 bg-red-50 text-red-700":"border-[var(--otari-line)] bg-[var(--otari-brand-tint)] text-[var(--otari-brand-dark)]";return s.jsx("span",{className:`inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium ${l}`,children:t})}const vt={gateway:"Gateway",claude_code:"Claude Code",codex:"Codex"};function kt(t){return vt[t]??t}function u({label:t,children:l}){return s.jsxs("div",{className:"flex flex-col gap-0.5",children:[s.jsx("span",{className:"text-[11px] font-medium uppercase tracking-wide text-[var(--otari-muted)]",children:t}),s.jsx("span",{className:"text-sm text-[var(--otari-ink)] break-all",children:l})]})}function St({entry:t}){var l;return s.jsxs("div",{className:"flex flex-col gap-4 px-4 py-4",children:[t.error_message?s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx("span",{className:"text-[11px] font-medium uppercase tracking-wide text-[var(--otari-muted)]",children:"Error"}),s.jsx("pre",{className:"max-h-48 overflow-auto rounded-lg border border-red-200 bg-red-50 p-3 text-xs whitespace-pre-wrap break-all text-red-700",children:"The provider returned an error. Inspect gateway logs for details."})]}):null,s.jsxs("div",{className:"grid gap-4 sm:grid-cols-2 lg:grid-cols-4",children:[s.jsx(u,{label:"Provider",children:t.provider??"—"}),s.jsx(u,{label:"Endpoint",children:t.endpoint}),s.jsx(u,{label:"Source",children:kt(t.source)}),t.source_label?s.jsx(u,{label:"Session",children:t.source_label}):null,s.jsx(u,{label:"User",children:t.user_id??"—"}),s.jsx(u,{label:"API key",children:t.api_key_id??"—"}),s.jsx(u,{label:"Prompt tokens",children:_(t.prompt_tokens)}),s.jsx(u,{label:"Completion tokens",children:_(t.completion_tokens)}),s.jsx(u,{label:"Total tokens",children:_(t.total_tokens)}),s.jsx(u,{label:"Cost",children:I(t.cost)}),s.jsx(u,{label:"Cache read tokens",children:_(t.cache_read_tokens)}),s.jsx(u,{label:"Cache write tokens",children:_(t.cache_write_tokens)}),s.jsx(u,{label:"1h cache writes",children:_(t.cache_write_1h_tokens??null)}),s.jsx(u,{label:"Total time",children:ke(t.latency_ms)}),s.jsx(u,{label:"Request ID",children:t.id})]}),(l=t.pricing_breakdown)!=null&&l.length?s.jsxs("div",{className:"flex flex-col gap-2",children:[s.jsx("span",{className:"text-[11px] font-medium uppercase tracking-wide text-[var(--otari-muted)]",children:"Billed meters"}),s.jsx("div",{className:"grid gap-2 sm:grid-cols-2 lg:grid-cols-3",children:t.pricing_breakdown.map(i=>s.jsxs(u,{label:i.meter.replaceAll("_"," "),children:[_(i.units)," at ",I(i.rate_per_million)," / 1M, ",I(i.cost)]},i.meter))})]}):null]})}function It(){var ce,de,ue,me,pe;const t=We(),l=Ye(),i=n.useMemo(()=>{const e=new Map;for(const r of l.data??[])e.set(r.id,r.key_name??`${r.id.slice(0,8)}…`);return e},[l.data]),a=ut(ft),o=a.get("range"),S=a.get("start_date"),h=a.get("end_date"),m=a.get("status"),c=a.get("model"),p=a.get("user_id"),x=a.get("api_key_id"),f=a.get("priced"),H=Math.max(0,a.getNumber("page")),V=a.getNumber("size"),U=dt.reduce((e,r)=>Math.abs(r-V)y(o,S,h));n.useEffect(()=>{Z(y(o,S,h))},[o,S,h]);const[A,J]=n.useState(()=>y(o,"",""));n.useEffect(()=>{J(y(o,"",""))},[o]);const Se=!!(d.start||d.end),E=f==="true"?!0:f==="false"?!1:void 0,b=n.useMemo(()=>({start_date:d.start,end_date:d.end,status:m||void 0,model:c.trim()||void 0,user_id:p||void 0,api_key_id:x||void 0,priced:E}),[d,m,c,p,x,E]),g=at(),F=JSON.stringify(b),Q=n.useRef(F);n.useEffect(()=>{Q.current!==F&&(Q.current=F,a.patch({page:0}),g.clear())},[F,a,g]);const v=Ge(b,H,U),j=he(b),ye=n.useMemo(()=>({start_date:d.start,end_date:d.end,status:m||void 0,user_id:p||void 0,api_key_id:x||void 0}),[d,m,p,x]),X=xe(ye,"day"),L=((de=(ce=X.data)==null?void 0:ce.by_model)==null?void 0:de.filter(e=>!e.is_other&&e.key!==null).map(e=>e.key))??[],ee=(l.data??[]).map(e=>({value:e.id,label:e.key_name??`${e.id.slice(0,8)}…`})),w=O(N,o)??O(N,G),C=!!(d.start&&A.start&&new Date(d.start).getTime()({start_date:C?d.start:A.start,end_date:C?d.end:void 0,status:m||void 0,model:c.trim()||void 0,user_id:p||void 0,api_key_id:x||void 0,priced:E}),[C,d,A,m,c,p,x,E]),R=xe(we,te),Ce=(((ue=R.data)==null?void 0:ue.series)??[]).map(e=>({bucketStart:e.bucket_start,requests:e.requests})),k=v.data??[],Pe=j.isSuccess&&!j.isPlaceholderData?((me=j.data)==null?void 0:me.total)??0:null,Ne=!!(m||c.trim()||p||x||f||Se),M=(e,r)=>{var ge;return((ge=e.find(qe=>qe.value===r))==null?void 0:ge.label)??r},se=(t.data??[]).map(e=>({value:e.user_id,label:e.alias?`${e.alias} (${e.user_id})`:e.user_id})),Ae=()=>a.patch({status:"",priced:"",model:"",user_id:"",api_key_id:""}),Ee=[...m?[{key:"status",label:"Status",value:M(fe,m),onClear:()=>a.patch({status:""})}]:[],...f?[{key:"priced",label:"Priced",value:M(_e,f),onClear:()=>a.patch({priced:""})}]:[],...p?[{key:"user",label:"User",value:M(se,p),onClear:()=>a.patch({user_id:""})}]:[],...c.trim()?[{key:"model",label:"Model",value:c.trim(),onClear:()=>a.patch({model:""})}]:[],...x?[{key:"key",label:"API key",value:M(ee,x),onClear:()=>a.patch({api_key_id:""})}]:[]],K=n.useMemo(()=>k.filter(e=>!e.counts_toward_budget).map(e=>e.id),[k]),Fe=n.useMemo(()=>k.filter(e=>e.counts_toward_budget).map(e=>e.id),[k]),ae=rt(g.selectedKeys,K),P=ae.length,re=g.allMatching||P>0,Me=n.useMemo(()=>({...b,counts_toward_budget:!1}),[b]),le=he(Me,re),T=le.isSuccess?((pe=le.data)==null?void 0:pe.total)??null:null,Te=K.length>0&&P===K.length&&T!=null&&T>P,D=g.allMatching?T??P:P,B=He(),$=Ve(),[De,q]=n.useState(!1),[Ie,z]=n.useState(!1),[Oe,ne]=n.useState(null),Ue=n.useCallback(e=>s.jsxs("div",{children:[s.jsxs("div",{className:"flex items-center justify-between border-b border-[var(--otari-line)] px-4 py-2",children:[s.jsx("span",{className:"text-sm font-medium text-[var(--otari-ink)]",children:"Request detail"}),s.jsx(Y,{size:"sm",variant:"ghost",onPress:()=>ne(null),children:"Close"})]}),s.jsx(St,{entry:e})]}),[]),oe=()=>g.allMatching?{by_filter:!0,model:b.model,user_id:b.user_id,api_key_id:b.api_key_id,status:b.status,start_date:b.start_date,end_date:b.end_date,priced:b.priced}:{ids:ae},Le=()=>{B.mutate(oe(),{onSuccess:()=>{q(!1),g.clear()}})},Re=e=>{$.mutate({...oe(),...e},{onSuccess:()=>{z(!1),g.clear()}})},Ke=()=>{Z(y(o,S,h)),J(y(o,"","")),v.refetch(),j.refetch(),R.refetch(),X.refetch()},ie=e=>a.patch({range:e.key,start_date:"",end_date:""}),Be=(e,r)=>a.patch({start_date:e,end_date:r}),$e=n.useMemo(()=>{const e=r=>r===null?"—":i.get(r)??`${r.slice(0,8)}…`;return[{id:"time",header:"Time",cell:r=>s.jsx("span",{title:pt(r.timestamp),className:"text-[var(--otari-muted)]",children:gt(r.timestamp)})},{id:"user",header:"User",cell:r=>r.user_id??"—"},{id:"model",header:"Model",isRowHeader:!0,cell:r=>r.model},{id:"api_key",header:"API key",cell:r=>s.jsx("span",{className:"text-[var(--otari-muted)]",children:e(r.api_key_id)})},{id:"tokens",header:"Tokens",align:"end",cell:r=>_(r.total_tokens)},{id:"cost",header:"Cost",align:"end",cell:r=>I(r.cost)},{id:"latency",header:"Total time",align:"end",cell:r=>ke(r.latency_ms)},{id:"status",header:"Status",cell:r=>s.jsx(_t,{status:r.status})}]},[i]);return s.jsxs("div",{className:"flex flex-col gap-6",children:[s.jsx(Ze,{title:"Activity",description:"A per-request log of what the gateway served: tokens, cost, latency, and failures. No request or response content is stored."}),s.jsx(Je,{error:v.error??j.error}),s.jsxs("div",{className:"flex flex-col gap-3",children:[s.jsx(et,{presets:N,extentKey:je,onPreset:ie,onSelectRange:Be,onSelectFull:()=>w?ie(w):void 0,series:Ce,bucket:te,windowStart:d.start,windowEnd:d.end,loading:R.isLoading,ariaLabel:"Activity request volume over the selected window",action:s.jsx(Qe,{onRefresh:Ke,isFetching:v.isFetching,updatedAt:v.dataUpdatedAt})}),s.jsxs(tt,{chips:Ee,onClearAll:Ae,children:[s.jsx(be,{id:"filter-status",label:"Status",value:m,onChange:e=>a.patch({status:e}),children:fe.map(e=>s.jsx("option",{value:e.value,children:e.label},e.value))}),s.jsx(be,{id:"filter-priced",label:"Priced?",value:f,onChange:e=>a.patch({priced:e}),children:_e.map(e=>s.jsx("option",{value:e.value,children:e.label},e.value))}),s.jsx(W,{label:"API key",value:x,onChange:e=>a.patch({api_key_id:e}),placeholder:"All keys",options:ee}),s.jsx(W,{label:"User",value:p,onChange:e=>a.patch({user_id:e}),placeholder:"All users",options:se}),s.jsx(W,{label:"Model",value:c,onChange:e=>a.patch({model:e}),allowsCustom:!0,placeholder:"Any model",options:(c&&!L.includes(c)?[c,...L]:L).map(e=>({value:e,label:e}))})]})]}),re?s.jsxs(lt,{selectedCount:D,allMatching:g.allMatching,matchingTotal:T,canSelectAllMatching:Te,onSelectAllMatching:g.enableAllMatching,onClear:g.clear,children:[s.jsx(Y,{size:"sm",variant:"primary",onPress:()=>z(!0),children:"Set price"}),s.jsx(Y,{size:"sm",variant:"danger",onPress:()=>q(!0),children:"Delete"})]}):null,s.jsx(ot,{ariaLabel:"Activity log",columns:$e,rows:k,getRowKey:ht,isLoading:v.isLoading,emptyContent:Ne?"No requests match these filters.":"No requests recorded yet.",selectionMode:"multiple",selectedKeys:g.selectedKeys,onSelectionChange:g.onSelectionChange,disabledKeys:Fe,onRowAction:e=>ne(r=>r===e?null:e),rowClassName:xt,detailKey:Oe,renderDetail:Ue}),s.jsx(it,{page:H,pageSize:U,total:Pe,rowsOnPage:k.length,onPageChange:e=>a.patch({page:e}),onPageSizeChange:e=>a.patch({size:e,page:0}),isFetching:v.isFetching,hasNextFallback:k.length===U}),s.jsx(nt,{isOpen:De,onOpenChange:q,heading:"Delete usage rows",body:`Delete ${D.toLocaleString()} imported ${D===1?"row":"rows"}? Only imported rows are removed, and this cannot be undone.`,confirmLabel:"Delete",isPending:B.isPending,error:B.error,onConfirm:Le}),s.jsx(ct,{isOpen:Ie,onOpenChange:z,targetCount:D,isPending:$.isPending,error:$.error,onSubmit:Re})]})}export{It as ActivityPage}; diff --git a/src/gateway/static/dashboard/assets/AliasesPage-CPjhdIJQ.js b/src/gateway/static/dashboard/assets/AliasesPage-0BMZtDwo.js similarity index 98% rename from src/gateway/static/dashboard/assets/AliasesPage-CPjhdIJQ.js rename to src/gateway/static/dashboard/assets/AliasesPage-0BMZtDwo.js index 33954edf..a9a98998 100644 --- a/src/gateway/static/dashboard/assets/AliasesPage-CPjhdIJQ.js +++ b/src/gateway/static/dashboard/assets/AliasesPage-0BMZtDwo.js @@ -1 +1 @@ -import{j as e}from"./tanstack-query-1t81HyiD.js";import{r as d,u as L}from"./react-dgEcD0HR.js";import{h as T,i as E,j as M,C as I,P as K,E as S,k as A}from"./index-JlWCttWt.js";import{u as R,r as F,B as $}from"./tableSelection-9hV37uhu.js";import{C as q}from"./ConfirmDialog-DXR8OubG.js";import{D as O}from"./DataTable-Bmn_eYSV.js";import{F as V}from"./Field-Dwp6u3t8.js";import{C as N,L as z,I as H,a as G,b as W,f as X,B as h,d as k}from"./heroui-BI50yK5B.js";const _=50;function P({label:t,value:a,onChange:r,description:n,placeholder:u="provider:model",autoFocus:i,isRequired:m}){const c=T(),{visible:o,total:x,failed:p}=d.useMemo(()=>{var y;const l=a.trim().toLowerCase(),f=((y=c.data)==null?void 0:y.providers)??[],C=f.flatMap(g=>g.models),j=l?C.filter(g=>g.key.toLowerCase().includes(l)):C;return{visible:j.slice(0,_),total:j.length,failed:f.filter(g=>!g.ok)}},[c.data,a]),b=c.isLoading?"Loading models from your providers…":p.length>0?`Could not list models for ${p.map(f=>f.provider).join(", ")}. Check that provider's credentials, or type the model key directly.`:x>o.length?`Showing ${o.length} of ${x} matches. Keep typing to narrow them.`:n;return e.jsxs(N.Root,{allowsCustomValue:!0,allowsEmptyCollection:!0,menuTrigger:"input",inputValue:a,onInputChange:r,onSelectionChange:l=>{l!=null&&r(String(l))},isRequired:m,className:"flex max-w-md flex-col gap-1",children:[e.jsx(z,{className:"text-sm font-medium text-[var(--otari-ink)]",children:t}),e.jsxs(N.InputGroup,{children:[e.jsx(H,{placeholder:u,autoFocus:i}),e.jsx(N.Trigger,{})]}),e.jsx(N.Popover,{children:e.jsx(G,{items:o,className:"max-h-72 overflow-auto",children:l=>e.jsx(W,{id:l.key,textValue:l.key,children:l.key})})}),b?e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:b}):null]})}const J=t=>t.name;function Q({alias:t,onClose:a}){const r=A(),[n,u]=d.useState(t.target),i=n.trim()!==""&&n.trim()!==t.target,m=()=>{i&&r.mutate({name:t.name,target:n.trim()},{onSuccess:a})};return e.jsx(k,{children:e.jsxs(k.Content,{className:"flex flex-col gap-4 p-5",children:[e.jsxs("div",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:["Edit alias ",e.jsx("code",{children:t.name})]}),e.jsx(S,{error:r.error}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("span",{className:"text-sm font-medium text-[var(--otari-ink)]",children:"Alias name"}),e.jsx("code",{className:"text-sm text-[var(--otari-muted)]",children:t.name}),e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"The alias name is the key and cannot be changed here. Delete and recreate to rename."})]}),e.jsx(P,{label:"Target",value:n,onChange:u,isRequired:!0,description:"The real model this resolves to. Callers never see it."})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(h,{variant:"primary",isDisabled:!i||r.isPending,onPress:m,children:r.isPending?"Saving…":"Save changes"}),e.jsx(h,{variant:"ghost",onPress:a,children:"Cancel"})]})]})})}function U({onClose:t,initialTarget:a=""}){const r=A(),[n,u]=d.useState(""),[i,m]=d.useState(a),c=/[:/]/.test(n),o=n.trim()!==""&&i.trim()!==""&&!c,x=()=>{o&&r.mutate({name:n.trim(),target:i.trim()},{onSuccess:t})};return e.jsx(k,{children:e.jsxs(k.Content,{className:"flex flex-col gap-4 p-5",children:[e.jsx("div",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:"New alias"}),e.jsx(S,{error:r.error}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsx(V,{label:"Alias name",value:n,onChange:u,placeholder:"fast-model",isRequired:!0,autoFocus:!0,description:c?e.jsx("span",{className:"text-red-700",children:"An alias name cannot contain “:” or “/”."}):"What callers send as `model`."}),e.jsx(P,{label:"Target",value:i,onChange:m,isRequired:!0,description:"The real model this resolves to. Callers never see it."})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(h,{variant:"primary",isDisabled:!o||r.isPending,onPress:x,children:r.isPending?"Creating…":"Create alias"}),e.jsx(h,{variant:"ghost",onPress:t,children:"Cancel"})]})]})})}function le(){const t=E(),a=M(),[r]=L(),n=r.get("target")??"",[u,i]=d.useState(n!==""),[m,c]=d.useState(null),o=R(),[x,p]=d.useState(!1),[b,l]=d.useState(void 0),[f,C]=d.useState(!1),j=[...t.data??[]].sort((s,B)=>s.name.localeCompare(B.name)),y=j.filter(s=>s.source==="stored").map(s=>s.name),g=j.filter(s=>s.source!=="stored").map(s=>s.name),v=F(o.selectedKeys,y),w=async()=>{C(!0),l(void 0);try{for(const s of v)await a.mutateAsync(s);o.clear(),p(!1)}catch(s){l(s)}finally{C(!1)}},D=d.useMemo(()=>[{id:"alias",header:"Alias",isRowHeader:!0,cell:s=>e.jsx("span",{className:"font-medium break-all text-[var(--otari-ink)]",children:s.name})},{id:"target",header:"Target",cell:s=>e.jsx("span",{className:"break-all text-[var(--otari-muted)]",children:s.target})},{id:"source",header:"Source",cell:s=>e.jsx(X,{size:"sm",color:s.source==="stored"?"accent":"default",children:s.source})},{id:"actions",header:"Actions",align:"end",cell:s=>s.source==="stored"?e.jsxs("span",{className:"inline-flex items-center gap-2 whitespace-nowrap",children:[e.jsx(h,{size:"sm",variant:"ghost",onPress:()=>{i(!1),c(s)},children:"Edit"}),e.jsx(I,{confirmLabel:"Delete",isPending:a.isPending,onConfirm:()=>a.mutate(s.name),children:"Delete"})]}):e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"set in config.yml"})}],[a.isPending,a.mutate]);return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(K,{title:"Aliases",description:"Friendly names that map to a real provider:model. Callers send the alias as the model; pricing, budgets, and usage key on the target.",action:u||m?null:e.jsx(h,{variant:"primary",onPress:()=>{c(null),i(!0)},children:"New alias"})}),e.jsx(S,{error:t.error}),u?e.jsx(U,{initialTarget:n,onClose:()=>i(!1)}):null,m?e.jsx(Q,{alias:m,onClose:()=>c(null)}):null,a.error?e.jsx(S,{error:a.error}):null,v.length>0?e.jsx($,{selectedCount:v.length,allMatching:!1,matchingTotal:null,canSelectAllMatching:!1,onSelectAllMatching:()=>{},onClear:o.clear,children:e.jsx(h,{size:"sm",variant:"danger",onPress:()=>p(!0),children:"Delete"})}):null,e.jsx(O,{ariaLabel:"Aliases",columns:D,rows:j,getRowKey:J,isLoading:t.isLoading,emptyContent:"No aliases yet. Create one to give a model a friendly name.",selectionMode:"multiple",selectedKeys:o.selectedKeys,onSelectionChange:o.onSelectionChange,disabledKeys:g}),e.jsx(q,{isOpen:x,onOpenChange:p,heading:"Delete aliases",body:`Delete ${v.length} stored ${v.length===1?"alias":"aliases"}? Callers using ${v.length===1?"it":"them"} will get a model-not-found error.`,confirmLabel:"Delete",isPending:f,error:b,onConfirm:w})]})}export{le as AliasesPage}; +import{j as e}from"./tanstack-query-1t81HyiD.js";import{r as d,u as L}from"./react-dgEcD0HR.js";import{h as T,i as E,j as M,C as I,P as K,E as S,k as A}from"./index-BP-wLuMr.js";import{u as R,r as F,B as $}from"./tableSelection-9hV37uhu.js";import{C as q}from"./ConfirmDialog-BFS2k4X_.js";import{D as O}from"./DataTable-Bmn_eYSV.js";import{F as V}from"./Field-Dwp6u3t8.js";import{C as N,L as z,I as H,a as G,b as W,f as X,B as h,d as k}from"./heroui-BI50yK5B.js";const _=50;function P({label:t,value:a,onChange:r,description:n,placeholder:u="provider:model",autoFocus:i,isRequired:m}){const c=T(),{visible:o,total:x,failed:p}=d.useMemo(()=>{var y;const l=a.trim().toLowerCase(),f=((y=c.data)==null?void 0:y.providers)??[],C=f.flatMap(g=>g.models),j=l?C.filter(g=>g.key.toLowerCase().includes(l)):C;return{visible:j.slice(0,_),total:j.length,failed:f.filter(g=>!g.ok)}},[c.data,a]),b=c.isLoading?"Loading models from your providers…":p.length>0?`Could not list models for ${p.map(f=>f.provider).join(", ")}. Check that provider's credentials, or type the model key directly.`:x>o.length?`Showing ${o.length} of ${x} matches. Keep typing to narrow them.`:n;return e.jsxs(N.Root,{allowsCustomValue:!0,allowsEmptyCollection:!0,menuTrigger:"input",inputValue:a,onInputChange:r,onSelectionChange:l=>{l!=null&&r(String(l))},isRequired:m,className:"flex max-w-md flex-col gap-1",children:[e.jsx(z,{className:"text-sm font-medium text-[var(--otari-ink)]",children:t}),e.jsxs(N.InputGroup,{children:[e.jsx(H,{placeholder:u,autoFocus:i}),e.jsx(N.Trigger,{})]}),e.jsx(N.Popover,{children:e.jsx(G,{items:o,className:"max-h-72 overflow-auto",children:l=>e.jsx(W,{id:l.key,textValue:l.key,children:l.key})})}),b?e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:b}):null]})}const J=t=>t.name;function Q({alias:t,onClose:a}){const r=A(),[n,u]=d.useState(t.target),i=n.trim()!==""&&n.trim()!==t.target,m=()=>{i&&r.mutate({name:t.name,target:n.trim()},{onSuccess:a})};return e.jsx(k,{children:e.jsxs(k.Content,{className:"flex flex-col gap-4 p-5",children:[e.jsxs("div",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:["Edit alias ",e.jsx("code",{children:t.name})]}),e.jsx(S,{error:r.error}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("span",{className:"text-sm font-medium text-[var(--otari-ink)]",children:"Alias name"}),e.jsx("code",{className:"text-sm text-[var(--otari-muted)]",children:t.name}),e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"The alias name is the key and cannot be changed here. Delete and recreate to rename."})]}),e.jsx(P,{label:"Target",value:n,onChange:u,isRequired:!0,description:"The real model this resolves to. Callers never see it."})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(h,{variant:"primary",isDisabled:!i||r.isPending,onPress:m,children:r.isPending?"Saving…":"Save changes"}),e.jsx(h,{variant:"ghost",onPress:a,children:"Cancel"})]})]})})}function U({onClose:t,initialTarget:a=""}){const r=A(),[n,u]=d.useState(""),[i,m]=d.useState(a),c=/[:/]/.test(n),o=n.trim()!==""&&i.trim()!==""&&!c,x=()=>{o&&r.mutate({name:n.trim(),target:i.trim()},{onSuccess:t})};return e.jsx(k,{children:e.jsxs(k.Content,{className:"flex flex-col gap-4 p-5",children:[e.jsx("div",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:"New alias"}),e.jsx(S,{error:r.error}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsx(V,{label:"Alias name",value:n,onChange:u,placeholder:"fast-model",isRequired:!0,autoFocus:!0,description:c?e.jsx("span",{className:"text-red-700",children:"An alias name cannot contain “:” or “/”."}):"What callers send as `model`."}),e.jsx(P,{label:"Target",value:i,onChange:m,isRequired:!0,description:"The real model this resolves to. Callers never see it."})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(h,{variant:"primary",isDisabled:!o||r.isPending,onPress:x,children:r.isPending?"Creating…":"Create alias"}),e.jsx(h,{variant:"ghost",onPress:t,children:"Cancel"})]})]})})}function le(){const t=E(),a=M(),[r]=L(),n=r.get("target")??"",[u,i]=d.useState(n!==""),[m,c]=d.useState(null),o=R(),[x,p]=d.useState(!1),[b,l]=d.useState(void 0),[f,C]=d.useState(!1),j=[...t.data??[]].sort((s,B)=>s.name.localeCompare(B.name)),y=j.filter(s=>s.source==="stored").map(s=>s.name),g=j.filter(s=>s.source!=="stored").map(s=>s.name),v=F(o.selectedKeys,y),w=async()=>{C(!0),l(void 0);try{for(const s of v)await a.mutateAsync(s);o.clear(),p(!1)}catch(s){l(s)}finally{C(!1)}},D=d.useMemo(()=>[{id:"alias",header:"Alias",isRowHeader:!0,cell:s=>e.jsx("span",{className:"font-medium break-all text-[var(--otari-ink)]",children:s.name})},{id:"target",header:"Target",cell:s=>e.jsx("span",{className:"break-all text-[var(--otari-muted)]",children:s.target})},{id:"source",header:"Source",cell:s=>e.jsx(X,{size:"sm",color:s.source==="stored"?"accent":"default",children:s.source})},{id:"actions",header:"Actions",align:"end",cell:s=>s.source==="stored"?e.jsxs("span",{className:"inline-flex items-center gap-2 whitespace-nowrap",children:[e.jsx(h,{size:"sm",variant:"ghost",onPress:()=>{i(!1),c(s)},children:"Edit"}),e.jsx(I,{confirmLabel:"Delete",isPending:a.isPending,onConfirm:()=>a.mutate(s.name),children:"Delete"})]}):e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"set in config.yml"})}],[a.isPending,a.mutate]);return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(K,{title:"Aliases",description:"Friendly names that map to a real provider:model. Callers send the alias as the model; pricing, budgets, and usage key on the target.",action:u||m?null:e.jsx(h,{variant:"primary",onPress:()=>{c(null),i(!0)},children:"New alias"})}),e.jsx(S,{error:t.error}),u?e.jsx(U,{initialTarget:n,onClose:()=>i(!1)}):null,m?e.jsx(Q,{alias:m,onClose:()=>c(null)}):null,a.error?e.jsx(S,{error:a.error}):null,v.length>0?e.jsx($,{selectedCount:v.length,allMatching:!1,matchingTotal:null,canSelectAllMatching:!1,onSelectAllMatching:()=>{},onClear:o.clear,children:e.jsx(h,{size:"sm",variant:"danger",onPress:()=>p(!0),children:"Delete"})}):null,e.jsx(O,{ariaLabel:"Aliases",columns:D,rows:j,getRowKey:J,isLoading:t.isLoading,emptyContent:"No aliases yet. Create one to give a model a friendly name.",selectionMode:"multiple",selectedKeys:o.selectedKeys,onSelectionChange:o.onSelectionChange,disabledKeys:g}),e.jsx(q,{isOpen:x,onOpenChange:p,heading:"Delete aliases",body:`Delete ${v.length} stored ${v.length===1?"alias":"aliases"}? Callers using ${v.length===1?"it":"them"} will get a model-not-found error.`,confirmLabel:"Delete",isPending:f,error:b,onConfirm:w})]})}export{le as AliasesPage}; diff --git a/src/gateway/static/dashboard/assets/BudgetsPage-BuN1cg5q.js b/src/gateway/static/dashboard/assets/BudgetsPage-DSFlTi1s.js similarity index 99% rename from src/gateway/static/dashboard/assets/BudgetsPage-BuN1cg5q.js rename to src/gateway/static/dashboard/assets/BudgetsPage-DSFlTi1s.js index e2625c88..e242ec1a 100644 --- a/src/gateway/static/dashboard/assets/BudgetsPage-BuN1cg5q.js +++ b/src/gateway/static/dashboard/assets/BudgetsPage-DSFlTi1s.js @@ -1 +1 @@ -import{j as e}from"./tanstack-query-1t81HyiD.js";import{r as i}from"./react-dgEcD0HR.js";import{l as ae,u as re,m as le,n as ie,o as oe,p as de,P as ue,E as T,I as ce,q as me,r as xe}from"./index-JlWCttWt.js";import{u as ge,r as he,B as pe}from"./tableSelection-9hV37uhu.js";import{C as fe}from"./ConfirmDialog-DXR8OubG.js";import{D as be}from"./DataTable-Bmn_eYSV.js";import{F as z}from"./Field-Dwp6u3t8.js";import{C as E,I as je,a as ve,b as ye,B as x,d as k,S as Ne}from"./heroui-BI50yK5B.js";const Se=50;function _e({value:t,onChange:r,users:a,label:o,description:l}){const[g,h]=i.useState(""),d=i.useMemo(()=>a.filter(s=>!s.user_id.startsWith("apikey-")).map(s=>({id:s.user_id,label:s.alias?`${s.user_id} (${s.alias})`:s.user_id})),[a]),p=i.useMemo(()=>{const s=g.trim().toLowerCase();return d.filter(u=>!t.includes(u.id)).filter(u=>!s||u.id.toLowerCase().includes(s)||u.label.toLowerCase().includes(s)).slice(0,Se)},[d,t,g]),c=s=>{t.includes(s)||r([...t,s]),h("")},m=s=>r(t.filter(u=>u!==s));return e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsxs("div",{children:[e.jsx("span",{className:"text-sm font-medium text-[var(--otari-ink)]",children:o}),l?e.jsx("p",{className:"text-xs text-[var(--otari-muted)]",children:l}):null]}),t.length>0?e.jsx("div",{className:"flex flex-wrap gap-1.5",children:t.map(s=>e.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full bg-[var(--otari-brand-tint)] px-2.5 py-1 font-mono text-xs text-[var(--otari-brand-dark)]",children:[s,e.jsx("button",{type:"button","aria-label":`Remove ${s}`,onClick:()=>m(s),className:"text-[var(--otari-brand-dark)] hover:text-red-700",children:"×"})]},s))}):null,d.length===0?e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"No users yet. Create users first, then assign them here or from the Users page."}):e.jsxs(E.Root,{allowsEmptyCollection:!0,menuTrigger:"input",inputValue:g,onInputChange:h,selectedKey:null,onSelectionChange:s=>{s!=null&&c(String(s))},className:"flex flex-col gap-1",children:[e.jsxs(E.InputGroup,{children:[e.jsx(je,{"aria-label":"Add a user",placeholder:"Search users…",autoComplete:"off"}),e.jsx(E.Trigger,{})]}),e.jsx(E.Popover,{children:e.jsx(ve,{items:p,className:"max-h-72 overflow-auto",children:s=>e.jsx(ye,{id:s.id,textValue:s.label,children:s.label})})})]})]})}const Ce=new Intl.NumberFormat(void 0,{style:"currency",currency:"USD",maximumFractionDigits:2});function D(t){return Ce.format(t)}const j=86400,q=3600,O=[{label:"No reset",seconds:null},{label:"Daily",seconds:j},{label:"Weekly",seconds:7*j},{label:"Monthly",seconds:30*j}];function we(t){if(t===null)return"No reset";const r=O.find(a=>a.seconds===t);return r?r.label:t%j===0?`Every ${t/j} days`:t%q===0?`Every ${t/q} hours`:`Every ${t}s`}function W(t){if(!t)return"—";const r=new Date(t);return Number.isNaN(r.getTime())?"—":r.toLocaleString()}function De(t){const r=t.trim();if(r==="")return{value:null,valid:!0};const a=Number(r);return!Number.isFinite(a)||a<0?{value:null,valid:!1}:{value:a,valid:!0}}function Y(t){return t!==null&&t%j===0?String(t/j):""}function Be({value:t,onChange:r,onInvalidChange:a}){const o=O.some(s=>s.seconds===t),[l,g]=i.useState(!o),[h,d]=i.useState(()=>Y(t)),p=h.trim(),c=Number(p),m=p!==""&&(!Number.isSafeInteger(c)||c<=0);return i.useEffect(()=>{a==null||a(m)},[m,a]),e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx("span",{className:"text-sm font-medium text-[var(--otari-ink)]",children:"Reset period"}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[O.map(s=>e.jsx(x,{size:"sm",variant:!l&&t===s.seconds?"primary":"outline",onPress:()=>{g(!1),d(Y(s.seconds)),r(s.seconds)},children:s.label},s.label)),e.jsx(x,{size:"sm",variant:l?"primary":"outline",onPress:()=>g(!0),children:"Custom"})]}),l?e.jsx("div",{className:"flex items-end gap-2",children:e.jsx(z,{label:"Every N days",value:h,onChange:s=>{d(s);const u=Number(s.trim());r(s.trim()===""||!Number.isSafeInteger(u)||u<=0?null:u*j)},placeholder:"14",description:m?e.jsx("span",{className:"text-red-700",children:"Enter a whole number of days."}):"Whole days between resets."})}):null,e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"Spend returns to zero each period. A user’s clock starts when the budget is assigned to them."})]})}function G({title:t,submitLabel:r,initial:a,error:o,isPending:l,onSubmit:g,onClose:h,assignUsers:d}){const[p,c]=i.useState(a.name??""),[m,s]=i.useState(a.max_budget===null?"":String(a.max_budget)),[u,b]=i.useState(a.budget_duration_sec),[S,v]=i.useState(!1),[B,P]=i.useState([]),f=De(m),A=!l&&f.valid&&!S,C=()=>{A&&g({name:p.trim()||null,max_budget:f.value,budget_duration_sec:u},B)};return e.jsx(k,{children:e.jsxs(k.Content,{className:"flex flex-col gap-4 p-5",children:[e.jsx("div",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:t}),e.jsx(T,{error:o}),e.jsx(z,{label:"Name (optional)",value:p,onChange:c,autoFocus:!0,placeholder:"team-free-tier",description:"A label to recognize this budget later."}),e.jsx(z,{label:"Spending limit (USD)",value:m,onChange:s,placeholder:"100.00",description:f.valid?"The most a single user on this budget may spend per period. Leave blank for no limit.":e.jsx("span",{className:"text-red-700",children:"Enter a non-negative number, or leave blank for no limit."})}),e.jsx(Be,{value:u,onChange:b,onInvalidChange:v}),d?e.jsx(_e,{label:"Assign to users (optional)",description:"Attach this budget to existing users now. You can also manage assignments later on the Users page.",value:B,onChange:P,users:d}):null,e.jsxs("div",{className:"flex gap-2",children:[e.jsx(x,{variant:"primary",isDisabled:!A,onPress:C,children:l?"Saving…":r}),e.jsx(x,{variant:"ghost",isDisabled:l,onPress:h,children:"Cancel"})]})]})})}function Pe({budget:t}){if(t.user_count===0)return e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"No users assigned"});const r=t.total_spend;if(t.max_budget===null)return e.jsxs("span",{className:"text-xs text-[var(--otari-ink)]",children:[D(r)," spent",e.jsx("span",{className:"text-[var(--otari-muted)]",children:" · no limit"})]});const a=t.max_budget*t.user_count,o=a>0?Math.min(100,r/a*100):0,l=r>a;return e.jsxs("div",{className:"flex min-w-[140px] flex-col gap-1",children:[e.jsxs("div",{className:"flex items-baseline justify-between gap-2 text-xs",children:[e.jsx("span",{className:"text-[var(--otari-ink)]",children:D(r)}),e.jsxs("span",{className:"text-[var(--otari-muted)]",children:["of ",D(a)]})]}),e.jsx("div",{className:"h-1.5 w-full overflow-hidden rounded-full bg-[var(--otari-line)]",role:"progressbar","aria-valuenow":Math.round(o),"aria-valuemin":0,"aria-valuemax":100,"aria-label":"Aggregate spend against total allocation",children:e.jsx("div",{className:`h-full rounded-full ${l?"bg-red-500":"bg-[var(--otari-brand)]"}`,style:{width:`${Math.max(o,l?100:2)}%`}})})]})}function Ae({budgetId:t}){const r=xe(t);if(r.isLoading)return e.jsxs("div",{className:"flex items-center gap-2 px-4 py-4 text-sm text-[var(--otari-muted)]",children:[e.jsx(Ne,{size:"sm"})," Loading reset history…"]});if(r.error)return e.jsx("div",{className:"px-4 py-4",children:e.jsx(T,{error:r.error})});const a=r.data??[];return a.length===0?e.jsx("div",{className:"px-4 py-4 text-sm text-[var(--otari-muted)]",children:"No resets recorded yet for this budget."}):e.jsx("div",{className:"overflow-x-auto px-4 py-3",children:e.jsxs("table",{className:"w-full border-collapse text-xs",children:[e.jsx("thead",{className:"text-left text-[var(--otari-muted)]",children:e.jsxs("tr",{children:[e.jsx("th",{className:"py-1.5 pr-4 font-medium",children:"User"}),e.jsx("th",{className:"py-1.5 pr-4 font-medium",children:"Spend cleared"}),e.jsx("th",{className:"py-1.5 pr-4 font-medium",children:"Reset at"}),e.jsx("th",{className:"py-1.5 font-medium",children:"Next reset"})]})}),e.jsx("tbody",{children:a.map(o=>e.jsxs("tr",{className:"border-t border-[var(--otari-line)]",children:[e.jsx("td",{className:"py-1.5 pr-4",children:e.jsx("code",{children:o.user_id??"—"})}),e.jsx("td",{className:"py-1.5 pr-4 text-[var(--otari-ink)]",children:D(o.previous_spend)}),e.jsx("td",{className:"py-1.5 pr-4 text-[var(--otari-muted)]",children:W(o.reset_at)}),e.jsx("td",{className:"py-1.5 text-[var(--otari-muted)]",children:W(o.next_reset_at)})]},o.id))})]})})}function Ee({label:t,isPending:r,onConfirm:a}){const[o,l]=i.useState(!1);return o?e.jsxs("div",{className:"flex flex-col items-end gap-1.5 rounded-lg border border-amber-200 bg-amber-50 p-2 text-right",children:[e.jsxs("span",{className:"max-w-xs text-xs text-amber-800",children:["Delete ",e.jsx("strong",{children:t}),"? Users keep their spend but lose this limit. Cannot be undone."]}),e.jsxs("span",{className:"inline-flex gap-1",children:[e.jsx(x,{size:"sm",variant:"danger",isDisabled:r,onPress:a,children:"Delete permanently"}),e.jsx(x,{size:"sm",variant:"ghost",isDisabled:r,onPress:()=>l(!1),children:"Cancel"})]})]}):e.jsx(x,{size:"sm",variant:"danger-soft",onPress:()=>l(!0),children:"Delete"})}const ke=t=>t.budget_id;function Q(t){return t.split("-")[0]}function $(t){return t.name??Q(t.budget_id)}function Te(){const t=ae(),r=re(),a=le(),o=ie(),l=oe(),g=de(),[h,d]=i.useState(!1),[p,c]=i.useState(null),[m,s]=i.useState(null),[u,b]=i.useState(null),[S,v]=i.useState(null),[B,P]=i.useState(!1),f=ge(),[A,C]=i.useState(!1),[X,F]=i.useState(void 0),[J,H]=i.useState(!1),w=t.data??[],K=t.isLoading,y=w.find(n=>n.budget_id===p)??null,U=w.find(n=>n.budget_id===m)??null,L=!K&&w.length===0&&!h,Z=w.map(n=>n.budget_id),_=he(f.selectedKeys,Z),ee=async()=>{H(!0),F(void 0);try{for(const n of _)await l.mutateAsync(n);f.clear(),C(!1)}catch(n){F(n)}finally{H(!1)}},te=i.useMemo(()=>[{id:"budget",header:"Budget",isRowHeader:!0,cell:n=>e.jsxs("div",{className:"flex flex-col gap-0.5",children:[e.jsx("span",{className:"font-medium text-[var(--otari-ink)]",children:n.name??e.jsx("span",{className:"text-[var(--otari-muted)]",children:"(unnamed)"})}),e.jsx("code",{className:"text-[11px] text-[var(--otari-muted)]",title:n.budget_id,children:Q(n.budget_id)})]})},{id:"limit",header:"Limit (per user)",cell:n=>n.max_budget===null?e.jsx("span",{className:"text-[var(--otari-muted)]",children:"Unlimited"}):D(n.max_budget)},{id:"reset",header:"Reset",cell:n=>e.jsx("span",{className:"text-[var(--otari-muted)]",children:we(n.budget_duration_sec)})},{id:"users",header:"Users",cell:n=>e.jsx("span",{className:"text-[var(--otari-muted)]",children:n.user_count})},{id:"usage",header:"Usage",cell:n=>e.jsx(Pe,{budget:n})},{id:"actions",header:"Actions",align:"end",cell:n=>e.jsxs("div",{className:"flex items-center justify-end gap-1.5",children:[e.jsx(x,{size:"sm",variant:"ghost",onPress:()=>s(N=>N===n.budget_id?null:n.budget_id),children:m===n.budget_id?"Hide history":"History"}),e.jsx(x,{size:"sm",variant:"ghost",onPress:()=>{d(!1),c(n.budget_id)},children:"Edit"}),e.jsx(Ee,{label:$(n),isPending:l.isPending,onConfirm:()=>l.mutate(n.budget_id)})]})}],[m,l.isPending,l.mutate]),V=async(n,N)=>{P(!0),b(null);const I=await Promise.allSettled(N.map(M=>g.mutateAsync({id:M,body:{budget_id:n}})));P(!1);const R=I.flatMap((M,ne)=>M.status==="rejected"?[N[ne]]:[]);if(R.length>0){v({budgetId:n,userIds:R}),b(new Error(`Budget created, but could not assign it to: ${R.join(", ")}. Retry to try again.`));return}v(null),d(!1)},se=(n,N)=>{if(S){V(S.budgetId,S.userIds);return}b(null),a.mutate(n,{onSuccess:async I=>{if(N.length>0){await V(I.budget_id,N);return}d(!1)}})};return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(ue,{title:"Budgets",description:"Define spending limits and reset schedules. Assign a budget to users to enforce it.",action:h||L?null:e.jsx(x,{variant:"primary",onPress:()=>{c(null),b(null),v(null),d(!0)},children:"Create budget"})}),e.jsx(T,{error:t.error??a.error??o.error??l.error??g.error}),e.jsx(ce,{children:"Assign a budget to users when you create it, or later from the Users page. Each row’s usage aggregates the spend of the users currently on that budget."}),L?e.jsx(me,{title:"No budgets yet",description:"A budget caps how much a user may spend and, optionally, resets that spend on a schedule. Create one, then assign it to users to enforce a limit.",actionLabel:"Create your first budget",onAction:()=>{c(null),b(null),v(null),d(!0)}}):null,h?e.jsx(G,{title:"Create budget",submitLabel:S?"Retry assignments":"Create budget",initial:{name:null,max_budget:null,budget_duration_sec:null},error:a.error??u,isPending:a.isPending||B,assignUsers:r.data??[],onSubmit:se,onClose:()=>{b(null),v(null),d(!1)}}):null,y?e.jsx(G,{title:`Edit budget ${$(y)}`,submitLabel:"Save changes",initial:{name:y.name,max_budget:y.max_budget,budget_duration_sec:y.budget_duration_sec},error:o.error,isPending:o.isPending,onSubmit:n=>o.mutate({id:y.budget_id,body:n},{onSuccess:()=>c(null)}),onClose:()=>c(null)},y.budget_id):null,_.length>0?e.jsx(pe,{selectedCount:_.length,allMatching:!1,matchingTotal:null,canSelectAllMatching:!1,onSelectAllMatching:()=>{},onClear:f.clear,children:e.jsx(x,{size:"sm",variant:"danger",onPress:()=>C(!0),children:"Delete"})}):null,L?null:e.jsx(be,{ariaLabel:"Budgets",columns:te,rows:w,getRowKey:ke,isLoading:K,emptyContent:"No budgets yet. Create one to cap spending.",selectionMode:"multiple",selectedKeys:f.selectedKeys,onSelectionChange:f.onSelectionChange}),U?e.jsx(k,{children:e.jsxs(k.Content,{className:"p-0",children:[e.jsxs("div",{className:"flex items-center justify-between border-b border-[var(--otari-line)] px-4 py-2",children:[e.jsxs("span",{className:"text-sm font-medium text-[var(--otari-ink)]",children:["Reset history — ",$(U)]}),e.jsx(x,{size:"sm",variant:"ghost",onPress:()=>s(null),children:"Close"})]}),e.jsx(Ae,{budgetId:U.budget_id})]})}):null,e.jsx(fe,{isOpen:A,onOpenChange:C,heading:"Delete budgets",body:`Delete ${_.length} ${_.length===1?"budget":"budgets"}? Users on ${_.length===1?"it":"them"} will no longer be capped.`,confirmLabel:"Delete",isPending:J,error:X,onConfirm:ee})]})}export{Te as BudgetsPage}; +import{j as e}from"./tanstack-query-1t81HyiD.js";import{r as i}from"./react-dgEcD0HR.js";import{l as ae,u as re,m as le,n as ie,o as oe,p as de,P as ue,E as T,I as ce,q as me,r as xe}from"./index-BP-wLuMr.js";import{u as ge,r as he,B as pe}from"./tableSelection-9hV37uhu.js";import{C as fe}from"./ConfirmDialog-BFS2k4X_.js";import{D as be}from"./DataTable-Bmn_eYSV.js";import{F as z}from"./Field-Dwp6u3t8.js";import{C as E,I as je,a as ve,b as ye,B as x,d as k,S as Ne}from"./heroui-BI50yK5B.js";const Se=50;function _e({value:t,onChange:r,users:a,label:o,description:l}){const[g,h]=i.useState(""),d=i.useMemo(()=>a.filter(s=>!s.user_id.startsWith("apikey-")).map(s=>({id:s.user_id,label:s.alias?`${s.user_id} (${s.alias})`:s.user_id})),[a]),p=i.useMemo(()=>{const s=g.trim().toLowerCase();return d.filter(u=>!t.includes(u.id)).filter(u=>!s||u.id.toLowerCase().includes(s)||u.label.toLowerCase().includes(s)).slice(0,Se)},[d,t,g]),c=s=>{t.includes(s)||r([...t,s]),h("")},m=s=>r(t.filter(u=>u!==s));return e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsxs("div",{children:[e.jsx("span",{className:"text-sm font-medium text-[var(--otari-ink)]",children:o}),l?e.jsx("p",{className:"text-xs text-[var(--otari-muted)]",children:l}):null]}),t.length>0?e.jsx("div",{className:"flex flex-wrap gap-1.5",children:t.map(s=>e.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full bg-[var(--otari-brand-tint)] px-2.5 py-1 font-mono text-xs text-[var(--otari-brand-dark)]",children:[s,e.jsx("button",{type:"button","aria-label":`Remove ${s}`,onClick:()=>m(s),className:"text-[var(--otari-brand-dark)] hover:text-red-700",children:"×"})]},s))}):null,d.length===0?e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"No users yet. Create users first, then assign them here or from the Users page."}):e.jsxs(E.Root,{allowsEmptyCollection:!0,menuTrigger:"input",inputValue:g,onInputChange:h,selectedKey:null,onSelectionChange:s=>{s!=null&&c(String(s))},className:"flex flex-col gap-1",children:[e.jsxs(E.InputGroup,{children:[e.jsx(je,{"aria-label":"Add a user",placeholder:"Search users…",autoComplete:"off"}),e.jsx(E.Trigger,{})]}),e.jsx(E.Popover,{children:e.jsx(ve,{items:p,className:"max-h-72 overflow-auto",children:s=>e.jsx(ye,{id:s.id,textValue:s.label,children:s.label})})})]})]})}const Ce=new Intl.NumberFormat(void 0,{style:"currency",currency:"USD",maximumFractionDigits:2});function D(t){return Ce.format(t)}const j=86400,q=3600,O=[{label:"No reset",seconds:null},{label:"Daily",seconds:j},{label:"Weekly",seconds:7*j},{label:"Monthly",seconds:30*j}];function we(t){if(t===null)return"No reset";const r=O.find(a=>a.seconds===t);return r?r.label:t%j===0?`Every ${t/j} days`:t%q===0?`Every ${t/q} hours`:`Every ${t}s`}function W(t){if(!t)return"—";const r=new Date(t);return Number.isNaN(r.getTime())?"—":r.toLocaleString()}function De(t){const r=t.trim();if(r==="")return{value:null,valid:!0};const a=Number(r);return!Number.isFinite(a)||a<0?{value:null,valid:!1}:{value:a,valid:!0}}function Y(t){return t!==null&&t%j===0?String(t/j):""}function Be({value:t,onChange:r,onInvalidChange:a}){const o=O.some(s=>s.seconds===t),[l,g]=i.useState(!o),[h,d]=i.useState(()=>Y(t)),p=h.trim(),c=Number(p),m=p!==""&&(!Number.isSafeInteger(c)||c<=0);return i.useEffect(()=>{a==null||a(m)},[m,a]),e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx("span",{className:"text-sm font-medium text-[var(--otari-ink)]",children:"Reset period"}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[O.map(s=>e.jsx(x,{size:"sm",variant:!l&&t===s.seconds?"primary":"outline",onPress:()=>{g(!1),d(Y(s.seconds)),r(s.seconds)},children:s.label},s.label)),e.jsx(x,{size:"sm",variant:l?"primary":"outline",onPress:()=>g(!0),children:"Custom"})]}),l?e.jsx("div",{className:"flex items-end gap-2",children:e.jsx(z,{label:"Every N days",value:h,onChange:s=>{d(s);const u=Number(s.trim());r(s.trim()===""||!Number.isSafeInteger(u)||u<=0?null:u*j)},placeholder:"14",description:m?e.jsx("span",{className:"text-red-700",children:"Enter a whole number of days."}):"Whole days between resets."})}):null,e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"Spend returns to zero each period. A user’s clock starts when the budget is assigned to them."})]})}function G({title:t,submitLabel:r,initial:a,error:o,isPending:l,onSubmit:g,onClose:h,assignUsers:d}){const[p,c]=i.useState(a.name??""),[m,s]=i.useState(a.max_budget===null?"":String(a.max_budget)),[u,b]=i.useState(a.budget_duration_sec),[S,v]=i.useState(!1),[B,P]=i.useState([]),f=De(m),A=!l&&f.valid&&!S,C=()=>{A&&g({name:p.trim()||null,max_budget:f.value,budget_duration_sec:u},B)};return e.jsx(k,{children:e.jsxs(k.Content,{className:"flex flex-col gap-4 p-5",children:[e.jsx("div",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:t}),e.jsx(T,{error:o}),e.jsx(z,{label:"Name (optional)",value:p,onChange:c,autoFocus:!0,placeholder:"team-free-tier",description:"A label to recognize this budget later."}),e.jsx(z,{label:"Spending limit (USD)",value:m,onChange:s,placeholder:"100.00",description:f.valid?"The most a single user on this budget may spend per period. Leave blank for no limit.":e.jsx("span",{className:"text-red-700",children:"Enter a non-negative number, or leave blank for no limit."})}),e.jsx(Be,{value:u,onChange:b,onInvalidChange:v}),d?e.jsx(_e,{label:"Assign to users (optional)",description:"Attach this budget to existing users now. You can also manage assignments later on the Users page.",value:B,onChange:P,users:d}):null,e.jsxs("div",{className:"flex gap-2",children:[e.jsx(x,{variant:"primary",isDisabled:!A,onPress:C,children:l?"Saving…":r}),e.jsx(x,{variant:"ghost",isDisabled:l,onPress:h,children:"Cancel"})]})]})})}function Pe({budget:t}){if(t.user_count===0)return e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"No users assigned"});const r=t.total_spend;if(t.max_budget===null)return e.jsxs("span",{className:"text-xs text-[var(--otari-ink)]",children:[D(r)," spent",e.jsx("span",{className:"text-[var(--otari-muted)]",children:" · no limit"})]});const a=t.max_budget*t.user_count,o=a>0?Math.min(100,r/a*100):0,l=r>a;return e.jsxs("div",{className:"flex min-w-[140px] flex-col gap-1",children:[e.jsxs("div",{className:"flex items-baseline justify-between gap-2 text-xs",children:[e.jsx("span",{className:"text-[var(--otari-ink)]",children:D(r)}),e.jsxs("span",{className:"text-[var(--otari-muted)]",children:["of ",D(a)]})]}),e.jsx("div",{className:"h-1.5 w-full overflow-hidden rounded-full bg-[var(--otari-line)]",role:"progressbar","aria-valuenow":Math.round(o),"aria-valuemin":0,"aria-valuemax":100,"aria-label":"Aggregate spend against total allocation",children:e.jsx("div",{className:`h-full rounded-full ${l?"bg-red-500":"bg-[var(--otari-brand)]"}`,style:{width:`${Math.max(o,l?100:2)}%`}})})]})}function Ae({budgetId:t}){const r=xe(t);if(r.isLoading)return e.jsxs("div",{className:"flex items-center gap-2 px-4 py-4 text-sm text-[var(--otari-muted)]",children:[e.jsx(Ne,{size:"sm"})," Loading reset history…"]});if(r.error)return e.jsx("div",{className:"px-4 py-4",children:e.jsx(T,{error:r.error})});const a=r.data??[];return a.length===0?e.jsx("div",{className:"px-4 py-4 text-sm text-[var(--otari-muted)]",children:"No resets recorded yet for this budget."}):e.jsx("div",{className:"overflow-x-auto px-4 py-3",children:e.jsxs("table",{className:"w-full border-collapse text-xs",children:[e.jsx("thead",{className:"text-left text-[var(--otari-muted)]",children:e.jsxs("tr",{children:[e.jsx("th",{className:"py-1.5 pr-4 font-medium",children:"User"}),e.jsx("th",{className:"py-1.5 pr-4 font-medium",children:"Spend cleared"}),e.jsx("th",{className:"py-1.5 pr-4 font-medium",children:"Reset at"}),e.jsx("th",{className:"py-1.5 font-medium",children:"Next reset"})]})}),e.jsx("tbody",{children:a.map(o=>e.jsxs("tr",{className:"border-t border-[var(--otari-line)]",children:[e.jsx("td",{className:"py-1.5 pr-4",children:e.jsx("code",{children:o.user_id??"—"})}),e.jsx("td",{className:"py-1.5 pr-4 text-[var(--otari-ink)]",children:D(o.previous_spend)}),e.jsx("td",{className:"py-1.5 pr-4 text-[var(--otari-muted)]",children:W(o.reset_at)}),e.jsx("td",{className:"py-1.5 text-[var(--otari-muted)]",children:W(o.next_reset_at)})]},o.id))})]})})}function Ee({label:t,isPending:r,onConfirm:a}){const[o,l]=i.useState(!1);return o?e.jsxs("div",{className:"flex flex-col items-end gap-1.5 rounded-lg border border-amber-200 bg-amber-50 p-2 text-right",children:[e.jsxs("span",{className:"max-w-xs text-xs text-amber-800",children:["Delete ",e.jsx("strong",{children:t}),"? Users keep their spend but lose this limit. Cannot be undone."]}),e.jsxs("span",{className:"inline-flex gap-1",children:[e.jsx(x,{size:"sm",variant:"danger",isDisabled:r,onPress:a,children:"Delete permanently"}),e.jsx(x,{size:"sm",variant:"ghost",isDisabled:r,onPress:()=>l(!1),children:"Cancel"})]})]}):e.jsx(x,{size:"sm",variant:"danger-soft",onPress:()=>l(!0),children:"Delete"})}const ke=t=>t.budget_id;function Q(t){return t.split("-")[0]}function $(t){return t.name??Q(t.budget_id)}function Te(){const t=ae(),r=re(),a=le(),o=ie(),l=oe(),g=de(),[h,d]=i.useState(!1),[p,c]=i.useState(null),[m,s]=i.useState(null),[u,b]=i.useState(null),[S,v]=i.useState(null),[B,P]=i.useState(!1),f=ge(),[A,C]=i.useState(!1),[X,F]=i.useState(void 0),[J,H]=i.useState(!1),w=t.data??[],K=t.isLoading,y=w.find(n=>n.budget_id===p)??null,U=w.find(n=>n.budget_id===m)??null,L=!K&&w.length===0&&!h,Z=w.map(n=>n.budget_id),_=he(f.selectedKeys,Z),ee=async()=>{H(!0),F(void 0);try{for(const n of _)await l.mutateAsync(n);f.clear(),C(!1)}catch(n){F(n)}finally{H(!1)}},te=i.useMemo(()=>[{id:"budget",header:"Budget",isRowHeader:!0,cell:n=>e.jsxs("div",{className:"flex flex-col gap-0.5",children:[e.jsx("span",{className:"font-medium text-[var(--otari-ink)]",children:n.name??e.jsx("span",{className:"text-[var(--otari-muted)]",children:"(unnamed)"})}),e.jsx("code",{className:"text-[11px] text-[var(--otari-muted)]",title:n.budget_id,children:Q(n.budget_id)})]})},{id:"limit",header:"Limit (per user)",cell:n=>n.max_budget===null?e.jsx("span",{className:"text-[var(--otari-muted)]",children:"Unlimited"}):D(n.max_budget)},{id:"reset",header:"Reset",cell:n=>e.jsx("span",{className:"text-[var(--otari-muted)]",children:we(n.budget_duration_sec)})},{id:"users",header:"Users",cell:n=>e.jsx("span",{className:"text-[var(--otari-muted)]",children:n.user_count})},{id:"usage",header:"Usage",cell:n=>e.jsx(Pe,{budget:n})},{id:"actions",header:"Actions",align:"end",cell:n=>e.jsxs("div",{className:"flex items-center justify-end gap-1.5",children:[e.jsx(x,{size:"sm",variant:"ghost",onPress:()=>s(N=>N===n.budget_id?null:n.budget_id),children:m===n.budget_id?"Hide history":"History"}),e.jsx(x,{size:"sm",variant:"ghost",onPress:()=>{d(!1),c(n.budget_id)},children:"Edit"}),e.jsx(Ee,{label:$(n),isPending:l.isPending,onConfirm:()=>l.mutate(n.budget_id)})]})}],[m,l.isPending,l.mutate]),V=async(n,N)=>{P(!0),b(null);const I=await Promise.allSettled(N.map(M=>g.mutateAsync({id:M,body:{budget_id:n}})));P(!1);const R=I.flatMap((M,ne)=>M.status==="rejected"?[N[ne]]:[]);if(R.length>0){v({budgetId:n,userIds:R}),b(new Error(`Budget created, but could not assign it to: ${R.join(", ")}. Retry to try again.`));return}v(null),d(!1)},se=(n,N)=>{if(S){V(S.budgetId,S.userIds);return}b(null),a.mutate(n,{onSuccess:async I=>{if(N.length>0){await V(I.budget_id,N);return}d(!1)}})};return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(ue,{title:"Budgets",description:"Define spending limits and reset schedules. Assign a budget to users to enforce it.",action:h||L?null:e.jsx(x,{variant:"primary",onPress:()=>{c(null),b(null),v(null),d(!0)},children:"Create budget"})}),e.jsx(T,{error:t.error??a.error??o.error??l.error??g.error}),e.jsx(ce,{children:"Assign a budget to users when you create it, or later from the Users page. Each row’s usage aggregates the spend of the users currently on that budget."}),L?e.jsx(me,{title:"No budgets yet",description:"A budget caps how much a user may spend and, optionally, resets that spend on a schedule. Create one, then assign it to users to enforce a limit.",actionLabel:"Create your first budget",onAction:()=>{c(null),b(null),v(null),d(!0)}}):null,h?e.jsx(G,{title:"Create budget",submitLabel:S?"Retry assignments":"Create budget",initial:{name:null,max_budget:null,budget_duration_sec:null},error:a.error??u,isPending:a.isPending||B,assignUsers:r.data??[],onSubmit:se,onClose:()=>{b(null),v(null),d(!1)}}):null,y?e.jsx(G,{title:`Edit budget ${$(y)}`,submitLabel:"Save changes",initial:{name:y.name,max_budget:y.max_budget,budget_duration_sec:y.budget_duration_sec},error:o.error,isPending:o.isPending,onSubmit:n=>o.mutate({id:y.budget_id,body:n},{onSuccess:()=>c(null)}),onClose:()=>c(null)},y.budget_id):null,_.length>0?e.jsx(pe,{selectedCount:_.length,allMatching:!1,matchingTotal:null,canSelectAllMatching:!1,onSelectAllMatching:()=>{},onClear:f.clear,children:e.jsx(x,{size:"sm",variant:"danger",onPress:()=>C(!0),children:"Delete"})}):null,L?null:e.jsx(be,{ariaLabel:"Budgets",columns:te,rows:w,getRowKey:ke,isLoading:K,emptyContent:"No budgets yet. Create one to cap spending.",selectionMode:"multiple",selectedKeys:f.selectedKeys,onSelectionChange:f.onSelectionChange}),U?e.jsx(k,{children:e.jsxs(k.Content,{className:"p-0",children:[e.jsxs("div",{className:"flex items-center justify-between border-b border-[var(--otari-line)] px-4 py-2",children:[e.jsxs("span",{className:"text-sm font-medium text-[var(--otari-ink)]",children:["Reset history — ",$(U)]}),e.jsx(x,{size:"sm",variant:"ghost",onPress:()=>s(null),children:"Close"})]}),e.jsx(Ae,{budgetId:U.budget_id})]})}):null,e.jsx(fe,{isOpen:A,onOpenChange:C,heading:"Delete budgets",body:`Delete ${_.length} ${_.length===1?"budget":"budgets"}? Users on ${_.length===1?"it":"them"} will no longer be capped.`,confirmLabel:"Delete",isPending:J,error:X,onConfirm:ee})]})}export{Te as BudgetsPage}; diff --git a/src/gateway/static/dashboard/assets/ConfirmDialog-DXR8OubG.js b/src/gateway/static/dashboard/assets/ConfirmDialog-BFS2k4X_.js similarity index 92% rename from src/gateway/static/dashboard/assets/ConfirmDialog-DXR8OubG.js rename to src/gateway/static/dashboard/assets/ConfirmDialog-BFS2k4X_.js index 5a0cf640..0b06213f 100644 --- a/src/gateway/static/dashboard/assets/ConfirmDialog-DXR8OubG.js +++ b/src/gateway/static/dashboard/assets/ConfirmDialog-BFS2k4X_.js @@ -1 +1 @@ -import{j as r}from"./tanstack-query-1t81HyiD.js";import{E as j}from"./index-JlWCttWt.js";import{A as e,B as l}from"./heroui-BI50yK5B.js";function p({isOpen:s,onOpenChange:a,heading:n,body:o,confirmLabel:t,confirmVariant:c="danger",isPending:i,error:d,onConfirm:x}){return r.jsx(e,{isOpen:s,onOpenChange:a,children:s?r.jsx(e.Backdrop,{children:r.jsx(e.Container,{placement:"center",size:"md",children:r.jsxs(e.Dialog,{children:[r.jsx(e.Header,{children:r.jsx(e.Heading,{children:n})}),r.jsxs(e.Body,{className:"flex flex-col gap-4",children:[r.jsx("div",{className:"text-sm text-[var(--otari-muted)]",children:o}),r.jsx(j,{error:d})]}),r.jsxs(e.Footer,{children:[r.jsx(l,{variant:"ghost",isDisabled:i,onPress:()=>a(!1),children:"Cancel"}),r.jsx(l,{variant:c,isPending:i,onPress:x,children:t})]})]})})}):null})}export{p as C}; +import{j as r}from"./tanstack-query-1t81HyiD.js";import{E as j}from"./index-BP-wLuMr.js";import{A as e,B as l}from"./heroui-BI50yK5B.js";function p({isOpen:s,onOpenChange:a,heading:n,body:o,confirmLabel:t,confirmVariant:c="danger",isPending:i,error:d,onConfirm:x}){return r.jsx(e,{isOpen:s,onOpenChange:a,children:s?r.jsx(e.Backdrop,{children:r.jsx(e.Container,{placement:"center",size:"md",children:r.jsxs(e.Dialog,{children:[r.jsx(e.Header,{children:r.jsx(e.Heading,{children:n})}),r.jsxs(e.Body,{className:"flex flex-col gap-4",children:[r.jsx("div",{className:"text-sm text-[var(--otari-muted)]",children:o}),r.jsx(j,{error:d})]}),r.jsxs(e.Footer,{children:[r.jsx(l,{variant:"ghost",isDisabled:i,onPress:()=>a(!1),children:"Cancel"}),r.jsx(l,{variant:c,isPending:i,onPress:x,children:t})]})]})})}):null})}export{p as C}; diff --git a/src/gateway/static/dashboard/assets/DocsPage-Bw1czoYN.js b/src/gateway/static/dashboard/assets/DocsPage-DneryjqV.js similarity index 90% rename from src/gateway/static/dashboard/assets/DocsPage-Bw1czoYN.js rename to src/gateway/static/dashboard/assets/DocsPage-DneryjqV.js index 712631c3..46813b45 100644 --- a/src/gateway/static/dashboard/assets/DocsPage-Bw1czoYN.js +++ b/src/gateway/static/dashboard/assets/DocsPage-DneryjqV.js @@ -1,32 +1,32 @@ -import{j as re}from"./tanstack-query-1t81HyiD.js";import{P as gi}from"./index-JlWCttWt.js";import{d as ct}from"./heroui-BI50yK5B.js";import{g as nr}from"./react-dgEcD0HR.js";function yi(e,t){const n={};return(e[e.length-1]===""?[...e,""]:e).join((n.padRight?" ":"")+","+(n.padLeft===!1?"":" ")).trim()}const ki=/^[$_\p{ID_Start}][$_\u{200C}\u{200D}\p{ID_Continue}]*$/u,xi=/^[$_\p{ID_Start}][-$_\u{200C}\u{200D}\p{ID_Continue}]*$/u,bi={};function ft(e,t){return(bi.jsx?xi:ki).test(e)}const wi=/[ \t\n\f\r]/g;function Si(e){return typeof e=="object"?e.type==="text"?ht(e.value):!1:ht(e)}function ht(e){return e.replace(wi,"")===""}class Ke{constructor(t,n,r){this.normal=n,this.property=t,r&&(this.space=r)}}Ke.prototype.normal={};Ke.prototype.property={};Ke.prototype.space=void 0;function tr(e,t){const n={},r={};for(const i of e)Object.assign(n,i.property),Object.assign(r,i.normal);return new Ke(n,r,t)}function zn(e){return e.toLowerCase()}class ee{constructor(t,n){this.attribute=n,this.property=t}}ee.prototype.attribute="";ee.prototype.booleanish=!1;ee.prototype.boolean=!1;ee.prototype.commaOrSpaceSeparated=!1;ee.prototype.commaSeparated=!1;ee.prototype.defined=!1;ee.prototype.mustUseProperty=!1;ee.prototype.number=!1;ee.prototype.overloadedBoolean=!1;ee.prototype.property="";ee.prototype.spaceSeparated=!1;ee.prototype.space=void 0;let Ci=0;const L=Ae(),Y=Ae(),Dn=Ae(),E=Ae(),$=Ae(),Ie=Ae(),te=Ae();function Ae(){return 2**++Ci}const Ln=Object.freeze(Object.defineProperty({__proto__:null,boolean:L,booleanish:Y,commaOrSpaceSeparated:te,commaSeparated:Ie,number:E,overloadedBoolean:Dn,spaceSeparated:$},Symbol.toStringTag,{value:"Module"})),pn=Object.keys(Ln);class Hn extends ee{constructor(t,n,r,i){let o=-1;if(super(t,n),pt(this,"space",i),typeof r=="number")for(;++o4&&n.slice(0,4)==="data"&&vi.test(t)){if(t.charAt(4)==="-"){const o=t.slice(5).replace(mt,Di);r="data"+o.charAt(0).toUpperCase()+o.slice(1)}else{const o=t.slice(4);if(!mt.test(o)){let l=o.replace(Ai,zi);l.charAt(0)!=="-"&&(l="-"+l),t="data"+l}}i=Hn}return new i(r,t)}function zi(e){return"-"+e.toLowerCase()}function Di(e){return e.charAt(1).toUpperCase()}const Li=tr([rr,Ei,or,ar,ur],"html"),Un=tr([rr,Ii,or,ar,ur],"svg");function Fi(e){return e.join(" ").trim()}var De={},mn,dt;function Ri(){if(dt)return mn;dt=1;var e=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//g,t=/\n/g,n=/^\s*/,r=/^(\*?[-#/*\\\w]+(\[[0-9a-z_-]+\])?)\s*/,i=/^:\s*/,o=/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^)]*?\)|[^};])+)/,l=/^[;\s]*/,a=/^\s+|\s+$/g,u=` -`,s="/",f="*",c="",p="comment",h="declaration";function g(S,y){if(typeof S!="string")throw new TypeError("First argument must be a string");if(!S)return[];y=y||{};var I=1,C=1;function R(D){var A=D.match(t);A&&(I+=A.length);var q=D.lastIndexOf(u);C=~q?D.length-q:C+D.length}function _(){var D={line:I,column:C};return function(A){return A.position=new b(D),j(),A}}function b(D){this.start=D,this.end={line:I,column:C},this.source=y.source}b.prototype.content=S;function M(D){var A=new Error(y.source+":"+I+":"+C+": "+D);if(A.reason=D,A.filename=y.source,A.line=I,A.column=C,A.source=S,!y.silent)throw A}function H(D){var A=D.exec(S);if(A){var q=A[0];return R(q),S=S.slice(q.length),A}}function j(){H(n)}function k(D){var A;for(D=D||[];A=v();)A!==!1&&D.push(A);return D}function v(){var D=_();if(!(s!=S.charAt(0)||f!=S.charAt(1))){for(var A=2;c!=S.charAt(A)&&(f!=S.charAt(A)||s!=S.charAt(A+1));)++A;if(A+=2,c===S.charAt(A-1))return M("End of comment missing");var q=S.slice(2,A-2);return C+=2,R(q),S=S.slice(A),C+=2,D({type:p,comment:q})}}function P(){var D=_(),A=H(r);if(A){if(v(),!H(i))return M("property missing ':'");var q=H(o),K=D({type:h,property:w(A[0].replace(e,c)),value:q?w(q[0].replace(e,c)):c});return H(l),K}}function U(){var D=[];k(D);for(var A;A=P();)A!==!1&&(D.push(A),k(D));return D}return j(),U()}function w(S){return S?S.replace(a,c):c}return mn=g,mn}var gt;function _i(){if(gt)return De;gt=1;var e=De&&De.__importDefault||function(r){return r&&r.__esModule?r:{default:r}};Object.defineProperty(De,"__esModule",{value:!0}),De.default=n;const t=e(Ri());function n(r,i){let o=null;if(!r||typeof r!="string")return o;const l=(0,t.default)(r),a=typeof i=="function";return l.forEach(u=>{if(u.type!=="declaration")return;const{property:s,value:f}=u;a?i(s,f,u):f&&(o=o||{},o[s]=f)}),o}return De}var Be={},yt;function Oi(){if(yt)return Be;yt=1,Object.defineProperty(Be,"__esModule",{value:!0}),Be.camelCase=void 0;var e=/^--[a-zA-Z0-9_-]+$/,t=/-([a-z])/g,n=/^[^-]+$/,r=/^-(webkit|moz|ms|o|khtml)-/,i=/^-(ms)-/,o=function(s){return!s||n.test(s)||e.test(s)},l=function(s,f){return f.toUpperCase()},a=function(s,f){return"".concat(f,"-")},u=function(s,f){return f===void 0&&(f={}),o(s)?s:(s=s.toLowerCase(),f.reactCompat?s=s.replace(i,a):s=s.replace(r,a),s.replace(t,l))};return Be.camelCase=u,Be}var je,kt;function Mi(){if(kt)return je;kt=1;var e=je&&je.__importDefault||function(i){return i&&i.__esModule?i:{default:i}},t=e(_i()),n=Oi();function r(i,o){var l={};return!i||typeof i!="string"||(0,t.default)(i,function(a,u){a&&u&&(l[(0,n.camelCase)(a,o)]=u)}),l}return r.default=r,je=r,je}var Ni=Mi();const Bi=nr(Ni),sr=cr("end"),qn=cr("start");function cr(e){return t;function t(n){const r=n&&n.position&&n.position[e]||{};if(typeof r.line=="number"&&r.line>0&&typeof r.column=="number"&&r.column>0)return{line:r.line,column:r.column,offset:typeof r.offset=="number"&&r.offset>-1?r.offset:void 0}}}function ji(e){const t=qn(e),n=sr(e);if(t&&n)return{start:t,end:n}}function qe(e){return!e||typeof e!="object"?"":"position"in e||"type"in e?xt(e.position):"start"in e||"end"in e?xt(e):"line"in e||"column"in e?Fn(e):""}function Fn(e){return bt(e&&e.line)+":"+bt(e&&e.column)}function xt(e){return Fn(e&&e.start)+"-"+Fn(e&&e.end)}function bt(e){return e&&typeof e=="number"?e:1}class G extends Error{constructor(t,n,r){super(),typeof n=="string"&&(r=n,n=void 0);let i="",o={},l=!1;if(n&&("line"in n&&"column"in n?o={place:n}:"start"in n&&"end"in n?o={place:n}:"type"in n?o={ancestors:[n],place:n.position}:o={...n}),typeof t=="string"?i=t:!o.cause&&t&&(l=!0,i=t.message,o.cause=t),!o.ruleId&&!o.source&&typeof r=="string"){const u=r.indexOf(":");u===-1?o.ruleId=r:(o.source=r.slice(0,u),o.ruleId=r.slice(u+1))}if(!o.place&&o.ancestors&&o.ancestors){const u=o.ancestors[o.ancestors.length-1];u&&(o.place=u.position)}const a=o.place&&"start"in o.place?o.place.start:o.place;this.ancestors=o.ancestors||void 0,this.cause=o.cause||void 0,this.column=a?a.column:void 0,this.fatal=void 0,this.file="",this.message=i,this.line=a?a.line:void 0,this.name=qe(o.place)||"1:1",this.place=o.place||void 0,this.reason=this.message,this.ruleId=o.ruleId||void 0,this.source=o.source||void 0,this.stack=l&&o.cause&&typeof o.cause.stack=="string"?o.cause.stack:"",this.actual=void 0,this.expected=void 0,this.note=void 0,this.url=void 0}}G.prototype.file="";G.prototype.name="";G.prototype.reason="";G.prototype.message="";G.prototype.stack="";G.prototype.column=void 0;G.prototype.line=void 0;G.prototype.ancestors=void 0;G.prototype.cause=void 0;G.prototype.fatal=void 0;G.prototype.place=void 0;G.prototype.ruleId=void 0;G.prototype.source=void 0;const Vn={}.hasOwnProperty,Hi=new Map,Ui=/[A-Z]/g,qi=new Set(["table","tbody","thead","tfoot","tr"]),Vi=new Set(["td","th"]),fr="https://github.com/syntax-tree/hast-util-to-jsx-runtime";function $i(e,t){if(!t||t.Fragment===void 0)throw new TypeError("Expected `Fragment` in options");const n=t.filePath||void 0;let r;if(t.development){if(typeof t.jsxDEV!="function")throw new TypeError("Expected `jsxDEV` in options when `development: true`");r=Zi(n,t.jsxDEV)}else{if(typeof t.jsx!="function")throw new TypeError("Expected `jsx` in production options");if(typeof t.jsxs!="function")throw new TypeError("Expected `jsxs` in production options");r=Ji(n,t.jsx,t.jsxs)}const i={Fragment:t.Fragment,ancestors:[],components:t.components||{},create:r,elementAttributeNameCase:t.elementAttributeNameCase||"react",evaluater:t.createEvaluater?t.createEvaluater():void 0,filePath:n,ignoreInvalidStyle:t.ignoreInvalidStyle||!1,passKeys:t.passKeys!==!1,passNode:t.passNode||!1,schema:t.space==="svg"?Un:Li,stylePropertyNameCase:t.stylePropertyNameCase||"dom",tableCellAlignToStyle:t.tableCellAlignToStyle!==!1},o=hr(i,e,void 0);return o&&typeof o!="string"?o:i.create(e,i.Fragment,{children:o||void 0},void 0)}function hr(e,t,n){if(t.type==="element")return Wi(e,t,n);if(t.type==="mdxFlowExpression"||t.type==="mdxTextExpression")return Yi(e,t);if(t.type==="mdxJsxFlowElement"||t.type==="mdxJsxTextElement")return Qi(e,t,n);if(t.type==="mdxjsEsm")return Ki(e,t);if(t.type==="root")return Xi(e,t,n);if(t.type==="text")return Gi(e,t)}function Wi(e,t,n){const r=e.schema;let i=r;t.tagName.toLowerCase()==="svg"&&r.space==="html"&&(i=Un,e.schema=i),e.ancestors.push(t);const o=mr(e,t.tagName,!1),l=el(e,t);let a=Wn(e,t);return qi.has(t.tagName)&&(a=a.filter(function(u){return typeof u=="string"?!Si(u):!0})),pr(e,l,o,t),$n(l,a),e.ancestors.pop(),e.schema=r,e.create(t,o,l,n)}function Yi(e,t){if(t.data&&t.data.estree&&e.evaluater){const r=t.data.estree.body[0];return r.type,e.evaluater.evaluateExpression(r.expression)}We(e,t.position)}function Ki(e,t){if(t.data&&t.data.estree&&e.evaluater)return e.evaluater.evaluateProgram(t.data.estree);We(e,t.position)}function Qi(e,t,n){const r=e.schema;let i=r;t.name==="svg"&&r.space==="html"&&(i=Un,e.schema=i),e.ancestors.push(t);const o=t.name===null?e.Fragment:mr(e,t.name,!0),l=nl(e,t),a=Wn(e,t);return pr(e,l,o,t),$n(l,a),e.ancestors.pop(),e.schema=r,e.create(t,o,l,n)}function Xi(e,t,n){const r={};return $n(r,Wn(e,t)),e.create(t,e.Fragment,r,n)}function Gi(e,t){return t.value}function pr(e,t,n,r){typeof n!="string"&&n!==e.Fragment&&e.passNode&&(t.node=r)}function $n(e,t){if(t.length>0){const n=t.length>1?t:t[0];n&&(e.children=n)}}function Ji(e,t,n){return r;function r(i,o,l,a){const s=Array.isArray(l.children)?n:t;return a?s(o,l,a):s(o,l)}}function Zi(e,t){return n;function n(r,i,o,l){const a=Array.isArray(o.children),u=qn(r);return t(i,o,l,a,{columnNumber:u?u.column-1:void 0,fileName:e,lineNumber:u?u.line:void 0},void 0)}}function el(e,t){const n={};let r,i;for(i in t.properties)if(i!=="children"&&Vn.call(t.properties,i)){const o=tl(e,i,t.properties[i]);if(o){const[l,a]=o;e.tableCellAlignToStyle&&l==="align"&&typeof a=="string"&&Vi.has(t.tagName)?r=a:n[l]=a}}if(r){const o=n.style||(n.style={});o[e.stylePropertyNameCase==="css"?"text-align":"textAlign"]=r}return n}function nl(e,t){const n={};for(const r of t.attributes)if(r.type==="mdxJsxExpressionAttribute")if(r.data&&r.data.estree&&e.evaluater){const o=r.data.estree.body[0];o.type;const l=o.expression;l.type;const a=l.properties[0];a.type,Object.assign(n,e.evaluater.evaluateExpression(a.argument))}else We(e,t.position);else{const i=r.name;let o;if(r.value&&typeof r.value=="object")if(r.value.data&&r.value.data.estree&&e.evaluater){const a=r.value.data.estree.body[0];a.type,o=e.evaluater.evaluateExpression(a.expression)}else We(e,t.position);else o=r.value===null?!0:r.value;n[i]=o}return n}function Wn(e,t){const n=[];let r=-1;const i=e.passKeys?new Map:Hi;for(;++ri?0:i+t:t=t>i?i:t,n=n>0?n:0,r.length<1e4)l=Array.from(r),l.unshift(t,n),e.splice(...l);else for(n&&e.splice(t,n);o0?(ie(e,e.length,0,t),e):t}const Ct={}.hasOwnProperty;function gr(e){const t={};let n=-1;for(;++n13&&n<32||n>126&&n<160||n>55295&&n<57344||n>64975&&n<65008||(n&65535)===65535||(n&65535)===65534||n>1114111?"�":String.fromCodePoint(n)}function ce(e){return e.replace(/[\t\n\r ]+/g," ").replace(/^ | $/g,"").toLowerCase().toUpperCase()}const J=be(/[A-Za-z]/),X=be(/[\dA-Za-z]/),fl=be(/[#-'*+\--9=?A-Z^-~]/);function rn(e){return e!==null&&(e<32||e===127)}const Rn=be(/\d/),hl=be(/[\dA-Fa-f]/),pl=be(/[!-/:-@[-`{-~]/);function z(e){return e!==null&&e<-2}function W(e){return e!==null&&(e<0||e===32)}function O(e){return e===-2||e===-1||e===32}const un=be(new RegExp("\\p{P}|\\p{S}","u")),Te=be(/\s/);function be(e){return t;function t(n){return n!==null&&n>-1&&e.test(String.fromCharCode(n))}}function _e(e){const t=[];let n=-1,r=0,i=0;for(;++n55295&&o<57344){const a=e.charCodeAt(n+1);o<56320&&a>56319&&a<57344?(l=String.fromCharCode(o,a),i=1):l="�"}else l=String.fromCharCode(o);l&&(t.push(e.slice(r,n),encodeURIComponent(l)),r=n+i+1,l=""),i&&(n+=i,i=0)}return t.join("")+e.slice(r)}function B(e,t,n,r){const i=r?r-1:Number.POSITIVE_INFINITY;let o=0;return l;function l(u){return O(u)?(e.enter(n),a(u)):t(u)}function a(u){return O(u)&&o++l))return;const M=t.events.length;let H=M,j,k;for(;H--;)if(t.events[H][0]==="exit"&&t.events[H][1].type==="chunkFlow"){if(j){k=t.events[H][1].end;break}j=!0}for(y(r),b=M;bC;){const _=n[R];t.containerState=_[1],_[0].exit.call(t,e)}n.length=C}function I(){i.write([null]),o=void 0,i=void 0,t.containerState._closeFlow=void 0}}function kl(e,t,n){return B(e,e.attempt(this.parser.constructs.document,t,n),"linePrefix",this.parser.constructs.disable.null.includes("codeIndented")?void 0:4)}function Fe(e){if(e===null||W(e)||Te(e))return 1;if(un(e))return 2}function sn(e,t,n){const r=[];let i=-1;for(;++i1&&e[n][1].end.offset-e[n][1].start.offset>1?2:1;const c={...e[r][1].end},p={...e[n][1].start};It(c,-u),It(p,u),l={type:u>1?"strongSequence":"emphasisSequence",start:c,end:{...e[r][1].end}},a={type:u>1?"strongSequence":"emphasisSequence",start:{...e[n][1].start},end:p},o={type:u>1?"strongText":"emphasisText",start:{...e[r][1].end},end:{...e[n][1].start}},i={type:u>1?"strong":"emphasis",start:{...l.start},end:{...a.end}},e[r][1].end={...l.start},e[n][1].start={...a.end},s=[],e[r][1].end.offset-e[r][1].start.offset&&(s=le(s,[["enter",e[r][1],t],["exit",e[r][1],t]])),s=le(s,[["enter",i,t],["enter",l,t],["exit",l,t],["enter",o,t]]),s=le(s,sn(t.parser.constructs.insideSpan.null,e.slice(r+1,n),t)),s=le(s,[["exit",o,t],["enter",a,t],["exit",a,t],["exit",i,t]]),e[n][1].end.offset-e[n][1].start.offset?(f=2,s=le(s,[["enter",e[n][1],t],["exit",e[n][1],t]])):f=0,ie(e,r-1,n-r+3,s),n=r+s.length-f-2;break}}for(n=-1;++n0&&O(b)?B(e,I,"linePrefix",o+1)(b):I(b)}function I(b){return b===null||z(b)?e.check(Tt,w,R)(b):(e.enter("codeFlowValue"),C(b))}function C(b){return b===null||z(b)?(e.exit("codeFlowValue"),I(b)):(e.consume(b),C)}function R(b){return e.exit("codeFenced"),t(b)}function _(b,M,H){let j=0;return k;function k(A){return b.enter("lineEnding"),b.consume(A),b.exit("lineEnding"),v}function v(A){return b.enter("codeFencedFence"),O(A)?B(b,P,"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(A):P(A)}function P(A){return A===a?(b.enter("codeFencedFenceSequence"),U(A)):H(A)}function U(A){return A===a?(j++,b.consume(A),U):j>=l?(b.exit("codeFencedFenceSequence"),O(A)?B(b,D,"whitespace")(A):D(A)):H(A)}function D(A){return A===null||z(A)?(b.exit("codeFencedFence"),M(A)):H(A)}}}function zl(e,t,n){const r=this;return i;function i(l){return l===null?n(l):(e.enter("lineEnding"),e.consume(l),e.exit("lineEnding"),o)}function o(l){return r.parser.lazy[r.now().line]?n(l):t(l)}}const gn={name:"codeIndented",tokenize:Ll},Dl={partial:!0,tokenize:Fl};function Ll(e,t,n){const r=this;return i;function i(s){return e.enter("codeIndented"),B(e,o,"linePrefix",5)(s)}function o(s){const f=r.events[r.events.length-1];return f&&f[1].type==="linePrefix"&&f[2].sliceSerialize(f[1],!0).length>=4?l(s):n(s)}function l(s){return s===null?u(s):z(s)?e.attempt(Dl,l,u)(s):(e.enter("codeFlowValue"),a(s))}function a(s){return s===null||z(s)?(e.exit("codeFlowValue"),l(s)):(e.consume(s),a)}function u(s){return e.exit("codeIndented"),t(s)}}function Fl(e,t,n){const r=this;return i;function i(l){return r.parser.lazy[r.now().line]?n(l):z(l)?(e.enter("lineEnding"),e.consume(l),e.exit("lineEnding"),i):B(e,o,"linePrefix",5)(l)}function o(l){const a=r.events[r.events.length-1];return a&&a[1].type==="linePrefix"&&a[2].sliceSerialize(a[1],!0).length>=4?t(l):z(l)?i(l):n(l)}}const Rl={name:"codeText",previous:Ol,resolve:_l,tokenize:Ml};function _l(e){let t=e.length-4,n=3,r,i;if((e[n][1].type==="lineEnding"||e[n][1].type==="space")&&(e[t][1].type==="lineEnding"||e[t][1].type==="space")){for(r=n;++r=this.left.length+this.right.length)throw new RangeError("Cannot access index `"+t+"` in a splice buffer of size `"+(this.left.length+this.right.length)+"`");return tthis.left.length?this.right.slice(this.right.length-r+this.left.length,this.right.length-t+this.left.length).reverse():this.left.slice(t).concat(this.right.slice(this.right.length-r+this.left.length).reverse())}splice(t,n,r){const i=n||0;this.setCursor(Math.trunc(t));const o=this.right.splice(this.right.length-i,Number.POSITIVE_INFINITY);return r&&He(this.left,r),o.reverse()}pop(){return this.setCursor(Number.POSITIVE_INFINITY),this.left.pop()}push(t){this.setCursor(Number.POSITIVE_INFINITY),this.left.push(t)}pushMany(t){this.setCursor(Number.POSITIVE_INFINITY),He(this.left,t)}unshift(t){this.setCursor(0),this.right.push(t)}unshiftMany(t){this.setCursor(0),He(this.right,t.reverse())}setCursor(t){if(!(t===this.left.length||t>this.left.length&&this.right.length===0||t<0&&this.left.length===0))if(t=4?t(l):e.interrupt(r.parser.constructs.flow,n,t)(l)}}function Sr(e,t,n,r,i,o,l,a,u){const s=u||Number.POSITIVE_INFINITY;let f=0;return c;function c(y){return y===60?(e.enter(r),e.enter(i),e.enter(o),e.consume(y),e.exit(o),p):y===null||y===32||y===41||rn(y)?n(y):(e.enter(r),e.enter(l),e.enter(a),e.enter("chunkString",{contentType:"string"}),w(y))}function p(y){return y===62?(e.enter(o),e.consume(y),e.exit(o),e.exit(i),e.exit(r),t):(e.enter(a),e.enter("chunkString",{contentType:"string"}),h(y))}function h(y){return y===62?(e.exit("chunkString"),e.exit(a),p(y)):y===null||y===60||z(y)?n(y):(e.consume(y),y===92?g:h)}function g(y){return y===60||y===62||y===92?(e.consume(y),h):h(y)}function w(y){return!f&&(y===null||y===41||W(y))?(e.exit("chunkString"),e.exit(a),e.exit(l),e.exit(r),t(y)):f999||h===null||h===91||h===93&&!u||h===94&&!a&&"_hiddenFootnoteSupport"in l.parser.constructs?n(h):h===93?(e.exit(o),e.enter(i),e.consume(h),e.exit(i),e.exit(r),t):z(h)?(e.enter("lineEnding"),e.consume(h),e.exit("lineEnding"),f):(e.enter("chunkString",{contentType:"string"}),c(h))}function c(h){return h===null||h===91||h===93||z(h)||a++>999?(e.exit("chunkString"),f(h)):(e.consume(h),u||(u=!O(h)),h===92?p:c)}function p(h){return h===91||h===92||h===93?(e.consume(h),a++,c):c(h)}}function Er(e,t,n,r,i,o){let l;return a;function a(p){return p===34||p===39||p===40?(e.enter(r),e.enter(i),e.consume(p),e.exit(i),l=p===40?41:p,u):n(p)}function u(p){return p===l?(e.enter(i),e.consume(p),e.exit(i),e.exit(r),t):(e.enter(o),s(p))}function s(p){return p===l?(e.exit(o),u(l)):p===null?n(p):z(p)?(e.enter("lineEnding"),e.consume(p),e.exit("lineEnding"),B(e,s,"linePrefix")):(e.enter("chunkString",{contentType:"string"}),f(p))}function f(p){return p===l||p===null||z(p)?(e.exit("chunkString"),s(p)):(e.consume(p),p===92?c:f)}function c(p){return p===l||p===92?(e.consume(p),f):f(p)}}function Ve(e,t){let n;return r;function r(i){return z(i)?(e.enter("lineEnding"),e.consume(i),e.exit("lineEnding"),n=!0,r):O(i)?B(e,r,n?"linePrefix":"lineSuffix")(i):t(i)}}const $l={name:"definition",tokenize:Yl},Wl={partial:!0,tokenize:Kl};function Yl(e,t,n){const r=this;let i;return o;function o(h){return e.enter("definition"),l(h)}function l(h){return Cr.call(r,e,a,n,"definitionLabel","definitionLabelMarker","definitionLabelString")(h)}function a(h){return i=ce(r.sliceSerialize(r.events[r.events.length-1][1]).slice(1,-1)),h===58?(e.enter("definitionMarker"),e.consume(h),e.exit("definitionMarker"),u):n(h)}function u(h){return W(h)?Ve(e,s)(h):s(h)}function s(h){return Sr(e,f,n,"definitionDestination","definitionDestinationLiteral","definitionDestinationLiteralMarker","definitionDestinationRaw","definitionDestinationString")(h)}function f(h){return e.attempt(Wl,c,c)(h)}function c(h){return O(h)?B(e,p,"whitespace")(h):p(h)}function p(h){return h===null||z(h)?(e.exit("definition"),r.parser.defined.push(i),t(h)):n(h)}}function Kl(e,t,n){return r;function r(a){return W(a)?Ve(e,i)(a):n(a)}function i(a){return Er(e,o,n,"definitionTitle","definitionTitleMarker","definitionTitleString")(a)}function o(a){return O(a)?B(e,l,"whitespace")(a):l(a)}function l(a){return a===null||z(a)?t(a):n(a)}}const Ql={name:"hardBreakEscape",tokenize:Xl};function Xl(e,t,n){return r;function r(o){return e.enter("hardBreakEscape"),e.consume(o),i}function i(o){return z(o)?(e.exit("hardBreakEscape"),t(o)):n(o)}}const Gl={name:"headingAtx",resolve:Jl,tokenize:Zl};function Jl(e,t){let n=e.length-2,r=3,i,o;return e[r][1].type==="whitespace"&&(r+=2),n-2>r&&e[n][1].type==="whitespace"&&(n-=2),e[n][1].type==="atxHeadingSequence"&&(r===n-1||n-4>r&&e[n-2][1].type==="whitespace")&&(n-=r+1===n?2:4),n>r&&(i={type:"atxHeadingText",start:e[r][1].start,end:e[n][1].end},o={type:"chunkText",start:e[r][1].start,end:e[n][1].end,contentType:"text"},ie(e,r,n-r+1,[["enter",i,t],["enter",o,t],["exit",o,t],["exit",i,t]])),e}function Zl(e,t,n){let r=0;return i;function i(f){return e.enter("atxHeading"),o(f)}function o(f){return e.enter("atxHeadingSequence"),l(f)}function l(f){return f===35&&r++<6?(e.consume(f),l):f===null||W(f)?(e.exit("atxHeadingSequence"),a(f)):n(f)}function a(f){return f===35?(e.enter("atxHeadingSequence"),u(f)):f===null||z(f)?(e.exit("atxHeading"),t(f)):O(f)?B(e,a,"whitespace")(f):(e.enter("atxHeadingText"),s(f))}function u(f){return f===35?(e.consume(f),u):(e.exit("atxHeadingSequence"),a(f))}function s(f){return f===null||f===35||W(f)?(e.exit("atxHeadingText"),a(f)):(e.consume(f),s)}}const eo=["address","article","aside","base","basefont","blockquote","body","caption","center","col","colgroup","dd","details","dialog","dir","div","dl","dt","fieldset","figcaption","figure","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hr","html","iframe","legend","li","link","main","menu","menuitem","nav","noframes","ol","optgroup","option","p","param","search","section","summary","table","tbody","td","tfoot","th","thead","title","tr","track","ul"],vt=["pre","script","style","textarea"],no={concrete:!0,name:"htmlFlow",resolveTo:io,tokenize:lo},to={partial:!0,tokenize:ao},ro={partial:!0,tokenize:oo};function io(e){let t=e.length;for(;t--&&!(e[t][0]==="enter"&&e[t][1].type==="htmlFlow"););return t>1&&e[t-2][1].type==="linePrefix"&&(e[t][1].start=e[t-2][1].start,e[t+1][1].start=e[t-2][1].start,e.splice(t-2,2)),e}function lo(e,t,n){const r=this;let i,o,l,a,u;return s;function s(d){return f(d)}function f(d){return e.enter("htmlFlow"),e.enter("htmlFlowData"),e.consume(d),c}function c(d){return d===33?(e.consume(d),p):d===47?(e.consume(d),o=!0,w):d===63?(e.consume(d),i=3,r.interrupt?t:m):J(d)?(e.consume(d),l=String.fromCharCode(d),S):n(d)}function p(d){return d===45?(e.consume(d),i=2,h):d===91?(e.consume(d),i=5,a=0,g):J(d)?(e.consume(d),i=4,r.interrupt?t:m):n(d)}function h(d){return d===45?(e.consume(d),r.interrupt?t:m):n(d)}function g(d){const ue="CDATA[";return d===ue.charCodeAt(a++)?(e.consume(d),a===ue.length?r.interrupt?t:P:g):n(d)}function w(d){return J(d)?(e.consume(d),l=String.fromCharCode(d),S):n(d)}function S(d){if(d===null||d===47||d===62||W(d)){const ue=d===47,we=l.toLowerCase();return!ue&&!o&&vt.includes(we)?(i=1,r.interrupt?t(d):P(d)):eo.includes(l.toLowerCase())?(i=6,ue?(e.consume(d),y):r.interrupt?t(d):P(d)):(i=7,r.interrupt&&!r.parser.lazy[r.now().line]?n(d):o?I(d):C(d))}return d===45||X(d)?(e.consume(d),l+=String.fromCharCode(d),S):n(d)}function y(d){return d===62?(e.consume(d),r.interrupt?t:P):n(d)}function I(d){return O(d)?(e.consume(d),I):k(d)}function C(d){return d===47?(e.consume(d),k):d===58||d===95||J(d)?(e.consume(d),R):O(d)?(e.consume(d),C):k(d)}function R(d){return d===45||d===46||d===58||d===95||X(d)?(e.consume(d),R):_(d)}function _(d){return d===61?(e.consume(d),b):O(d)?(e.consume(d),_):C(d)}function b(d){return d===null||d===60||d===61||d===62||d===96?n(d):d===34||d===39?(e.consume(d),u=d,M):O(d)?(e.consume(d),b):H(d)}function M(d){return d===u?(e.consume(d),u=null,j):d===null||z(d)?n(d):(e.consume(d),M)}function H(d){return d===null||d===34||d===39||d===47||d===60||d===61||d===62||d===96||W(d)?_(d):(e.consume(d),H)}function j(d){return d===47||d===62||O(d)?C(d):n(d)}function k(d){return d===62?(e.consume(d),v):n(d)}function v(d){return d===null||z(d)?P(d):O(d)?(e.consume(d),v):n(d)}function P(d){return d===45&&i===2?(e.consume(d),q):d===60&&i===1?(e.consume(d),K):d===62&&i===4?(e.consume(d),ae):d===63&&i===3?(e.consume(d),m):d===93&&i===5?(e.consume(d),pe):z(d)&&(i===6||i===7)?(e.exit("htmlFlowData"),e.check(to,me,U)(d)):d===null||z(d)?(e.exit("htmlFlowData"),U(d)):(e.consume(d),P)}function U(d){return e.check(ro,D,me)(d)}function D(d){return e.enter("lineEnding"),e.consume(d),e.exit("lineEnding"),A}function A(d){return d===null||z(d)?U(d):(e.enter("htmlFlowData"),P(d))}function q(d){return d===45?(e.consume(d),m):P(d)}function K(d){return d===47?(e.consume(d),l="",oe):P(d)}function oe(d){if(d===62){const ue=l.toLowerCase();return vt.includes(ue)?(e.consume(d),ae):P(d)}return J(d)&&l.length<8?(e.consume(d),l+=String.fromCharCode(d),oe):P(d)}function pe(d){return d===93?(e.consume(d),m):P(d)}function m(d){return d===62?(e.consume(d),ae):d===45&&i===2?(e.consume(d),m):P(d)}function ae(d){return d===null||z(d)?(e.exit("htmlFlowData"),me(d)):(e.consume(d),ae)}function me(d){return e.exit("htmlFlow"),t(d)}}function oo(e,t,n){const r=this;return i;function i(l){return z(l)?(e.enter("lineEnding"),e.consume(l),e.exit("lineEnding"),o):n(l)}function o(l){return r.parser.lazy[r.now().line]?n(l):t(l)}}function ao(e,t,n){return r;function r(i){return e.enter("lineEnding"),e.consume(i),e.exit("lineEnding"),e.attempt(Qe,t,n)}}const uo={name:"htmlText",tokenize:so};function so(e,t,n){const r=this;let i,o,l;return a;function a(m){return e.enter("htmlText"),e.enter("htmlTextData"),e.consume(m),u}function u(m){return m===33?(e.consume(m),s):m===47?(e.consume(m),_):m===63?(e.consume(m),C):J(m)?(e.consume(m),H):n(m)}function s(m){return m===45?(e.consume(m),f):m===91?(e.consume(m),o=0,g):J(m)?(e.consume(m),I):n(m)}function f(m){return m===45?(e.consume(m),h):n(m)}function c(m){return m===null?n(m):m===45?(e.consume(m),p):z(m)?(l=c,K(m)):(e.consume(m),c)}function p(m){return m===45?(e.consume(m),h):c(m)}function h(m){return m===62?q(m):m===45?p(m):c(m)}function g(m){const ae="CDATA[";return m===ae.charCodeAt(o++)?(e.consume(m),o===ae.length?w:g):n(m)}function w(m){return m===null?n(m):m===93?(e.consume(m),S):z(m)?(l=w,K(m)):(e.consume(m),w)}function S(m){return m===93?(e.consume(m),y):w(m)}function y(m){return m===62?q(m):m===93?(e.consume(m),y):w(m)}function I(m){return m===null||m===62?q(m):z(m)?(l=I,K(m)):(e.consume(m),I)}function C(m){return m===null?n(m):m===63?(e.consume(m),R):z(m)?(l=C,K(m)):(e.consume(m),C)}function R(m){return m===62?q(m):C(m)}function _(m){return J(m)?(e.consume(m),b):n(m)}function b(m){return m===45||X(m)?(e.consume(m),b):M(m)}function M(m){return z(m)?(l=M,K(m)):O(m)?(e.consume(m),M):q(m)}function H(m){return m===45||X(m)?(e.consume(m),H):m===47||m===62||W(m)?j(m):n(m)}function j(m){return m===47?(e.consume(m),q):m===58||m===95||J(m)?(e.consume(m),k):z(m)?(l=j,K(m)):O(m)?(e.consume(m),j):q(m)}function k(m){return m===45||m===46||m===58||m===95||X(m)?(e.consume(m),k):v(m)}function v(m){return m===61?(e.consume(m),P):z(m)?(l=v,K(m)):O(m)?(e.consume(m),v):j(m)}function P(m){return m===null||m===60||m===61||m===62||m===96?n(m):m===34||m===39?(e.consume(m),i=m,U):z(m)?(l=P,K(m)):O(m)?(e.consume(m),P):(e.consume(m),D)}function U(m){return m===i?(e.consume(m),i=void 0,A):m===null?n(m):z(m)?(l=U,K(m)):(e.consume(m),U)}function D(m){return m===null||m===34||m===39||m===60||m===61||m===96?n(m):m===47||m===62||W(m)?j(m):(e.consume(m),D)}function A(m){return m===47||m===62||W(m)?j(m):n(m)}function q(m){return m===62?(e.consume(m),e.exit("htmlTextData"),e.exit("htmlText"),t):n(m)}function K(m){return e.exit("htmlTextData"),e.enter("lineEnding"),e.consume(m),e.exit("lineEnding"),oe}function oe(m){return O(m)?B(e,pe,"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(m):pe(m)}function pe(m){return e.enter("htmlTextData"),l(m)}}const Qn={name:"labelEnd",resolveAll:po,resolveTo:mo,tokenize:go},co={tokenize:yo},fo={tokenize:ko},ho={tokenize:xo};function po(e){let t=-1;const n=[];for(;++t=3&&(s===null||z(s))?(e.exit("thematicBreak"),t(s)):n(s)}function u(s){return s===i?(e.consume(s),r++,u):(e.exit("thematicBreakSequence"),O(s)?B(e,a,"whitespace")(s):a(s))}}const Z={continuation:{tokenize:Po},exit:Do,name:"list",tokenize:vo},To={partial:!0,tokenize:Lo},Ao={partial:!0,tokenize:zo};function vo(e,t,n){const r=this,i=r.events[r.events.length-1];let o=i&&i[1].type==="linePrefix"?i[2].sliceSerialize(i[1],!0).length:0,l=0;return a;function a(h){const g=r.containerState.type||(h===42||h===43||h===45?"listUnordered":"listOrdered");if(g==="listUnordered"?!r.containerState.marker||h===r.containerState.marker:Rn(h)){if(r.containerState.type||(r.containerState.type=g,e.enter(g,{_container:!0})),g==="listUnordered")return e.enter("listItemPrefix"),h===42||h===45?e.check(tn,n,s)(h):s(h);if(!r.interrupt||h===49)return e.enter("listItemPrefix"),e.enter("listItemValue"),u(h)}return n(h)}function u(h){return Rn(h)&&++l<10?(e.consume(h),u):(!r.interrupt||l<2)&&(r.containerState.marker?h===r.containerState.marker:h===41||h===46)?(e.exit("listItemValue"),s(h)):n(h)}function s(h){return e.enter("listItemMarker"),e.consume(h),e.exit("listItemMarker"),r.containerState.marker=r.containerState.marker||h,e.check(Qe,r.interrupt?n:f,e.attempt(To,p,c))}function f(h){return r.containerState.initialBlankLine=!0,o++,p(h)}function c(h){return O(h)?(e.enter("listItemPrefixWhitespace"),e.consume(h),e.exit("listItemPrefixWhitespace"),p):n(h)}function p(h){return r.containerState.size=o+r.sliceSerialize(e.exit("listItemPrefix"),!0).length,t(h)}}function Po(e,t,n){const r=this;return r.containerState._closeFlow=void 0,e.check(Qe,i,o);function i(a){return r.containerState.furtherBlankLines=r.containerState.furtherBlankLines||r.containerState.initialBlankLine,B(e,t,"listItemIndent",r.containerState.size+1)(a)}function o(a){return r.containerState.furtherBlankLines||!O(a)?(r.containerState.furtherBlankLines=void 0,r.containerState.initialBlankLine=void 0,l(a)):(r.containerState.furtherBlankLines=void 0,r.containerState.initialBlankLine=void 0,e.attempt(Ao,t,l)(a))}function l(a){return r.containerState._closeFlow=!0,r.interrupt=void 0,B(e,e.attempt(Z,t,n),"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(a)}}function zo(e,t,n){const r=this;return B(e,i,"listItemIndent",r.containerState.size+1);function i(o){const l=r.events[r.events.length-1];return l&&l[1].type==="listItemIndent"&&l[2].sliceSerialize(l[1],!0).length===r.containerState.size?t(o):n(o)}}function Do(e){e.exit(this.containerState.type)}function Lo(e,t,n){const r=this;return B(e,i,"listItemPrefixWhitespace",r.parser.constructs.disable.null.includes("codeIndented")?void 0:5);function i(o){const l=r.events[r.events.length-1];return!O(o)&&l&&l[1].type==="listItemPrefixWhitespace"?t(o):n(o)}}const Pt={name:"setextUnderline",resolveTo:Fo,tokenize:Ro};function Fo(e,t){let n=e.length,r,i,o;for(;n--;)if(e[n][0]==="enter"){if(e[n][1].type==="content"){r=n;break}e[n][1].type==="paragraph"&&(i=n)}else e[n][1].type==="content"&&e.splice(n,1),!o&&e[n][1].type==="definition"&&(o=n);const l={type:"setextHeading",start:{...e[r][1].start},end:{...e[e.length-1][1].end}};return e[i][1].type="setextHeadingText",o?(e.splice(i,0,["enter",l,t]),e.splice(o+1,0,["exit",e[r][1],t]),e[r][1].end={...e[o][1].end}):e[r][1]=l,e.push(["exit",l,t]),e}function Ro(e,t,n){const r=this;let i;return o;function o(s){let f=r.events.length,c;for(;f--;)if(r.events[f][1].type!=="lineEnding"&&r.events[f][1].type!=="linePrefix"&&r.events[f][1].type!=="content"){c=r.events[f][1].type==="paragraph";break}return!r.parser.lazy[r.now().line]&&(r.interrupt||c)?(e.enter("setextHeadingLine"),i=s,l(s)):n(s)}function l(s){return e.enter("setextHeadingLineSequence"),a(s)}function a(s){return s===i?(e.consume(s),a):(e.exit("setextHeadingLineSequence"),O(s)?B(e,u,"lineSuffix")(s):u(s))}function u(s){return s===null||z(s)?(e.exit("setextHeadingLine"),t(s)):n(s)}}const _o={tokenize:Oo};function Oo(e){const t=this,n=e.attempt(Qe,r,e.attempt(this.parser.constructs.flowInitial,i,B(e,e.attempt(this.parser.constructs.flow,i,e.attempt(jl,i)),"linePrefix")));return n;function r(o){if(o===null){e.consume(o);return}return e.enter("lineEndingBlank"),e.consume(o),e.exit("lineEndingBlank"),t.currentConstruct=void 0,n}function i(o){if(o===null){e.consume(o);return}return e.enter("lineEnding"),e.consume(o),e.exit("lineEnding"),t.currentConstruct=void 0,n}}const Mo={resolveAll:Tr()},No=Ir("string"),Bo=Ir("text");function Ir(e){return{resolveAll:Tr(e==="text"?jo:void 0),tokenize:t};function t(n){const r=this,i=this.parser.constructs[e],o=n.attempt(i,l,a);return l;function l(f){return s(f)?o(f):a(f)}function a(f){if(f===null){n.consume(f);return}return n.enter("data"),n.consume(f),u}function u(f){return s(f)?(n.exit("data"),o(f)):(n.consume(f),u)}function s(f){if(f===null)return!0;const c=i[f];let p=-1;if(c)for(;++p-1){const a=l[0];typeof a=="string"?l[0]=a.slice(r):l.shift()}o>0&&l.push(e[i].slice(0,o))}return l}function Zo(e,t){let n=-1;const r=[];let i;for(;++n4&&n.slice(0,4)==="data"&&Ai.test(t)){if(t.charAt(4)==="-"){const o=t.slice(5).replace(mt,Di);r="data"+o.charAt(0).toUpperCase()+o.slice(1)}else{const o=t.slice(4);if(!mt.test(o)){let l=o.replace(vi,zi);l.charAt(0)!=="-"&&(l="-"+l),t="data"+l}}i=Hn}return new i(r,t)}function zi(e){return"-"+e.toLowerCase()}function Di(e){return e.charAt(1).toUpperCase()}const Li=tr([rr,Ei,or,ar,ur],"html"),Un=tr([rr,Ii,or,ar,ur],"svg");function _i(e){return e.join(" ").trim()}var De={},mn,dt;function Ri(){if(dt)return mn;dt=1;var e=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//g,t=/\n/g,n=/^\s*/,r=/^(\*?[-#/*\\\w]+(\[[0-9a-z_-]+\])?)\s*/,i=/^:\s*/,o=/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^)]*?\)|[^};])+)/,l=/^[;\s]*/,a=/^\s+|\s+$/g,u=` +`,s="/",f="*",c="",p="comment",h="declaration";function g(S,y){if(typeof S!="string")throw new TypeError("First argument must be a string");if(!S)return[];y=y||{};var I=1,C=1;function R(D){var v=D.match(t);v&&(I+=v.length);var q=D.lastIndexOf(u);C=~q?D.length-q:C+D.length}function F(){var D={line:I,column:C};return function(v){return v.position=new b(D),j(),v}}function b(D){this.start=D,this.end={line:I,column:C},this.source=y.source}b.prototype.content=S;function M(D){var v=new Error(y.source+":"+I+":"+C+": "+D);if(v.reason=D,v.filename=y.source,v.line=I,v.column=C,v.source=S,!y.silent)throw v}function H(D){var v=D.exec(S);if(v){var q=v[0];return R(q),S=S.slice(q.length),v}}function j(){H(n)}function k(D){var v;for(D=D||[];v=A();)v!==!1&&D.push(v);return D}function A(){var D=F();if(!(s!=S.charAt(0)||f!=S.charAt(1))){for(var v=2;c!=S.charAt(v)&&(f!=S.charAt(v)||s!=S.charAt(v+1));)++v;if(v+=2,c===S.charAt(v-1))return M("End of comment missing");var q=S.slice(2,v-2);return C+=2,R(q),S=S.slice(v),C+=2,D({type:p,comment:q})}}function P(){var D=F(),v=H(r);if(v){if(A(),!H(i))return M("property missing ':'");var q=H(o),K=D({type:h,property:w(v[0].replace(e,c)),value:q?w(q[0].replace(e,c)):c});return H(l),K}}function U(){var D=[];k(D);for(var v;v=P();)v!==!1&&(D.push(v),k(D));return D}return j(),U()}function w(S){return S?S.replace(a,c):c}return mn=g,mn}var gt;function Fi(){if(gt)return De;gt=1;var e=De&&De.__importDefault||function(r){return r&&r.__esModule?r:{default:r}};Object.defineProperty(De,"__esModule",{value:!0}),De.default=n;const t=e(Ri());function n(r,i){let o=null;if(!r||typeof r!="string")return o;const l=(0,t.default)(r),a=typeof i=="function";return l.forEach(u=>{if(u.type!=="declaration")return;const{property:s,value:f}=u;a?i(s,f,u):f&&(o=o||{},o[s]=f)}),o}return De}var Be={},yt;function Oi(){if(yt)return Be;yt=1,Object.defineProperty(Be,"__esModule",{value:!0}),Be.camelCase=void 0;var e=/^--[a-zA-Z0-9_-]+$/,t=/-([a-z])/g,n=/^[^-]+$/,r=/^-(webkit|moz|ms|o|khtml)-/,i=/^-(ms)-/,o=function(s){return!s||n.test(s)||e.test(s)},l=function(s,f){return f.toUpperCase()},a=function(s,f){return"".concat(f,"-")},u=function(s,f){return f===void 0&&(f={}),o(s)?s:(s=s.toLowerCase(),f.reactCompat?s=s.replace(i,a):s=s.replace(r,a),s.replace(t,l))};return Be.camelCase=u,Be}var je,kt;function Mi(){if(kt)return je;kt=1;var e=je&&je.__importDefault||function(i){return i&&i.__esModule?i:{default:i}},t=e(Fi()),n=Oi();function r(i,o){var l={};return!i||typeof i!="string"||(0,t.default)(i,function(a,u){a&&u&&(l[(0,n.camelCase)(a,o)]=u)}),l}return r.default=r,je=r,je}var Ni=Mi();const Bi=nr(Ni),sr=cr("end"),qn=cr("start");function cr(e){return t;function t(n){const r=n&&n.position&&n.position[e]||{};if(typeof r.line=="number"&&r.line>0&&typeof r.column=="number"&&r.column>0)return{line:r.line,column:r.column,offset:typeof r.offset=="number"&&r.offset>-1?r.offset:void 0}}}function ji(e){const t=qn(e),n=sr(e);if(t&&n)return{start:t,end:n}}function qe(e){return!e||typeof e!="object"?"":"position"in e||"type"in e?xt(e.position):"start"in e||"end"in e?xt(e):"line"in e||"column"in e?_n(e):""}function _n(e){return bt(e&&e.line)+":"+bt(e&&e.column)}function xt(e){return _n(e&&e.start)+"-"+_n(e&&e.end)}function bt(e){return e&&typeof e=="number"?e:1}class G extends Error{constructor(t,n,r){super(),typeof n=="string"&&(r=n,n=void 0);let i="",o={},l=!1;if(n&&("line"in n&&"column"in n?o={place:n}:"start"in n&&"end"in n?o={place:n}:"type"in n?o={ancestors:[n],place:n.position}:o={...n}),typeof t=="string"?i=t:!o.cause&&t&&(l=!0,i=t.message,o.cause=t),!o.ruleId&&!o.source&&typeof r=="string"){const u=r.indexOf(":");u===-1?o.ruleId=r:(o.source=r.slice(0,u),o.ruleId=r.slice(u+1))}if(!o.place&&o.ancestors&&o.ancestors){const u=o.ancestors[o.ancestors.length-1];u&&(o.place=u.position)}const a=o.place&&"start"in o.place?o.place.start:o.place;this.ancestors=o.ancestors||void 0,this.cause=o.cause||void 0,this.column=a?a.column:void 0,this.fatal=void 0,this.file="",this.message=i,this.line=a?a.line:void 0,this.name=qe(o.place)||"1:1",this.place=o.place||void 0,this.reason=this.message,this.ruleId=o.ruleId||void 0,this.source=o.source||void 0,this.stack=l&&o.cause&&typeof o.cause.stack=="string"?o.cause.stack:"",this.actual=void 0,this.expected=void 0,this.note=void 0,this.url=void 0}}G.prototype.file="";G.prototype.name="";G.prototype.reason="";G.prototype.message="";G.prototype.stack="";G.prototype.column=void 0;G.prototype.line=void 0;G.prototype.ancestors=void 0;G.prototype.cause=void 0;G.prototype.fatal=void 0;G.prototype.place=void 0;G.prototype.ruleId=void 0;G.prototype.source=void 0;const Vn={}.hasOwnProperty,Hi=new Map,Ui=/[A-Z]/g,qi=new Set(["table","tbody","thead","tfoot","tr"]),Vi=new Set(["td","th"]),fr="https://github.com/syntax-tree/hast-util-to-jsx-runtime";function $i(e,t){if(!t||t.Fragment===void 0)throw new TypeError("Expected `Fragment` in options");const n=t.filePath||void 0;let r;if(t.development){if(typeof t.jsxDEV!="function")throw new TypeError("Expected `jsxDEV` in options when `development: true`");r=Zi(n,t.jsxDEV)}else{if(typeof t.jsx!="function")throw new TypeError("Expected `jsx` in production options");if(typeof t.jsxs!="function")throw new TypeError("Expected `jsxs` in production options");r=Ji(n,t.jsx,t.jsxs)}const i={Fragment:t.Fragment,ancestors:[],components:t.components||{},create:r,elementAttributeNameCase:t.elementAttributeNameCase||"react",evaluater:t.createEvaluater?t.createEvaluater():void 0,filePath:n,ignoreInvalidStyle:t.ignoreInvalidStyle||!1,passKeys:t.passKeys!==!1,passNode:t.passNode||!1,schema:t.space==="svg"?Un:Li,stylePropertyNameCase:t.stylePropertyNameCase||"dom",tableCellAlignToStyle:t.tableCellAlignToStyle!==!1},o=hr(i,e,void 0);return o&&typeof o!="string"?o:i.create(e,i.Fragment,{children:o||void 0},void 0)}function hr(e,t,n){if(t.type==="element")return Wi(e,t,n);if(t.type==="mdxFlowExpression"||t.type==="mdxTextExpression")return Yi(e,t);if(t.type==="mdxJsxFlowElement"||t.type==="mdxJsxTextElement")return Qi(e,t,n);if(t.type==="mdxjsEsm")return Ki(e,t);if(t.type==="root")return Xi(e,t,n);if(t.type==="text")return Gi(e,t)}function Wi(e,t,n){const r=e.schema;let i=r;t.tagName.toLowerCase()==="svg"&&r.space==="html"&&(i=Un,e.schema=i),e.ancestors.push(t);const o=mr(e,t.tagName,!1),l=el(e,t);let a=Wn(e,t);return qi.has(t.tagName)&&(a=a.filter(function(u){return typeof u=="string"?!Si(u):!0})),pr(e,l,o,t),$n(l,a),e.ancestors.pop(),e.schema=r,e.create(t,o,l,n)}function Yi(e,t){if(t.data&&t.data.estree&&e.evaluater){const r=t.data.estree.body[0];return r.type,e.evaluater.evaluateExpression(r.expression)}We(e,t.position)}function Ki(e,t){if(t.data&&t.data.estree&&e.evaluater)return e.evaluater.evaluateProgram(t.data.estree);We(e,t.position)}function Qi(e,t,n){const r=e.schema;let i=r;t.name==="svg"&&r.space==="html"&&(i=Un,e.schema=i),e.ancestors.push(t);const o=t.name===null?e.Fragment:mr(e,t.name,!0),l=nl(e,t),a=Wn(e,t);return pr(e,l,o,t),$n(l,a),e.ancestors.pop(),e.schema=r,e.create(t,o,l,n)}function Xi(e,t,n){const r={};return $n(r,Wn(e,t)),e.create(t,e.Fragment,r,n)}function Gi(e,t){return t.value}function pr(e,t,n,r){typeof n!="string"&&n!==e.Fragment&&e.passNode&&(t.node=r)}function $n(e,t){if(t.length>0){const n=t.length>1?t:t[0];n&&(e.children=n)}}function Ji(e,t,n){return r;function r(i,o,l,a){const s=Array.isArray(l.children)?n:t;return a?s(o,l,a):s(o,l)}}function Zi(e,t){return n;function n(r,i,o,l){const a=Array.isArray(o.children),u=qn(r);return t(i,o,l,a,{columnNumber:u?u.column-1:void 0,fileName:e,lineNumber:u?u.line:void 0},void 0)}}function el(e,t){const n={};let r,i;for(i in t.properties)if(i!=="children"&&Vn.call(t.properties,i)){const o=tl(e,i,t.properties[i]);if(o){const[l,a]=o;e.tableCellAlignToStyle&&l==="align"&&typeof a=="string"&&Vi.has(t.tagName)?r=a:n[l]=a}}if(r){const o=n.style||(n.style={});o[e.stylePropertyNameCase==="css"?"text-align":"textAlign"]=r}return n}function nl(e,t){const n={};for(const r of t.attributes)if(r.type==="mdxJsxExpressionAttribute")if(r.data&&r.data.estree&&e.evaluater){const o=r.data.estree.body[0];o.type;const l=o.expression;l.type;const a=l.properties[0];a.type,Object.assign(n,e.evaluater.evaluateExpression(a.argument))}else We(e,t.position);else{const i=r.name;let o;if(r.value&&typeof r.value=="object")if(r.value.data&&r.value.data.estree&&e.evaluater){const a=r.value.data.estree.body[0];a.type,o=e.evaluater.evaluateExpression(a.expression)}else We(e,t.position);else o=r.value===null?!0:r.value;n[i]=o}return n}function Wn(e,t){const n=[];let r=-1;const i=e.passKeys?new Map:Hi;for(;++ri?0:i+t:t=t>i?i:t,n=n>0?n:0,r.length<1e4)l=Array.from(r),l.unshift(t,n),e.splice(...l);else for(n&&e.splice(t,n);o0?(ie(e,e.length,0,t),e):t}const Ct={}.hasOwnProperty;function gr(e){const t={};let n=-1;for(;++n13&&n<32||n>126&&n<160||n>55295&&n<57344||n>64975&&n<65008||(n&65535)===65535||(n&65535)===65534||n>1114111?"�":String.fromCodePoint(n)}function ce(e){return e.replace(/[\t\n\r ]+/g," ").replace(/^ | $/g,"").toLowerCase().toUpperCase()}const J=be(/[A-Za-z]/),X=be(/[\dA-Za-z]/),fl=be(/[#-'*+\--9=?A-Z^-~]/);function rn(e){return e!==null&&(e<32||e===127)}const Rn=be(/\d/),hl=be(/[\dA-Fa-f]/),pl=be(/[!-/:-@[-`{-~]/);function z(e){return e!==null&&e<-2}function W(e){return e!==null&&(e<0||e===32)}function O(e){return e===-2||e===-1||e===32}const un=be(new RegExp("\\p{P}|\\p{S}","u")),Te=be(/\s/);function be(e){return t;function t(n){return n!==null&&n>-1&&e.test(String.fromCharCode(n))}}function Fe(e){const t=[];let n=-1,r=0,i=0;for(;++n55295&&o<57344){const a=e.charCodeAt(n+1);o<56320&&a>56319&&a<57344?(l=String.fromCharCode(o,a),i=1):l="�"}else l=String.fromCharCode(o);l&&(t.push(e.slice(r,n),encodeURIComponent(l)),r=n+i+1,l=""),i&&(n+=i,i=0)}return t.join("")+e.slice(r)}function B(e,t,n,r){const i=r?r-1:Number.POSITIVE_INFINITY;let o=0;return l;function l(u){return O(u)?(e.enter(n),a(u)):t(u)}function a(u){return O(u)&&o++l))return;const M=t.events.length;let H=M,j,k;for(;H--;)if(t.events[H][0]==="exit"&&t.events[H][1].type==="chunkFlow"){if(j){k=t.events[H][1].end;break}j=!0}for(y(r),b=M;bC;){const F=n[R];t.containerState=F[1],F[0].exit.call(t,e)}n.length=C}function I(){i.write([null]),o=void 0,i=void 0,t.containerState._closeFlow=void 0}}function kl(e,t,n){return B(e,e.attempt(this.parser.constructs.document,t,n),"linePrefix",this.parser.constructs.disable.null.includes("codeIndented")?void 0:4)}function _e(e){if(e===null||W(e)||Te(e))return 1;if(un(e))return 2}function sn(e,t,n){const r=[];let i=-1;for(;++i1&&e[n][1].end.offset-e[n][1].start.offset>1?2:1;const c={...e[r][1].end},p={...e[n][1].start};It(c,-u),It(p,u),l={type:u>1?"strongSequence":"emphasisSequence",start:c,end:{...e[r][1].end}},a={type:u>1?"strongSequence":"emphasisSequence",start:{...e[n][1].start},end:p},o={type:u>1?"strongText":"emphasisText",start:{...e[r][1].end},end:{...e[n][1].start}},i={type:u>1?"strong":"emphasis",start:{...l.start},end:{...a.end}},e[r][1].end={...l.start},e[n][1].start={...a.end},s=[],e[r][1].end.offset-e[r][1].start.offset&&(s=le(s,[["enter",e[r][1],t],["exit",e[r][1],t]])),s=le(s,[["enter",i,t],["enter",l,t],["exit",l,t],["enter",o,t]]),s=le(s,sn(t.parser.constructs.insideSpan.null,e.slice(r+1,n),t)),s=le(s,[["exit",o,t],["enter",a,t],["exit",a,t],["exit",i,t]]),e[n][1].end.offset-e[n][1].start.offset?(f=2,s=le(s,[["enter",e[n][1],t],["exit",e[n][1],t]])):f=0,ie(e,r-1,n-r+3,s),n=r+s.length-f-2;break}}for(n=-1;++n0&&O(b)?B(e,I,"linePrefix",o+1)(b):I(b)}function I(b){return b===null||z(b)?e.check(Tt,w,R)(b):(e.enter("codeFlowValue"),C(b))}function C(b){return b===null||z(b)?(e.exit("codeFlowValue"),I(b)):(e.consume(b),C)}function R(b){return e.exit("codeFenced"),t(b)}function F(b,M,H){let j=0;return k;function k(v){return b.enter("lineEnding"),b.consume(v),b.exit("lineEnding"),A}function A(v){return b.enter("codeFencedFence"),O(v)?B(b,P,"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(v):P(v)}function P(v){return v===a?(b.enter("codeFencedFenceSequence"),U(v)):H(v)}function U(v){return v===a?(j++,b.consume(v),U):j>=l?(b.exit("codeFencedFenceSequence"),O(v)?B(b,D,"whitespace")(v):D(v)):H(v)}function D(v){return v===null||z(v)?(b.exit("codeFencedFence"),M(v)):H(v)}}}function zl(e,t,n){const r=this;return i;function i(l){return l===null?n(l):(e.enter("lineEnding"),e.consume(l),e.exit("lineEnding"),o)}function o(l){return r.parser.lazy[r.now().line]?n(l):t(l)}}const gn={name:"codeIndented",tokenize:Ll},Dl={partial:!0,tokenize:_l};function Ll(e,t,n){const r=this;return i;function i(s){return e.enter("codeIndented"),B(e,o,"linePrefix",5)(s)}function o(s){const f=r.events[r.events.length-1];return f&&f[1].type==="linePrefix"&&f[2].sliceSerialize(f[1],!0).length>=4?l(s):n(s)}function l(s){return s===null?u(s):z(s)?e.attempt(Dl,l,u)(s):(e.enter("codeFlowValue"),a(s))}function a(s){return s===null||z(s)?(e.exit("codeFlowValue"),l(s)):(e.consume(s),a)}function u(s){return e.exit("codeIndented"),t(s)}}function _l(e,t,n){const r=this;return i;function i(l){return r.parser.lazy[r.now().line]?n(l):z(l)?(e.enter("lineEnding"),e.consume(l),e.exit("lineEnding"),i):B(e,o,"linePrefix",5)(l)}function o(l){const a=r.events[r.events.length-1];return a&&a[1].type==="linePrefix"&&a[2].sliceSerialize(a[1],!0).length>=4?t(l):z(l)?i(l):n(l)}}const Rl={name:"codeText",previous:Ol,resolve:Fl,tokenize:Ml};function Fl(e){let t=e.length-4,n=3,r,i;if((e[n][1].type==="lineEnding"||e[n][1].type==="space")&&(e[t][1].type==="lineEnding"||e[t][1].type==="space")){for(r=n;++r=this.left.length+this.right.length)throw new RangeError("Cannot access index `"+t+"` in a splice buffer of size `"+(this.left.length+this.right.length)+"`");return tthis.left.length?this.right.slice(this.right.length-r+this.left.length,this.right.length-t+this.left.length).reverse():this.left.slice(t).concat(this.right.slice(this.right.length-r+this.left.length).reverse())}splice(t,n,r){const i=n||0;this.setCursor(Math.trunc(t));const o=this.right.splice(this.right.length-i,Number.POSITIVE_INFINITY);return r&&He(this.left,r),o.reverse()}pop(){return this.setCursor(Number.POSITIVE_INFINITY),this.left.pop()}push(t){this.setCursor(Number.POSITIVE_INFINITY),this.left.push(t)}pushMany(t){this.setCursor(Number.POSITIVE_INFINITY),He(this.left,t)}unshift(t){this.setCursor(0),this.right.push(t)}unshiftMany(t){this.setCursor(0),He(this.right,t.reverse())}setCursor(t){if(!(t===this.left.length||t>this.left.length&&this.right.length===0||t<0&&this.left.length===0))if(t=4?t(l):e.interrupt(r.parser.constructs.flow,n,t)(l)}}function Sr(e,t,n,r,i,o,l,a,u){const s=u||Number.POSITIVE_INFINITY;let f=0;return c;function c(y){return y===60?(e.enter(r),e.enter(i),e.enter(o),e.consume(y),e.exit(o),p):y===null||y===32||y===41||rn(y)?n(y):(e.enter(r),e.enter(l),e.enter(a),e.enter("chunkString",{contentType:"string"}),w(y))}function p(y){return y===62?(e.enter(o),e.consume(y),e.exit(o),e.exit(i),e.exit(r),t):(e.enter(a),e.enter("chunkString",{contentType:"string"}),h(y))}function h(y){return y===62?(e.exit("chunkString"),e.exit(a),p(y)):y===null||y===60||z(y)?n(y):(e.consume(y),y===92?g:h)}function g(y){return y===60||y===62||y===92?(e.consume(y),h):h(y)}function w(y){return!f&&(y===null||y===41||W(y))?(e.exit("chunkString"),e.exit(a),e.exit(l),e.exit(r),t(y)):f999||h===null||h===91||h===93&&!u||h===94&&!a&&"_hiddenFootnoteSupport"in l.parser.constructs?n(h):h===93?(e.exit(o),e.enter(i),e.consume(h),e.exit(i),e.exit(r),t):z(h)?(e.enter("lineEnding"),e.consume(h),e.exit("lineEnding"),f):(e.enter("chunkString",{contentType:"string"}),c(h))}function c(h){return h===null||h===91||h===93||z(h)||a++>999?(e.exit("chunkString"),f(h)):(e.consume(h),u||(u=!O(h)),h===92?p:c)}function p(h){return h===91||h===92||h===93?(e.consume(h),a++,c):c(h)}}function Er(e,t,n,r,i,o){let l;return a;function a(p){return p===34||p===39||p===40?(e.enter(r),e.enter(i),e.consume(p),e.exit(i),l=p===40?41:p,u):n(p)}function u(p){return p===l?(e.enter(i),e.consume(p),e.exit(i),e.exit(r),t):(e.enter(o),s(p))}function s(p){return p===l?(e.exit(o),u(l)):p===null?n(p):z(p)?(e.enter("lineEnding"),e.consume(p),e.exit("lineEnding"),B(e,s,"linePrefix")):(e.enter("chunkString",{contentType:"string"}),f(p))}function f(p){return p===l||p===null||z(p)?(e.exit("chunkString"),s(p)):(e.consume(p),p===92?c:f)}function c(p){return p===l||p===92?(e.consume(p),f):f(p)}}function Ve(e,t){let n;return r;function r(i){return z(i)?(e.enter("lineEnding"),e.consume(i),e.exit("lineEnding"),n=!0,r):O(i)?B(e,r,n?"linePrefix":"lineSuffix")(i):t(i)}}const $l={name:"definition",tokenize:Yl},Wl={partial:!0,tokenize:Kl};function Yl(e,t,n){const r=this;let i;return o;function o(h){return e.enter("definition"),l(h)}function l(h){return Cr.call(r,e,a,n,"definitionLabel","definitionLabelMarker","definitionLabelString")(h)}function a(h){return i=ce(r.sliceSerialize(r.events[r.events.length-1][1]).slice(1,-1)),h===58?(e.enter("definitionMarker"),e.consume(h),e.exit("definitionMarker"),u):n(h)}function u(h){return W(h)?Ve(e,s)(h):s(h)}function s(h){return Sr(e,f,n,"definitionDestination","definitionDestinationLiteral","definitionDestinationLiteralMarker","definitionDestinationRaw","definitionDestinationString")(h)}function f(h){return e.attempt(Wl,c,c)(h)}function c(h){return O(h)?B(e,p,"whitespace")(h):p(h)}function p(h){return h===null||z(h)?(e.exit("definition"),r.parser.defined.push(i),t(h)):n(h)}}function Kl(e,t,n){return r;function r(a){return W(a)?Ve(e,i)(a):n(a)}function i(a){return Er(e,o,n,"definitionTitle","definitionTitleMarker","definitionTitleString")(a)}function o(a){return O(a)?B(e,l,"whitespace")(a):l(a)}function l(a){return a===null||z(a)?t(a):n(a)}}const Ql={name:"hardBreakEscape",tokenize:Xl};function Xl(e,t,n){return r;function r(o){return e.enter("hardBreakEscape"),e.consume(o),i}function i(o){return z(o)?(e.exit("hardBreakEscape"),t(o)):n(o)}}const Gl={name:"headingAtx",resolve:Jl,tokenize:Zl};function Jl(e,t){let n=e.length-2,r=3,i,o;return e[r][1].type==="whitespace"&&(r+=2),n-2>r&&e[n][1].type==="whitespace"&&(n-=2),e[n][1].type==="atxHeadingSequence"&&(r===n-1||n-4>r&&e[n-2][1].type==="whitespace")&&(n-=r+1===n?2:4),n>r&&(i={type:"atxHeadingText",start:e[r][1].start,end:e[n][1].end},o={type:"chunkText",start:e[r][1].start,end:e[n][1].end,contentType:"text"},ie(e,r,n-r+1,[["enter",i,t],["enter",o,t],["exit",o,t],["exit",i,t]])),e}function Zl(e,t,n){let r=0;return i;function i(f){return e.enter("atxHeading"),o(f)}function o(f){return e.enter("atxHeadingSequence"),l(f)}function l(f){return f===35&&r++<6?(e.consume(f),l):f===null||W(f)?(e.exit("atxHeadingSequence"),a(f)):n(f)}function a(f){return f===35?(e.enter("atxHeadingSequence"),u(f)):f===null||z(f)?(e.exit("atxHeading"),t(f)):O(f)?B(e,a,"whitespace")(f):(e.enter("atxHeadingText"),s(f))}function u(f){return f===35?(e.consume(f),u):(e.exit("atxHeadingSequence"),a(f))}function s(f){return f===null||f===35||W(f)?(e.exit("atxHeadingText"),a(f)):(e.consume(f),s)}}const eo=["address","article","aside","base","basefont","blockquote","body","caption","center","col","colgroup","dd","details","dialog","dir","div","dl","dt","fieldset","figcaption","figure","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hr","html","iframe","legend","li","link","main","menu","menuitem","nav","noframes","ol","optgroup","option","p","param","search","section","summary","table","tbody","td","tfoot","th","thead","title","tr","track","ul"],At=["pre","script","style","textarea"],no={concrete:!0,name:"htmlFlow",resolveTo:io,tokenize:lo},to={partial:!0,tokenize:ao},ro={partial:!0,tokenize:oo};function io(e){let t=e.length;for(;t--&&!(e[t][0]==="enter"&&e[t][1].type==="htmlFlow"););return t>1&&e[t-2][1].type==="linePrefix"&&(e[t][1].start=e[t-2][1].start,e[t+1][1].start=e[t-2][1].start,e.splice(t-2,2)),e}function lo(e,t,n){const r=this;let i,o,l,a,u;return s;function s(d){return f(d)}function f(d){return e.enter("htmlFlow"),e.enter("htmlFlowData"),e.consume(d),c}function c(d){return d===33?(e.consume(d),p):d===47?(e.consume(d),o=!0,w):d===63?(e.consume(d),i=3,r.interrupt?t:m):J(d)?(e.consume(d),l=String.fromCharCode(d),S):n(d)}function p(d){return d===45?(e.consume(d),i=2,h):d===91?(e.consume(d),i=5,a=0,g):J(d)?(e.consume(d),i=4,r.interrupt?t:m):n(d)}function h(d){return d===45?(e.consume(d),r.interrupt?t:m):n(d)}function g(d){const ue="CDATA[";return d===ue.charCodeAt(a++)?(e.consume(d),a===ue.length?r.interrupt?t:P:g):n(d)}function w(d){return J(d)?(e.consume(d),l=String.fromCharCode(d),S):n(d)}function S(d){if(d===null||d===47||d===62||W(d)){const ue=d===47,we=l.toLowerCase();return!ue&&!o&&At.includes(we)?(i=1,r.interrupt?t(d):P(d)):eo.includes(l.toLowerCase())?(i=6,ue?(e.consume(d),y):r.interrupt?t(d):P(d)):(i=7,r.interrupt&&!r.parser.lazy[r.now().line]?n(d):o?I(d):C(d))}return d===45||X(d)?(e.consume(d),l+=String.fromCharCode(d),S):n(d)}function y(d){return d===62?(e.consume(d),r.interrupt?t:P):n(d)}function I(d){return O(d)?(e.consume(d),I):k(d)}function C(d){return d===47?(e.consume(d),k):d===58||d===95||J(d)?(e.consume(d),R):O(d)?(e.consume(d),C):k(d)}function R(d){return d===45||d===46||d===58||d===95||X(d)?(e.consume(d),R):F(d)}function F(d){return d===61?(e.consume(d),b):O(d)?(e.consume(d),F):C(d)}function b(d){return d===null||d===60||d===61||d===62||d===96?n(d):d===34||d===39?(e.consume(d),u=d,M):O(d)?(e.consume(d),b):H(d)}function M(d){return d===u?(e.consume(d),u=null,j):d===null||z(d)?n(d):(e.consume(d),M)}function H(d){return d===null||d===34||d===39||d===47||d===60||d===61||d===62||d===96||W(d)?F(d):(e.consume(d),H)}function j(d){return d===47||d===62||O(d)?C(d):n(d)}function k(d){return d===62?(e.consume(d),A):n(d)}function A(d){return d===null||z(d)?P(d):O(d)?(e.consume(d),A):n(d)}function P(d){return d===45&&i===2?(e.consume(d),q):d===60&&i===1?(e.consume(d),K):d===62&&i===4?(e.consume(d),ae):d===63&&i===3?(e.consume(d),m):d===93&&i===5?(e.consume(d),pe):z(d)&&(i===6||i===7)?(e.exit("htmlFlowData"),e.check(to,me,U)(d)):d===null||z(d)?(e.exit("htmlFlowData"),U(d)):(e.consume(d),P)}function U(d){return e.check(ro,D,me)(d)}function D(d){return e.enter("lineEnding"),e.consume(d),e.exit("lineEnding"),v}function v(d){return d===null||z(d)?U(d):(e.enter("htmlFlowData"),P(d))}function q(d){return d===45?(e.consume(d),m):P(d)}function K(d){return d===47?(e.consume(d),l="",oe):P(d)}function oe(d){if(d===62){const ue=l.toLowerCase();return At.includes(ue)?(e.consume(d),ae):P(d)}return J(d)&&l.length<8?(e.consume(d),l+=String.fromCharCode(d),oe):P(d)}function pe(d){return d===93?(e.consume(d),m):P(d)}function m(d){return d===62?(e.consume(d),ae):d===45&&i===2?(e.consume(d),m):P(d)}function ae(d){return d===null||z(d)?(e.exit("htmlFlowData"),me(d)):(e.consume(d),ae)}function me(d){return e.exit("htmlFlow"),t(d)}}function oo(e,t,n){const r=this;return i;function i(l){return z(l)?(e.enter("lineEnding"),e.consume(l),e.exit("lineEnding"),o):n(l)}function o(l){return r.parser.lazy[r.now().line]?n(l):t(l)}}function ao(e,t,n){return r;function r(i){return e.enter("lineEnding"),e.consume(i),e.exit("lineEnding"),e.attempt(Qe,t,n)}}const uo={name:"htmlText",tokenize:so};function so(e,t,n){const r=this;let i,o,l;return a;function a(m){return e.enter("htmlText"),e.enter("htmlTextData"),e.consume(m),u}function u(m){return m===33?(e.consume(m),s):m===47?(e.consume(m),F):m===63?(e.consume(m),C):J(m)?(e.consume(m),H):n(m)}function s(m){return m===45?(e.consume(m),f):m===91?(e.consume(m),o=0,g):J(m)?(e.consume(m),I):n(m)}function f(m){return m===45?(e.consume(m),h):n(m)}function c(m){return m===null?n(m):m===45?(e.consume(m),p):z(m)?(l=c,K(m)):(e.consume(m),c)}function p(m){return m===45?(e.consume(m),h):c(m)}function h(m){return m===62?q(m):m===45?p(m):c(m)}function g(m){const ae="CDATA[";return m===ae.charCodeAt(o++)?(e.consume(m),o===ae.length?w:g):n(m)}function w(m){return m===null?n(m):m===93?(e.consume(m),S):z(m)?(l=w,K(m)):(e.consume(m),w)}function S(m){return m===93?(e.consume(m),y):w(m)}function y(m){return m===62?q(m):m===93?(e.consume(m),y):w(m)}function I(m){return m===null||m===62?q(m):z(m)?(l=I,K(m)):(e.consume(m),I)}function C(m){return m===null?n(m):m===63?(e.consume(m),R):z(m)?(l=C,K(m)):(e.consume(m),C)}function R(m){return m===62?q(m):C(m)}function F(m){return J(m)?(e.consume(m),b):n(m)}function b(m){return m===45||X(m)?(e.consume(m),b):M(m)}function M(m){return z(m)?(l=M,K(m)):O(m)?(e.consume(m),M):q(m)}function H(m){return m===45||X(m)?(e.consume(m),H):m===47||m===62||W(m)?j(m):n(m)}function j(m){return m===47?(e.consume(m),q):m===58||m===95||J(m)?(e.consume(m),k):z(m)?(l=j,K(m)):O(m)?(e.consume(m),j):q(m)}function k(m){return m===45||m===46||m===58||m===95||X(m)?(e.consume(m),k):A(m)}function A(m){return m===61?(e.consume(m),P):z(m)?(l=A,K(m)):O(m)?(e.consume(m),A):j(m)}function P(m){return m===null||m===60||m===61||m===62||m===96?n(m):m===34||m===39?(e.consume(m),i=m,U):z(m)?(l=P,K(m)):O(m)?(e.consume(m),P):(e.consume(m),D)}function U(m){return m===i?(e.consume(m),i=void 0,v):m===null?n(m):z(m)?(l=U,K(m)):(e.consume(m),U)}function D(m){return m===null||m===34||m===39||m===60||m===61||m===96?n(m):m===47||m===62||W(m)?j(m):(e.consume(m),D)}function v(m){return m===47||m===62||W(m)?j(m):n(m)}function q(m){return m===62?(e.consume(m),e.exit("htmlTextData"),e.exit("htmlText"),t):n(m)}function K(m){return e.exit("htmlTextData"),e.enter("lineEnding"),e.consume(m),e.exit("lineEnding"),oe}function oe(m){return O(m)?B(e,pe,"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(m):pe(m)}function pe(m){return e.enter("htmlTextData"),l(m)}}const Qn={name:"labelEnd",resolveAll:po,resolveTo:mo,tokenize:go},co={tokenize:yo},fo={tokenize:ko},ho={tokenize:xo};function po(e){let t=-1;const n=[];for(;++t=3&&(s===null||z(s))?(e.exit("thematicBreak"),t(s)):n(s)}function u(s){return s===i?(e.consume(s),r++,u):(e.exit("thematicBreakSequence"),O(s)?B(e,a,"whitespace")(s):a(s))}}const Z={continuation:{tokenize:Po},exit:Do,name:"list",tokenize:Ao},To={partial:!0,tokenize:Lo},vo={partial:!0,tokenize:zo};function Ao(e,t,n){const r=this,i=r.events[r.events.length-1];let o=i&&i[1].type==="linePrefix"?i[2].sliceSerialize(i[1],!0).length:0,l=0;return a;function a(h){const g=r.containerState.type||(h===42||h===43||h===45?"listUnordered":"listOrdered");if(g==="listUnordered"?!r.containerState.marker||h===r.containerState.marker:Rn(h)){if(r.containerState.type||(r.containerState.type=g,e.enter(g,{_container:!0})),g==="listUnordered")return e.enter("listItemPrefix"),h===42||h===45?e.check(tn,n,s)(h):s(h);if(!r.interrupt||h===49)return e.enter("listItemPrefix"),e.enter("listItemValue"),u(h)}return n(h)}function u(h){return Rn(h)&&++l<10?(e.consume(h),u):(!r.interrupt||l<2)&&(r.containerState.marker?h===r.containerState.marker:h===41||h===46)?(e.exit("listItemValue"),s(h)):n(h)}function s(h){return e.enter("listItemMarker"),e.consume(h),e.exit("listItemMarker"),r.containerState.marker=r.containerState.marker||h,e.check(Qe,r.interrupt?n:f,e.attempt(To,p,c))}function f(h){return r.containerState.initialBlankLine=!0,o++,p(h)}function c(h){return O(h)?(e.enter("listItemPrefixWhitespace"),e.consume(h),e.exit("listItemPrefixWhitespace"),p):n(h)}function p(h){return r.containerState.size=o+r.sliceSerialize(e.exit("listItemPrefix"),!0).length,t(h)}}function Po(e,t,n){const r=this;return r.containerState._closeFlow=void 0,e.check(Qe,i,o);function i(a){return r.containerState.furtherBlankLines=r.containerState.furtherBlankLines||r.containerState.initialBlankLine,B(e,t,"listItemIndent",r.containerState.size+1)(a)}function o(a){return r.containerState.furtherBlankLines||!O(a)?(r.containerState.furtherBlankLines=void 0,r.containerState.initialBlankLine=void 0,l(a)):(r.containerState.furtherBlankLines=void 0,r.containerState.initialBlankLine=void 0,e.attempt(vo,t,l)(a))}function l(a){return r.containerState._closeFlow=!0,r.interrupt=void 0,B(e,e.attempt(Z,t,n),"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(a)}}function zo(e,t,n){const r=this;return B(e,i,"listItemIndent",r.containerState.size+1);function i(o){const l=r.events[r.events.length-1];return l&&l[1].type==="listItemIndent"&&l[2].sliceSerialize(l[1],!0).length===r.containerState.size?t(o):n(o)}}function Do(e){e.exit(this.containerState.type)}function Lo(e,t,n){const r=this;return B(e,i,"listItemPrefixWhitespace",r.parser.constructs.disable.null.includes("codeIndented")?void 0:5);function i(o){const l=r.events[r.events.length-1];return!O(o)&&l&&l[1].type==="listItemPrefixWhitespace"?t(o):n(o)}}const Pt={name:"setextUnderline",resolveTo:_o,tokenize:Ro};function _o(e,t){let n=e.length,r,i,o;for(;n--;)if(e[n][0]==="enter"){if(e[n][1].type==="content"){r=n;break}e[n][1].type==="paragraph"&&(i=n)}else e[n][1].type==="content"&&e.splice(n,1),!o&&e[n][1].type==="definition"&&(o=n);const l={type:"setextHeading",start:{...e[r][1].start},end:{...e[e.length-1][1].end}};return e[i][1].type="setextHeadingText",o?(e.splice(i,0,["enter",l,t]),e.splice(o+1,0,["exit",e[r][1],t]),e[r][1].end={...e[o][1].end}):e[r][1]=l,e.push(["exit",l,t]),e}function Ro(e,t,n){const r=this;let i;return o;function o(s){let f=r.events.length,c;for(;f--;)if(r.events[f][1].type!=="lineEnding"&&r.events[f][1].type!=="linePrefix"&&r.events[f][1].type!=="content"){c=r.events[f][1].type==="paragraph";break}return!r.parser.lazy[r.now().line]&&(r.interrupt||c)?(e.enter("setextHeadingLine"),i=s,l(s)):n(s)}function l(s){return e.enter("setextHeadingLineSequence"),a(s)}function a(s){return s===i?(e.consume(s),a):(e.exit("setextHeadingLineSequence"),O(s)?B(e,u,"lineSuffix")(s):u(s))}function u(s){return s===null||z(s)?(e.exit("setextHeadingLine"),t(s)):n(s)}}const Fo={tokenize:Oo};function Oo(e){const t=this,n=e.attempt(Qe,r,e.attempt(this.parser.constructs.flowInitial,i,B(e,e.attempt(this.parser.constructs.flow,i,e.attempt(jl,i)),"linePrefix")));return n;function r(o){if(o===null){e.consume(o);return}return e.enter("lineEndingBlank"),e.consume(o),e.exit("lineEndingBlank"),t.currentConstruct=void 0,n}function i(o){if(o===null){e.consume(o);return}return e.enter("lineEnding"),e.consume(o),e.exit("lineEnding"),t.currentConstruct=void 0,n}}const Mo={resolveAll:Tr()},No=Ir("string"),Bo=Ir("text");function Ir(e){return{resolveAll:Tr(e==="text"?jo:void 0),tokenize:t};function t(n){const r=this,i=this.parser.constructs[e],o=n.attempt(i,l,a);return l;function l(f){return s(f)?o(f):a(f)}function a(f){if(f===null){n.consume(f);return}return n.enter("data"),n.consume(f),u}function u(f){return s(f)?(n.exit("data"),o(f)):(n.consume(f),u)}function s(f){if(f===null)return!0;const c=i[f];let p=-1;if(c)for(;++p-1){const a=l[0];typeof a=="string"?l[0]=a.slice(r):l.shift()}o>0&&l.push(e[i].slice(0,o))}return l}function Zo(e,t){let n=-1;const r=[];let i;for(;++n0){const se=F.tokenStack[F.tokenStack.length-1];(se[1]||Dt).call(F,void 0,se[0])}for(T.position={start:xe(x.length>0?x[0][1].start:{line:1,column:1,offset:0}),end:xe(x.length>0?x[x.length-2][1].end:{line:1,column:1,offset:0})},V=-1;++V0){const se=_.tokenStack[_.tokenStack.length-1];(se[1]||Dt).call(_,void 0,se[0])}for(T.position={start:xe(x.length>0?x[0][1].start:{line:1,column:1,offset:0}),end:xe(x.length>0?x[x.length-2][1].end:{line:1,column:1,offset:0})},V=-1;++V0&&(r.className=["language-"+i[0]]);let o={type:"element",tagName:"code",properties:r,children:[{type:"text",value:n}]};return t.meta&&(o.data={meta:t.meta}),e.patch(t,o),o=e.applyData(t,o),o={type:"element",tagName:"pre",properties:{},children:[o]},e.patch(t,o),o}function pa(e,t){const n={type:"element",tagName:"del",properties:{},children:e.all(t)};return e.patch(t,n),e.applyData(t,n)}function ma(e,t){const n={type:"element",tagName:"em",properties:{},children:e.all(t)};return e.patch(t,n),e.applyData(t,n)}function da(e,t){const n=typeof e.options.clobberPrefix=="string"?e.options.clobberPrefix:"user-content-",r=String(t.identifier).toUpperCase(),i=_e(r.toLowerCase()),o=e.footnoteOrder.indexOf(r);let l,a=e.footnoteCounts.get(r);a===void 0?(a=0,e.footnoteOrder.push(r),l=e.footnoteOrder.length):l=o+1,a+=1,e.footnoteCounts.set(r,a);const u={type:"element",tagName:"a",properties:{href:"#"+n+"fn-"+i,id:n+"fnref-"+i+(a>1?"-"+a:""),dataFootnoteRef:!0,ariaDescribedBy:["footnote-label"]},children:[{type:"text",value:String(l)}]};e.patch(t,u);const s={type:"element",tagName:"sup",properties:{},children:[u]};return e.patch(t,s),e.applyData(t,s)}function ga(e,t){const n={type:"element",tagName:"h"+t.depth,properties:{},children:e.all(t)};return e.patch(t,n),e.applyData(t,n)}function ya(e,t){if(e.options.allowDangerousHtml){const n={type:"raw",value:t.value};return e.patch(t,n),e.applyData(t,n)}}function Pr(e,t){const n=t.referenceType;let r="]";if(n==="collapsed"?r+="[]":n==="full"&&(r+="["+(t.label||t.identifier)+"]"),t.type==="imageReference")return[{type:"text",value:"!["+t.alt+r}];const i=e.all(t),o=i[0];o&&o.type==="text"?o.value="["+o.value:i.unshift({type:"text",value:"["});const l=i[i.length-1];return l&&l.type==="text"?l.value+=r:i.push({type:"text",value:r}),i}function ka(e,t){const n=String(t.identifier).toUpperCase(),r=e.definitionById.get(n);if(!r)return Pr(e,t);const i={src:_e(r.url||""),alt:t.alt};r.title!==null&&r.title!==void 0&&(i.title=r.title);const o={type:"element",tagName:"img",properties:i,children:[]};return e.patch(t,o),e.applyData(t,o)}function xa(e,t){const n={src:_e(t.url)};t.alt!==null&&t.alt!==void 0&&(n.alt=t.alt),t.title!==null&&t.title!==void 0&&(n.title=t.title);const r={type:"element",tagName:"img",properties:n,children:[]};return e.patch(t,r),e.applyData(t,r)}function ba(e,t){const n={type:"text",value:t.value.replace(/\r?\n|\r/g," ")};e.patch(t,n);const r={type:"element",tagName:"code",properties:{},children:[n]};return e.patch(t,r),e.applyData(t,r)}function wa(e,t){const n=String(t.identifier).toUpperCase(),r=e.definitionById.get(n);if(!r)return Pr(e,t);const i={href:_e(r.url||"")};r.title!==null&&r.title!==void 0&&(i.title=r.title);const o={type:"element",tagName:"a",properties:i,children:e.all(t)};return e.patch(t,o),e.applyData(t,o)}function Sa(e,t){const n={href:_e(t.url)};t.title!==null&&t.title!==void 0&&(n.title=t.title);const r={type:"element",tagName:"a",properties:n,children:e.all(t)};return e.patch(t,r),e.applyData(t,r)}function Ca(e,t,n){const r=e.all(t),i=n?Ea(n):zr(t),o={},l=[];if(typeof t.checked=="boolean"){const f=r[0];let c;f&&f.type==="element"&&f.tagName==="p"?c=f:(c={type:"element",tagName:"p",properties:{},children:[]},r.unshift(c)),c.children.length>0&&c.children.unshift({type:"text",value:" "}),c.children.unshift({type:"element",tagName:"input",properties:{type:"checkbox",checked:t.checked,disabled:!0},children:[]}),o.className=["task-list-item"]}let a=-1;for(;++a0&&(r.className=["language-"+i[0]]);let o={type:"element",tagName:"code",properties:r,children:[{type:"text",value:n}]};return t.meta&&(o.data={meta:t.meta}),e.patch(t,o),o=e.applyData(t,o),o={type:"element",tagName:"pre",properties:{},children:[o]},e.patch(t,o),o}function pa(e,t){const n={type:"element",tagName:"del",properties:{},children:e.all(t)};return e.patch(t,n),e.applyData(t,n)}function ma(e,t){const n={type:"element",tagName:"em",properties:{},children:e.all(t)};return e.patch(t,n),e.applyData(t,n)}function da(e,t){const n=typeof e.options.clobberPrefix=="string"?e.options.clobberPrefix:"user-content-",r=String(t.identifier).toUpperCase(),i=Fe(r.toLowerCase()),o=e.footnoteOrder.indexOf(r);let l,a=e.footnoteCounts.get(r);a===void 0?(a=0,e.footnoteOrder.push(r),l=e.footnoteOrder.length):l=o+1,a+=1,e.footnoteCounts.set(r,a);const u={type:"element",tagName:"a",properties:{href:"#"+n+"fn-"+i,id:n+"fnref-"+i+(a>1?"-"+a:""),dataFootnoteRef:!0,ariaDescribedBy:["footnote-label"]},children:[{type:"text",value:String(l)}]};e.patch(t,u);const s={type:"element",tagName:"sup",properties:{},children:[u]};return e.patch(t,s),e.applyData(t,s)}function ga(e,t){const n={type:"element",tagName:"h"+t.depth,properties:{},children:e.all(t)};return e.patch(t,n),e.applyData(t,n)}function ya(e,t){if(e.options.allowDangerousHtml){const n={type:"raw",value:t.value};return e.patch(t,n),e.applyData(t,n)}}function Pr(e,t){const n=t.referenceType;let r="]";if(n==="collapsed"?r+="[]":n==="full"&&(r+="["+(t.label||t.identifier)+"]"),t.type==="imageReference")return[{type:"text",value:"!["+t.alt+r}];const i=e.all(t),o=i[0];o&&o.type==="text"?o.value="["+o.value:i.unshift({type:"text",value:"["});const l=i[i.length-1];return l&&l.type==="text"?l.value+=r:i.push({type:"text",value:r}),i}function ka(e,t){const n=String(t.identifier).toUpperCase(),r=e.definitionById.get(n);if(!r)return Pr(e,t);const i={src:Fe(r.url||""),alt:t.alt};r.title!==null&&r.title!==void 0&&(i.title=r.title);const o={type:"element",tagName:"img",properties:i,children:[]};return e.patch(t,o),e.applyData(t,o)}function xa(e,t){const n={src:Fe(t.url)};t.alt!==null&&t.alt!==void 0&&(n.alt=t.alt),t.title!==null&&t.title!==void 0&&(n.title=t.title);const r={type:"element",tagName:"img",properties:n,children:[]};return e.patch(t,r),e.applyData(t,r)}function ba(e,t){const n={type:"text",value:t.value.replace(/\r?\n|\r/g," ")};e.patch(t,n);const r={type:"element",tagName:"code",properties:{},children:[n]};return e.patch(t,r),e.applyData(t,r)}function wa(e,t){const n=String(t.identifier).toUpperCase(),r=e.definitionById.get(n);if(!r)return Pr(e,t);const i={href:Fe(r.url||"")};r.title!==null&&r.title!==void 0&&(i.title=r.title);const o={type:"element",tagName:"a",properties:i,children:e.all(t)};return e.patch(t,o),e.applyData(t,o)}function Sa(e,t){const n={href:Fe(t.url)};t.title!==null&&t.title!==void 0&&(n.title=t.title);const r={type:"element",tagName:"a",properties:n,children:e.all(t)};return e.patch(t,r),e.applyData(t,r)}function Ca(e,t,n){const r=e.all(t),i=n?Ea(n):zr(t),o={},l=[];if(typeof t.checked=="boolean"){const f=r[0];let c;f&&f.type==="element"&&f.tagName==="p"?c=f:(c={type:"element",tagName:"p",properties:{},children:[]},r.unshift(c)),c.children.length>0&&c.children.unshift({type:"text",value:" "}),c.children.unshift({type:"element",tagName:"input",properties:{type:"checkbox",checked:t.checked,disabled:!0},children:[]}),o.className=["task-list-item"]}let a=-1;for(;++a1}function Ia(e,t){const n={},r=e.all(t);let i=-1;for(typeof t.start=="number"&&t.start!==1&&(n.start=t.start);++i0){const l={type:"element",tagName:"tbody",properties:{},children:e.wrap(n,!0)},a=qn(t.children[1]),u=sr(t.children[t.children.length-1]);a&&u&&(l.position={start:a,end:u}),i.push(l)}const o={type:"element",tagName:"table",properties:{},children:e.wrap(i,!0)};return e.patch(t,o),e.applyData(t,o)}function za(e,t,n){const r=n?n.children:void 0,o=(r?r.indexOf(t):1)===0?"th":"td",l=n&&n.type==="table"?n.align:void 0,a=l?l.length:t.children.length;let u=-1;const s=[];for(;++u0,!0),r[0]),i=r.index+r[0].length,r=n.exec(t);return o.push(Rt(t.slice(i),i>0,!1)),o.join("")}function Rt(e,t,n){let r=0,i=e.length;if(t){let o=e.codePointAt(r);for(;o===Lt||o===Ft;)r++,o=e.codePointAt(r)}if(n){let o=e.codePointAt(i-1);for(;o===Lt||o===Ft;)i--,o=e.codePointAt(i-1)}return i>r?e.slice(r,i):""}function Fa(e,t){const n={type:"text",value:La(String(t.value))};return e.patch(t,n),e.applyData(t,n)}function Ra(e,t){const n={type:"element",tagName:"hr",properties:{},children:[]};return e.patch(t,n),e.applyData(t,n)}const _a={blockquote:ca,break:fa,code:ha,delete:pa,emphasis:ma,footnoteReference:da,heading:ga,html:ya,imageReference:ka,image:xa,inlineCode:ba,linkReference:wa,link:Sa,listItem:Ca,list:Ia,paragraph:Ta,root:Aa,strong:va,table:Pa,tableCell:Da,tableRow:za,text:Fa,thematicBreak:Ra,toml:Je,yaml:Je,definition:Je,footnoteDefinition:Je};function Je(){}const Dr=-1,cn=0,$e=1,ln=2,Xn=3,Gn=4,Jn=5,Zn=6,Lr=7,Fr=8,Rr=typeof self=="object"?self:globalThis,_t=(e,t)=>{switch(e){case"Function":case"SharedWorker":case"Worker":case"eval":case"setInterval":case"setTimeout":throw new TypeError("unable to deserialize "+e)}return new Rr[e](t)},Oa=(e,t)=>{const n=(i,o)=>(e.set(o,i),i),r=i=>{if(e.has(i))return e.get(i);const[o,l]=t[i];switch(o){case cn:case Dr:return n(l,i);case $e:{const a=n([],i);for(const u of l)a.push(r(u));return a}case ln:{const a=n({},i);for(const[u,s]of l)a[r(u)]=r(s);return a}case Xn:return n(new Date(l),i);case Gn:{const{source:a,flags:u}=l;return n(new RegExp(a,u),i)}case Jn:{const a=n(new Map,i);for(const[u,s]of l)a.set(r(u),r(s));return a}case Zn:{const a=n(new Set,i);for(const u of l)a.add(r(u));return a}case Lr:{const{name:a,message:u}=l;return n(typeof Rr[a]=="function"?_t(a,u):new Error(u),i)}case Fr:return n(BigInt(l),i);case"BigInt":return n(Object(BigInt(l)),i);case"ArrayBuffer":return n(new Uint8Array(l).buffer,l);case"DataView":{const{buffer:a}=new Uint8Array(l);return n(new DataView(a),l)}}return n(_t(o,l),i)};return r},Ot=e=>Oa(new Map,e)(0),Ee="",{toString:Ma}={},{keys:Na}=Object,Ue=e=>{const t=typeof e;if(t!=="object"||!e)return[cn,t];const n=Ma.call(e).slice(8,-1);switch(n){case"Array":return[$e,Ee];case"Object":return[ln,Ee];case"Date":return[Xn,Ee];case"RegExp":return[Gn,Ee];case"Map":return[Jn,Ee];case"Set":return[Zn,Ee];case"DataView":return[$e,n]}return n.includes("Array")?[$e,n]:e instanceof Error?[Lr,e.name||"Error"]:[ln,n]},Ze=([e,t])=>e===cn&&(t==="function"||t==="symbol"),Ba=(e,t,n,r)=>{const i=(l,a)=>{const u=r.push(l)-1;return n.set(a,u),u},o=l=>{if(n.has(l))return n.get(l);let[a,u]=Ue(l);switch(a){case cn:{let f=l;switch(u){case"bigint":a=Fr,f=l.toString();break;case"function":case"symbol":if(e)throw new TypeError("unable to serialize "+u);f=null;break;case"undefined":return i([Dr],l)}return i([a,f],l)}case $e:{if(u){let p=l;return u==="DataView"?p=new Uint8Array(l.buffer):u==="ArrayBuffer"&&(p=new Uint8Array(l)),i([u,[...p]],l)}const f=[],c=i([a,f],l);for(const p of l)f.push(o(p));return c}case ln:{if(u)switch(u){case"BigInt":return i([u,l.toString()],l);case"Boolean":case"Number":case"String":return i([u,l.valueOf()],l)}if(t&&"toJSON"in l)return o(l.toJSON());const f=[],c=i([a,f],l);for(const p of Na(l))(e||!Ze(Ue(l[p])))&&f.push([o(p),o(l[p])]);return c}case Xn:return i([a,isNaN(l.getTime())?Ee:l.toISOString()],l);case Gn:{const{source:f,flags:c}=l;return i([a,{source:f,flags:c}],l)}case Jn:{const f=[],c=i([a,f],l);for(const[p,h]of l)(e||!(Ze(Ue(p))||Ze(Ue(h))))&&f.push([o(p),o(h)]);return c}case Zn:{const f=[],c=i([a,f],l);for(const p of l)(e||!Ze(Ue(p)))&&f.push(o(p));return c}}const{message:s}=l;return i([a,{name:u,message:s}],l)};return o},Mt=(e,{json:t,lossy:n}={})=>{const r=[];return Ba(!(t||n),!!t,new Map,r)(e),r},on=typeof structuredClone=="function"?(e,t)=>t&&("json"in t||"lossy"in t)?Ot(Mt(e,t)):structuredClone(e):(e,t)=>Ot(Mt(e,t));function ja(e,t){const n=[{type:"text",value:"↩"}];return t>1&&n.push({type:"element",tagName:"sup",properties:{},children:[{type:"text",value:String(t)}]}),n}function Ha(e,t){return"Back to reference "+(e+1)+(t>1?"-"+t:"")}function Ua(e){const t=typeof e.options.clobberPrefix=="string"?e.options.clobberPrefix:"user-content-",n=e.options.footnoteBackContent||ja,r=e.options.footnoteBackLabel||Ha,i=e.options.footnoteLabel||"Footnotes",o=e.options.footnoteLabelTagName||"h2",l=e.options.footnoteLabelProperties||{className:["sr-only"]},a=[];let u=-1;for(;++u0&&g.push({type:"text",value:" "});let I=typeof n=="string"?n:n(u,h);typeof I=="string"&&(I={type:"text",value:I}),g.push({type:"element",tagName:"a",properties:{href:"#"+t+"fnref-"+p+(h>1?"-"+h:""),dataFootnoteBackref:"",ariaLabel:typeof r=="string"?r:r(u,h),className:["data-footnote-backref"]},children:Array.isArray(I)?I:[I]})}const S=f[f.length-1];if(S&&S.type==="element"&&S.tagName==="p"){const I=S.children[S.children.length-1];I&&I.type==="text"?I.value+=" ":S.children.push({type:"text",value:" "}),S.children.push(...g)}else f.push(...g);const y={type:"element",tagName:"li",properties:{id:t+"fn-"+p},children:e.wrap(f,!0)};e.patch(s,y),a.push(y)}if(a.length!==0)return{type:"element",tagName:"section",properties:{dataFootnotes:!0,className:["footnotes"]},children:[{type:"element",tagName:o,properties:{...on(l),id:"footnote-label"},children:[{type:"text",value:i}]},{type:"text",value:` +`});const s={type:"element",tagName:"li",properties:o,children:l};return e.patch(t,s),e.applyData(t,s)}function Ea(e){let t=!1;if(e.type==="list"){t=e.spread||!1;const n=e.children;let r=-1;for(;!t&&++r1}function Ia(e,t){const n={},r=e.all(t);let i=-1;for(typeof t.start=="number"&&t.start!==1&&(n.start=t.start);++i0){const l={type:"element",tagName:"tbody",properties:{},children:e.wrap(n,!0)},a=qn(t.children[1]),u=sr(t.children[t.children.length-1]);a&&u&&(l.position={start:a,end:u}),i.push(l)}const o={type:"element",tagName:"table",properties:{},children:e.wrap(i,!0)};return e.patch(t,o),e.applyData(t,o)}function za(e,t,n){const r=n?n.children:void 0,o=(r?r.indexOf(t):1)===0?"th":"td",l=n&&n.type==="table"?n.align:void 0,a=l?l.length:t.children.length;let u=-1;const s=[];for(;++u0,!0),r[0]),i=r.index+r[0].length,r=n.exec(t);return o.push(Rt(t.slice(i),i>0,!1)),o.join("")}function Rt(e,t,n){let r=0,i=e.length;if(t){let o=e.codePointAt(r);for(;o===Lt||o===_t;)r++,o=e.codePointAt(r)}if(n){let o=e.codePointAt(i-1);for(;o===Lt||o===_t;)i--,o=e.codePointAt(i-1)}return i>r?e.slice(r,i):""}function _a(e,t){const n={type:"text",value:La(String(t.value))};return e.patch(t,n),e.applyData(t,n)}function Ra(e,t){const n={type:"element",tagName:"hr",properties:{},children:[]};return e.patch(t,n),e.applyData(t,n)}const Fa={blockquote:ca,break:fa,code:ha,delete:pa,emphasis:ma,footnoteReference:da,heading:ga,html:ya,imageReference:ka,image:xa,inlineCode:ba,linkReference:wa,link:Sa,listItem:Ca,list:Ia,paragraph:Ta,root:va,strong:Aa,table:Pa,tableCell:Da,tableRow:za,text:_a,thematicBreak:Ra,toml:Je,yaml:Je,definition:Je,footnoteDefinition:Je};function Je(){}const Dr=-1,cn=0,$e=1,ln=2,Xn=3,Gn=4,Jn=5,Zn=6,Lr=7,_r=8,Rr=typeof self=="object"?self:globalThis,Ft=(e,t)=>{switch(e){case"Function":case"SharedWorker":case"Worker":case"eval":case"setInterval":case"setTimeout":throw new TypeError("unable to deserialize "+e)}return new Rr[e](t)},Oa=(e,t)=>{const n=(i,o)=>(e.set(o,i),i),r=i=>{if(e.has(i))return e.get(i);const[o,l]=t[i];switch(o){case cn:case Dr:return n(l,i);case $e:{const a=n([],i);for(const u of l)a.push(r(u));return a}case ln:{const a=n({},i);for(const[u,s]of l)a[r(u)]=r(s);return a}case Xn:return n(new Date(l),i);case Gn:{const{source:a,flags:u}=l;return n(new RegExp(a,u),i)}case Jn:{const a=n(new Map,i);for(const[u,s]of l)a.set(r(u),r(s));return a}case Zn:{const a=n(new Set,i);for(const u of l)a.add(r(u));return a}case Lr:{const{name:a,message:u}=l;return n(typeof Rr[a]=="function"?Ft(a,u):new Error(u),i)}case _r:return n(BigInt(l),i);case"BigInt":return n(Object(BigInt(l)),i);case"ArrayBuffer":return n(new Uint8Array(l).buffer,l);case"DataView":{const{buffer:a}=new Uint8Array(l);return n(new DataView(a),l)}}return n(Ft(o,l),i)};return r},Ot=e=>Oa(new Map,e)(0),Ee="",{toString:Ma}={},{keys:Na}=Object,Ue=e=>{const t=typeof e;if(t!=="object"||!e)return[cn,t];const n=Ma.call(e).slice(8,-1);switch(n){case"Array":return[$e,Ee];case"Object":return[ln,Ee];case"Date":return[Xn,Ee];case"RegExp":return[Gn,Ee];case"Map":return[Jn,Ee];case"Set":return[Zn,Ee];case"DataView":return[$e,n]}return n.includes("Array")?[$e,n]:e instanceof Error?[Lr,e.name||"Error"]:[ln,n]},Ze=([e,t])=>e===cn&&(t==="function"||t==="symbol"),Ba=(e,t,n,r)=>{const i=(l,a)=>{const u=r.push(l)-1;return n.set(a,u),u},o=l=>{if(n.has(l))return n.get(l);let[a,u]=Ue(l);switch(a){case cn:{let f=l;switch(u){case"bigint":a=_r,f=l.toString();break;case"function":case"symbol":if(e)throw new TypeError("unable to serialize "+u);f=null;break;case"undefined":return i([Dr],l)}return i([a,f],l)}case $e:{if(u){let p=l;return u==="DataView"?p=new Uint8Array(l.buffer):u==="ArrayBuffer"&&(p=new Uint8Array(l)),i([u,[...p]],l)}const f=[],c=i([a,f],l);for(const p of l)f.push(o(p));return c}case ln:{if(u)switch(u){case"BigInt":return i([u,l.toString()],l);case"Boolean":case"Number":case"String":return i([u,l.valueOf()],l)}if(t&&"toJSON"in l)return o(l.toJSON());const f=[],c=i([a,f],l);for(const p of Na(l))(e||!Ze(Ue(l[p])))&&f.push([o(p),o(l[p])]);return c}case Xn:return i([a,isNaN(l.getTime())?Ee:l.toISOString()],l);case Gn:{const{source:f,flags:c}=l;return i([a,{source:f,flags:c}],l)}case Jn:{const f=[],c=i([a,f],l);for(const[p,h]of l)(e||!(Ze(Ue(p))||Ze(Ue(h))))&&f.push([o(p),o(h)]);return c}case Zn:{const f=[],c=i([a,f],l);for(const p of l)(e||!Ze(Ue(p)))&&f.push(o(p));return c}}const{message:s}=l;return i([a,{name:u,message:s}],l)};return o},Mt=(e,{json:t,lossy:n}={})=>{const r=[];return Ba(!(t||n),!!t,new Map,r)(e),r},on=typeof structuredClone=="function"?(e,t)=>t&&("json"in t||"lossy"in t)?Ot(Mt(e,t)):structuredClone(e):(e,t)=>Ot(Mt(e,t));function ja(e,t){const n=[{type:"text",value:"↩"}];return t>1&&n.push({type:"element",tagName:"sup",properties:{},children:[{type:"text",value:String(t)}]}),n}function Ha(e,t){return"Back to reference "+(e+1)+(t>1?"-"+t:"")}function Ua(e){const t=typeof e.options.clobberPrefix=="string"?e.options.clobberPrefix:"user-content-",n=e.options.footnoteBackContent||ja,r=e.options.footnoteBackLabel||Ha,i=e.options.footnoteLabel||"Footnotes",o=e.options.footnoteLabelTagName||"h2",l=e.options.footnoteLabelProperties||{className:["sr-only"]},a=[];let u=-1;for(;++u0&&g.push({type:"text",value:" "});let I=typeof n=="string"?n:n(u,h);typeof I=="string"&&(I={type:"text",value:I}),g.push({type:"element",tagName:"a",properties:{href:"#"+t+"fnref-"+p+(h>1?"-"+h:""),dataFootnoteBackref:"",ariaLabel:typeof r=="string"?r:r(u,h),className:["data-footnote-backref"]},children:Array.isArray(I)?I:[I]})}const S=f[f.length-1];if(S&&S.type==="element"&&S.tagName==="p"){const I=S.children[S.children.length-1];I&&I.type==="text"?I.value+=" ":S.children.push({type:"text",value:" "}),S.children.push(...g)}else f.push(...g);const y={type:"element",tagName:"li",properties:{id:t+"fn-"+p},children:e.wrap(f,!0)};e.patch(s,y),a.push(y)}if(a.length!==0)return{type:"element",tagName:"section",properties:{dataFootnotes:!0,className:["footnotes"]},children:[{type:"element",tagName:o,properties:{...on(l),id:"footnote-label"},children:[{type:"text",value:i}]},{type:"text",value:` `},{type:"element",tagName:"ol",properties:{},children:e.wrap(a,!0)},{type:"text",value:` -`}]}}const fn=(function(e){if(e==null)return Wa;if(typeof e=="function")return hn(e);if(typeof e=="object")return Array.isArray(e)?qa(e):Va(e);if(typeof e=="string")return $a(e);throw new Error("Expected function, string, or object as test")});function qa(e){const t=[];let n=-1;for(;++n":""))+")"})}return p;function p(){let h=_r,g,w,S;if((!t||o(u,s,f[f.length-1]||void 0))&&(h=Xa(n(u,f)),h[0]===On))return h;if("children"in u&&u.children){const y=u;if(y.children&&h[0]!==Qa)for(w=(r?y.children.length:-1)+l,S=f.concat(y);w>-1&&w":""))+")"})}return p;function p(){let h=Fr,g,w,S;if((!t||o(u,s,f[f.length-1]||void 0))&&(h=Xa(n(u,f)),h[0]===On))return h;if("children"in u&&u.children){const y=u;if(y.children&&h[0]!==Qa)for(w=(r?y.children.length:-1)+l,S=f.concat(y);w>-1&&w0&&n.push({type:"text",value:` `}),n}function Nt(e){let t=0,n=e.charCodeAt(t);for(;n===9||n===32;)t++,n=e.charCodeAt(t);return e.slice(t)}function Bt(e,t){const n=Ja(e,t),r=n.one(e,void 0),i=Ua(n),o=Array.isArray(r)?{type:"root",children:r}:r||{type:"root",children:[]};return i&&o.children.push({type:"text",value:` -`},i),o}function ru(e,t){return e&&"run"in e?async function(n,r){const i=Bt(n,{file:r,...t});await e.run(i,r)}:function(n,r){return Bt(n,{file:r,...e||t})}}function jt(e){if(e)throw e}var kn,Ht;function iu(){if(Ht)return kn;Ht=1;var e=Object.prototype.hasOwnProperty,t=Object.prototype.toString,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=function(s){return typeof Array.isArray=="function"?Array.isArray(s):t.call(s)==="[object Array]"},o=function(s){if(!s||t.call(s)!=="[object Object]")return!1;var f=e.call(s,"constructor"),c=s.constructor&&s.constructor.prototype&&e.call(s.constructor.prototype,"isPrototypeOf");if(s.constructor&&!f&&!c)return!1;var p;for(p in s);return typeof p>"u"||e.call(s,p)},l=function(s,f){n&&f.name==="__proto__"?n(s,f.name,{enumerable:!0,configurable:!0,value:f.newValue,writable:!0}):s[f.name]=f.newValue},a=function(s,f){if(f==="__proto__")if(e.call(s,f)){if(r)return r(s,f).value}else return;return s[f]};return kn=function u(){var s,f,c,p,h,g,w=arguments[0],S=1,y=arguments.length,I=!1;for(typeof w=="boolean"&&(I=w,w=arguments[1]||{},S=2),(w==null||typeof w!="object"&&typeof w!="function")&&(w={});Sl.length;let u;a&&l.push(i);try{u=e.apply(this,l)}catch(s){const f=s;if(a&&n)throw f;return i(f)}a||(u&&u.then&&typeof u.then=="function"?u.then(o,i):u instanceof Error?i(u):o(u))}function i(l,...a){n||(n=!0,t(l,...a))}function o(l){i(null,l)}}const fe={basename:uu,dirname:su,extname:cu,join:fu,sep:"/"};function uu(e,t){if(t!==void 0&&typeof t!="string")throw new TypeError('"ext" argument must be a string');Xe(e);let n=0,r=-1,i=e.length,o;if(t===void 0||t.length===0||t.length>e.length){for(;i--;)if(e.codePointAt(i)===47){if(o){n=i+1;break}}else r<0&&(o=!0,r=i+1);return r<0?"":e.slice(n,r)}if(t===e)return"";let l=-1,a=t.length-1;for(;i--;)if(e.codePointAt(i)===47){if(o){n=i+1;break}}else l<0&&(o=!0,l=i+1),a>-1&&(e.codePointAt(i)===t.codePointAt(a--)?a<0&&(r=i):(a=-1,r=l));return n===r?r=l:r<0&&(r=e.length),e.slice(n,r)}function su(e){if(Xe(e),e.length===0)return".";let t=-1,n=e.length,r;for(;--n;)if(e.codePointAt(n)===47){if(r){t=n;break}}else r||(r=!0);return t<0?e.codePointAt(0)===47?"/":".":t===1&&e.codePointAt(0)===47?"//":e.slice(0,t)}function cu(e){Xe(e);let t=e.length,n=-1,r=0,i=-1,o=0,l;for(;t--;){const a=e.codePointAt(t);if(a===47){if(l){r=t+1;break}continue}n<0&&(l=!0,n=t+1),a===46?i<0?i=t:o!==1&&(o=1):i>-1&&(o=-1)}return i<0||n<0||o===0||o===1&&i===n-1&&i===r+1?"":e.slice(i,n)}function fu(...e){let t=-1,n;for(;++t0&&e.codePointAt(e.length-1)===47&&(n+="/"),t?"/"+n:n}function pu(e,t){let n="",r=0,i=-1,o=0,l=-1,a,u;for(;++l<=e.length;){if(l2){if(u=n.lastIndexOf("/"),u!==n.length-1){u<0?(n="",r=0):(n=n.slice(0,u),r=n.length-1-n.lastIndexOf("/")),i=l,o=0;continue}}else if(n.length>0){n="",r=0,i=l,o=0;continue}}t&&(n=n.length>0?n+"/..":"..",r=2)}else n.length>0?n+="/"+e.slice(i+1,l):n=e.slice(i+1,l),r=l-i-1;i=l,o=0}else a===46&&o>-1?o++:o=-1}return n}function Xe(e){if(typeof e!="string")throw new TypeError("Path must be a string. Received "+JSON.stringify(e))}const mu={cwd:du};function du(){return"/"}function Bn(e){return!!(e!==null&&typeof e=="object"&&"href"in e&&e.href&&"protocol"in e&&e.protocol&&e.auth===void 0)}function gu(e){if(typeof e=="string")e=new URL(e);else if(!Bn(e)){const t=new TypeError('The "path" argument must be of type string or an instance of URL. Received `'+e+"`");throw t.code="ERR_INVALID_ARG_TYPE",t}if(e.protocol!=="file:"){const t=new TypeError("The URL must be of scheme file");throw t.code="ERR_INVALID_URL_SCHEME",t}return yu(e)}function yu(e){if(e.hostname!==""){const r=new TypeError('File URL host must be "localhost" or empty on darwin');throw r.code="ERR_INVALID_FILE_URL_HOST",r}const t=e.pathname;let n=-1;for(;++n0){let[h,...g]=f;const w=r[p][1];Nn(w)&&Nn(h)&&(h=xn(!0,w,h)),r[p]=[s,h,...g]}}}}const wu=new nt().freeze();function Cn(e,t){if(typeof t!="function")throw new TypeError("Cannot `"+e+"` without `parser`")}function En(e,t){if(typeof t!="function")throw new TypeError("Cannot `"+e+"` without `compiler`")}function In(e,t){if(t)throw new Error("Cannot call `"+e+"` on a frozen processor.\nCreate a new processor first, by calling it: use `processor()` instead of `processor`.")}function qt(e){if(!Nn(e)||typeof e.type!="string")throw new TypeError("Expected node, got `"+e+"`")}function Vt(e,t,n){if(!n)throw new Error("`"+e+"` finished async. Use `"+t+"` instead")}function en(e){return Su(e)?e:new Mr(e)}function Su(e){return!!(e&&typeof e=="object"&&"message"in e&&"messages"in e)}function Cu(e){return typeof e=="string"||Eu(e)}function Eu(e){return!!(e&&typeof e=="object"&&"byteLength"in e&&"byteOffset"in e)}const Iu="https://github.com/remarkjs/react-markdown/blob/main/changelog.md",$t=[],Wt={allowDangerousHtml:!0},Tu=/^(https?|ircs?|mailto|xmpp)$/i,Au=[{from:"astPlugins",id:"remove-buggy-html-in-markdown-parser"},{from:"allowDangerousHtml",id:"remove-buggy-html-in-markdown-parser"},{from:"allowNode",id:"replace-allownode-allowedtypes-and-disallowedtypes",to:"allowElement"},{from:"allowedTypes",id:"replace-allownode-allowedtypes-and-disallowedtypes",to:"allowedElements"},{from:"disallowedTypes",id:"replace-allownode-allowedtypes-and-disallowedtypes",to:"disallowedElements"},{from:"escapeHtml",id:"remove-buggy-html-in-markdown-parser"},{from:"includeElementIndex",id:"#remove-includeelementindex"},{from:"includeNodeIndex",id:"change-includenodeindex-to-includeelementindex"},{from:"linkTarget",id:"remove-linktarget"},{from:"plugins",id:"change-plugins-to-remarkplugins",to:"remarkPlugins"},{from:"rawSourcePos",id:"#remove-rawsourcepos"},{from:"renderers",id:"change-renderers-to-components",to:"components"},{from:"source",id:"change-source-to-children",to:"children"},{from:"sourcePos",id:"#remove-sourcepos"},{from:"transformImageUri",id:"#add-urltransform",to:"urlTransform"},{from:"transformLinkUri",id:"#add-urltransform",to:"urlTransform"}];function vu(e){const t=Pu(e),n=zu(e);return Du(t.runSync(t.parse(n),n),e)}function Pu(e){const t=e.rehypePlugins||$t,n=e.remarkPlugins||$t,r=e.remarkRehypeOptions?{...e.remarkRehypeOptions,...Wt}:Wt;return wu().use(sa).use(n).use(ru,r).use(t)}function zu(e){const t=e.children||"",n=new Mr;return typeof t=="string"&&(n.value=t),n}function Du(e,t){const n=t.allowedElements,r=t.allowElement,i=t.components,o=t.disallowedElements,l=t.skipHtml,a=t.unwrapDisallowed,u=t.urlTransform||Lu;for(const f of Au)Object.hasOwn(t,f.from)&&(""+f.from+(f.to?"use `"+f.to+"` instead":"remove it")+Iu+f.id,void 0);return t.className&&(e={type:"element",tagName:"div",properties:{className:t.className},children:e.type==="root"?e.children:[e]}),et(e,s),$i(e,{Fragment:re.Fragment,components:i,ignoreInvalidStyle:!0,jsx:re.jsx,jsxs:re.jsxs,passKeys:!0,passNode:!0});function s(f,c,p){if(f.type==="raw"&&p&&typeof c=="number")return l?p.children.splice(c,1):p.children[c]={type:"text",value:f.value},c;if(f.type==="element"){let h;for(h in dn)if(Object.hasOwn(dn,h)&&Object.hasOwn(f.properties,h)){const g=f.properties[h],w=dn[h];(w===null||w.includes(f.tagName))&&(f.properties[h]=u(String(g||""),h,f))}}if(f.type==="element"){let h=n?!n.includes(f.tagName):o?o.includes(f.tagName):!1;if(!h&&r&&typeof c=="number"&&(h=!r(f,c,p)),h&&p&&typeof c=="number")return a&&f.children?p.children.splice(c,1,...f.children):p.children.splice(c,1),c}}}function Lu(e){const t=e.indexOf(":"),n=e.indexOf("?"),r=e.indexOf("#"),i=e.indexOf("/");return t===-1||i!==-1&&t>i||n!==-1&&t>n||r!==-1&&t>r||Tu.test(e.slice(0,t))?e:""}function Yt(e,t){const n=String(e);if(typeof t!="string")throw new TypeError("Expected character");let r=0,i=n.indexOf(t);for(;i!==-1;)r++,i=n.indexOf(t,i+t.length);return r}function Fu(e){if(typeof e!="string")throw new TypeError("Expected a string");return e.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}function Ru(e,t,n){const i=fn((n||{}).ignore||[]),o=_u(t);let l=-1;for(;++l0?{type:"text",value:b}:void 0),b===!1?p.lastIndex=R+1:(g!==R&&I.push({type:"text",value:s.value.slice(g,R)}),Array.isArray(b)?I.push(...b):b&&I.push(b),g=R+C[0].length,y=!0),!p.global)break;C=p.exec(s.value)}return y?(g?\]}]+$/.exec(e);if(!t)return[e,void 0];e=e.slice(0,t.index);let n=t[0],r=n.indexOf(")");const i=Yt(e,"(");let o=Yt(e,")");for(;r!==-1&&i>o;)e+=n.slice(0,r+1),n=n.slice(r+1),r=n.indexOf(")"),o++;return[e,n]}function Nr(e,t){const n=e.input.charCodeAt(e.index-1);return(e.index===0||Te(n)||un(n))&&(!t||n!==47)}Br.peek=is;function Xu(){this.buffer()}function Gu(e){this.enter({type:"footnoteReference",identifier:"",label:""},e)}function Ju(){this.buffer()}function Zu(e){this.enter({type:"footnoteDefinition",identifier:"",label:"",children:[]},e)}function es(e){const t=this.resume(),n=this.stack[this.stack.length-1];n.type,n.identifier=ce(this.sliceSerialize(e)).toLowerCase(),n.label=t}function ns(e){this.exit(e)}function ts(e){const t=this.resume(),n=this.stack[this.stack.length-1];n.type,n.identifier=ce(this.sliceSerialize(e)).toLowerCase(),n.label=t}function rs(e){this.exit(e)}function is(){return"["}function Br(e,t,n,r){const i=n.createTracker(r);let o=i.move("[^");const l=n.enter("footnoteReference"),a=n.enter("reference");return o+=i.move(n.safe(n.associationId(e),{after:"]",before:o})),a(),l(),o+=i.move("]"),o}function ls(){return{enter:{gfmFootnoteCallString:Xu,gfmFootnoteCall:Gu,gfmFootnoteDefinitionLabelString:Ju,gfmFootnoteDefinition:Zu},exit:{gfmFootnoteCallString:es,gfmFootnoteCall:ns,gfmFootnoteDefinitionLabelString:ts,gfmFootnoteDefinition:rs}}}function os(e){let t=!1;return e&&e.firstLineBlank&&(t=!0),{handlers:{footnoteDefinition:n,footnoteReference:Br},unsafe:[{character:"[",inConstruct:["label","phrasing","reference"]}]};function n(r,i,o,l){const a=o.createTracker(l);let u=a.move("[^");const s=o.enter("footnoteDefinition"),f=o.enter("label");return u+=a.move(o.safe(o.associationId(r),{before:u,after:"]"})),f(),u+=a.move("]:"),r.children&&r.children.length>0&&(a.shift(4),u+=a.move((t?` -`:" ")+o.indentLines(o.containerFlow(r,a.current()),t?jr:as))),s(),u}}function as(e,t,n){return t===0?e:jr(e,t,n)}function jr(e,t,n){return(n?"":" ")+e}const us=["autolink","destinationLiteral","destinationRaw","reference","titleQuote","titleApostrophe"];Hr.peek=ps;function ss(){return{canContainEols:["delete"],enter:{strikethrough:fs},exit:{strikethrough:hs}}}function cs(){return{unsafe:[{character:"~",inConstruct:"phrasing",notInConstruct:us}],handlers:{delete:Hr}}}function fs(e){this.enter({type:"delete",children:[]},e)}function hs(e){this.exit(e)}function Hr(e,t,n,r){const i=n.createTracker(r),o=n.enter("strikethrough");let l=i.move("~~");return l+=n.containerPhrasing(e,{...i.current(),before:l,after:"~"}),l+=i.move("~~"),o(),l}function ps(){return"~"}function ms(e){return e.length}function ds(e,t){const n=t||{},r=(n.align||[]).concat(),i=n.stringLength||ms,o=[],l=[],a=[],u=[];let s=0,f=-1;for(;++fs&&(s=e[f].length);++yu[y])&&(u[y]=C)}w.push(I)}l[f]=w,a[f]=S}let c=-1;if(typeof r=="object"&&"length"in r)for(;++cu[c]&&(u[c]=I),h[c]=I),p[c]=C}l.splice(1,0,p),a.splice(1,0,h),f=-1;const g=[];for(;++f"u"||e.call(s,p)},l=function(s,f){n&&f.name==="__proto__"?n(s,f.name,{enumerable:!0,configurable:!0,value:f.newValue,writable:!0}):s[f.name]=f.newValue},a=function(s,f){if(f==="__proto__")if(e.call(s,f)){if(r)return r(s,f).value}else return;return s[f]};return kn=function u(){var s,f,c,p,h,g,w=arguments[0],S=1,y=arguments.length,I=!1;for(typeof w=="boolean"&&(I=w,w=arguments[1]||{},S=2),(w==null||typeof w!="object"&&typeof w!="function")&&(w={});Sl.length;let u;a&&l.push(i);try{u=e.apply(this,l)}catch(s){const f=s;if(a&&n)throw f;return i(f)}a||(u&&u.then&&typeof u.then=="function"?u.then(o,i):u instanceof Error?i(u):o(u))}function i(l,...a){n||(n=!0,t(l,...a))}function o(l){i(null,l)}}const fe={basename:uu,dirname:su,extname:cu,join:fu,sep:"/"};function uu(e,t){if(t!==void 0&&typeof t!="string")throw new TypeError('"ext" argument must be a string');Xe(e);let n=0,r=-1,i=e.length,o;if(t===void 0||t.length===0||t.length>e.length){for(;i--;)if(e.codePointAt(i)===47){if(o){n=i+1;break}}else r<0&&(o=!0,r=i+1);return r<0?"":e.slice(n,r)}if(t===e)return"";let l=-1,a=t.length-1;for(;i--;)if(e.codePointAt(i)===47){if(o){n=i+1;break}}else l<0&&(o=!0,l=i+1),a>-1&&(e.codePointAt(i)===t.codePointAt(a--)?a<0&&(r=i):(a=-1,r=l));return n===r?r=l:r<0&&(r=e.length),e.slice(n,r)}function su(e){if(Xe(e),e.length===0)return".";let t=-1,n=e.length,r;for(;--n;)if(e.codePointAt(n)===47){if(r){t=n;break}}else r||(r=!0);return t<0?e.codePointAt(0)===47?"/":".":t===1&&e.codePointAt(0)===47?"//":e.slice(0,t)}function cu(e){Xe(e);let t=e.length,n=-1,r=0,i=-1,o=0,l;for(;t--;){const a=e.codePointAt(t);if(a===47){if(l){r=t+1;break}continue}n<0&&(l=!0,n=t+1),a===46?i<0?i=t:o!==1&&(o=1):i>-1&&(o=-1)}return i<0||n<0||o===0||o===1&&i===n-1&&i===r+1?"":e.slice(i,n)}function fu(...e){let t=-1,n;for(;++t0&&e.codePointAt(e.length-1)===47&&(n+="/"),t?"/"+n:n}function pu(e,t){let n="",r=0,i=-1,o=0,l=-1,a,u;for(;++l<=e.length;){if(l2){if(u=n.lastIndexOf("/"),u!==n.length-1){u<0?(n="",r=0):(n=n.slice(0,u),r=n.length-1-n.lastIndexOf("/")),i=l,o=0;continue}}else if(n.length>0){n="",r=0,i=l,o=0;continue}}t&&(n=n.length>0?n+"/..":"..",r=2)}else n.length>0?n+="/"+e.slice(i+1,l):n=e.slice(i+1,l),r=l-i-1;i=l,o=0}else a===46&&o>-1?o++:o=-1}return n}function Xe(e){if(typeof e!="string")throw new TypeError("Path must be a string. Received "+JSON.stringify(e))}const mu={cwd:du};function du(){return"/"}function Bn(e){return!!(e!==null&&typeof e=="object"&&"href"in e&&e.href&&"protocol"in e&&e.protocol&&e.auth===void 0)}function gu(e){if(typeof e=="string")e=new URL(e);else if(!Bn(e)){const t=new TypeError('The "path" argument must be of type string or an instance of URL. Received `'+e+"`");throw t.code="ERR_INVALID_ARG_TYPE",t}if(e.protocol!=="file:"){const t=new TypeError("The URL must be of scheme file");throw t.code="ERR_INVALID_URL_SCHEME",t}return yu(e)}function yu(e){if(e.hostname!==""){const r=new TypeError('File URL host must be "localhost" or empty on darwin');throw r.code="ERR_INVALID_FILE_URL_HOST",r}const t=e.pathname;let n=-1;for(;++n0){let[h,...g]=f;const w=r[p][1];Nn(w)&&Nn(h)&&(h=xn(!0,w,h)),r[p]=[s,h,...g]}}}}const wu=new nt().freeze();function Cn(e,t){if(typeof t!="function")throw new TypeError("Cannot `"+e+"` without `parser`")}function En(e,t){if(typeof t!="function")throw new TypeError("Cannot `"+e+"` without `compiler`")}function In(e,t){if(t)throw new Error("Cannot call `"+e+"` on a frozen processor.\nCreate a new processor first, by calling it: use `processor()` instead of `processor`.")}function qt(e){if(!Nn(e)||typeof e.type!="string")throw new TypeError("Expected node, got `"+e+"`")}function Vt(e,t,n){if(!n)throw new Error("`"+e+"` finished async. Use `"+t+"` instead")}function en(e){return Su(e)?e:new Mr(e)}function Su(e){return!!(e&&typeof e=="object"&&"message"in e&&"messages"in e)}function Cu(e){return typeof e=="string"||Eu(e)}function Eu(e){return!!(e&&typeof e=="object"&&"byteLength"in e&&"byteOffset"in e)}const Iu="https://github.com/remarkjs/react-markdown/blob/main/changelog.md",$t=[],Wt={allowDangerousHtml:!0},Tu=/^(https?|ircs?|mailto|xmpp)$/i,vu=[{from:"astPlugins",id:"remove-buggy-html-in-markdown-parser"},{from:"allowDangerousHtml",id:"remove-buggy-html-in-markdown-parser"},{from:"allowNode",id:"replace-allownode-allowedtypes-and-disallowedtypes",to:"allowElement"},{from:"allowedTypes",id:"replace-allownode-allowedtypes-and-disallowedtypes",to:"allowedElements"},{from:"disallowedTypes",id:"replace-allownode-allowedtypes-and-disallowedtypes",to:"disallowedElements"},{from:"escapeHtml",id:"remove-buggy-html-in-markdown-parser"},{from:"includeElementIndex",id:"#remove-includeelementindex"},{from:"includeNodeIndex",id:"change-includenodeindex-to-includeelementindex"},{from:"linkTarget",id:"remove-linktarget"},{from:"plugins",id:"change-plugins-to-remarkplugins",to:"remarkPlugins"},{from:"rawSourcePos",id:"#remove-rawsourcepos"},{from:"renderers",id:"change-renderers-to-components",to:"components"},{from:"source",id:"change-source-to-children",to:"children"},{from:"sourcePos",id:"#remove-sourcepos"},{from:"transformImageUri",id:"#add-urltransform",to:"urlTransform"},{from:"transformLinkUri",id:"#add-urltransform",to:"urlTransform"}];function Au(e){const t=Pu(e),n=zu(e);return Du(t.runSync(t.parse(n),n),e)}function Pu(e){const t=e.rehypePlugins||$t,n=e.remarkPlugins||$t,r=e.remarkRehypeOptions?{...e.remarkRehypeOptions,...Wt}:Wt;return wu().use(sa).use(n).use(ru,r).use(t)}function zu(e){const t=e.children||"",n=new Mr;return typeof t=="string"&&(n.value=t),n}function Du(e,t){const n=t.allowedElements,r=t.allowElement,i=t.components,o=t.disallowedElements,l=t.skipHtml,a=t.unwrapDisallowed,u=t.urlTransform||Lu;for(const f of vu)Object.hasOwn(t,f.from)&&(""+f.from+(f.to?"use `"+f.to+"` instead":"remove it")+Iu+f.id,void 0);return t.className&&(e={type:"element",tagName:"div",properties:{className:t.className},children:e.type==="root"?e.children:[e]}),et(e,s),$i(e,{Fragment:re.Fragment,components:i,ignoreInvalidStyle:!0,jsx:re.jsx,jsxs:re.jsxs,passKeys:!0,passNode:!0});function s(f,c,p){if(f.type==="raw"&&p&&typeof c=="number")return l?p.children.splice(c,1):p.children[c]={type:"text",value:f.value},c;if(f.type==="element"){let h;for(h in dn)if(Object.hasOwn(dn,h)&&Object.hasOwn(f.properties,h)){const g=f.properties[h],w=dn[h];(w===null||w.includes(f.tagName))&&(f.properties[h]=u(String(g||""),h,f))}}if(f.type==="element"){let h=n?!n.includes(f.tagName):o?o.includes(f.tagName):!1;if(!h&&r&&typeof c=="number"&&(h=!r(f,c,p)),h&&p&&typeof c=="number")return a&&f.children?p.children.splice(c,1,...f.children):p.children.splice(c,1),c}}}function Lu(e){const t=e.indexOf(":"),n=e.indexOf("?"),r=e.indexOf("#"),i=e.indexOf("/");return t===-1||i!==-1&&t>i||n!==-1&&t>n||r!==-1&&t>r||Tu.test(e.slice(0,t))?e:""}function Yt(e,t){const n=String(e);if(typeof t!="string")throw new TypeError("Expected character");let r=0,i=n.indexOf(t);for(;i!==-1;)r++,i=n.indexOf(t,i+t.length);return r}function _u(e){if(typeof e!="string")throw new TypeError("Expected a string");return e.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}function Ru(e,t,n){const i=fn((n||{}).ignore||[]),o=Fu(t);let l=-1;for(;++l0?{type:"text",value:b}:void 0),b===!1?p.lastIndex=R+1:(g!==R&&I.push({type:"text",value:s.value.slice(g,R)}),Array.isArray(b)?I.push(...b):b&&I.push(b),g=R+C[0].length,y=!0),!p.global)break;C=p.exec(s.value)}return y?(g?\]}]+$/.exec(e);if(!t)return[e,void 0];e=e.slice(0,t.index);let n=t[0],r=n.indexOf(")");const i=Yt(e,"(");let o=Yt(e,")");for(;r!==-1&&i>o;)e+=n.slice(0,r+1),n=n.slice(r+1),r=n.indexOf(")"),o++;return[e,n]}function Nr(e,t){const n=e.input.charCodeAt(e.index-1);return(e.index===0||Te(n)||un(n))&&(!t||n!==47)}Br.peek=is;function Xu(){this.buffer()}function Gu(e){this.enter({type:"footnoteReference",identifier:"",label:""},e)}function Ju(){this.buffer()}function Zu(e){this.enter({type:"footnoteDefinition",identifier:"",label:"",children:[]},e)}function es(e){const t=this.resume(),n=this.stack[this.stack.length-1];n.type,n.identifier=ce(this.sliceSerialize(e)).toLowerCase(),n.label=t}function ns(e){this.exit(e)}function ts(e){const t=this.resume(),n=this.stack[this.stack.length-1];n.type,n.identifier=ce(this.sliceSerialize(e)).toLowerCase(),n.label=t}function rs(e){this.exit(e)}function is(){return"["}function Br(e,t,n,r){const i=n.createTracker(r);let o=i.move("[^");const l=n.enter("footnoteReference"),a=n.enter("reference");return o+=i.move(n.safe(n.associationId(e),{after:"]",before:o})),a(),l(),o+=i.move("]"),o}function ls(){return{enter:{gfmFootnoteCallString:Xu,gfmFootnoteCall:Gu,gfmFootnoteDefinitionLabelString:Ju,gfmFootnoteDefinition:Zu},exit:{gfmFootnoteCallString:es,gfmFootnoteCall:ns,gfmFootnoteDefinitionLabelString:ts,gfmFootnoteDefinition:rs}}}function os(e){let t=!1;return e&&e.firstLineBlank&&(t=!0),{handlers:{footnoteDefinition:n,footnoteReference:Br},unsafe:[{character:"[",inConstruct:["label","phrasing","reference"]}]};function n(r,i,o,l){const a=o.createTracker(l);let u=a.move("[^");const s=o.enter("footnoteDefinition"),f=o.enter("label");return u+=a.move(o.safe(o.associationId(r),{before:u,after:"]"})),f(),u+=a.move("]:"),r.children&&r.children.length>0&&(a.shift(4),u+=a.move((t?` +`:" ")+o.indentLines(o.containerFlow(r,a.current()),t?jr:as))),s(),u}}function as(e,t,n){return t===0?e:jr(e,t,n)}function jr(e,t,n){return(n?"":" ")+e}const us=["autolink","destinationLiteral","destinationRaw","reference","titleQuote","titleApostrophe"];Hr.peek=ps;function ss(){return{canContainEols:["delete"],enter:{strikethrough:fs},exit:{strikethrough:hs}}}function cs(){return{unsafe:[{character:"~",inConstruct:"phrasing",notInConstruct:us}],handlers:{delete:Hr}}}function fs(e){this.enter({type:"delete",children:[]},e)}function hs(e){this.exit(e)}function Hr(e,t,n,r){const i=n.createTracker(r),o=n.enter("strikethrough");let l=i.move("~~");return l+=n.containerPhrasing(e,{...i.current(),before:l,after:"~"}),l+=i.move("~~"),o(),l}function ps(){return"~"}function ms(e){return e.length}function ds(e,t){const n=t||{},r=(n.align||[]).concat(),i=n.stringLength||ms,o=[],l=[],a=[],u=[];let s=0,f=-1;for(;++fs&&(s=e[f].length);++yu[y])&&(u[y]=C)}w.push(I)}l[f]=w,a[f]=S}let c=-1;if(typeof r=="object"&&"length"in r)for(;++cu[c]&&(u[c]=I),h[c]=I),p[c]=C}l.splice(1,0,p),a.splice(1,0,h),f=-1;const g=[];for(;++f "),o.shift(2);const l=n.indentLines(n.containerFlow(e,o.current()),ks);return i(),l}function ks(e,t,n){return">"+(n?"":" ")+e}function xs(e,t){return Qt(e,t.inConstruct,!0)&&!Qt(e,t.notInConstruct,!1)}function Qt(e,t,n){if(typeof t=="string"&&(t=[t]),!t||t.length===0)return n;let r=-1;for(;++rl&&(l=o):o=1,i=r+t.length,r=n.indexOf(t,i);return l}function ws(e,t){return!!(t.options.fences===!1&&e.value&&!e.lang&&/[^ \r\n]/.test(e.value)&&!/^[\t ]*(?:[\r\n]|$)|(?:^|[\r\n])[\t ]*$/.test(e.value))}function Ss(e){const t=e.options.fence||"`";if(t!=="`"&&t!=="~")throw new Error("Cannot serialize code with `"+t+"` for `options.fence`, expected `` ` `` or `~`");return t}function Cs(e,t,n,r){const i=Ss(n),o=e.value||"",l=i==="`"?"GraveAccent":"Tilde";if(ws(e,n)){const c=n.enter("codeIndented"),p=n.indentLines(o,Es);return c(),p}const a=n.createTracker(r),u=i.repeat(Math.max(bs(o,i)+1,3)),s=n.enter("codeFenced");let f=a.move(u);if(e.lang){const c=n.enter(`codeFencedLang${l}`);f+=a.move(n.safe(e.lang,{before:f,after:" ",encode:["`"],...a.current()})),c()}if(e.lang&&e.meta){const c=n.enter(`codeFencedMeta${l}`);f+=a.move(" "),f+=a.move(n.safe(e.meta,{before:f,after:` `,encode:["`"],...a.current()})),c()}return f+=a.move(` `),o&&(f+=a.move(o+` `)),f+=a.move(u),s(),f}function Es(e,t,n){return(n?"":" ")+e}function tt(e){const t=e.options.quote||'"';if(t!=='"'&&t!=="'")throw new Error("Cannot serialize title with `"+t+"` for `options.quote`, expected `\"`, or `'`");return t}function Is(e,t,n,r){const i=tt(n),o=i==='"'?"Quote":"Apostrophe",l=n.enter("definition");let a=n.enter("label");const u=n.createTracker(r);let s=u.move("[");return s+=u.move(n.safe(n.associationId(e),{before:s,after:"]",...u.current()})),s+=u.move("]: "),a(),!e.url||/[\0- \u007F]/.test(e.url)?(a=n.enter("destinationLiteral"),s+=u.move("<"),s+=u.move(n.safe(e.url,{before:s,after:">",...u.current()})),s+=u.move(">")):(a=n.enter("destinationRaw"),s+=u.move(n.safe(e.url,{before:s,after:e.title?" ":` -`,...u.current()}))),a(),e.title&&(a=n.enter(`title${o}`),s+=u.move(" "+i),s+=u.move(n.safe(e.title,{before:s,after:i,...u.current()})),s+=u.move(i),a()),l(),s}function Ts(e){const t=e.options.emphasis||"*";if(t!=="*"&&t!=="_")throw new Error("Cannot serialize emphasis with `"+t+"` for `options.emphasis`, expected `*`, or `_`");return t}function Ye(e){return"&#x"+e.toString(16).toUpperCase()+";"}function an(e,t,n){const r=Fe(e),i=Fe(t);return r===void 0?i===void 0?n==="_"?{inside:!0,outside:!0}:{inside:!1,outside:!1}:i===1?{inside:!0,outside:!0}:{inside:!1,outside:!0}:r===1?i===void 0?{inside:!1,outside:!1}:i===1?{inside:!0,outside:!0}:{inside:!1,outside:!1}:i===void 0?{inside:!1,outside:!1}:i===1?{inside:!0,outside:!1}:{inside:!1,outside:!1}}Ur.peek=As;function Ur(e,t,n,r){const i=Ts(n),o=n.enter("emphasis"),l=n.createTracker(r),a=l.move(i);let u=l.move(n.containerPhrasing(e,{after:i,before:a,...l.current()}));const s=u.charCodeAt(0),f=an(r.before.charCodeAt(r.before.length-1),s,i);f.inside&&(u=Ye(s)+u.slice(1));const c=u.charCodeAt(u.length-1),p=an(r.after.charCodeAt(0),c,i);p.inside&&(u=u.slice(0,-1)+Ye(c));const h=l.move(i);return o(),n.attentionEncodeSurroundingInfo={after:p.outside,before:f.outside},a+u+h}function As(e,t,n){return n.options.emphasis||"*"}function vs(e,t){let n=!1;return et(e,function(r){if("value"in r&&/\r?\n|\r/.test(r.value)||r.type==="break")return n=!0,On}),!!((!e.depth||e.depth<3)&&Yn(e)&&(t.options.setext||n))}function Ps(e,t,n,r){const i=Math.max(Math.min(6,e.depth||1),1),o=n.createTracker(r);if(vs(e,n)){const f=n.enter("headingSetext"),c=n.enter("phrasing"),p=n.containerPhrasing(e,{...o.current(),before:` +`,...u.current()}))),a(),e.title&&(a=n.enter(`title${o}`),s+=u.move(" "+i),s+=u.move(n.safe(e.title,{before:s,after:i,...u.current()})),s+=u.move(i),a()),l(),s}function Ts(e){const t=e.options.emphasis||"*";if(t!=="*"&&t!=="_")throw new Error("Cannot serialize emphasis with `"+t+"` for `options.emphasis`, expected `*`, or `_`");return t}function Ye(e){return"&#x"+e.toString(16).toUpperCase()+";"}function an(e,t,n){const r=_e(e),i=_e(t);return r===void 0?i===void 0?n==="_"?{inside:!0,outside:!0}:{inside:!1,outside:!1}:i===1?{inside:!0,outside:!0}:{inside:!1,outside:!0}:r===1?i===void 0?{inside:!1,outside:!1}:i===1?{inside:!0,outside:!0}:{inside:!1,outside:!1}:i===void 0?{inside:!1,outside:!1}:i===1?{inside:!0,outside:!1}:{inside:!1,outside:!1}}Ur.peek=vs;function Ur(e,t,n,r){const i=Ts(n),o=n.enter("emphasis"),l=n.createTracker(r),a=l.move(i);let u=l.move(n.containerPhrasing(e,{after:i,before:a,...l.current()}));const s=u.charCodeAt(0),f=an(r.before.charCodeAt(r.before.length-1),s,i);f.inside&&(u=Ye(s)+u.slice(1));const c=u.charCodeAt(u.length-1),p=an(r.after.charCodeAt(0),c,i);p.inside&&(u=u.slice(0,-1)+Ye(c));const h=l.move(i);return o(),n.attentionEncodeSurroundingInfo={after:p.outside,before:f.outside},a+u+h}function vs(e,t,n){return n.options.emphasis||"*"}function As(e,t){let n=!1;return et(e,function(r){if("value"in r&&/\r?\n|\r/.test(r.value)||r.type==="break")return n=!0,On}),!!((!e.depth||e.depth<3)&&Yn(e)&&(t.options.setext||n))}function Ps(e,t,n,r){const i=Math.max(Math.min(6,e.depth||1),1),o=n.createTracker(r);if(As(e,n)){const f=n.enter("headingSetext"),c=n.enter("phrasing"),p=n.containerPhrasing(e,{...o.current(),before:` `,after:` `});return c(),f(),p+` `+(i===1?"=":"-").repeat(p.length-(Math.max(p.lastIndexOf("\r"),p.lastIndexOf(` `))+1))}const l="#".repeat(i),a=n.enter("headingAtx"),u=n.enter("phrasing");o.move(l+" ");let s=n.containerPhrasing(e,{before:"# ",after:` -`,...o.current()});return/^[\t ]/.test(s)&&(s=Ye(s.charCodeAt(0))+s.slice(1)),s=s?l+" "+s:l,n.options.closeAtx&&(s+=" "+l),u(),a(),s}qr.peek=zs;function qr(e){return e.value||""}function zs(){return"<"}Vr.peek=Ds;function Vr(e,t,n,r){const i=tt(n),o=i==='"'?"Quote":"Apostrophe",l=n.enter("image");let a=n.enter("label");const u=n.createTracker(r);let s=u.move("![");return s+=u.move(n.safe(e.alt,{before:s,after:"]",...u.current()})),s+=u.move("]("),a(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(a=n.enter("destinationLiteral"),s+=u.move("<"),s+=u.move(n.safe(e.url,{before:s,after:">",...u.current()})),s+=u.move(">")):(a=n.enter("destinationRaw"),s+=u.move(n.safe(e.url,{before:s,after:e.title?" ":")",...u.current()}))),a(),e.title&&(a=n.enter(`title${o}`),s+=u.move(" "+i),s+=u.move(n.safe(e.title,{before:s,after:i,...u.current()})),s+=u.move(i),a()),s+=u.move(")"),l(),s}function Ds(){return"!"}$r.peek=Ls;function $r(e,t,n,r){const i=e.referenceType,o=n.enter("imageReference");let l=n.enter("label");const a=n.createTracker(r);let u=a.move("![");const s=n.safe(e.alt,{before:u,after:"]",...a.current()});u+=a.move(s+"]["),l();const f=n.stack;n.stack=[],l=n.enter("reference");const c=n.safe(n.associationId(e),{before:u,after:"]",...a.current()});return l(),n.stack=f,o(),i==="full"||!s||s!==c?u+=a.move(c+"]"):i==="shortcut"?u=u.slice(0,-1):u+=a.move("]"),u}function Ls(){return"!"}Wr.peek=Fs;function Wr(e,t,n){let r=e.value||"",i="`",o=-1;for(;new RegExp("(^|[^`])"+i+"([^`]|$)").test(r);)i+="`";for(/[^ \r\n]/.test(r)&&(/^[ \r\n]/.test(r)&&/[ \r\n]$/.test(r)||/^`|`$/.test(r))&&(r=" "+r+" ");++o\u007F]/.test(e.url))}Kr.peek=Rs;function Kr(e,t,n,r){const i=tt(n),o=i==='"'?"Quote":"Apostrophe",l=n.createTracker(r);let a,u;if(Yr(e,n)){const f=n.stack;n.stack=[],a=n.enter("autolink");let c=l.move("<");return c+=l.move(n.containerPhrasing(e,{before:c,after:">",...l.current()})),c+=l.move(">"),a(),n.stack=f,c}a=n.enter("link"),u=n.enter("label");let s=l.move("[");return s+=l.move(n.containerPhrasing(e,{before:s,after:"](",...l.current()})),s+=l.move("]("),u(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(u=n.enter("destinationLiteral"),s+=l.move("<"),s+=l.move(n.safe(e.url,{before:s,after:">",...l.current()})),s+=l.move(">")):(u=n.enter("destinationRaw"),s+=l.move(n.safe(e.url,{before:s,after:e.title?" ":")",...l.current()}))),u(),e.title&&(u=n.enter(`title${o}`),s+=l.move(" "+i),s+=l.move(n.safe(e.title,{before:s,after:i,...l.current()})),s+=l.move(i),u()),s+=l.move(")"),a(),s}function Rs(e,t,n){return Yr(e,n)?"<":"["}Qr.peek=_s;function Qr(e,t,n,r){const i=e.referenceType,o=n.enter("linkReference");let l=n.enter("label");const a=n.createTracker(r);let u=a.move("[");const s=n.containerPhrasing(e,{before:u,after:"]",...a.current()});u+=a.move(s+"]["),l();const f=n.stack;n.stack=[],l=n.enter("reference");const c=n.safe(n.associationId(e),{before:u,after:"]",...a.current()});return l(),n.stack=f,o(),i==="full"||!s||s!==c?u+=a.move(c+"]"):i==="shortcut"?u=u.slice(0,-1):u+=a.move("]"),u}function _s(){return"["}function rt(e){const t=e.options.bullet||"*";if(t!=="*"&&t!=="+"&&t!=="-")throw new Error("Cannot serialize items with `"+t+"` for `options.bullet`, expected `*`, `+`, or `-`");return t}function Os(e){const t=rt(e),n=e.options.bulletOther;if(!n)return t==="*"?"-":"*";if(n!=="*"&&n!=="+"&&n!=="-")throw new Error("Cannot serialize items with `"+n+"` for `options.bulletOther`, expected `*`, `+`, or `-`");if(n===t)throw new Error("Expected `bullet` (`"+t+"`) and `bulletOther` (`"+n+"`) to be different");return n}function Ms(e){const t=e.options.bulletOrdered||".";if(t!=="."&&t!==")")throw new Error("Cannot serialize items with `"+t+"` for `options.bulletOrdered`, expected `.` or `)`");return t}function Xr(e){const t=e.options.rule||"*";if(t!=="*"&&t!=="-"&&t!=="_")throw new Error("Cannot serialize rules with `"+t+"` for `options.rule`, expected `*`, `-`, or `_`");return t}function Ns(e,t,n,r){const i=n.enter("list"),o=n.bulletCurrent;let l=e.ordered?Ms(n):rt(n);const a=e.ordered?l==="."?")":".":Os(n);let u=t&&n.bulletLastUsed?l===n.bulletLastUsed:!1;if(!e.ordered){const f=e.children?e.children[0]:void 0;if((l==="*"||l==="-")&&f&&(!f.children||!f.children[0])&&n.stack[n.stack.length-1]==="list"&&n.stack[n.stack.length-2]==="listItem"&&n.stack[n.stack.length-3]==="list"&&n.stack[n.stack.length-4]==="listItem"&&n.indexStack[n.indexStack.length-1]===0&&n.indexStack[n.indexStack.length-2]===0&&n.indexStack[n.indexStack.length-3]===0&&(u=!0),Xr(n)===l&&f){let c=-1;for(;++c-1?t.start:1)+(n.options.incrementListMarker===!1?0:t.children.indexOf(e))+o);let l=o.length+1;(i==="tab"||i==="mixed"&&(t&&t.type==="list"&&t.spread||e.spread))&&(l=Math.ceil(l/4)*4);const a=n.createTracker(r);a.move(o+" ".repeat(l-o.length)),a.shift(l);const u=n.enter("listItem"),s=n.indentLines(n.containerFlow(e,a.current()),f);return u(),s;function f(c,p,h){return p?(h?"":" ".repeat(l))+c:(h?o:o+" ".repeat(l-o.length))+c}}function Hs(e,t,n,r){const i=n.enter("paragraph"),o=n.enter("phrasing"),l=n.containerPhrasing(e,r);return o(),i(),l}const Us=fn(["break","delete","emphasis","footnote","footnoteReference","image","imageReference","inlineCode","inlineMath","link","linkReference","mdxJsxTextElement","mdxTextExpression","strong","text","textDirective"]);function qs(e,t,n,r){return(e.children.some(function(l){return Us(l)})?n.containerPhrasing:n.containerFlow).call(n,e,r)}function Vs(e){const t=e.options.strong||"*";if(t!=="*"&&t!=="_")throw new Error("Cannot serialize strong with `"+t+"` for `options.strong`, expected `*`, or `_`");return t}Gr.peek=$s;function Gr(e,t,n,r){const i=Vs(n),o=n.enter("strong"),l=n.createTracker(r),a=l.move(i+i);let u=l.move(n.containerPhrasing(e,{after:i,before:a,...l.current()}));const s=u.charCodeAt(0),f=an(r.before.charCodeAt(r.before.length-1),s,i);f.inside&&(u=Ye(s)+u.slice(1));const c=u.charCodeAt(u.length-1),p=an(r.after.charCodeAt(0),c,i);p.inside&&(u=u.slice(0,-1)+Ye(c));const h=l.move(i+i);return o(),n.attentionEncodeSurroundingInfo={after:p.outside,before:f.outside},a+u+h}function $s(e,t,n){return n.options.strong||"*"}function Ws(e,t,n,r){return n.safe(e.value,r)}function Ys(e){const t=e.options.ruleRepetition||3;if(t<3)throw new Error("Cannot serialize rules with repetition `"+t+"` for `options.ruleRepetition`, expected `3` or more");return t}function Ks(e,t,n){const r=(Xr(n)+(n.options.ruleSpaces?" ":"")).repeat(Ys(n));return n.options.ruleSpaces?r.slice(0,-1):r}const Jr={blockquote:ys,break:Xt,code:Cs,definition:Is,emphasis:Ur,hardBreak:Xt,heading:Ps,html:qr,image:Vr,imageReference:$r,inlineCode:Wr,link:Kr,linkReference:Qr,list:Ns,listItem:js,paragraph:Hs,root:qs,strong:Gr,text:Ws,thematicBreak:Ks};function Qs(){return{enter:{table:Xs,tableData:Gt,tableHeader:Gt,tableRow:Js},exit:{codeText:Zs,table:Gs,tableData:Pn,tableHeader:Pn,tableRow:Pn}}}function Xs(e){const t=e._align;this.enter({type:"table",align:t.map(function(n){return n==="none"?null:n}),children:[]},e),this.data.inTable=!0}function Gs(e){this.exit(e),this.data.inTable=void 0}function Js(e){this.enter({type:"tableRow",children:[]},e)}function Pn(e){this.exit(e)}function Gt(e){this.enter({type:"tableCell",children:[]},e)}function Zs(e){let t=this.resume();this.data.inTable&&(t=t.replace(/\\([\\|])/g,ec));const n=this.stack[this.stack.length-1];n.type,n.value=t,this.exit(e)}function ec(e,t){return t==="|"?t:e}function nc(e){const t=e||{},n=t.tableCellPadding,r=t.tablePipeAlign,i=t.stringLength,o=n?" ":"|";return{unsafe:[{character:"\r",inConstruct:"tableCell"},{character:` +`,...o.current()});return/^[\t ]/.test(s)&&(s=Ye(s.charCodeAt(0))+s.slice(1)),s=s?l+" "+s:l,n.options.closeAtx&&(s+=" "+l),u(),a(),s}qr.peek=zs;function qr(e){return e.value||""}function zs(){return"<"}Vr.peek=Ds;function Vr(e,t,n,r){const i=tt(n),o=i==='"'?"Quote":"Apostrophe",l=n.enter("image");let a=n.enter("label");const u=n.createTracker(r);let s=u.move("![");return s+=u.move(n.safe(e.alt,{before:s,after:"]",...u.current()})),s+=u.move("]("),a(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(a=n.enter("destinationLiteral"),s+=u.move("<"),s+=u.move(n.safe(e.url,{before:s,after:">",...u.current()})),s+=u.move(">")):(a=n.enter("destinationRaw"),s+=u.move(n.safe(e.url,{before:s,after:e.title?" ":")",...u.current()}))),a(),e.title&&(a=n.enter(`title${o}`),s+=u.move(" "+i),s+=u.move(n.safe(e.title,{before:s,after:i,...u.current()})),s+=u.move(i),a()),s+=u.move(")"),l(),s}function Ds(){return"!"}$r.peek=Ls;function $r(e,t,n,r){const i=e.referenceType,o=n.enter("imageReference");let l=n.enter("label");const a=n.createTracker(r);let u=a.move("![");const s=n.safe(e.alt,{before:u,after:"]",...a.current()});u+=a.move(s+"]["),l();const f=n.stack;n.stack=[],l=n.enter("reference");const c=n.safe(n.associationId(e),{before:u,after:"]",...a.current()});return l(),n.stack=f,o(),i==="full"||!s||s!==c?u+=a.move(c+"]"):i==="shortcut"?u=u.slice(0,-1):u+=a.move("]"),u}function Ls(){return"!"}Wr.peek=_s;function Wr(e,t,n){let r=e.value||"",i="`",o=-1;for(;new RegExp("(^|[^`])"+i+"([^`]|$)").test(r);)i+="`";for(/[^ \r\n]/.test(r)&&(/^[ \r\n]/.test(r)&&/[ \r\n]$/.test(r)||/^`|`$/.test(r))&&(r=" "+r+" ");++o\u007F]/.test(e.url))}Kr.peek=Rs;function Kr(e,t,n,r){const i=tt(n),o=i==='"'?"Quote":"Apostrophe",l=n.createTracker(r);let a,u;if(Yr(e,n)){const f=n.stack;n.stack=[],a=n.enter("autolink");let c=l.move("<");return c+=l.move(n.containerPhrasing(e,{before:c,after:">",...l.current()})),c+=l.move(">"),a(),n.stack=f,c}a=n.enter("link"),u=n.enter("label");let s=l.move("[");return s+=l.move(n.containerPhrasing(e,{before:s,after:"](",...l.current()})),s+=l.move("]("),u(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(u=n.enter("destinationLiteral"),s+=l.move("<"),s+=l.move(n.safe(e.url,{before:s,after:">",...l.current()})),s+=l.move(">")):(u=n.enter("destinationRaw"),s+=l.move(n.safe(e.url,{before:s,after:e.title?" ":")",...l.current()}))),u(),e.title&&(u=n.enter(`title${o}`),s+=l.move(" "+i),s+=l.move(n.safe(e.title,{before:s,after:i,...l.current()})),s+=l.move(i),u()),s+=l.move(")"),a(),s}function Rs(e,t,n){return Yr(e,n)?"<":"["}Qr.peek=Fs;function Qr(e,t,n,r){const i=e.referenceType,o=n.enter("linkReference");let l=n.enter("label");const a=n.createTracker(r);let u=a.move("[");const s=n.containerPhrasing(e,{before:u,after:"]",...a.current()});u+=a.move(s+"]["),l();const f=n.stack;n.stack=[],l=n.enter("reference");const c=n.safe(n.associationId(e),{before:u,after:"]",...a.current()});return l(),n.stack=f,o(),i==="full"||!s||s!==c?u+=a.move(c+"]"):i==="shortcut"?u=u.slice(0,-1):u+=a.move("]"),u}function Fs(){return"["}function rt(e){const t=e.options.bullet||"*";if(t!=="*"&&t!=="+"&&t!=="-")throw new Error("Cannot serialize items with `"+t+"` for `options.bullet`, expected `*`, `+`, or `-`");return t}function Os(e){const t=rt(e),n=e.options.bulletOther;if(!n)return t==="*"?"-":"*";if(n!=="*"&&n!=="+"&&n!=="-")throw new Error("Cannot serialize items with `"+n+"` for `options.bulletOther`, expected `*`, `+`, or `-`");if(n===t)throw new Error("Expected `bullet` (`"+t+"`) and `bulletOther` (`"+n+"`) to be different");return n}function Ms(e){const t=e.options.bulletOrdered||".";if(t!=="."&&t!==")")throw new Error("Cannot serialize items with `"+t+"` for `options.bulletOrdered`, expected `.` or `)`");return t}function Xr(e){const t=e.options.rule||"*";if(t!=="*"&&t!=="-"&&t!=="_")throw new Error("Cannot serialize rules with `"+t+"` for `options.rule`, expected `*`, `-`, or `_`");return t}function Ns(e,t,n,r){const i=n.enter("list"),o=n.bulletCurrent;let l=e.ordered?Ms(n):rt(n);const a=e.ordered?l==="."?")":".":Os(n);let u=t&&n.bulletLastUsed?l===n.bulletLastUsed:!1;if(!e.ordered){const f=e.children?e.children[0]:void 0;if((l==="*"||l==="-")&&f&&(!f.children||!f.children[0])&&n.stack[n.stack.length-1]==="list"&&n.stack[n.stack.length-2]==="listItem"&&n.stack[n.stack.length-3]==="list"&&n.stack[n.stack.length-4]==="listItem"&&n.indexStack[n.indexStack.length-1]===0&&n.indexStack[n.indexStack.length-2]===0&&n.indexStack[n.indexStack.length-3]===0&&(u=!0),Xr(n)===l&&f){let c=-1;for(;++c-1?t.start:1)+(n.options.incrementListMarker===!1?0:t.children.indexOf(e))+o);let l=o.length+1;(i==="tab"||i==="mixed"&&(t&&t.type==="list"&&t.spread||e.spread))&&(l=Math.ceil(l/4)*4);const a=n.createTracker(r);a.move(o+" ".repeat(l-o.length)),a.shift(l);const u=n.enter("listItem"),s=n.indentLines(n.containerFlow(e,a.current()),f);return u(),s;function f(c,p,h){return p?(h?"":" ".repeat(l))+c:(h?o:o+" ".repeat(l-o.length))+c}}function Hs(e,t,n,r){const i=n.enter("paragraph"),o=n.enter("phrasing"),l=n.containerPhrasing(e,r);return o(),i(),l}const Us=fn(["break","delete","emphasis","footnote","footnoteReference","image","imageReference","inlineCode","inlineMath","link","linkReference","mdxJsxTextElement","mdxTextExpression","strong","text","textDirective"]);function qs(e,t,n,r){return(e.children.some(function(l){return Us(l)})?n.containerPhrasing:n.containerFlow).call(n,e,r)}function Vs(e){const t=e.options.strong||"*";if(t!=="*"&&t!=="_")throw new Error("Cannot serialize strong with `"+t+"` for `options.strong`, expected `*`, or `_`");return t}Gr.peek=$s;function Gr(e,t,n,r){const i=Vs(n),o=n.enter("strong"),l=n.createTracker(r),a=l.move(i+i);let u=l.move(n.containerPhrasing(e,{after:i,before:a,...l.current()}));const s=u.charCodeAt(0),f=an(r.before.charCodeAt(r.before.length-1),s,i);f.inside&&(u=Ye(s)+u.slice(1));const c=u.charCodeAt(u.length-1),p=an(r.after.charCodeAt(0),c,i);p.inside&&(u=u.slice(0,-1)+Ye(c));const h=l.move(i+i);return o(),n.attentionEncodeSurroundingInfo={after:p.outside,before:f.outside},a+u+h}function $s(e,t,n){return n.options.strong||"*"}function Ws(e,t,n,r){return n.safe(e.value,r)}function Ys(e){const t=e.options.ruleRepetition||3;if(t<3)throw new Error("Cannot serialize rules with repetition `"+t+"` for `options.ruleRepetition`, expected `3` or more");return t}function Ks(e,t,n){const r=(Xr(n)+(n.options.ruleSpaces?" ":"")).repeat(Ys(n));return n.options.ruleSpaces?r.slice(0,-1):r}const Jr={blockquote:ys,break:Xt,code:Cs,definition:Is,emphasis:Ur,hardBreak:Xt,heading:Ps,html:qr,image:Vr,imageReference:$r,inlineCode:Wr,link:Kr,linkReference:Qr,list:Ns,listItem:js,paragraph:Hs,root:qs,strong:Gr,text:Ws,thematicBreak:Ks};function Qs(){return{enter:{table:Xs,tableData:Gt,tableHeader:Gt,tableRow:Js},exit:{codeText:Zs,table:Gs,tableData:Pn,tableHeader:Pn,tableRow:Pn}}}function Xs(e){const t=e._align;this.enter({type:"table",align:t.map(function(n){return n==="none"?null:n}),children:[]},e),this.data.inTable=!0}function Gs(e){this.exit(e),this.data.inTable=void 0}function Js(e){this.enter({type:"tableRow",children:[]},e)}function Pn(e){this.exit(e)}function Gt(e){this.enter({type:"tableCell",children:[]},e)}function Zs(e){let t=this.resume();this.data.inTable&&(t=t.replace(/\\([\\|])/g,ec));const n=this.stack[this.stack.length-1];n.type,n.value=t,this.exit(e)}function ec(e,t){return t==="|"?t:e}function nc(e){const t=e||{},n=t.tableCellPadding,r=t.tablePipeAlign,i=t.stringLength,o=n?" ":"|";return{unsafe:[{character:"\r",inConstruct:"tableCell"},{character:` `,inConstruct:"tableCell"},{atBreak:!0,character:"|",after:"[ :-]"},{character:"|",inConstruct:"tableCell"},{atBreak:!0,character:":",after:"-"},{atBreak:!0,character:"-",after:"[:|-]"}],handlers:{inlineCode:p,table:l,tableCell:u,tableRow:a}};function l(h,g,w,S){return s(f(h,w,S),h.align)}function a(h,g,w,S){const y=c(h,w,S),I=s([y]);return I.slice(0,I.indexOf(` -`))}function u(h,g,w,S){const y=w.enter("tableCell"),I=w.enter("phrasing"),C=w.containerPhrasing(h,{...S,before:o,after:o});return I(),y(),C}function s(h,g){return ds(h,{align:g,alignDelimiters:r,padding:n,stringLength:i})}function f(h,g,w){const S=h.children;let y=-1;const I=[],C=g.enter("table");for(;++y0&&!n&&(e[e.length-1][1]._gfmAutolinkLiteralWalkedInto=!0),n}const xc={tokenize:Ac,partial:!0};function bc(){return{document:{91:{name:"gfmFootnoteDefinition",tokenize:Ec,continuation:{tokenize:Ic},exit:Tc}},text:{91:{name:"gfmFootnoteCall",tokenize:Cc},93:{name:"gfmPotentialFootnoteCall",add:"after",tokenize:wc,resolveTo:Sc}}}}function wc(e,t,n){const r=this;let i=r.events.length;const o=r.parser.gfmFootnotes||(r.parser.gfmFootnotes=[]);let l;for(;i--;){const u=r.events[i][1];if(u.type==="labelImage"){l=u;break}if(u.type==="gfmFootnoteCall"||u.type==="labelLink"||u.type==="label"||u.type==="image"||u.type==="link")break}return a;function a(u){if(!l||!l._balanced)return n(u);const s=ce(r.sliceSerialize({start:l.end,end:r.now()}));return s.codePointAt(0)!==94||!o.includes(s.slice(1))?n(u):(e.enter("gfmFootnoteCallLabelMarker"),e.consume(u),e.exit("gfmFootnoteCallLabelMarker"),t(u))}}function Sc(e,t){let n=e.length;for(;n--;)if(e[n][1].type==="labelImage"&&e[n][0]==="enter"){e[n][1];break}e[n+1][1].type="data",e[n+3][1].type="gfmFootnoteCallLabelMarker";const r={type:"gfmFootnoteCall",start:Object.assign({},e[n+3][1].start),end:Object.assign({},e[e.length-1][1].end)},i={type:"gfmFootnoteCallMarker",start:Object.assign({},e[n+3][1].end),end:Object.assign({},e[n+3][1].end)};i.end.column++,i.end.offset++,i.end._bufferIndex++;const o={type:"gfmFootnoteCallString",start:Object.assign({},i.end),end:Object.assign({},e[e.length-1][1].start)},l={type:"chunkString",contentType:"string",start:Object.assign({},o.start),end:Object.assign({},o.end)},a=[e[n+1],e[n+2],["enter",r,t],e[n+3],e[n+4],["enter",i,t],["exit",i,t],["enter",o,t],["enter",l,t],["exit",l,t],["exit",o,t],e[e.length-2],e[e.length-1],["exit",r,t]];return e.splice(n,e.length-n+1,...a),e}function Cc(e,t,n){const r=this,i=r.parser.gfmFootnotes||(r.parser.gfmFootnotes=[]);let o=0,l;return a;function a(c){return e.enter("gfmFootnoteCall"),e.enter("gfmFootnoteCallLabelMarker"),e.consume(c),e.exit("gfmFootnoteCallLabelMarker"),u}function u(c){return c!==94?n(c):(e.enter("gfmFootnoteCallMarker"),e.consume(c),e.exit("gfmFootnoteCallMarker"),e.enter("gfmFootnoteCallString"),e.enter("chunkString").contentType="string",s)}function s(c){if(o>999||c===93&&!l||c===null||c===91||W(c))return n(c);if(c===93){e.exit("chunkString");const p=e.exit("gfmFootnoteCallString");return i.includes(ce(r.sliceSerialize(p)))?(e.enter("gfmFootnoteCallLabelMarker"),e.consume(c),e.exit("gfmFootnoteCallLabelMarker"),e.exit("gfmFootnoteCall"),t):n(c)}return W(c)||(l=!0),o++,e.consume(c),c===92?f:s}function f(c){return c===91||c===92||c===93?(e.consume(c),o++,s):s(c)}}function Ec(e,t,n){const r=this,i=r.parser.gfmFootnotes||(r.parser.gfmFootnotes=[]);let o,l=0,a;return u;function u(g){return e.enter("gfmFootnoteDefinition")._container=!0,e.enter("gfmFootnoteDefinitionLabel"),e.enter("gfmFootnoteDefinitionLabelMarker"),e.consume(g),e.exit("gfmFootnoteDefinitionLabelMarker"),s}function s(g){return g===94?(e.enter("gfmFootnoteDefinitionMarker"),e.consume(g),e.exit("gfmFootnoteDefinitionMarker"),e.enter("gfmFootnoteDefinitionLabelString"),e.enter("chunkString").contentType="string",f):n(g)}function f(g){if(l>999||g===93&&!a||g===null||g===91||W(g))return n(g);if(g===93){e.exit("chunkString");const w=e.exit("gfmFootnoteDefinitionLabelString");return o=ce(r.sliceSerialize(w)),e.enter("gfmFootnoteDefinitionLabelMarker"),e.consume(g),e.exit("gfmFootnoteDefinitionLabelMarker"),e.exit("gfmFootnoteDefinitionLabel"),p}return W(g)||(a=!0),l++,e.consume(g),g===92?c:f}function c(g){return g===91||g===92||g===93?(e.consume(g),l++,f):f(g)}function p(g){return g===58?(e.enter("definitionMarker"),e.consume(g),e.exit("definitionMarker"),i.includes(o)||i.push(o),B(e,h,"gfmFootnoteDefinitionWhitespace")):n(g)}function h(g){return t(g)}}function Ic(e,t,n){return e.check(Qe,t,e.attempt(xc,t,n))}function Tc(e){e.exit("gfmFootnoteDefinition")}function Ac(e,t,n){const r=this;return B(e,i,"gfmFootnoteDefinitionIndent",5);function i(o){const l=r.events[r.events.length-1];return l&&l[1].type==="gfmFootnoteDefinitionIndent"&&l[2].sliceSerialize(l[1],!0).length===4?t(o):n(o)}}function vc(e){let n=(e||{}).singleTilde;const r={name:"strikethrough",tokenize:o,resolveAll:i};return n==null&&(n=!0),{text:{126:r},insideSpan:{null:[r]},attentionMarkers:{null:[126]}};function i(l,a){let u=-1;for(;++u1?u(g):(l.consume(g),c++,h);if(c<2&&!n)return u(g);const S=l.exit("strikethroughSequenceTemporary"),y=Fe(g);return S._open=!y||y===2&&!!w,S._close=!w||w===2&&!!y,a(g)}}}class Pc{constructor(){this.map=[]}add(t,n,r){zc(this,t,n,r)}consume(t){if(this.map.sort(function(o,l){return o[0]-l[0]}),this.map.length===0)return;let n=this.map.length;const r=[];for(;n>0;)n-=1,r.push(t.slice(this.map[n][0]+this.map[n][1]),this.map[n][2]),t.length=this.map[n][0];r.push(t.slice()),t.length=0;let i=r.pop();for(;i;){for(const o of i)t.push(o);i=r.pop()}this.map.length=0}}function zc(e,t,n,r){let i=0;if(!(n===0&&r.length===0)){for(;i-1;){const D=r.events[v][1].type;if(D==="lineEnding"||D==="linePrefix")v--;else break}const P=v>-1?r.events[v][1].type:null,U=P==="tableHead"||P==="tableRow"?b:u;return U===b&&r.parser.lazy[r.now().line]?n(k):U(k)}function u(k){return e.enter("tableHead"),e.enter("tableRow"),s(k)}function s(k){return k===124||(l=!0,o+=1),f(k)}function f(k){return k===null?n(k):z(k)?o>1?(o=0,r.interrupt=!0,e.exit("tableRow"),e.enter("lineEnding"),e.consume(k),e.exit("lineEnding"),h):n(k):O(k)?B(e,f,"whitespace")(k):(o+=1,l&&(l=!1,i+=1),k===124?(e.enter("tableCellDivider"),e.consume(k),e.exit("tableCellDivider"),l=!0,f):(e.enter("data"),c(k)))}function c(k){return k===null||k===124||W(k)?(e.exit("data"),f(k)):(e.consume(k),k===92?p:c)}function p(k){return k===92||k===124?(e.consume(k),c):c(k)}function h(k){return r.interrupt=!1,r.parser.lazy[r.now().line]?n(k):(e.enter("tableDelimiterRow"),l=!1,O(k)?B(e,g,"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(k):g(k))}function g(k){return k===45||k===58?S(k):k===124?(l=!0,e.enter("tableCellDivider"),e.consume(k),e.exit("tableCellDivider"),w):_(k)}function w(k){return O(k)?B(e,S,"whitespace")(k):S(k)}function S(k){return k===58?(o+=1,l=!0,e.enter("tableDelimiterMarker"),e.consume(k),e.exit("tableDelimiterMarker"),y):k===45?(o+=1,y(k)):k===null||z(k)?R(k):_(k)}function y(k){return k===45?(e.enter("tableDelimiterFiller"),I(k)):_(k)}function I(k){return k===45?(e.consume(k),I):k===58?(l=!0,e.exit("tableDelimiterFiller"),e.enter("tableDelimiterMarker"),e.consume(k),e.exit("tableDelimiterMarker"),C):(e.exit("tableDelimiterFiller"),C(k))}function C(k){return O(k)?B(e,R,"whitespace")(k):R(k)}function R(k){return k===124?g(k):k===null||z(k)?!l||i!==o?_(k):(e.exit("tableDelimiterRow"),e.exit("tableHead"),t(k)):_(k)}function _(k){return n(k)}function b(k){return e.enter("tableRow"),M(k)}function M(k){return k===124?(e.enter("tableCellDivider"),e.consume(k),e.exit("tableCellDivider"),M):k===null||z(k)?(e.exit("tableRow"),t(k)):O(k)?B(e,M,"whitespace")(k):(e.enter("data"),H(k))}function H(k){return k===null||k===124||W(k)?(e.exit("data"),M(k)):(e.consume(k),k===92?j:H)}function j(k){return k===92||k===124?(e.consume(k),H):H(k)}}function Rc(e,t){let n=-1,r=!0,i=0,o=[0,0,0,0],l=[0,0,0,0],a=!1,u=0,s,f,c;const p=new Pc;for(;++nn[2]+1){const g=n[2]+1,w=n[3]-n[2]-1;e.add(g,w,[])}}e.add(n[3]+1,0,[["exit",c,t]])}return i!==void 0&&(o.end=Object.assign({},Le(t.events,i)),e.add(i,0,[["exit",o,t]]),o=void 0),o}function Zt(e,t,n,r,i){const o=[],l=Le(t.events,n);i&&(i.end=Object.assign({},l),o.push(["exit",i,t])),r.end=Object.assign({},l),o.push(["exit",r,t]),e.add(n+1,0,o)}function Le(e,t){const n=e[t],r=n[0]==="enter"?"start":"end";return n[1][r]}const _c={name:"tasklistCheck",tokenize:Mc};function Oc(){return{text:{91:_c}}}function Mc(e,t,n){const r=this;return i;function i(u){return r.previous!==null||!r._gfmTasklistFirstContentOfListItem?n(u):(e.enter("taskListCheck"),e.enter("taskListCheckMarker"),e.consume(u),e.exit("taskListCheckMarker"),o)}function o(u){return W(u)?(e.enter("taskListCheckValueUnchecked"),e.consume(u),e.exit("taskListCheckValueUnchecked"),l):u===88||u===120?(e.enter("taskListCheckValueChecked"),e.consume(u),e.exit("taskListCheckValueChecked"),l):n(u)}function l(u){return u===93?(e.enter("taskListCheckMarker"),e.consume(u),e.exit("taskListCheckMarker"),e.exit("taskListCheck"),a):n(u)}function a(u){return z(u)?t(u):O(u)?e.check({tokenize:Nc},t,n)(u):n(u)}}function Nc(e,t,n){return B(e,r,"whitespace");function r(i){return i===null?n(i):t(i)}}function Bc(e){return gr([cc(),bc(),vc(e),Lc(),Oc()])}const jc={};function Hc(e){const t=this,n=e||jc,r=t.data(),i=r.micromarkExtensions||(r.micromarkExtensions=[]),o=r.fromMarkdownExtensions||(r.fromMarkdownExtensions=[]),l=r.toMarkdownExtensions||(r.toMarkdownExtensions=[]);i.push(Bc(n)),o.push(oc()),l.push(ac(n))}const Uc=`# Admin dashboard +`))}function u(h,g,w,S){const y=w.enter("tableCell"),I=w.enter("phrasing"),C=w.containerPhrasing(h,{...S,before:o,after:o});return I(),y(),C}function s(h,g){return ds(h,{align:g,alignDelimiters:r,padding:n,stringLength:i})}function f(h,g,w){const S=h.children;let y=-1;const I=[],C=g.enter("table");for(;++y0&&!n&&(e[e.length-1][1]._gfmAutolinkLiteralWalkedInto=!0),n}const xc={tokenize:vc,partial:!0};function bc(){return{document:{91:{name:"gfmFootnoteDefinition",tokenize:Ec,continuation:{tokenize:Ic},exit:Tc}},text:{91:{name:"gfmFootnoteCall",tokenize:Cc},93:{name:"gfmPotentialFootnoteCall",add:"after",tokenize:wc,resolveTo:Sc}}}}function wc(e,t,n){const r=this;let i=r.events.length;const o=r.parser.gfmFootnotes||(r.parser.gfmFootnotes=[]);let l;for(;i--;){const u=r.events[i][1];if(u.type==="labelImage"){l=u;break}if(u.type==="gfmFootnoteCall"||u.type==="labelLink"||u.type==="label"||u.type==="image"||u.type==="link")break}return a;function a(u){if(!l||!l._balanced)return n(u);const s=ce(r.sliceSerialize({start:l.end,end:r.now()}));return s.codePointAt(0)!==94||!o.includes(s.slice(1))?n(u):(e.enter("gfmFootnoteCallLabelMarker"),e.consume(u),e.exit("gfmFootnoteCallLabelMarker"),t(u))}}function Sc(e,t){let n=e.length;for(;n--;)if(e[n][1].type==="labelImage"&&e[n][0]==="enter"){e[n][1];break}e[n+1][1].type="data",e[n+3][1].type="gfmFootnoteCallLabelMarker";const r={type:"gfmFootnoteCall",start:Object.assign({},e[n+3][1].start),end:Object.assign({},e[e.length-1][1].end)},i={type:"gfmFootnoteCallMarker",start:Object.assign({},e[n+3][1].end),end:Object.assign({},e[n+3][1].end)};i.end.column++,i.end.offset++,i.end._bufferIndex++;const o={type:"gfmFootnoteCallString",start:Object.assign({},i.end),end:Object.assign({},e[e.length-1][1].start)},l={type:"chunkString",contentType:"string",start:Object.assign({},o.start),end:Object.assign({},o.end)},a=[e[n+1],e[n+2],["enter",r,t],e[n+3],e[n+4],["enter",i,t],["exit",i,t],["enter",o,t],["enter",l,t],["exit",l,t],["exit",o,t],e[e.length-2],e[e.length-1],["exit",r,t]];return e.splice(n,e.length-n+1,...a),e}function Cc(e,t,n){const r=this,i=r.parser.gfmFootnotes||(r.parser.gfmFootnotes=[]);let o=0,l;return a;function a(c){return e.enter("gfmFootnoteCall"),e.enter("gfmFootnoteCallLabelMarker"),e.consume(c),e.exit("gfmFootnoteCallLabelMarker"),u}function u(c){return c!==94?n(c):(e.enter("gfmFootnoteCallMarker"),e.consume(c),e.exit("gfmFootnoteCallMarker"),e.enter("gfmFootnoteCallString"),e.enter("chunkString").contentType="string",s)}function s(c){if(o>999||c===93&&!l||c===null||c===91||W(c))return n(c);if(c===93){e.exit("chunkString");const p=e.exit("gfmFootnoteCallString");return i.includes(ce(r.sliceSerialize(p)))?(e.enter("gfmFootnoteCallLabelMarker"),e.consume(c),e.exit("gfmFootnoteCallLabelMarker"),e.exit("gfmFootnoteCall"),t):n(c)}return W(c)||(l=!0),o++,e.consume(c),c===92?f:s}function f(c){return c===91||c===92||c===93?(e.consume(c),o++,s):s(c)}}function Ec(e,t,n){const r=this,i=r.parser.gfmFootnotes||(r.parser.gfmFootnotes=[]);let o,l=0,a;return u;function u(g){return e.enter("gfmFootnoteDefinition")._container=!0,e.enter("gfmFootnoteDefinitionLabel"),e.enter("gfmFootnoteDefinitionLabelMarker"),e.consume(g),e.exit("gfmFootnoteDefinitionLabelMarker"),s}function s(g){return g===94?(e.enter("gfmFootnoteDefinitionMarker"),e.consume(g),e.exit("gfmFootnoteDefinitionMarker"),e.enter("gfmFootnoteDefinitionLabelString"),e.enter("chunkString").contentType="string",f):n(g)}function f(g){if(l>999||g===93&&!a||g===null||g===91||W(g))return n(g);if(g===93){e.exit("chunkString");const w=e.exit("gfmFootnoteDefinitionLabelString");return o=ce(r.sliceSerialize(w)),e.enter("gfmFootnoteDefinitionLabelMarker"),e.consume(g),e.exit("gfmFootnoteDefinitionLabelMarker"),e.exit("gfmFootnoteDefinitionLabel"),p}return W(g)||(a=!0),l++,e.consume(g),g===92?c:f}function c(g){return g===91||g===92||g===93?(e.consume(g),l++,f):f(g)}function p(g){return g===58?(e.enter("definitionMarker"),e.consume(g),e.exit("definitionMarker"),i.includes(o)||i.push(o),B(e,h,"gfmFootnoteDefinitionWhitespace")):n(g)}function h(g){return t(g)}}function Ic(e,t,n){return e.check(Qe,t,e.attempt(xc,t,n))}function Tc(e){e.exit("gfmFootnoteDefinition")}function vc(e,t,n){const r=this;return B(e,i,"gfmFootnoteDefinitionIndent",5);function i(o){const l=r.events[r.events.length-1];return l&&l[1].type==="gfmFootnoteDefinitionIndent"&&l[2].sliceSerialize(l[1],!0).length===4?t(o):n(o)}}function Ac(e){let n=(e||{}).singleTilde;const r={name:"strikethrough",tokenize:o,resolveAll:i};return n==null&&(n=!0),{text:{126:r},insideSpan:{null:[r]},attentionMarkers:{null:[126]}};function i(l,a){let u=-1;for(;++u1?u(g):(l.consume(g),c++,h);if(c<2&&!n)return u(g);const S=l.exit("strikethroughSequenceTemporary"),y=_e(g);return S._open=!y||y===2&&!!w,S._close=!w||w===2&&!!y,a(g)}}}class Pc{constructor(){this.map=[]}add(t,n,r){zc(this,t,n,r)}consume(t){if(this.map.sort(function(o,l){return o[0]-l[0]}),this.map.length===0)return;let n=this.map.length;const r=[];for(;n>0;)n-=1,r.push(t.slice(this.map[n][0]+this.map[n][1]),this.map[n][2]),t.length=this.map[n][0];r.push(t.slice()),t.length=0;let i=r.pop();for(;i;){for(const o of i)t.push(o);i=r.pop()}this.map.length=0}}function zc(e,t,n,r){let i=0;if(!(n===0&&r.length===0)){for(;i-1;){const D=r.events[A][1].type;if(D==="lineEnding"||D==="linePrefix")A--;else break}const P=A>-1?r.events[A][1].type:null,U=P==="tableHead"||P==="tableRow"?b:u;return U===b&&r.parser.lazy[r.now().line]?n(k):U(k)}function u(k){return e.enter("tableHead"),e.enter("tableRow"),s(k)}function s(k){return k===124||(l=!0,o+=1),f(k)}function f(k){return k===null?n(k):z(k)?o>1?(o=0,r.interrupt=!0,e.exit("tableRow"),e.enter("lineEnding"),e.consume(k),e.exit("lineEnding"),h):n(k):O(k)?B(e,f,"whitespace")(k):(o+=1,l&&(l=!1,i+=1),k===124?(e.enter("tableCellDivider"),e.consume(k),e.exit("tableCellDivider"),l=!0,f):(e.enter("data"),c(k)))}function c(k){return k===null||k===124||W(k)?(e.exit("data"),f(k)):(e.consume(k),k===92?p:c)}function p(k){return k===92||k===124?(e.consume(k),c):c(k)}function h(k){return r.interrupt=!1,r.parser.lazy[r.now().line]?n(k):(e.enter("tableDelimiterRow"),l=!1,O(k)?B(e,g,"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(k):g(k))}function g(k){return k===45||k===58?S(k):k===124?(l=!0,e.enter("tableCellDivider"),e.consume(k),e.exit("tableCellDivider"),w):F(k)}function w(k){return O(k)?B(e,S,"whitespace")(k):S(k)}function S(k){return k===58?(o+=1,l=!0,e.enter("tableDelimiterMarker"),e.consume(k),e.exit("tableDelimiterMarker"),y):k===45?(o+=1,y(k)):k===null||z(k)?R(k):F(k)}function y(k){return k===45?(e.enter("tableDelimiterFiller"),I(k)):F(k)}function I(k){return k===45?(e.consume(k),I):k===58?(l=!0,e.exit("tableDelimiterFiller"),e.enter("tableDelimiterMarker"),e.consume(k),e.exit("tableDelimiterMarker"),C):(e.exit("tableDelimiterFiller"),C(k))}function C(k){return O(k)?B(e,R,"whitespace")(k):R(k)}function R(k){return k===124?g(k):k===null||z(k)?!l||i!==o?F(k):(e.exit("tableDelimiterRow"),e.exit("tableHead"),t(k)):F(k)}function F(k){return n(k)}function b(k){return e.enter("tableRow"),M(k)}function M(k){return k===124?(e.enter("tableCellDivider"),e.consume(k),e.exit("tableCellDivider"),M):k===null||z(k)?(e.exit("tableRow"),t(k)):O(k)?B(e,M,"whitespace")(k):(e.enter("data"),H(k))}function H(k){return k===null||k===124||W(k)?(e.exit("data"),M(k)):(e.consume(k),k===92?j:H)}function j(k){return k===92||k===124?(e.consume(k),H):H(k)}}function Rc(e,t){let n=-1,r=!0,i=0,o=[0,0,0,0],l=[0,0,0,0],a=!1,u=0,s,f,c;const p=new Pc;for(;++nn[2]+1){const g=n[2]+1,w=n[3]-n[2]-1;e.add(g,w,[])}}e.add(n[3]+1,0,[["exit",c,t]])}return i!==void 0&&(o.end=Object.assign({},Le(t.events,i)),e.add(i,0,[["exit",o,t]]),o=void 0),o}function Zt(e,t,n,r,i){const o=[],l=Le(t.events,n);i&&(i.end=Object.assign({},l),o.push(["exit",i,t])),r.end=Object.assign({},l),o.push(["exit",r,t]),e.add(n+1,0,o)}function Le(e,t){const n=e[t],r=n[0]==="enter"?"start":"end";return n[1][r]}const Fc={name:"tasklistCheck",tokenize:Mc};function Oc(){return{text:{91:Fc}}}function Mc(e,t,n){const r=this;return i;function i(u){return r.previous!==null||!r._gfmTasklistFirstContentOfListItem?n(u):(e.enter("taskListCheck"),e.enter("taskListCheckMarker"),e.consume(u),e.exit("taskListCheckMarker"),o)}function o(u){return W(u)?(e.enter("taskListCheckValueUnchecked"),e.consume(u),e.exit("taskListCheckValueUnchecked"),l):u===88||u===120?(e.enter("taskListCheckValueChecked"),e.consume(u),e.exit("taskListCheckValueChecked"),l):n(u)}function l(u){return u===93?(e.enter("taskListCheckMarker"),e.consume(u),e.exit("taskListCheckMarker"),e.exit("taskListCheck"),a):n(u)}function a(u){return z(u)?t(u):O(u)?e.check({tokenize:Nc},t,n)(u):n(u)}}function Nc(e,t,n){return B(e,r,"whitespace");function r(i){return i===null?n(i):t(i)}}function Bc(e){return gr([cc(),bc(),Ac(e),Lc(),Oc()])}const jc={};function Hc(e){const t=this,n=e||jc,r=t.data(),i=r.micromarkExtensions||(r.micromarkExtensions=[]),o=r.fromMarkdownExtensions||(r.fromMarkdownExtensions=[]),l=r.toMarkdownExtensions||(r.toMarkdownExtensions=[]);i.push(Bc(n)),o.push(oc()),l.push(ac(n))}const Uc=`# Admin dashboard Otari ships with a web admin dashboard for operators. It browses the model catalogue, sets model pricing, manages aliases, adds and edits provider API @@ -49,7 +49,7 @@ straight. | **Purpose** | Signs in to the dashboard and authorizes every management API call | Encrypts provider API keys stored through the dashboard (encryption at rest) | | **Set via** | \`OTARI_MASTER_KEY\` (or \`master_key\` in \`config.yml\`); generated on first run if unset | \`OTARI_SECRET_KEY\` only; never generated for you | | **Format** | Any string you choose, or a generated \`otari-mk-…\` value | A Fernet key (generate with \`otari gen-secret-key\`) | -| **Where it lives** | Only its SHA-256 hash is stored; in the browser it is held in the tab's session storage | Supplied out of band at runtime; never written to the database | +| **Where it lives** | Only its SHA-256 hash is stored; the browser never keeps the key itself, just the session cookie it is exchanged for | Supplied out of band at runtime; never written to the database | | **If you lose it** | Rotate or reset it; nothing else is affected | Every provider key stored in the dashboard becomes undecryptable | A few consequences worth internalizing: @@ -123,11 +123,16 @@ can skip this step if all your providers live in \`config.yml\`. ### 4. Open the dashboard and sign in Browse to the gateway root, for example \`http://localhost:8000/\`. You land on a -sign-in screen. Paste your master key and select **Sign in**. The key is held -only in this browser tab's session storage and sent directly to this gateway; it -is never persisted to disk by the browser and is cleared when you sign out. If -you are on a fresh install and are not sure where your key is, the "First run? -Where to find your key" hint on the sign-in screen points you back at the logs. +sign-in screen. Paste your master key and select **Sign in**. The key is sent +once to this gateway and exchanged for a session cookie; the browser never stores +the key itself, so it cannot be read back out of the page. The sign-in lasts +\`dashboard_session_ttl_hours\` (a week by default) and survives closing the tab, +so you normally sign in once and not again. It survives restarting the gateway +too, as long as the gateway's database does: sessions are rows in it, so a +container running the default SQLite file with no mounted volume starts every run +signed out. If you are on a fresh install and are not sure where your key is, the +"First run? Where to find your key" hint on the sign-in screen points you back at +the logs. ### 5. Add a provider @@ -234,10 +239,18 @@ put it behind HTTPS, as the security notes below describe. authorizes every management request and must never travel over cleartext HTTP, so put the gateway behind HTTPS or a trusted reverse proxy before signing in from another host. -- **Session storage, not local storage.** The dashboard keeps the master key in - the browser tab's session storage, so it does not persist across tabs or - survive closing the tab, and signing out clears it along with any cached admin - data. +- **A session cookie, not a stored key.** The dashboard trades your master key + for an HttpOnly cookie (\`SameSite=Strict\`, and \`Secure\` whenever the request + arrives over HTTPS), so the key itself is never kept in the browser and script + on the page cannot read the cookie. Signing out revokes the session on the + server, expires the cookie, and clears any cached admin data. Rotating the + master key revokes every session and re-mints the one you are using, so other + signed-in browsers are logged out. +- **Sign out on a machine you share.** A session runs for its full + \`dashboard_session_ttl_hours\` with no idle timeout, so an unattended browser + stays signed in until the cookie expires. Use **Sign out** when you are done on + a shared or public machine, or shorten \`dashboard_session_ttl_hours\`. Rotating + the master key is the way to revoke a session you can no longer reach. - **Provider keys are write-only over the API.** Once stored, the plaintext is never returned; the UI shows only the last four characters. Losing \`OTARI_SECRET_KEY\` makes stored keys undecryptable, so back it up separately @@ -256,4 +269,4 @@ put it behind HTTPS, as the security notes below describe. `),r=n.findIndex(l=>l.trim()===`## ${t}`);if(r===-1)return e;let i=n.length,o=!1;for(let l=r+1;l{const i=Vc(t),o=$c(i);return re.jsx("a",{href:i,...o?{target:"_blank",rel:"noreferrer"}:{},...r,children:n})},table:({node:e,...t})=>re.jsx("div",{className:"otari-markdown-scroll",tabIndex:0,role:"region","aria-label":"Table",children:re.jsx("table",{...t})}),pre:({node:e,...t})=>re.jsx("pre",{tabIndex:0,role:"region","aria-label":"Code",...t})};function Zc(){return re.jsxs("div",{className:"flex flex-col gap-6",children:[re.jsx(gi,{title:"User guide",description:"A reference for operating this dashboard, bundled with and version-matched to the running gateway. New here? The get-started walkthrough lives at /welcome."}),re.jsx(ct,{children:re.jsx(ct.Content,{className:"p-5 sm:p-6",children:re.jsx("div",{className:"otari-markdown",children:re.jsx(vu,{remarkPlugins:[Hc],components:Kc,children:Yc})})})})]})}export{Zc as DocsPage}; +`)}const Yc=Wc(Uc.replace(/^#{1,6}[ \t]+.*\r?\n+/,""),"First-run walkthrough"),Kc={a:({node:e,href:t,children:n,...r})=>{const i=Vc(t),o=$c(i);return re.jsx("a",{href:i,...o?{target:"_blank",rel:"noreferrer"}:{},...r,children:n})},table:({node:e,...t})=>re.jsx("div",{className:"otari-markdown-scroll",tabIndex:0,role:"region","aria-label":"Table",children:re.jsx("table",{...t})}),pre:({node:e,...t})=>re.jsx("pre",{tabIndex:0,role:"region","aria-label":"Code",...t})};function Zc(){return re.jsxs("div",{className:"flex flex-col gap-6",children:[re.jsx(gi,{title:"User guide",description:"A reference for operating this dashboard, bundled with and version-matched to the running gateway. New here? The get-started walkthrough lives at /welcome."}),re.jsx(ct,{children:re.jsx(ct.Content,{className:"p-5 sm:p-6",children:re.jsx("div",{className:"otari-markdown",children:re.jsx(Au,{remarkPlugins:[Hc],components:Kc,children:Yc})})})})]})}export{Zc as DocsPage}; diff --git a/src/gateway/static/dashboard/assets/KeysPage-DHZEligd.js b/src/gateway/static/dashboard/assets/KeysPage-C0dFnjAw.js similarity index 98% rename from src/gateway/static/dashboard/assets/KeysPage-DHZEligd.js rename to src/gateway/static/dashboard/assets/KeysPage-C0dFnjAw.js index 5842c18d..63eeb378 100644 --- a/src/gateway/static/dashboard/assets/KeysPage-DHZEligd.js +++ b/src/gateway/static/dashboard/assets/KeysPage-C0dFnjAw.js @@ -1,4 +1,4 @@ -import{j as e}from"./tanstack-query-1t81HyiD.js";import{r as l}from"./react-dgEcD0HR.js";import{a as Q,s as q,t as X,v as Z,P as ee,E as O,q as te,w as se,u as U,I as ae}from"./index-JlWCttWt.js";import{u as ne,r as re,B as ie}from"./tableSelection-9hV37uhu.js";import{C as le}from"./ConfirmDialog-DXR8OubG.js";import{D as oe}from"./DataTable-Bmn_eYSV.js";import{F as D}from"./Field-Dwp6u3t8.js";import{a as F,M as W}from"./ModelScopeControl-Bcam0tnJ.js";import{C as P,L as ce,I as de,a as ue,b as me,D as xe,f as A,B as g,d as I}from"./heroui-BI50yK5B.js";function he({value:t,onChange:a,users:n,description:i}){const u=n.filter(r=>!r.user_id.startsWith("apikey-")).map(r=>({id:r.user_id,name:r.alias?`${r.user_id} (${r.alias})`:r.user_id})),[o,c]=l.useState(t),x=o.trim().toLowerCase(),y=u.filter(r=>!x||r.id.toLowerCase().includes(x)||r.name.toLowerCase().includes(x)).slice(0,50),p=r=>{const m=r.trim(),j=u.find(v=>v.id===m||v.name===m);return j?j.id:m},d=p(o),h=u.some(r=>r.id===d),f=d!==""&&!h?e.jsxs("span",{children:["Creates a new user ",e.jsx("code",{children:d}),"."]}):i??"Spend and budgets track against this user.";return e.jsxs(P.Root,{allowsCustomValue:!0,allowsEmptyCollection:!0,menuTrigger:"focus",inputValue:o,onInputChange:r=>{c(r),a(p(r))},onSelectionChange:r=>{if(r!=null){const m=String(r);c(m),a(m)}},className:"flex max-w-md flex-col gap-1",children:[e.jsx(ce,{className:"text-sm font-medium text-[var(--otari-ink)]",children:"Owner"}),e.jsxs(P.InputGroup,{children:[e.jsx(de,{placeholder:"Pick a user, or type a new id…",autoComplete:"off","data-1p-ignore":!0,"data-lpignore":"true",onFocus:r=>r.currentTarget.select()}),e.jsx(P.Trigger,{})]}),e.jsx(P.Popover,{children:e.jsx(ue,{items:y,className:"max-h-72 overflow-auto",children:r=>e.jsx(me,{id:r.id,textValue:r.name,children:r.name})})}),e.jsx(xe,{className:"text-xs text-[var(--otari-muted)]",children:f})]})}function H(t){if(!t)return"—";const a=new Date(t);return Number.isNaN(a.getTime())?"—":a.toLocaleDateString()}function fe(t){if(!t)return null;const a=new Date(t).getTime();if(Number.isNaN(a))return null;const n=Math.round((a-Date.now())/1e3),i=Math.abs(n),u=[["day",86400],["hour",3600],["minute",60]],o=new Intl.RelativeTimeFormat(void 0,{numeric:"auto"});for(const[c,x]of u)if(i>=x)return o.format(Math.round(n/x),c);return o.format(n,"second")}function pe(t){if(!t.expires_at)return!1;const a=new Date(t.expires_at).getTime();return!Number.isNaN(a)&&aString(i).padStart(2,"0");return`${a.getFullYear()}-${n(a.getMonth()+1)}-${n(a.getDate())}T${n(a.getHours())}:${n(a.getMinutes())}`}const ye=t=>(t??"").startsWith("apikey-"),M=t=>t.key_name??t.id,ve=t=>t.id;function K({label:t,value:a,multiline:n=!1,fieldRef:i}){const u=l.useRef(null),o=i??u,[c,x]=l.useState(!1),[y,p]=l.useState(!1),d=async()=>{var f,r,m;(f=o.current)==null||f.focus(),(r=o.current)==null||r.select();try{if((m=navigator.clipboard)!=null&&m.writeText){await navigator.clipboard.writeText(a),x(!0),p(!1),window.setTimeout(()=>x(!1),2e3);return}}catch{}p(!0)},h="w-full rounded-lg border border-[var(--otari-line)] bg-[var(--otari-bg)] px-3 py-2 font-mono text-xs text-[var(--otari-ink)]";return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-xs font-medium text-[var(--otari-muted)]",children:t}),e.jsx(g,{size:"sm",variant:"outline",onPress:d,children:c?"Copied":"Copy"})]}),n?e.jsx("textarea",{ref:o,readOnly:!0,rows:a.split(` +import{j as e}from"./tanstack-query-1t81HyiD.js";import{r as l}from"./react-dgEcD0HR.js";import{a as Q,s as q,t as X,v as Z,P as ee,E as O,q as te,w as se,u as U,I as ae}from"./index-BP-wLuMr.js";import{u as ne,r as re,B as ie}from"./tableSelection-9hV37uhu.js";import{C as le}from"./ConfirmDialog-BFS2k4X_.js";import{D as oe}from"./DataTable-Bmn_eYSV.js";import{F as D}from"./Field-Dwp6u3t8.js";import{a as F,M as W}from"./ModelScopeControl-hWii6vSv.js";import{C as P,L as ce,I as de,a as ue,b as me,D as xe,f as A,B as g,d as I}from"./heroui-BI50yK5B.js";function he({value:t,onChange:a,users:n,description:i}){const u=n.filter(r=>!r.user_id.startsWith("apikey-")).map(r=>({id:r.user_id,name:r.alias?`${r.user_id} (${r.alias})`:r.user_id})),[o,c]=l.useState(t),x=o.trim().toLowerCase(),y=u.filter(r=>!x||r.id.toLowerCase().includes(x)||r.name.toLowerCase().includes(x)).slice(0,50),p=r=>{const m=r.trim(),j=u.find(v=>v.id===m||v.name===m);return j?j.id:m},d=p(o),h=u.some(r=>r.id===d),f=d!==""&&!h?e.jsxs("span",{children:["Creates a new user ",e.jsx("code",{children:d}),"."]}):i??"Spend and budgets track against this user.";return e.jsxs(P.Root,{allowsCustomValue:!0,allowsEmptyCollection:!0,menuTrigger:"focus",inputValue:o,onInputChange:r=>{c(r),a(p(r))},onSelectionChange:r=>{if(r!=null){const m=String(r);c(m),a(m)}},className:"flex max-w-md flex-col gap-1",children:[e.jsx(ce,{className:"text-sm font-medium text-[var(--otari-ink)]",children:"Owner"}),e.jsxs(P.InputGroup,{children:[e.jsx(de,{placeholder:"Pick a user, or type a new id…",autoComplete:"off","data-1p-ignore":!0,"data-lpignore":"true",onFocus:r=>r.currentTarget.select()}),e.jsx(P.Trigger,{})]}),e.jsx(P.Popover,{children:e.jsx(ue,{items:y,className:"max-h-72 overflow-auto",children:r=>e.jsx(me,{id:r.id,textValue:r.name,children:r.name})})}),e.jsx(xe,{className:"text-xs text-[var(--otari-muted)]",children:f})]})}function H(t){if(!t)return"—";const a=new Date(t);return Number.isNaN(a.getTime())?"—":a.toLocaleDateString()}function fe(t){if(!t)return null;const a=new Date(t).getTime();if(Number.isNaN(a))return null;const n=Math.round((a-Date.now())/1e3),i=Math.abs(n),u=[["day",86400],["hour",3600],["minute",60]],o=new Intl.RelativeTimeFormat(void 0,{numeric:"auto"});for(const[c,x]of u)if(i>=x)return o.format(Math.round(n/x),c);return o.format(n,"second")}function pe(t){if(!t.expires_at)return!1;const a=new Date(t.expires_at).getTime();return!Number.isNaN(a)&&aString(i).padStart(2,"0");return`${a.getFullYear()}-${n(a.getMonth()+1)}-${n(a.getDate())}T${n(a.getHours())}:${n(a.getMinutes())}`}const ye=t=>(t??"").startsWith("apikey-"),M=t=>t.key_name??t.id,ve=t=>t.id;function K({label:t,value:a,multiline:n=!1,fieldRef:i}){const u=l.useRef(null),o=i??u,[c,x]=l.useState(!1),[y,p]=l.useState(!1),d=async()=>{var f,r,m;(f=o.current)==null||f.focus(),(r=o.current)==null||r.select();try{if((m=navigator.clipboard)!=null&&m.writeText){await navigator.clipboard.writeText(a),x(!0),p(!1),window.setTimeout(()=>x(!1),2e3);return}}catch{}p(!0)},h="w-full rounded-lg border border-[var(--otari-line)] bg-[var(--otari-bg)] px-3 py-2 font-mono text-xs text-[var(--otari-ink)]";return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-xs font-medium text-[var(--otari-muted)]",children:t}),e.jsx(g,{size:"sm",variant:"outline",onPress:d,children:c?"Copied":"Copy"})]}),n?e.jsx("textarea",{ref:o,readOnly:!0,rows:a.split(` `).length,value:a,onFocus:f=>f.currentTarget.select(),className:`${h} resize-none whitespace-pre`}):e.jsx("input",{ref:o,readOnly:!0,value:a,onFocus:f=>f.currentTarget.select(),className:h}),e.jsx("span",{"aria-live":"polite",className:"text-xs text-green-700",children:c?"Copied to clipboard.":""}),y?e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"Selected. Press Ctrl/Cmd-C to copy."}):null]})}function je({title:t,result:a,onClose:n}){const i=l.useRef(null),u=l.useRef(null),o=typeof window<"u"?window.location.origin:"",c=a.key;l.useEffect(()=>{var d,h;(d=u.current)==null||d.focus(),(h=u.current)==null||h.select()},[]);const x=d=>{var m;if(d.key!=="Tab")return;const h=(m=i.current)==null?void 0:m.querySelectorAll('button, input, textarea, a[href], [tabindex]:not([tabindex="-1"])');if(!h||h.length===0)return;const f=h[0],r=h[h.length-1];d.shiftKey&&document.activeElement===f?(d.preventDefault(),r.focus()):!d.shiftKey&&document.activeElement===r&&(d.preventDefault(),f.focus())},y=[`curl ${o}/v1/chat/completions \\`,` -H "Otari-Key: ${c}" \\`,' -H "Content-Type: application/json" \\',` -d '{"model": "your-model", "messages": [{"role": "user", "content": "Hello"}]}'`].join(` `),p=["from openai import OpenAI","",`client = OpenAI(base_url="${o}/v1", api_key="${c}")`,"resp = client.chat.completions.create(",' model="your-model",',' messages=[{"role": "user", "content": "Hello"}],',")","print(resp.choices[0].message.content)"].join(` `);return e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4",role:"presentation",children:e.jsxs("div",{ref:i,role:"dialog","aria-modal":"true","aria-labelledby":"reveal-title",onKeyDown:x,className:"flex max-h-[90vh] w-full max-w-2xl flex-col gap-4 overflow-y-auto rounded-xl bg-[var(--otari-surface)] p-6 shadow-xl",children:[e.jsx("h2",{id:"reveal-title",className:"text-lg font-semibold text-[var(--otari-ink)]",children:t}),e.jsx(ae,{tone:"warning",children:"Copy this key now. For security it is shown only once and cannot be retrieved later. If you lose it, use Regenerate to issue a new secret."}),e.jsxs("p",{className:"text-xs text-[var(--otari-muted)]",children:["Model access: ",F(a.allowed_models).text,"."]}),e.jsx(K,{label:"Secret key",value:c,fieldRef:u}),e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium text-[var(--otari-ink)]",children:"Make your first call"}),e.jsxs("p",{className:"text-xs text-[var(--otari-muted)]",children:["Replace ",e.jsx("code",{children:"your-model"})," with a model from the Models page."]})]}),e.jsx(K,{label:"curl",value:y,multiline:!0}),e.jsx(K,{label:"Python (OpenAI SDK)",value:p,multiline:!0})]}),e.jsx("div",{className:"flex justify-end",children:e.jsx(g,{variant:"primary",onPress:n,children:"I’ve saved this key"})})]})})}function V({trigger:t,message:a,confirmLabel:n,isPending:i,onConfirm:u}){const[o,c]=l.useState(!1);return o?e.jsxs("div",{className:"flex flex-col items-end gap-1.5 rounded-lg border border-amber-200 bg-amber-50 p-2 text-right",children:[e.jsx("span",{className:"max-w-xs text-xs text-amber-800",children:a}),e.jsxs("span",{className:"inline-flex gap-1",children:[e.jsx(g,{size:"sm",variant:"danger",isDisabled:i,onPress:u,children:n}),e.jsx(g,{size:"sm",variant:"ghost",isDisabled:i,onPress:()=>c(!1),children:"Cancel"})]})]}):e.jsx(g,{size:"sm",variant:"danger-soft",onPress:()=>c(!0),children:t})}function G({userId:t,users:a}){const n=t.trim();if(n==="")return e.jsx("p",{className:"text-xs text-[var(--otari-muted)]",children:"Choose an owner above to see the models this key can inherit."});const i=a.find(c=>c.user_id===n);if(!i)return e.jsxs("p",{className:"text-xs text-[var(--otari-muted)]",children:["New user ",e.jsx("code",{children:n})," starts unrestricted, so this key may allow any model."]});const{text:u}=F(i.allowed_models),o=i.allowed_models&&i.allowed_models.length>0?i.allowed_models.join(", "):null;return e.jsxs("p",{className:"text-xs text-[var(--otari-muted)]",children:["Owner ",e.jsx("code",{children:n})," allows ",e.jsx("span",{className:"font-medium text-[var(--otari-ink)]",children:u.toLowerCase()}),o?e.jsxs(e.Fragment,{children:[" (",e.jsx("span",{className:"font-mono",children:o}),")"]}):null,". This key inherits that, or narrows within it."]})}function Y({checked:t,onChange:a}){return e.jsxs("label",{className:"flex items-start gap-2 rounded-lg border border-[var(--otari-line)] p-3 text-sm",children:[e.jsx("input",{type:"checkbox",checked:t,onChange:n=>a(n.target.checked),className:"mt-0.5 h-4 w-4 accent-[var(--otari-brand)]","aria-label":"Exempt this key from budget"}),e.jsxs("span",{className:"flex flex-col gap-0.5",children:[e.jsx("span",{className:"font-medium text-[var(--otari-ink)]",children:"Exempt from budget"}),e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"Requests on this key are logged with their cost but never counted toward the owner's budget or spend, and never blocked by it."})]})]})}function be({onClose:t,onCreated:a}){const n=se(),i=U(),[u,o]=l.useState(""),[c,x]=l.useState(""),[y,p]=l.useState(!1),[d,h]=l.useState(""),[f,r]=l.useState(null),[m,j]=l.useState(!1),[v,E]=l.useState(!0),C=c!==""&&new Date(c).getTime(){if(n.isPending||!v||N)return;const b={key_name:u.trim()||null,user_id:d.trim(),expires_at:c?new Date(c).toISOString():null,allowed_models:f,exclude_from_budget:m};n.mutate(b,{onSuccess:w=>{a(w),t()}})};return e.jsx(I,{children:e.jsxs(I.Content,{className:"flex flex-col gap-4 p-5",children:[e.jsx("div",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:"Create API key"}),e.jsx(O,{error:n.error}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsx(D,{label:"Name",value:u,onChange:o,placeholder:"ci-bot",autoFocus:!0,description:"A label to recognize this key later."}),e.jsx(D,{label:"Expires (optional)",value:c,onChange:x,type:"datetime-local",description:C?e.jsx("span",{className:"text-red-700",children:"That time is in the past; the key would be rejected immediately."}):"Leave blank for a key that never expires."})]}),e.jsx(he,{value:d,onChange:h,users:i.data??[]}),e.jsx("button",{type:"button",className:"self-start text-xs font-medium text-[var(--otari-brand-dark)]",onClick:()=>p(b=>!b),children:y?"Hide advanced":"Advanced"}),y?e.jsxs("div",{className:"flex flex-col gap-4 rounded-lg border border-[var(--otari-line)] p-4",children:[e.jsx(G,{userId:d,users:i.data??[]}),e.jsx(W,{title:"Restrict this key's models",description:"By default this key inherits its owner's access. Optionally narrow it to a subset; a key can never exceed its owner's allowed models.",anyLabel:"Inherit owner access",initial:null,onChange:(b,w)=>{r(b),E(w)}}),e.jsx(Y,{checked:m,onChange:j})]}):null,e.jsxs("div",{className:"flex gap-2",children:[e.jsx(g,{variant:"primary",isDisabled:n.isPending||!v||N,onPress:S,children:n.isPending?"Creating…":"Create key"}),e.jsx(g,{variant:"ghost",onPress:t,children:"Cancel"})]})]})})}function we({apiKey:t,onClose:a}){const n=q(),i=U(),[u,o]=l.useState(t.key_name??""),[c,x]=l.useState(ge(t.expires_at)),[y,p]=l.useState(t.allowed_models),[d,h]=l.useState(t.exclude_from_budget),[f,r]=l.useState(!0),m=()=>{n.isPending||!f||n.mutate({id:t.id,body:{key_name:u.trim()||null,expires_at:c?new Date(c).toISOString():null,allowed_models:y,exclude_from_budget:d}},{onSuccess:a})};return e.jsx(I,{children:e.jsxs(I.Content,{className:"flex flex-col gap-4 p-5",children:[e.jsxs("div",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:["Edit ",e.jsx("code",{children:t.key_name??t.id})]}),e.jsx(O,{error:n.error}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsx(D,{label:"Name",value:u,onChange:o,placeholder:"ci-bot"}),e.jsx(D,{label:"Expires",value:c,onChange:x,type:"datetime-local",description:"Blank clears the expiry."})]}),t.user_id?e.jsx(G,{userId:t.user_id,users:i.data??[]}):null,e.jsx(W,{title:"Restrict this key's models",description:"This key inherits its owner's access by default. Narrow it to a subset here; it can never exceed the owner's allowed models.",anyLabel:"Inherit owner access",initial:t.allowed_models,onChange:(j,v)=>{p(j),r(v)}}),e.jsx(Y,{checked:d,onChange:h}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(g,{variant:"primary",isDisabled:n.isPending||!f,onPress:m,children:n.isPending?"Saving…":"Save changes"}),e.jsx(g,{variant:"ghost",onPress:a,children:"Cancel"})]})]})})}function Ne({apiKey:t}){return t.is_active?pe(t)?e.jsx(A,{size:"sm",color:"warning",children:"Expired"}):e.jsx(A,{size:"sm",color:"accent",children:"Active"}):e.jsx(A,{size:"sm",color:"default",children:"Disabled"})}function ke({allowed:t}){const{text:a,tone:n}=F(t),i=n==="danger"?"text-red-700 font-medium":n==="muted"?"text-[var(--otari-muted)]":"text-[var(--otari-brand-dark)] font-medium",u=t&&t.length>0?t.join(", "):void 0;return e.jsx("span",{className:`text-xs ${i}`,title:u,children:a})}function Re(){const t=Q(),a=q(),n=X(),i=Z(),[u,o]=l.useState(!1),[c,x]=l.useState(null),[y,p]=l.useState(null),d=t.data??[],h=t.isLoading,f=d.find(s=>s.id===c)??null,r=!h&&d.length===0&&!u,m=ne(),[j,v]=l.useState(!1),[E,C]=l.useState(void 0),[N,S]=l.useState(!1),b=d.map(s=>s.id),w=re(m.selectedKeys,b),T=d.filter(s=>w.includes(s.id)),$=l.useCallback((s,k)=>a.mutate({id:s.id,body:{is_active:k}}),[a.mutate]),z=l.useCallback(s=>n.mutate(s.id,{onSuccess:k=>p({title:`New secret for ${M(s)}`,result:k})}),[n.mutate]),R=async(s,k,B)=>{S(!0),C(void 0);try{for(const L of s)await k(L);m.clear(),B==null||B()}catch(L){C(L)}finally{S(!1)}},J=l.useMemo(()=>[{id:"name",header:"Name",isRowHeader:!0,cell:s=>e.jsxs("div",{className:"flex flex-col gap-0.5",children:[e.jsx("span",{className:"font-medium text-[var(--otari-ink)]",children:s.key_name??e.jsx("span",{className:"text-[var(--otari-muted)]",children:"(unnamed)"})}),e.jsxs("div",{className:"flex flex-wrap items-center gap-1",children:[e.jsx(ke,{allowed:s.allowed_models}),s.exclude_from_budget?e.jsx("span",{className:"inline-flex items-center rounded-full border border-[var(--otari-line)] bg-[var(--otari-brand-tint)] px-2 py-0.5 text-xs font-medium text-[var(--otari-brand-dark)]",title:"Requests on this key are logged with cost but never counted toward budget",children:"Budget-exempt"}):null]})]})},{id:"status",header:"Status",cell:s=>e.jsx(Ne,{apiKey:s})},{id:"owner",header:"Owner",cell:s=>ye(s.user_id)?e.jsx(A,{size:"sm",color:"default",children:"virtual"}):e.jsx("code",{className:"text-xs text-[var(--otari-muted)]",children:s.user_id??"—"})},{id:"key",header:"Key",cell:s=>e.jsx("code",{className:"text-xs text-[var(--otari-muted)]",children:s.key_prefix?`${s.key_prefix}…`:"—"})},{id:"created",header:"Created",cell:s=>e.jsx("span",{className:"text-[var(--otari-muted)]",children:H(s.created_at)})},{id:"last_used",header:"Last used",cell:s=>e.jsx("span",{className:"text-[var(--otari-muted)]",children:fe(s.last_used_at)??"never"})},{id:"expires",header:"Expires",cell:s=>e.jsx("span",{className:"text-[var(--otari-muted)]",title:s.expires_at?new Date(s.expires_at).toLocaleString():void 0,children:s.expires_at?H(s.expires_at):"never"})},{id:"actions",header:"Actions",align:"end",cell:s=>e.jsxs("div",{className:"flex items-center justify-end gap-1.5",children:[e.jsx(g,{size:"sm",variant:"outline",isDisabled:a.isPending,onPress:()=>$(s,!s.is_active),children:s.is_active?"Disable":"Enable"}),e.jsx(g,{size:"sm",variant:"ghost",onPress:()=>{o(!1),x(s.id)},children:"Edit"}),e.jsx(V,{trigger:"Regenerate",confirmLabel:"Regenerate",isPending:n.isPending,message:e.jsxs(e.Fragment,{children:["Regenerate the secret for ",e.jsx("strong",{children:M(s)}),"? The current secret stops working immediately, with no grace period."]}),onConfirm:()=>z(s)}),s.is_active?null:e.jsx(V,{trigger:"Delete",confirmLabel:"Delete permanently",isPending:i.isPending,message:e.jsxs(e.Fragment,{children:["Permanently delete ",e.jsx("strong",{children:M(s)}),"? This removes the key and unlinks its usage history. Cannot be undone."]}),onConfirm:()=>i.mutate(s.id)})]})}],[a.isPending,n.isPending,i.isPending,i.mutate,$,z]),_=T.filter(s=>!s.is_active);return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(ee,{title:"API keys",description:"Issue and revoke the keys that authenticate callers to this gateway. Secrets are shown once at creation.",action:u?null:e.jsx(g,{variant:"primary",onPress:()=>{x(null),o(!0)},children:"Create key"})}),e.jsx(O,{error:t.error??a.error??n.error??i.error}),r?e.jsx(te,{title:"No API keys yet",description:"An API key authenticates callers to this gateway. Create one to make your first request; the secret is shown once, so keep it somewhere safe.",actionLabel:"Create your first key",onAction:()=>{x(null),o(!0)}}):null,u?e.jsx(be,{onClose:()=>o(!1),onCreated:s=>p({title:"API key created",result:s})}):null,f?e.jsx(we,{apiKey:f,onClose:()=>x(null)},f.id):null,w.length>0?e.jsxs(ie,{selectedCount:w.length,allMatching:!1,matchingTotal:null,canSelectAllMatching:!1,onSelectAllMatching:()=>{},onClear:m.clear,children:[e.jsx(g,{size:"sm",variant:"outline",isDisabled:N,onPress:()=>void R(T,s=>a.mutateAsync({id:s.id,body:{is_active:!1}})),children:"Disable"}),e.jsx(g,{size:"sm",variant:"outline",isDisabled:N,onPress:()=>void R(T,s=>a.mutateAsync({id:s.id,body:{exclude_from_budget:!0}})),children:"Budget-exempt"}),e.jsx(g,{size:"sm",variant:"danger",isDisabled:_.length===0,onPress:()=>v(!0),children:"Delete"})]}):null,r?null:e.jsx(oe,{ariaLabel:"API keys",columns:J,rows:d,getRowKey:ve,isLoading:h,emptyContent:"No API keys yet. Create one to authenticate a caller.",selectionMode:"multiple",selectedKeys:m.selectedKeys,onSelectionChange:m.onSelectionChange}),e.jsx(le,{isOpen:j,onOpenChange:v,heading:"Delete API keys",body:`Permanently delete ${_.length} disabled ${_.length===1?"key":"keys"}? This removes them and unlinks their usage history. Cannot be undone. Active keys in the selection are skipped; disable them first.`,confirmLabel:"Delete permanently",isPending:N,error:E,onConfirm:()=>void R(_,s=>i.mutateAsync(s.id),()=>v(!1))}),y?e.jsx(je,{title:y.title,result:y.result,onClose:()=>{p(null),n.reset()}}):null]})}export{Re as KeysPage}; diff --git a/src/gateway/static/dashboard/assets/ModelScopeControl-Bcam0tnJ.js b/src/gateway/static/dashboard/assets/ModelScopeControl-hWii6vSv.js similarity index 98% rename from src/gateway/static/dashboard/assets/ModelScopeControl-Bcam0tnJ.js rename to src/gateway/static/dashboard/assets/ModelScopeControl-hWii6vSv.js index 647a5c4a..7d9ebcc0 100644 --- a/src/gateway/static/dashboard/assets/ModelScopeControl-Bcam0tnJ.js +++ b/src/gateway/static/dashboard/assets/ModelScopeControl-hWii6vSv.js @@ -1 +1 @@ -import{j as t}from"./tanstack-query-1t81HyiD.js";import{r as n}from"./react-dgEcD0HR.js";import{L as A,h as $,i as P}from"./index-JlWCttWt.js";import{C as d,I as R,a as T,b as V}from"./heroui-BI50yK5B.js";function q(r){return r===null?"any":r.length===0?"block":"only"}const O=50;function W({initial:r,onChange:m,title:N="Model access",description:w,anyLabel:C="Any model"}){const x=A(),u=$(),v=P(),[i,L]=n.useState(q(r)),[a,g]=n.useState(r??[]),[p,y]=n.useState(""),f=n.useMemo(()=>{var j,k;const e=new Set,s=[],l=(o,c)=>{o&&!e.has(o)&&(e.add(o),s.push({id:o,label:c}))};for(const o of((j=x.data)==null?void 0:j.providers)??[])l(`${o.instance}:*`,`${o.instance}:* · all ${o.instance} models`);for(const o of((k=u.data)==null?void 0:k.providers)??[])for(const c of o.models)l(c.key,c.key);for(const o of v.data??[])l(o.target,`${o.name} · alias`);return s},[x.data,u.data,v.data]),S=n.useMemo(()=>{const e=p.trim().toLowerCase();return f.filter(s=>!a.includes(s.id)).filter(s=>!e||s.id.toLowerCase().includes(e)||s.label.toLowerCase().includes(e)).slice(0,O)},[f,a,p]),h=(e,s)=>{e==="any"?m(null,!0):e==="block"?m([],!0):m(s,s.length>0)},B=e=>{L(e),h(e,a)},M=e=>{const s=a.includes(e)?a:[...a,e];g(s),y(""),h("only",s)},E=e=>{const s=a.filter(l=>l!==e);g(s),h("only",s)},b=(e,s)=>t.jsx("button",{type:"button","aria-pressed":i===e,onClick:()=>B(e),className:i===e?"rounded-md bg-white px-3 py-1.5 text-sm font-medium text-[var(--otari-ink)] shadow-sm":"rounded-md px-3 py-1.5 text-sm text-[var(--otari-muted)] hover:text-[var(--otari-ink)]",children:s}),I=!u.isLoading&&!x.isLoading&&f.length===0;return t.jsxs("div",{className:"flex flex-col gap-3",children:[t.jsxs("div",{children:[t.jsx("span",{className:"text-sm font-medium text-[var(--otari-ink)]",children:N}),t.jsx("p",{className:"text-xs text-[var(--otari-muted)]",children:w??"Which models this key may list and call. The master key is never restricted, so blocking a key cannot lock you out of the dashboard."})]}),t.jsxs("div",{className:"flex w-fit items-center gap-1 rounded-lg bg-[var(--otari-bg)] p-1",children:[b("any",C),b("only","Only selected"),b("block","Block all")]}),i==="block"?t.jsxs("div",{className:"rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-800",children:["Blocked from ",t.jsx("strong",{children:"every"})," model until you change this access."]}):null,i==="only"?t.jsxs("div",{className:"flex flex-col gap-2",children:[t.jsx("div",{className:"flex flex-wrap gap-1.5",children:a.length===0?t.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"Pick at least one model below, or choose “Block all”."}):a.map(e=>t.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full bg-[var(--otari-brand-tint)] px-2.5 py-1 font-mono text-xs text-[var(--otari-brand-dark)]",children:[e,t.jsx("button",{type:"button","aria-label":`Remove ${e}`,onClick:()=>E(e),className:"text-[var(--otari-brand-dark)] hover:text-red-700",children:"×"})]},e))}),I?t.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"No providers or models discovered yet. Configure a provider first, then scope this key."}):t.jsxs(d.Root,{allowsEmptyCollection:!0,menuTrigger:"input",inputValue:p,onInputChange:y,selectedKey:null,onSelectionChange:e=>{e!=null&&M(String(e))},className:"flex max-w-md flex-col gap-1",children:[t.jsxs(d.InputGroup,{children:[t.jsx(R,{"aria-label":"Add a model",placeholder:"Search providers, models, aliases…",autoComplete:"off"}),t.jsx(d.Trigger,{})]}),t.jsx(d.Popover,{children:t.jsx(T,{items:S,className:"max-h-72 overflow-auto",children:e=>t.jsx(V,{id:e.id,textValue:e.label,children:e.label})})})]})]}):null]})}function X(r){return r===null?{text:"All models",tone:"muted"}:r.length===0?{text:"No models",tone:"danger"}:{text:"Selected models",tone:"normal"}}export{W as M,X as a}; +import{j as t}from"./tanstack-query-1t81HyiD.js";import{r as n}from"./react-dgEcD0HR.js";import{L as A,h as $,i as P}from"./index-BP-wLuMr.js";import{C as d,I as R,a as T,b as V}from"./heroui-BI50yK5B.js";function q(r){return r===null?"any":r.length===0?"block":"only"}const O=50;function W({initial:r,onChange:m,title:N="Model access",description:w,anyLabel:C="Any model"}){const x=A(),u=$(),v=P(),[i,L]=n.useState(q(r)),[a,g]=n.useState(r??[]),[p,y]=n.useState(""),f=n.useMemo(()=>{var j,k;const e=new Set,s=[],l=(o,c)=>{o&&!e.has(o)&&(e.add(o),s.push({id:o,label:c}))};for(const o of((j=x.data)==null?void 0:j.providers)??[])l(`${o.instance}:*`,`${o.instance}:* · all ${o.instance} models`);for(const o of((k=u.data)==null?void 0:k.providers)??[])for(const c of o.models)l(c.key,c.key);for(const o of v.data??[])l(o.target,`${o.name} · alias`);return s},[x.data,u.data,v.data]),S=n.useMemo(()=>{const e=p.trim().toLowerCase();return f.filter(s=>!a.includes(s.id)).filter(s=>!e||s.id.toLowerCase().includes(e)||s.label.toLowerCase().includes(e)).slice(0,O)},[f,a,p]),h=(e,s)=>{e==="any"?m(null,!0):e==="block"?m([],!0):m(s,s.length>0)},B=e=>{L(e),h(e,a)},M=e=>{const s=a.includes(e)?a:[...a,e];g(s),y(""),h("only",s)},E=e=>{const s=a.filter(l=>l!==e);g(s),h("only",s)},b=(e,s)=>t.jsx("button",{type:"button","aria-pressed":i===e,onClick:()=>B(e),className:i===e?"rounded-md bg-white px-3 py-1.5 text-sm font-medium text-[var(--otari-ink)] shadow-sm":"rounded-md px-3 py-1.5 text-sm text-[var(--otari-muted)] hover:text-[var(--otari-ink)]",children:s}),I=!u.isLoading&&!x.isLoading&&f.length===0;return t.jsxs("div",{className:"flex flex-col gap-3",children:[t.jsxs("div",{children:[t.jsx("span",{className:"text-sm font-medium text-[var(--otari-ink)]",children:N}),t.jsx("p",{className:"text-xs text-[var(--otari-muted)]",children:w??"Which models this key may list and call. The master key is never restricted, so blocking a key cannot lock you out of the dashboard."})]}),t.jsxs("div",{className:"flex w-fit items-center gap-1 rounded-lg bg-[var(--otari-bg)] p-1",children:[b("any",C),b("only","Only selected"),b("block","Block all")]}),i==="block"?t.jsxs("div",{className:"rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-800",children:["Blocked from ",t.jsx("strong",{children:"every"})," model until you change this access."]}):null,i==="only"?t.jsxs("div",{className:"flex flex-col gap-2",children:[t.jsx("div",{className:"flex flex-wrap gap-1.5",children:a.length===0?t.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"Pick at least one model below, or choose “Block all”."}):a.map(e=>t.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full bg-[var(--otari-brand-tint)] px-2.5 py-1 font-mono text-xs text-[var(--otari-brand-dark)]",children:[e,t.jsx("button",{type:"button","aria-label":`Remove ${e}`,onClick:()=>E(e),className:"text-[var(--otari-brand-dark)] hover:text-red-700",children:"×"})]},e))}),I?t.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"No providers or models discovered yet. Configure a provider first, then scope this key."}):t.jsxs(d.Root,{allowsEmptyCollection:!0,menuTrigger:"input",inputValue:p,onInputChange:y,selectedKey:null,onSelectionChange:e=>{e!=null&&M(String(e))},className:"flex max-w-md flex-col gap-1",children:[t.jsxs(d.InputGroup,{children:[t.jsx(R,{"aria-label":"Add a model",placeholder:"Search providers, models, aliases…",autoComplete:"off"}),t.jsx(d.Trigger,{})]}),t.jsx(d.Popover,{children:t.jsx(T,{items:S,className:"max-h-72 overflow-auto",children:e=>t.jsx(V,{id:e.id,textValue:e.label,children:e.label})})})]})]}):null]})}function X(r){return r===null?{text:"All models",tone:"muted"}:r.length===0?{text:"No models",tone:"danger"}:{text:"Selected models",tone:"normal"}}export{W as M,X as a}; diff --git a/src/gateway/static/dashboard/assets/ModelsPage-avB5ycpT.js b/src/gateway/static/dashboard/assets/ModelsPage-CDwjz2Xn.js similarity index 99% rename from src/gateway/static/dashboard/assets/ModelsPage-avB5ycpT.js rename to src/gateway/static/dashboard/assets/ModelsPage-CDwjz2Xn.js index 22b0cc80..7ea899e2 100644 --- a/src/gateway/static/dashboard/assets/ModelsPage-avB5ycpT.js +++ b/src/gateway/static/dashboard/assets/ModelsPage-CDwjz2Xn.js @@ -1 +1 @@ -import{j as e}from"./tanstack-query-1t81HyiD.js";import{i as gt,u as vt,r as c}from"./react-dgEcD0HR.js";import{x as _t,y as bt,h as jt,z as yt,A as je,P as Pt,E as Nt,F as B,I as St,B as ae,D as Re,C as ze,G as be,H as Ct,J as kt,K as E}from"./index-JlWCttWt.js";import{u as Mt,r as Wt,B as It}from"./tableSelection-9hV37uhu.js";import{D as Tt}from"./DataTable-Bmn_eYSV.js";import{T as Lt,S as At}from"./TablePagination-CfsjgA8s.js";import{B as A,d as se,f as V}from"./heroui-BI50yK5B.js";function Oe(t){const i=t.indexOf(":");return i>0?t.slice(0,i):"—"}function $t(t,i=Date.now()){const r=new Map;for(const n of t){const a=r.get(n.model_key)??[];a.push(n),r.set(n.model_key,a)}const s=[];for(const n of r.values()){const a=[...n].sort((p,u)=>Date.parse(p.effective_at)-Date.parse(u.effective_at)),f=[...a].reverse().find(p=>Date.parse(p.effective_at)<=i);s.push(f??a[0])}return s.sort((n,a)=>n.model_key.localeCompare(a.model_key))}const Et="otari",De=[{value:"vision",label:"Vision",test:t=>Array.isArray(t.input_modalities)&&t.input_modalities.includes("image")},{value:"tool_call",label:"Tool calling",test:t=>!!t.tool_call},{value:"reasoning",label:"Reasoning",test:t=>!!t.reasoning},{value:"structured_output",label:"Structured output",test:t=>!!t.structured_output},{value:"attachment",label:"Attachments",test:t=>!!t.attachment},{value:"audio",label:"Audio",test:t=>Array.isArray(t.input_modalities)&&t.input_modalities.includes("audio")},{value:"pdf",label:"PDF",test:t=>Array.isArray(t.input_modalities)&&t.input_modalities.includes("pdf")}],Ot=[{key:"reasoning",label:"Reasoning"},{key:"tool_call",label:"Tool calling"},{key:"structured_output",label:"Structured output"},{key:"attachment",label:"Attachments"},{key:"temperature",label:"Temperature"}],Fe={text:"Text",image:"Image",audio:"Audio",video:"Video",pdf:"PDF"},Dt=[{value:"0",label:"Any context"},{value:"8000",label:"≥ 8K"},{value:"32000",label:"≥ 32K"},{value:"128000",label:"≥ 128K"},{value:"200000",label:"≥ 200K"},{value:"1000000",label:"≥ 1M"}],Ft=[{value:"",label:"Any price"},{value:"1",label:"≤ $1 / 1M in"},{value:"3",label:"≤ $3 / 1M in"},{value:"10",label:"≤ $10 / 1M in"},{value:"30",label:"≤ $30 / 1M in"}],Bt=[{value:"",label:"Base prices"},{value:"8000",label:"Compare at 8K"},{value:"128000",label:"Compare at 128K"},{value:"200000",label:"Compare at 200K"},{value:"500000",label:"Compare at 500K"},{value:"1000000",label:"Compare at 1M"}],Kt=[{value:"all",label:"Any release date"},{value:"365",label:"Past year"},{value:"730",label:"Past 2 years"},{value:"1095",label:"Past 3 years"}],Rt=1440*60*1e3,zt=t=>t.key;function Be(t,i){const r=`${i}:`;return t.startsWith(r)?t.slice(r.length):t}function Ke(t,i){const r={inputPrice:t.inputPrice,outputPrice:t.outputPrice,cacheReadPrice:t.cacheReadPrice,cacheWritePrice:t.cacheWritePrice,cacheWrite1hPrice:t.cacheWrite1hPrice};if(i==null)return r;const s=t.pricingTiers.filter(n=>n.min_input_tokens<=i).sort((n,a)=>a.min_input_tokens-n.min_input_tokens)[0];return s?{inputPrice:s.input_price_per_million??r.inputPrice,outputPrice:s.output_price_per_million??r.outputPrice,cacheReadPrice:s.cache_read_price_per_million??r.cacheReadPrice,cacheWritePrice:s.cache_write_price_per_million??r.cacheWritePrice,cacheWrite1hPrice:s.cache_write_1h_price_per_million??r.cacheWrite1hPrice}:r}function ce(t){const i=Number(t);return t.trim()!==""&&Number.isFinite(i)&&i>=0}function w(t){if(t.trim()==="")return!0;const i=Number(t);return Number.isFinite(i)&&i>=0}function Y(t){return t.trim()===""?null:Number(t)}function we(t){return t.map((i,r)=>({id:r,minInputTokens:String(i.min_input_tokens),input:i.input_price_per_million==null?"":String(i.input_price_per_million),output:i.output_price_per_million==null?"":String(i.output_price_per_million),cacheRead:i.cache_read_price_per_million==null?"":String(i.cache_read_price_per_million),cacheWrite:i.cache_write_price_per_million==null?"":String(i.cache_write_price_per_million),cacheWrite1h:i.cache_write_1h_price_per_million==null?"":String(i.cache_write_1h_price_per_million)}))}function Ve(t){const i=new Set;return t.every(r=>{const s=Number(r.minInputTokens),n=[r.input,r.output,r.cacheRead,r.cacheWrite,r.cacheWrite1h].some(a=>a.trim()!=="");return!Number.isInteger(s)||s<=0||i.has(s)||!n?!1:(i.add(s),[r.input,r.output,r.cacheRead,r.cacheWrite,r.cacheWrite1h].every(w))})}function Ye(t){return t.map(i=>({min_input_tokens:Number(i.minInputTokens),...i.input.trim()===""?{}:{input_price_per_million:Number(i.input)},...i.output.trim()===""?{}:{output_price_per_million:Number(i.output)},...i.cacheRead.trim()===""?{}:{cache_read_price_per_million:Number(i.cacheRead)},...i.cacheWrite.trim()===""?{}:{cache_write_price_per_million:Number(i.cacheWrite)},...i.cacheWrite1h.trim()===""?{}:{cache_write_1h_price_per_million:Number(i.cacheWrite1h)}}))}function b({value:t,onChange:i,ariaLabel:r}){return e.jsx("input",{type:"number",step:"any",min:"0",inputMode:"decimal","aria-label":r,value:t,onChange:s=>i(s.target.value),className:"w-28 rounded-md border border-[var(--otari-line)] bg-white px-2 py-1 text-right text-sm tabular-nums focus:border-[var(--otari-brand)] focus:outline-none"})}function He({tiers:t,onChange:i}){const r=(n,a,f)=>{i(t.map(p=>p.id===n?{...p,[a]:f}:p))},s=()=>{const n=t.reduce((a,f)=>Math.max(a,f.id),-1)+1;i([...t,{id:n,minInputTokens:"128000",input:"",output:"",cacheRead:"",cacheWrite:"",cacheWrite1h:""}])};return e.jsxs("div",{className:"flex flex-col gap-2 rounded-lg border border-[var(--otari-line)] p-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-xs font-medium text-[var(--otari-ink)]",children:"Long-context price tiers"}),e.jsx("p",{className:"text-xs text-[var(--otari-muted)]",children:"At a threshold, listed rates replace the base rate for the whole request."})]}),e.jsx(A,{size:"sm",variant:"outline",onPress:s,children:"Add tier"})]}),t.map(n=>e.jsxs("div",{className:"flex flex-wrap items-end gap-2 border-t border-[var(--otari-line)] pt-2",children:[e.jsxs("label",{className:"flex flex-col gap-1 text-xs text-[var(--otari-muted)]",children:["Context ≥ tokens",e.jsx("input",{type:"number",min:"1",step:"1",inputMode:"numeric","aria-label":"Tier context threshold",value:n.minInputTokens,onChange:a=>r(n.id,"minInputTokens",a.target.value),className:"w-28 rounded-md border border-[var(--otari-line)] bg-white px-2 py-1 text-right text-sm tabular-nums focus:border-[var(--otari-brand)] focus:outline-none"})]}),e.jsxs("label",{className:"flex flex-col gap-1 text-xs text-[var(--otari-muted)]",children:["Input",e.jsx(b,{value:n.input,onChange:a=>r(n.id,"input",a),ariaLabel:"Tier input price"})]}),e.jsxs("label",{className:"flex flex-col gap-1 text-xs text-[var(--otari-muted)]",children:["Output",e.jsx(b,{value:n.output,onChange:a=>r(n.id,"output",a),ariaLabel:"Tier output price"})]}),e.jsxs("label",{className:"flex flex-col gap-1 text-xs text-[var(--otari-muted)]",children:["Cache read",e.jsx(b,{value:n.cacheRead,onChange:a=>r(n.id,"cacheRead",a),ariaLabel:"Tier cache read price"})]}),e.jsxs("label",{className:"flex flex-col gap-1 text-xs text-[var(--otari-muted)]",children:["Cache write",e.jsx(b,{value:n.cacheWrite,onChange:a=>r(n.id,"cacheWrite",a),ariaLabel:"Tier cache write price"})]}),e.jsxs("label",{className:"flex flex-col gap-1 text-xs text-[var(--otari-muted)]",children:["1h write",e.jsx(b,{value:n.cacheWrite1h,onChange:a=>r(n.id,"cacheWrite1h",a),ariaLabel:"Tier 1 hour cache write price"})]}),e.jsx(A,{size:"sm",variant:"ghost",onPress:()=>i(t.filter(a=>a.id!==n.id)),children:"Remove"})]},n.id))]})}function wt({source:t}){return t==="configured"?e.jsx(V,{size:"sm",color:"default",children:"configured"}):t==="default"||t==="alias"?e.jsx(V,{size:"sm",color:"accent",children:t}):e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"not priced"})}function oe({label:t,tone:i="info",children:r}){const s=c.useId();return e.jsxs("span",{className:"group relative inline-flex items-center font-normal normal-case",children:[e.jsx("button",{type:"button","aria-label":t,"aria-describedby":s,className:`inline-flex h-4 w-4 items-center justify-center rounded-full border text-[10px] leading-none ${i==="warning"?"border-[#c2843a] text-[#b45309]":"border-[var(--otari-line)] text-[var(--otari-muted)] hover:border-[var(--otari-brand)] hover:text-[var(--otari-brand)]"}`,children:"i"}),e.jsx("span",{id:s,role:"tooltip",className:"pointer-events-none absolute top-full right-0 z-20 mt-1.5 w-72 rounded-lg border border-[var(--otari-line)] bg-[var(--otari-surface)] px-3 py-2 text-left text-xs font-normal whitespace-normal break-words text-[var(--otari-ink)] opacity-0 shadow-lg transition-opacity group-hover:opacity-100 group-focus-within:opacity-100",children:r})]})}function Vt(){const t=kt();return t.data?t.data.default_pricing?e.jsx(oe,{label:"How unpriced models are metered",tone:"info",children:"Default pricing is on: models without a configured price are metered using community-maintained rates (the bundled genai-prices dataset). Set a price to override the fallback."}):e.jsxs(oe,{label:"How unpriced models are metered",tone:"warning",children:["Default pricing is off: only models with a configured price are metered.",t.data.require_pricing?" Requests for any other model are rejected (HTTP 402) because require_pricing is on.":" Other models are served without cost tracking."]}):null}function I({label:t,value:i}){return e.jsxs("div",{className:"flex items-baseline justify-between gap-3",children:[e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:t}),e.jsx("span",{className:"text-right text-sm text-[var(--otari-ink)] tabular-nums",children:i})]})}function le({title:t,children:i}){return e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx("span",{className:"text-xs font-semibold uppercase tracking-wide text-[var(--otari-muted)]",children:t}),i]})}function Yt({row:t}){const i=je(),r=Re(),[s,n]=c.useState(!1),[a,f]=c.useState(""),[p,u]=c.useState(""),[P,j]=c.useState(""),[k,T]=c.useState(""),[y,h]=c.useState(""),[N,O]=c.useState([]),S=()=>{f(t.inputPrice==null?"":String(t.inputPrice)),u(t.outputPrice==null?"":String(t.outputPrice)),j(t.cacheReadPrice==null?"":String(t.cacheReadPrice)),T(t.cacheWritePrice==null?"":String(t.cacheWritePrice)),h(t.cacheWrite1hPrice==null?"":String(t.cacheWrite1hPrice)),O(we(t.pricingTiers)),n(!0)},Z=ce(a)&&ce(p)&&w(P)&&w(k)&&w(y)&&Ve(N),W=()=>{Z&&i.mutate({model_key:t.key,input_price_per_million:Number(a),output_price_per_million:Number(p),cache_read_price_per_million:Y(P),cache_write_price_per_million:Y(k),cache_write_1h_price_per_million:Y(y),pricing_tiers:Ye(N)},{onSuccess:()=>n(!1)})};return s?e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"Input $ / 1M"}),e.jsx(b,{value:a,onChange:f,ariaLabel:`Input price for ${t.key}`})]}),e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"Output $ / 1M"}),e.jsx(b,{value:p,onChange:u,ariaLabel:`Output price for ${t.key}`})]}),e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"Cache read $ / 1M"}),e.jsx(b,{value:P,onChange:j,ariaLabel:`Cache read price for ${t.key}`})]}),e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"Cache write $ / 1M"}),e.jsx(b,{value:k,onChange:T,ariaLabel:`Cache write price for ${t.key}`})]}),e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"1h cache write $ / 1M"}),e.jsx(b,{value:y,onChange:h,ariaLabel:`1 hour cache write price for ${t.key}`})]}),e.jsx(He,{tiers:N,onChange:O}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(A,{size:"sm",variant:"primary",isDisabled:i.isPending||!Z,onPress:W,children:"Save"}),e.jsx(A,{size:"sm",variant:"ghost",isDisabled:i.isPending,onPress:()=>n(!1),children:"Cancel"})]}),i.error?e.jsx("span",{className:"text-xs text-red-700",children:be(i.error)}):null]}):e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(I,{label:"Input",value:t.inputPrice==null?"—":`${E(t.inputPrice)} / 1M`}),e.jsx(I,{label:"Output",value:t.outputPrice==null?"—":`${E(t.outputPrice)} / 1M`}),e.jsx(I,{label:"Cache read",value:t.cacheReadPrice==null?"—":`${E(t.cacheReadPrice)} / 1M`}),e.jsx(I,{label:"Cache write",value:t.cacheWritePrice==null?"—":`${E(t.cacheWritePrice)} / 1M`}),e.jsx(I,{label:"1h cache write",value:t.cacheWrite1hPrice==null?"—":`${E(t.cacheWrite1hPrice)} / 1M`}),e.jsx(I,{label:"Context tiers",value:t.pricingTiers.length?`${t.pricingTiers.length} configured`:"—"}),e.jsxs("div",{className:"flex items-center gap-2 pt-1",children:[e.jsx(A,{size:"sm",variant:"outline",onPress:S,children:t.source==="configured"?"Edit price":"Set price"}),t.source==="configured"?e.jsxs(e.Fragment,{children:[e.jsx(ze,{confirmLabel:"Reset",isPending:r.isPending,onConfirm:()=>r.mutate(t.key),children:"Reset"}),e.jsx(oe,{label:"What reset does",children:"Removes the custom price. The model reverts to the default rate (genai-prices) when default pricing is on, otherwise it is metered at no cost."})]}):null,r.error?e.jsx("span",{className:"text-xs text-red-700",children:be(r.error)}):null]})]})}function Ht({row:t,metadata:i,metadataAvailable:r,onMakeAlias:s,onClose:n}){const a=(i==null?void 0:i.input_modalities)??[],f=(i==null?void 0:i.output_modalities)??[],p=Ot.filter(({key:u})=>i==null?void 0:i[u]);return e.jsx(se,{children:e.jsxs(se.Content,{className:"flex flex-col gap-5 p-5",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("h2",{className:"text-base font-semibold break-all text-[var(--otari-ink)]",children:t.model}),i!=null&&i.deprecated?e.jsx(V,{size:"sm",color:"danger",children:"deprecated"}):null]}),e.jsxs("p",{className:"mt-1 text-xs break-all text-[var(--otari-muted)]",children:["Selector: ",e.jsx("code",{children:t.key})]}),i!=null&&i.family?e.jsx("p",{className:"text-xs text-[var(--otari-muted)]",children:i.family}):null]}),e.jsx("button",{type:"button","aria-label":"Close model details",onClick:n,className:"-mt-1 -mr-1 shrink-0 rounded-md px-1.5 py-0.5 text-lg leading-none text-[var(--otari-muted)] hover:bg-[var(--otari-bg)] hover:text-[var(--otari-ink)]",children:"✕"})]}),i!=null&&i.description?e.jsx("p",{className:"text-sm text-[var(--otari-ink)]",children:i.description}):null,e.jsxs(le,{title:"Pricing",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(wt,{source:t.source}),t.isDiscovered?null:e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"not discovered"})]}),e.jsx(Yt,{row:t},t.key),e.jsx(A,{size:"sm",variant:"outline",onPress:()=>s(t.key),children:"Make an alias"})]}),e.jsxs(le,{title:"Specs",children:[e.jsx(I,{label:"Context window",value:ae(t.contextWindow)}),e.jsx(I,{label:"Max output",value:ae((i==null?void 0:i.max_output_tokens)??null)}),e.jsx(I,{label:"Knowledge cutoff",value:(i==null?void 0:i.knowledge_cutoff)??"—"}),e.jsx(I,{label:"Released",value:Ct(i==null?void 0:i.release_date)}),e.jsx(I,{label:"Open weights",value:i?i.open_weights?"Yes":"No":"—"})]}),e.jsx(le,{title:"Modalities",children:a.length===0&&f.length===0?e.jsx("span",{className:"text-sm text-[var(--otari-muted)]",children:"Unknown."}):e.jsxs("div",{className:"flex flex-col gap-1.5 text-xs text-[var(--otari-muted)]",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-1",children:[e.jsx("span",{children:"In:"}),a.map(u=>e.jsx(V,{size:"sm",color:"default",children:Fe[u]??u},u))]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-1",children:[e.jsx("span",{children:"Out:"}),f.map(u=>e.jsx(V,{size:"sm",color:"default",children:Fe[u]??u},u))]})]})}),e.jsx(le,{title:"Capabilities",children:p.length>0?e.jsx("div",{className:"flex flex-wrap gap-1.5",children:p.map(({key:u,label:P})=>e.jsx(V,{size:"sm",color:"default",children:P},u))}):e.jsx("span",{className:"text-sm text-[var(--otari-muted)]",children:r?"None reported.":"Extended metadata unavailable (models.dev disabled or unreachable)."})})]})})}const qt=15;function Ut({value:t,onChange:i,placeholder:r}){return e.jsx("input",{type:"search",value:t,onChange:s=>i(s.target.value),placeholder:r,"aria-label":r,className:"w-full max-w-xs rounded-md border border-[var(--otari-line)] bg-white px-3 py-1.5 text-sm focus:border-[var(--otari-brand)] focus:outline-none"})}const qe="otari.dashboard.modelsSort",_e={col:"model",dir:"asc"},Gt=["model","released","input","output"];function Jt(){if(typeof window>"u")return _e;try{const t=window.localStorage.getItem(qe);if(!t)return _e;const i=JSON.parse(t);if(Gt.includes(i.col)&&(i.dir==="asc"||i.dir==="desc"))return{col:i.col,dir:i.dir}}catch{}return _e}function Xt({row:t,onClose:i}){const r=je(),s=Re(),[n,a]=c.useState(t.inputPrice==null?"":String(t.inputPrice)),[f,p]=c.useState(t.outputPrice==null?"":String(t.outputPrice)),[u,P]=c.useState(t.cacheReadPrice==null?"":String(t.cacheReadPrice)),[j,k]=c.useState(t.cacheWritePrice==null?"":String(t.cacheWritePrice)),[T,y]=c.useState(t.cacheWrite1hPrice==null?"":String(t.cacheWrite1hPrice)),[h,N]=c.useState(we(t.pricingTiers)),O=ce(n)&&ce(f)&&w(u)&&w(j)&&w(T)&&Ve(h),S=()=>{O&&r.mutate({model_key:t.key,input_price_per_million:Number(n),output_price_per_million:Number(f),cache_read_price_per_million:Y(u),cache_write_price_per_million:Y(j),cache_write_1h_price_per_million:Y(T),pricing_tiers:Ye(h)},{onSuccess:i})};return e.jsxs("div",{className:"flex flex-col gap-3 px-4 py-3",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("span",{className:"text-xs font-medium break-all text-[var(--otari-muted)]",children:t.key}),e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-[var(--otari-muted)]",children:["Input $ / 1M",e.jsx(b,{value:n,onChange:a,ariaLabel:`Input price for ${t.key}`})]}),e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-[var(--otari-muted)]",children:["Output $ / 1M",e.jsx(b,{value:f,onChange:p,ariaLabel:`Output price for ${t.key}`})]}),e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-[var(--otari-muted)]",children:["Cache read $ / 1M",e.jsx(b,{value:u,onChange:P,ariaLabel:`Cache read price for ${t.key}`})]}),e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-[var(--otari-muted)]",children:["Cache write $ / 1M",e.jsx(b,{value:j,onChange:k,ariaLabel:`Cache write price for ${t.key}`})]}),e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-[var(--otari-muted)]",children:["1h cache write $ / 1M",e.jsx(b,{value:T,onChange:y,ariaLabel:`1 hour cache write price for ${t.key}`})]}),e.jsx(A,{size:"sm",variant:"primary",isDisabled:r.isPending||!O,onPress:S,children:r.isPending?"Saving…":"Save"}),e.jsx(A,{size:"sm",variant:"ghost",isDisabled:r.isPending,onPress:i,children:"Cancel"}),t.source==="configured"?e.jsxs("span",{className:"inline-flex items-center gap-1",children:[e.jsx(ze,{confirmLabel:"Reset",isPending:s.isPending,onConfirm:()=>s.mutate(t.key,{onSuccess:i}),children:"Reset"}),e.jsx(oe,{label:"What reset does",children:"Removes the custom price. The model reverts to the default rate (genai-prices) when default pricing is on, otherwise it is metered at no cost."})]}):null,r.error||s.error?e.jsx("span",{className:"text-xs text-red-700",children:be(r.error??s.error)}):null]}),e.jsx(He,{tiers:h,onChange:N})]})}function Zt({primary:t,secondary:i,rowKey:r,primaryLabel:s,secondaryLabel:n,onEdit:a}){const f=(p,u)=>e.jsx("button",{type:"button","aria-label":`Edit ${u} price for ${r}`,className:"tabular-nums hover:text-[var(--otari-brand-dark)] hover:underline",onClick:P=>{P.stopPropagation(),a()},children:p==null?"—":E(p)});return e.jsxs("span",{className:"inline-flex items-center justify-end gap-1",children:[f(t,s),e.jsx("span",{className:"text-[var(--otari-muted)]",children:"/"}),f(i,n)]})}function Qt({rates:t,rowKey:i,onEdit:r}){const s=[t.cacheReadPrice==null?null:`R ${E(t.cacheReadPrice)}`,t.cacheWritePrice==null?null:`W ${E(t.cacheWritePrice)}`,t.cacheWrite1hPrice==null?null:`1h ${E(t.cacheWrite1hPrice)}`].filter(n=>n!==null);return e.jsx("button",{type:"button","aria-label":`Edit caching price for ${i}`,className:"max-w-44 text-right text-xs leading-5 text-[var(--otari-muted)] hover:text-[var(--otari-brand-dark)] hover:underline",onClick:n=>{n.stopPropagation(),r()},children:s.length>0?s.join(" · "):"Input-rate fallback"})}function ei({row:t,onEdit:i}){const r=[...t.pricingTiers].sort((n,a)=>n.min_input_tokens-a.min_input_tokens).map(n=>ae(n.min_input_tokens)),s=r.length===0?"Base only":`${r.length} tier${r.length===1?"":"s"} · ≥ ${r.join(", ")}`;return e.jsx("button",{type:"button","aria-label":`Edit pricing policy for ${t.key}`,className:"max-w-40 text-right text-xs leading-5 text-[var(--otari-muted)] hover:text-[var(--otari-brand-dark)] hover:underline",onClick:n=>{n.stopPropagation(),i()},children:s})}function ti({rows:t,isLoading:i,empty:r,sortDescriptor:s,onSortChange:n,selectedKey:a,onSelect:f,onEditPricing:p,comparisonContextTokens:u,selectedKeys:P,onSelectionChange:j}){const k=c.useMemo(()=>{const y=u==null?"Base":`at ${ae(u)}`;return[{id:"model",header:"Model",isRowHeader:!0,allowsSorting:!0,cell:h=>e.jsxs("span",{className:"font-medium break-all",children:[h.model,e.jsx("span",{className:"sr-only",children:h.key})]})},{id:"provider",header:"Provider",cell:h=>e.jsx("span",{className:"text-[var(--otari-muted)]",children:h.provider})},{id:"input",header:e.jsxs("span",{className:"inline-flex items-center gap-1",children:[`${y} in / out $ / 1M`,e.jsx(Vt,{})]}),align:"end",allowsSorting:!0,cell:h=>{const N=Ke(h,u);return e.jsx(Zt,{primary:N.inputPrice,secondary:N.outputPrice,rowKey:h.key,primaryLabel:"input",secondaryLabel:"output",onEdit:()=>p(h.key)})}},{id:"caching",header:`Caching ${u==null?"policy":y}`,align:"end",cell:h=>e.jsx(Qt,{rates:Ke(h,u),rowKey:h.key,onEdit:()=>p(h.key)})},{id:"policy",header:"Pricing policy",align:"end",cell:h=>e.jsx(ei,{row:h,onEdit:()=>p(h.key)})}]},[u,p]),T=c.useCallback(y=>y.key===a?"bg-[var(--otari-brand-tint)]":void 0,[a]);return e.jsx(Tt,{ariaLabel:"Models",columns:k,rows:t,getRowKey:zt,isLoading:i,emptyContent:r,selectionMode:"multiple",selectedKeys:P,onSelectionChange:j,sortDescriptor:s,onSortChange:n,onRowAction:f,rowClassName:T})}function ii({providers:t}){return t.length===0?null:e.jsxs(St,{tone:"warning",children:["Could not list ",t.map(i=>i.provider).join(", "),". Check that provider's credentials in config.yml; its models are missing from the list below."]})}function pi(){var Te,Le,Ae;const t=gt(),[i]=vt(),r=_t(),s=bt(),n=jt(),a=yt(),f=je(),[p,u]=c.useState(""),[P,j]=c.useState(0),[k,T]=c.useState(qt),[y,h]=c.useState(null),[N,O]=c.useState(null),[S,Z]=c.useState(Jt),W=Mt(),[Ue,ue]=c.useState(!1),[Ge,ye]=c.useState(!1),[Je,Pe]=c.useState(void 0);c.useEffect(()=>{try{window.localStorage.setItem(qe,JSON.stringify(S))}catch{}},[S]);const[D,Ne]=c.useState(i.get("provider")||"all"),[K,Xe]=c.useState("all"),[H,Ze]=c.useState("all"),[q,Qe]=c.useState("all"),[de,et]=c.useState("0"),[Q,tt]=c.useState(""),[ee,it]=c.useState("all"),[pe,rt]=c.useState(""),F=((Te=a.data)==null?void 0:Te.models)??{},nt=((Le=a.data)==null?void 0:Le.available)??!1,Se=c.useMemo(()=>{var l;return new Set((((l=n.data)==null?void 0:l.providers)??[]).flatMap(m=>m.models.map(o=>o.key)))},[n.data]),lt=l=>{u(l),j(0)},R=l=>m=>{l(m),j(0)},te=c.useMemo(()=>{var M,v,_,$,L,z,$e;const l=new Map($t(s.data??[]).map(d=>[d.model_key,d])),m=[],o=new Set,g=(d,ve,Ee,x)=>{if(o.has(d))return;o.add(d);const C=l.get(d);m.push({key:d,model:Be(ve,Ee),provider:Ee,isDiscovered:Se.has(d),contextWindow:(x==null?void 0:x.contextWindow)??null,inputPrice:C?C.input_price_per_million:(x==null?void 0:x.inputPrice)??null,outputPrice:C?C.output_price_per_million:(x==null?void 0:x.outputPrice)??null,cacheReadPrice:C?C.cache_read_price_per_million:(x==null?void 0:x.cacheReadPrice)??null,cacheWritePrice:C?C.cache_write_price_per_million:(x==null?void 0:x.cacheWritePrice)??null,cacheWrite1hPrice:C?C.cache_write_1h_price_per_million??null:(x==null?void 0:x.cacheWrite1hPrice)??null,pricingTiers:C?C.pricing_tiers??[]:(x==null?void 0:x.pricingTiers)??[],source:C?"configured":(x==null?void 0:x.source)??"none"})};for(const d of((M=r.data)==null?void 0:M.data)??[]){if(d.owned_by===Et)continue;const ve=d.pricing_source==="default"?"default":d.pricing?"configured":"none";g(d.id,d.id,d.owned_by||Oe(d.id),{key:d.id,model:d.id,provider:d.owned_by,contextWindow:d.context_window,inputPrice:((v=d.pricing)==null?void 0:v.input_price_per_million)??null,outputPrice:((_=d.pricing)==null?void 0:_.output_price_per_million)??null,cacheReadPrice:(($=d.pricing)==null?void 0:$.cache_read_price_per_million)??null,cacheWritePrice:((L=d.pricing)==null?void 0:L.cache_write_price_per_million)??null,cacheWrite1hPrice:((z=d.pricing)==null?void 0:z.cache_write_1h_price_per_million)??null,pricingTiers:(($e=d.pricing)==null?void 0:$e.pricing_tiers)??[],source:ve})}for(const d of l.keys())g(d,d,Oe(d));return m},[r.data,s.data,Se]),Ce=c.useMemo(()=>new Map(te.map(l=>[l.key,l])),[te]),ie=c.useMemo(()=>{var o,g,M;const l=te.map(v=>{var _,$;return{...v,contextWindow:v.contextWindow??((_=F[v.key])==null?void 0:_.context_window)??null,releaseDate:(($=F[v.key])==null?void 0:$.release_date)??null}}),m=new Set(l.map(v=>v.key));for(const v of((o=n.data)==null?void 0:o.providers)??[])for(const _ of v.models)m.has(_.key)||(m.add(_.key),l.push({key:_.key,model:Be(_.key,v.provider),provider:v.provider,isDiscovered:!0,contextWindow:((g=F[_.key])==null?void 0:g.context_window)??null,releaseDate:((M=F[_.key])==null?void 0:M.release_date)??null,inputPrice:null,outputPrice:null,cacheReadPrice:null,cacheWritePrice:null,cacheWrite1hPrice:null,pricingTiers:[],source:"none"}));return l},[te,n.data,F]),at=(((Ae=n.data)==null?void 0:Ae.providers)??[]).filter(l=>!l.ok),re=c.useMemo(()=>{const l=Array.from(new Set(ie.map(m=>m.provider))).sort((m,o)=>m.localeCompare(o));return[{value:"all",label:"All providers"},...l.map(m=>({value:m,label:m}))]},[ie]);c.useEffect(()=>{D==="all"||re.length<=1||re.some(l=>l.value===D)||Ne("all")},[re,D]);const U=p.trim().toLowerCase(),he=Number(de)||0,me=Q===""?Number.POSITIVE_INFINITY:Number(Q),st=pe===""?null:Number(pe),xe=ee==="all"?null:Date.now()-Number(ee)*Rt,G=c.useMemo(()=>{const l=o=>{if(U&&!o.key.toLowerCase().includes(U)&&!o.provider.toLowerCase().includes(U)||D!=="all"&&o.provider!==D||K==="configured"&&o.source!=="configured"||K==="default"&&o.source!=="default"||K==="priced"&&o.inputPrice==null||K==="unpriced"&&o.inputPrice!=null||H==="discovered"&&!o.isDiscovered||H==="custom"&&o.isDiscovered)return!1;if(q!=="all"){const g=De.find(v=>v.value===q),M=F[o.key];if(!g||!M||!g.test(M))return!1}if(he>0&&(o.contextWindow==null||o.contextWindowme))return!1;if(xe!=null){const g=o.releaseDate?Date.parse(o.releaseDate):Number.NaN;if(Number.isNaN(g)||g{const M=S.dir==="asc"?1:-1;if(S.col==="model")return o.model.localeCompare(g.model)*M;if(S.col==="released"){const L=o.releaseDate??null,z=g.releaseDate??null;return!L&&!z?o.model.localeCompare(g.model):L?z?(Lz?1:0)*M||o.model.localeCompare(g.model):-1:1}const v=L=>S.col==="input"?L.inputPrice:L.outputPrice,_=v(o),$=v(g);return _==null&&$==null?o.model.localeCompare(g.model):_==null?1:$==null?-1:(_-$)*M||o.model.localeCompare(g.model)};return ie.filter(l).sort(m)},[ie,U,D,K,H,q,he,me,xe,F,S]),J=G.length,ct=Math.max(1,Math.ceil(J/k)),ke=Math.min(P,ct-1),Me=ke*k,fe=G.slice(Me,Me+k),ot={column:S.col,direction:S.dir==="asc"?"ascending":"descending"},ut=l=>{Z({col:String(l.column),dir:l.direction==="ascending"?"asc":"desc"}),j(0)},dt=c.useCallback(l=>h(m=>m===l?null:l),[]),ge=fe.map(l=>l.key),X=Wt(W.selectedKeys,ge),pt=ge.length>0&&X.length===ge.length&&J>X.length,ht=W.allMatching?G.map(l=>l.key):X,We=W.allMatching?J:X.length,Ie=y?G.find(l=>l.key===y)??Ce.get(y)??null:null,mt=async l=>{ye(!0),Pe(void 0);try{for(const m of ht)await f.mutateAsync({model_key:m,input_price_per_million:l.input_price_per_million,output_price_per_million:l.output_price_per_million,cache_read_price_per_million:l.cache_read_price_per_million??null,cache_write_price_per_million:l.cache_write_price_per_million??null,cache_write_1h_price_per_million:null,pricing_tiers:[]});W.clear(),ue(!1)}catch(m){Pe(m)}finally{ye(!1)}},xt=r.isLoading||s.isLoading||n.isLoading,ft=U!==""||D!=="all"||K!=="all"||H!=="all"||q!=="all"||de!=="0"||Q!==""||ee!=="all"?"No models match your filters.":"No models yet. Add a provider on the Providers page, or price a model below.",ne=N?G.find(l=>l.key===N)??Ce.get(N)??null:null;return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(Pt,{title:"Models",description:"Every model your providers can serve. Set a price on any model so budgets and usage tracking work."}),e.jsx(Nt,{error:r.error??s.error??n.error??a.error}),e.jsxs("div",{className:`grid gap-4 lg:items-start ${ne?"lg:grid-cols-[minmax(0,1fr)_360px]":"grid-cols-1"}`,children:[e.jsxs("div",{className:"flex min-w-0 flex-col gap-3",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(Ut,{value:p,onChange:lt,placeholder:"Search models…"}),e.jsx(B,{ariaLabel:"Filter by provider",value:D,onChange:R(Ne),options:re}),e.jsx(B,{ariaLabel:"Filter by pricing",value:K,onChange:R(Xe),options:[{value:"all",label:"Any pricing"},{value:"configured",label:"Custom price"},{value:"default",label:"Default price"},{value:"priced",label:"Priced"},{value:"unpriced",label:"Unpriced"}]}),e.jsx(B,{ariaLabel:"Filter by source",value:H,onChange:R(Ze),options:[{value:"all",label:"Any source"},{value:"discovered",label:"Discovered"},{value:"custom",label:"Custom (not discovered)"}]}),e.jsx(B,{ariaLabel:"Filter by capability",value:q,onChange:R(Qe),options:[{value:"all",label:"Any capability"},...De.map(l=>({value:l.value,label:l.label}))]}),e.jsx(B,{ariaLabel:"Minimum context window",value:de,onChange:R(et),options:Dt}),e.jsx(B,{ariaLabel:"Maximum input price",value:Q,onChange:R(tt),options:Ft}),e.jsx(B,{ariaLabel:"Compare prices at context",value:pe,onChange:rt,options:Bt}),e.jsx(B,{ariaLabel:"Filter by release date",value:ee,onChange:R(it),options:Kt})]}),e.jsx(ii,{providers:at}),X.length>0?e.jsx(It,{selectedCount:We,allMatching:W.allMatching,matchingTotal:J,canSelectAllMatching:pt,onSelectAllMatching:W.enableAllMatching,onClear:W.clear,children:e.jsx(A,{size:"sm",variant:"primary",onPress:()=>ue(!0),children:"Set pricing"})}):null,e.jsx(ti,{rows:fe,isLoading:xt,empty:ft,sortDescriptor:ot,onSortChange:ut,selectedKey:N,onSelect:O,onEditPricing:dt,comparisonContextTokens:st,selectedKeys:W.selectedKeys,onSelectionChange:W.onSelectionChange}),Ie?e.jsx(se,{children:e.jsxs(se.Content,{className:"p-0",children:[e.jsxs("div",{className:"flex items-center justify-between border-b border-[var(--otari-line)] px-4 py-2",children:[e.jsx("span",{className:"text-sm font-medium text-[var(--otari-ink)]",children:"Edit pricing"}),e.jsx(A,{size:"sm",variant:"ghost",onPress:()=>h(null),children:"Close"})]}),e.jsx(Xt,{row:Ie,onClose:()=>h(null)})]})}):null,e.jsx(Lt,{page:ke,pageSize:k,total:J,rowsOnPage:fe.length,onPageChange:j,onPageSizeChange:l=>{T(l),j(0)},pageSizeOptions:[15,25,50]})]}),ne?e.jsx("aside",{className:"lg:sticky lg:top-4",children:e.jsx(Ht,{row:ne,metadata:F[ne.key],metadataAvailable:nt,onMakeAlias:l=>t(`/aliases?target=${encodeURIComponent(l)}`),onClose:()=>O(null)})}):null]}),e.jsx(At,{isOpen:Ue,onOpenChange:ue,targetCount:We,isPending:Ge,error:Je,onSubmit:mt,title:"Set pricing",description:l=>`Apply these per-1M rates to ${l.toLocaleString()} selected ${l===1?"model":"models"}. This replaces each model's price; pricing tiers and the 1h cache rate are cleared. Edit a single model for tiers.`})]})}export{pi as ModelsPage}; +import{j as e}from"./tanstack-query-1t81HyiD.js";import{i as gt,u as vt,r as c}from"./react-dgEcD0HR.js";import{x as _t,y as bt,h as jt,z as yt,A as je,P as Pt,E as Nt,F as B,I as St,B as ae,D as Re,C as ze,G as be,H as Ct,J as kt,K as E}from"./index-BP-wLuMr.js";import{u as Mt,r as Wt,B as It}from"./tableSelection-9hV37uhu.js";import{D as Tt}from"./DataTable-Bmn_eYSV.js";import{T as Lt,S as At}from"./TablePagination-BtDO5gaH.js";import{B as A,d as se,f as V}from"./heroui-BI50yK5B.js";function Oe(t){const i=t.indexOf(":");return i>0?t.slice(0,i):"—"}function $t(t,i=Date.now()){const r=new Map;for(const n of t){const a=r.get(n.model_key)??[];a.push(n),r.set(n.model_key,a)}const s=[];for(const n of r.values()){const a=[...n].sort((p,u)=>Date.parse(p.effective_at)-Date.parse(u.effective_at)),f=[...a].reverse().find(p=>Date.parse(p.effective_at)<=i);s.push(f??a[0])}return s.sort((n,a)=>n.model_key.localeCompare(a.model_key))}const Et="otari",De=[{value:"vision",label:"Vision",test:t=>Array.isArray(t.input_modalities)&&t.input_modalities.includes("image")},{value:"tool_call",label:"Tool calling",test:t=>!!t.tool_call},{value:"reasoning",label:"Reasoning",test:t=>!!t.reasoning},{value:"structured_output",label:"Structured output",test:t=>!!t.structured_output},{value:"attachment",label:"Attachments",test:t=>!!t.attachment},{value:"audio",label:"Audio",test:t=>Array.isArray(t.input_modalities)&&t.input_modalities.includes("audio")},{value:"pdf",label:"PDF",test:t=>Array.isArray(t.input_modalities)&&t.input_modalities.includes("pdf")}],Ot=[{key:"reasoning",label:"Reasoning"},{key:"tool_call",label:"Tool calling"},{key:"structured_output",label:"Structured output"},{key:"attachment",label:"Attachments"},{key:"temperature",label:"Temperature"}],Fe={text:"Text",image:"Image",audio:"Audio",video:"Video",pdf:"PDF"},Dt=[{value:"0",label:"Any context"},{value:"8000",label:"≥ 8K"},{value:"32000",label:"≥ 32K"},{value:"128000",label:"≥ 128K"},{value:"200000",label:"≥ 200K"},{value:"1000000",label:"≥ 1M"}],Ft=[{value:"",label:"Any price"},{value:"1",label:"≤ $1 / 1M in"},{value:"3",label:"≤ $3 / 1M in"},{value:"10",label:"≤ $10 / 1M in"},{value:"30",label:"≤ $30 / 1M in"}],Bt=[{value:"",label:"Base prices"},{value:"8000",label:"Compare at 8K"},{value:"128000",label:"Compare at 128K"},{value:"200000",label:"Compare at 200K"},{value:"500000",label:"Compare at 500K"},{value:"1000000",label:"Compare at 1M"}],Kt=[{value:"all",label:"Any release date"},{value:"365",label:"Past year"},{value:"730",label:"Past 2 years"},{value:"1095",label:"Past 3 years"}],Rt=1440*60*1e3,zt=t=>t.key;function Be(t,i){const r=`${i}:`;return t.startsWith(r)?t.slice(r.length):t}function Ke(t,i){const r={inputPrice:t.inputPrice,outputPrice:t.outputPrice,cacheReadPrice:t.cacheReadPrice,cacheWritePrice:t.cacheWritePrice,cacheWrite1hPrice:t.cacheWrite1hPrice};if(i==null)return r;const s=t.pricingTiers.filter(n=>n.min_input_tokens<=i).sort((n,a)=>a.min_input_tokens-n.min_input_tokens)[0];return s?{inputPrice:s.input_price_per_million??r.inputPrice,outputPrice:s.output_price_per_million??r.outputPrice,cacheReadPrice:s.cache_read_price_per_million??r.cacheReadPrice,cacheWritePrice:s.cache_write_price_per_million??r.cacheWritePrice,cacheWrite1hPrice:s.cache_write_1h_price_per_million??r.cacheWrite1hPrice}:r}function ce(t){const i=Number(t);return t.trim()!==""&&Number.isFinite(i)&&i>=0}function w(t){if(t.trim()==="")return!0;const i=Number(t);return Number.isFinite(i)&&i>=0}function Y(t){return t.trim()===""?null:Number(t)}function we(t){return t.map((i,r)=>({id:r,minInputTokens:String(i.min_input_tokens),input:i.input_price_per_million==null?"":String(i.input_price_per_million),output:i.output_price_per_million==null?"":String(i.output_price_per_million),cacheRead:i.cache_read_price_per_million==null?"":String(i.cache_read_price_per_million),cacheWrite:i.cache_write_price_per_million==null?"":String(i.cache_write_price_per_million),cacheWrite1h:i.cache_write_1h_price_per_million==null?"":String(i.cache_write_1h_price_per_million)}))}function Ve(t){const i=new Set;return t.every(r=>{const s=Number(r.minInputTokens),n=[r.input,r.output,r.cacheRead,r.cacheWrite,r.cacheWrite1h].some(a=>a.trim()!=="");return!Number.isInteger(s)||s<=0||i.has(s)||!n?!1:(i.add(s),[r.input,r.output,r.cacheRead,r.cacheWrite,r.cacheWrite1h].every(w))})}function Ye(t){return t.map(i=>({min_input_tokens:Number(i.minInputTokens),...i.input.trim()===""?{}:{input_price_per_million:Number(i.input)},...i.output.trim()===""?{}:{output_price_per_million:Number(i.output)},...i.cacheRead.trim()===""?{}:{cache_read_price_per_million:Number(i.cacheRead)},...i.cacheWrite.trim()===""?{}:{cache_write_price_per_million:Number(i.cacheWrite)},...i.cacheWrite1h.trim()===""?{}:{cache_write_1h_price_per_million:Number(i.cacheWrite1h)}}))}function b({value:t,onChange:i,ariaLabel:r}){return e.jsx("input",{type:"number",step:"any",min:"0",inputMode:"decimal","aria-label":r,value:t,onChange:s=>i(s.target.value),className:"w-28 rounded-md border border-[var(--otari-line)] bg-white px-2 py-1 text-right text-sm tabular-nums focus:border-[var(--otari-brand)] focus:outline-none"})}function He({tiers:t,onChange:i}){const r=(n,a,f)=>{i(t.map(p=>p.id===n?{...p,[a]:f}:p))},s=()=>{const n=t.reduce((a,f)=>Math.max(a,f.id),-1)+1;i([...t,{id:n,minInputTokens:"128000",input:"",output:"",cacheRead:"",cacheWrite:"",cacheWrite1h:""}])};return e.jsxs("div",{className:"flex flex-col gap-2 rounded-lg border border-[var(--otari-line)] p-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-xs font-medium text-[var(--otari-ink)]",children:"Long-context price tiers"}),e.jsx("p",{className:"text-xs text-[var(--otari-muted)]",children:"At a threshold, listed rates replace the base rate for the whole request."})]}),e.jsx(A,{size:"sm",variant:"outline",onPress:s,children:"Add tier"})]}),t.map(n=>e.jsxs("div",{className:"flex flex-wrap items-end gap-2 border-t border-[var(--otari-line)] pt-2",children:[e.jsxs("label",{className:"flex flex-col gap-1 text-xs text-[var(--otari-muted)]",children:["Context ≥ tokens",e.jsx("input",{type:"number",min:"1",step:"1",inputMode:"numeric","aria-label":"Tier context threshold",value:n.minInputTokens,onChange:a=>r(n.id,"minInputTokens",a.target.value),className:"w-28 rounded-md border border-[var(--otari-line)] bg-white px-2 py-1 text-right text-sm tabular-nums focus:border-[var(--otari-brand)] focus:outline-none"})]}),e.jsxs("label",{className:"flex flex-col gap-1 text-xs text-[var(--otari-muted)]",children:["Input",e.jsx(b,{value:n.input,onChange:a=>r(n.id,"input",a),ariaLabel:"Tier input price"})]}),e.jsxs("label",{className:"flex flex-col gap-1 text-xs text-[var(--otari-muted)]",children:["Output",e.jsx(b,{value:n.output,onChange:a=>r(n.id,"output",a),ariaLabel:"Tier output price"})]}),e.jsxs("label",{className:"flex flex-col gap-1 text-xs text-[var(--otari-muted)]",children:["Cache read",e.jsx(b,{value:n.cacheRead,onChange:a=>r(n.id,"cacheRead",a),ariaLabel:"Tier cache read price"})]}),e.jsxs("label",{className:"flex flex-col gap-1 text-xs text-[var(--otari-muted)]",children:["Cache write",e.jsx(b,{value:n.cacheWrite,onChange:a=>r(n.id,"cacheWrite",a),ariaLabel:"Tier cache write price"})]}),e.jsxs("label",{className:"flex flex-col gap-1 text-xs text-[var(--otari-muted)]",children:["1h write",e.jsx(b,{value:n.cacheWrite1h,onChange:a=>r(n.id,"cacheWrite1h",a),ariaLabel:"Tier 1 hour cache write price"})]}),e.jsx(A,{size:"sm",variant:"ghost",onPress:()=>i(t.filter(a=>a.id!==n.id)),children:"Remove"})]},n.id))]})}function wt({source:t}){return t==="configured"?e.jsx(V,{size:"sm",color:"default",children:"configured"}):t==="default"||t==="alias"?e.jsx(V,{size:"sm",color:"accent",children:t}):e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"not priced"})}function oe({label:t,tone:i="info",children:r}){const s=c.useId();return e.jsxs("span",{className:"group relative inline-flex items-center font-normal normal-case",children:[e.jsx("button",{type:"button","aria-label":t,"aria-describedby":s,className:`inline-flex h-4 w-4 items-center justify-center rounded-full border text-[10px] leading-none ${i==="warning"?"border-[#c2843a] text-[#b45309]":"border-[var(--otari-line)] text-[var(--otari-muted)] hover:border-[var(--otari-brand)] hover:text-[var(--otari-brand)]"}`,children:"i"}),e.jsx("span",{id:s,role:"tooltip",className:"pointer-events-none absolute top-full right-0 z-20 mt-1.5 w-72 rounded-lg border border-[var(--otari-line)] bg-[var(--otari-surface)] px-3 py-2 text-left text-xs font-normal whitespace-normal break-words text-[var(--otari-ink)] opacity-0 shadow-lg transition-opacity group-hover:opacity-100 group-focus-within:opacity-100",children:r})]})}function Vt(){const t=kt();return t.data?t.data.default_pricing?e.jsx(oe,{label:"How unpriced models are metered",tone:"info",children:"Default pricing is on: models without a configured price are metered using community-maintained rates (the bundled genai-prices dataset). Set a price to override the fallback."}):e.jsxs(oe,{label:"How unpriced models are metered",tone:"warning",children:["Default pricing is off: only models with a configured price are metered.",t.data.require_pricing?" Requests for any other model are rejected (HTTP 402) because require_pricing is on.":" Other models are served without cost tracking."]}):null}function I({label:t,value:i}){return e.jsxs("div",{className:"flex items-baseline justify-between gap-3",children:[e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:t}),e.jsx("span",{className:"text-right text-sm text-[var(--otari-ink)] tabular-nums",children:i})]})}function le({title:t,children:i}){return e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx("span",{className:"text-xs font-semibold uppercase tracking-wide text-[var(--otari-muted)]",children:t}),i]})}function Yt({row:t}){const i=je(),r=Re(),[s,n]=c.useState(!1),[a,f]=c.useState(""),[p,u]=c.useState(""),[P,j]=c.useState(""),[k,T]=c.useState(""),[y,h]=c.useState(""),[N,O]=c.useState([]),S=()=>{f(t.inputPrice==null?"":String(t.inputPrice)),u(t.outputPrice==null?"":String(t.outputPrice)),j(t.cacheReadPrice==null?"":String(t.cacheReadPrice)),T(t.cacheWritePrice==null?"":String(t.cacheWritePrice)),h(t.cacheWrite1hPrice==null?"":String(t.cacheWrite1hPrice)),O(we(t.pricingTiers)),n(!0)},Z=ce(a)&&ce(p)&&w(P)&&w(k)&&w(y)&&Ve(N),W=()=>{Z&&i.mutate({model_key:t.key,input_price_per_million:Number(a),output_price_per_million:Number(p),cache_read_price_per_million:Y(P),cache_write_price_per_million:Y(k),cache_write_1h_price_per_million:Y(y),pricing_tiers:Ye(N)},{onSuccess:()=>n(!1)})};return s?e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"Input $ / 1M"}),e.jsx(b,{value:a,onChange:f,ariaLabel:`Input price for ${t.key}`})]}),e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"Output $ / 1M"}),e.jsx(b,{value:p,onChange:u,ariaLabel:`Output price for ${t.key}`})]}),e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"Cache read $ / 1M"}),e.jsx(b,{value:P,onChange:j,ariaLabel:`Cache read price for ${t.key}`})]}),e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"Cache write $ / 1M"}),e.jsx(b,{value:k,onChange:T,ariaLabel:`Cache write price for ${t.key}`})]}),e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"1h cache write $ / 1M"}),e.jsx(b,{value:y,onChange:h,ariaLabel:`1 hour cache write price for ${t.key}`})]}),e.jsx(He,{tiers:N,onChange:O}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(A,{size:"sm",variant:"primary",isDisabled:i.isPending||!Z,onPress:W,children:"Save"}),e.jsx(A,{size:"sm",variant:"ghost",isDisabled:i.isPending,onPress:()=>n(!1),children:"Cancel"})]}),i.error?e.jsx("span",{className:"text-xs text-red-700",children:be(i.error)}):null]}):e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(I,{label:"Input",value:t.inputPrice==null?"—":`${E(t.inputPrice)} / 1M`}),e.jsx(I,{label:"Output",value:t.outputPrice==null?"—":`${E(t.outputPrice)} / 1M`}),e.jsx(I,{label:"Cache read",value:t.cacheReadPrice==null?"—":`${E(t.cacheReadPrice)} / 1M`}),e.jsx(I,{label:"Cache write",value:t.cacheWritePrice==null?"—":`${E(t.cacheWritePrice)} / 1M`}),e.jsx(I,{label:"1h cache write",value:t.cacheWrite1hPrice==null?"—":`${E(t.cacheWrite1hPrice)} / 1M`}),e.jsx(I,{label:"Context tiers",value:t.pricingTiers.length?`${t.pricingTiers.length} configured`:"—"}),e.jsxs("div",{className:"flex items-center gap-2 pt-1",children:[e.jsx(A,{size:"sm",variant:"outline",onPress:S,children:t.source==="configured"?"Edit price":"Set price"}),t.source==="configured"?e.jsxs(e.Fragment,{children:[e.jsx(ze,{confirmLabel:"Reset",isPending:r.isPending,onConfirm:()=>r.mutate(t.key),children:"Reset"}),e.jsx(oe,{label:"What reset does",children:"Removes the custom price. The model reverts to the default rate (genai-prices) when default pricing is on, otherwise it is metered at no cost."})]}):null,r.error?e.jsx("span",{className:"text-xs text-red-700",children:be(r.error)}):null]})]})}function Ht({row:t,metadata:i,metadataAvailable:r,onMakeAlias:s,onClose:n}){const a=(i==null?void 0:i.input_modalities)??[],f=(i==null?void 0:i.output_modalities)??[],p=Ot.filter(({key:u})=>i==null?void 0:i[u]);return e.jsx(se,{children:e.jsxs(se.Content,{className:"flex flex-col gap-5 p-5",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("h2",{className:"text-base font-semibold break-all text-[var(--otari-ink)]",children:t.model}),i!=null&&i.deprecated?e.jsx(V,{size:"sm",color:"danger",children:"deprecated"}):null]}),e.jsxs("p",{className:"mt-1 text-xs break-all text-[var(--otari-muted)]",children:["Selector: ",e.jsx("code",{children:t.key})]}),i!=null&&i.family?e.jsx("p",{className:"text-xs text-[var(--otari-muted)]",children:i.family}):null]}),e.jsx("button",{type:"button","aria-label":"Close model details",onClick:n,className:"-mt-1 -mr-1 shrink-0 rounded-md px-1.5 py-0.5 text-lg leading-none text-[var(--otari-muted)] hover:bg-[var(--otari-bg)] hover:text-[var(--otari-ink)]",children:"✕"})]}),i!=null&&i.description?e.jsx("p",{className:"text-sm text-[var(--otari-ink)]",children:i.description}):null,e.jsxs(le,{title:"Pricing",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(wt,{source:t.source}),t.isDiscovered?null:e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"not discovered"})]}),e.jsx(Yt,{row:t},t.key),e.jsx(A,{size:"sm",variant:"outline",onPress:()=>s(t.key),children:"Make an alias"})]}),e.jsxs(le,{title:"Specs",children:[e.jsx(I,{label:"Context window",value:ae(t.contextWindow)}),e.jsx(I,{label:"Max output",value:ae((i==null?void 0:i.max_output_tokens)??null)}),e.jsx(I,{label:"Knowledge cutoff",value:(i==null?void 0:i.knowledge_cutoff)??"—"}),e.jsx(I,{label:"Released",value:Ct(i==null?void 0:i.release_date)}),e.jsx(I,{label:"Open weights",value:i?i.open_weights?"Yes":"No":"—"})]}),e.jsx(le,{title:"Modalities",children:a.length===0&&f.length===0?e.jsx("span",{className:"text-sm text-[var(--otari-muted)]",children:"Unknown."}):e.jsxs("div",{className:"flex flex-col gap-1.5 text-xs text-[var(--otari-muted)]",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-1",children:[e.jsx("span",{children:"In:"}),a.map(u=>e.jsx(V,{size:"sm",color:"default",children:Fe[u]??u},u))]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-1",children:[e.jsx("span",{children:"Out:"}),f.map(u=>e.jsx(V,{size:"sm",color:"default",children:Fe[u]??u},u))]})]})}),e.jsx(le,{title:"Capabilities",children:p.length>0?e.jsx("div",{className:"flex flex-wrap gap-1.5",children:p.map(({key:u,label:P})=>e.jsx(V,{size:"sm",color:"default",children:P},u))}):e.jsx("span",{className:"text-sm text-[var(--otari-muted)]",children:r?"None reported.":"Extended metadata unavailable (models.dev disabled or unreachable)."})})]})})}const qt=15;function Ut({value:t,onChange:i,placeholder:r}){return e.jsx("input",{type:"search",value:t,onChange:s=>i(s.target.value),placeholder:r,"aria-label":r,className:"w-full max-w-xs rounded-md border border-[var(--otari-line)] bg-white px-3 py-1.5 text-sm focus:border-[var(--otari-brand)] focus:outline-none"})}const qe="otari.dashboard.modelsSort",_e={col:"model",dir:"asc"},Gt=["model","released","input","output"];function Jt(){if(typeof window>"u")return _e;try{const t=window.localStorage.getItem(qe);if(!t)return _e;const i=JSON.parse(t);if(Gt.includes(i.col)&&(i.dir==="asc"||i.dir==="desc"))return{col:i.col,dir:i.dir}}catch{}return _e}function Xt({row:t,onClose:i}){const r=je(),s=Re(),[n,a]=c.useState(t.inputPrice==null?"":String(t.inputPrice)),[f,p]=c.useState(t.outputPrice==null?"":String(t.outputPrice)),[u,P]=c.useState(t.cacheReadPrice==null?"":String(t.cacheReadPrice)),[j,k]=c.useState(t.cacheWritePrice==null?"":String(t.cacheWritePrice)),[T,y]=c.useState(t.cacheWrite1hPrice==null?"":String(t.cacheWrite1hPrice)),[h,N]=c.useState(we(t.pricingTiers)),O=ce(n)&&ce(f)&&w(u)&&w(j)&&w(T)&&Ve(h),S=()=>{O&&r.mutate({model_key:t.key,input_price_per_million:Number(n),output_price_per_million:Number(f),cache_read_price_per_million:Y(u),cache_write_price_per_million:Y(j),cache_write_1h_price_per_million:Y(T),pricing_tiers:Ye(h)},{onSuccess:i})};return e.jsxs("div",{className:"flex flex-col gap-3 px-4 py-3",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("span",{className:"text-xs font-medium break-all text-[var(--otari-muted)]",children:t.key}),e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-[var(--otari-muted)]",children:["Input $ / 1M",e.jsx(b,{value:n,onChange:a,ariaLabel:`Input price for ${t.key}`})]}),e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-[var(--otari-muted)]",children:["Output $ / 1M",e.jsx(b,{value:f,onChange:p,ariaLabel:`Output price for ${t.key}`})]}),e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-[var(--otari-muted)]",children:["Cache read $ / 1M",e.jsx(b,{value:u,onChange:P,ariaLabel:`Cache read price for ${t.key}`})]}),e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-[var(--otari-muted)]",children:["Cache write $ / 1M",e.jsx(b,{value:j,onChange:k,ariaLabel:`Cache write price for ${t.key}`})]}),e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-[var(--otari-muted)]",children:["1h cache write $ / 1M",e.jsx(b,{value:T,onChange:y,ariaLabel:`1 hour cache write price for ${t.key}`})]}),e.jsx(A,{size:"sm",variant:"primary",isDisabled:r.isPending||!O,onPress:S,children:r.isPending?"Saving…":"Save"}),e.jsx(A,{size:"sm",variant:"ghost",isDisabled:r.isPending,onPress:i,children:"Cancel"}),t.source==="configured"?e.jsxs("span",{className:"inline-flex items-center gap-1",children:[e.jsx(ze,{confirmLabel:"Reset",isPending:s.isPending,onConfirm:()=>s.mutate(t.key,{onSuccess:i}),children:"Reset"}),e.jsx(oe,{label:"What reset does",children:"Removes the custom price. The model reverts to the default rate (genai-prices) when default pricing is on, otherwise it is metered at no cost."})]}):null,r.error||s.error?e.jsx("span",{className:"text-xs text-red-700",children:be(r.error??s.error)}):null]}),e.jsx(He,{tiers:h,onChange:N})]})}function Zt({primary:t,secondary:i,rowKey:r,primaryLabel:s,secondaryLabel:n,onEdit:a}){const f=(p,u)=>e.jsx("button",{type:"button","aria-label":`Edit ${u} price for ${r}`,className:"tabular-nums hover:text-[var(--otari-brand-dark)] hover:underline",onClick:P=>{P.stopPropagation(),a()},children:p==null?"—":E(p)});return e.jsxs("span",{className:"inline-flex items-center justify-end gap-1",children:[f(t,s),e.jsx("span",{className:"text-[var(--otari-muted)]",children:"/"}),f(i,n)]})}function Qt({rates:t,rowKey:i,onEdit:r}){const s=[t.cacheReadPrice==null?null:`R ${E(t.cacheReadPrice)}`,t.cacheWritePrice==null?null:`W ${E(t.cacheWritePrice)}`,t.cacheWrite1hPrice==null?null:`1h ${E(t.cacheWrite1hPrice)}`].filter(n=>n!==null);return e.jsx("button",{type:"button","aria-label":`Edit caching price for ${i}`,className:"max-w-44 text-right text-xs leading-5 text-[var(--otari-muted)] hover:text-[var(--otari-brand-dark)] hover:underline",onClick:n=>{n.stopPropagation(),r()},children:s.length>0?s.join(" · "):"Input-rate fallback"})}function ei({row:t,onEdit:i}){const r=[...t.pricingTiers].sort((n,a)=>n.min_input_tokens-a.min_input_tokens).map(n=>ae(n.min_input_tokens)),s=r.length===0?"Base only":`${r.length} tier${r.length===1?"":"s"} · ≥ ${r.join(", ")}`;return e.jsx("button",{type:"button","aria-label":`Edit pricing policy for ${t.key}`,className:"max-w-40 text-right text-xs leading-5 text-[var(--otari-muted)] hover:text-[var(--otari-brand-dark)] hover:underline",onClick:n=>{n.stopPropagation(),i()},children:s})}function ti({rows:t,isLoading:i,empty:r,sortDescriptor:s,onSortChange:n,selectedKey:a,onSelect:f,onEditPricing:p,comparisonContextTokens:u,selectedKeys:P,onSelectionChange:j}){const k=c.useMemo(()=>{const y=u==null?"Base":`at ${ae(u)}`;return[{id:"model",header:"Model",isRowHeader:!0,allowsSorting:!0,cell:h=>e.jsxs("span",{className:"font-medium break-all",children:[h.model,e.jsx("span",{className:"sr-only",children:h.key})]})},{id:"provider",header:"Provider",cell:h=>e.jsx("span",{className:"text-[var(--otari-muted)]",children:h.provider})},{id:"input",header:e.jsxs("span",{className:"inline-flex items-center gap-1",children:[`${y} in / out $ / 1M`,e.jsx(Vt,{})]}),align:"end",allowsSorting:!0,cell:h=>{const N=Ke(h,u);return e.jsx(Zt,{primary:N.inputPrice,secondary:N.outputPrice,rowKey:h.key,primaryLabel:"input",secondaryLabel:"output",onEdit:()=>p(h.key)})}},{id:"caching",header:`Caching ${u==null?"policy":y}`,align:"end",cell:h=>e.jsx(Qt,{rates:Ke(h,u),rowKey:h.key,onEdit:()=>p(h.key)})},{id:"policy",header:"Pricing policy",align:"end",cell:h=>e.jsx(ei,{row:h,onEdit:()=>p(h.key)})}]},[u,p]),T=c.useCallback(y=>y.key===a?"bg-[var(--otari-brand-tint)]":void 0,[a]);return e.jsx(Tt,{ariaLabel:"Models",columns:k,rows:t,getRowKey:zt,isLoading:i,emptyContent:r,selectionMode:"multiple",selectedKeys:P,onSelectionChange:j,sortDescriptor:s,onSortChange:n,onRowAction:f,rowClassName:T})}function ii({providers:t}){return t.length===0?null:e.jsxs(St,{tone:"warning",children:["Could not list ",t.map(i=>i.provider).join(", "),". Check that provider's credentials in config.yml; its models are missing from the list below."]})}function pi(){var Te,Le,Ae;const t=gt(),[i]=vt(),r=_t(),s=bt(),n=jt(),a=yt(),f=je(),[p,u]=c.useState(""),[P,j]=c.useState(0),[k,T]=c.useState(qt),[y,h]=c.useState(null),[N,O]=c.useState(null),[S,Z]=c.useState(Jt),W=Mt(),[Ue,ue]=c.useState(!1),[Ge,ye]=c.useState(!1),[Je,Pe]=c.useState(void 0);c.useEffect(()=>{try{window.localStorage.setItem(qe,JSON.stringify(S))}catch{}},[S]);const[D,Ne]=c.useState(i.get("provider")||"all"),[K,Xe]=c.useState("all"),[H,Ze]=c.useState("all"),[q,Qe]=c.useState("all"),[de,et]=c.useState("0"),[Q,tt]=c.useState(""),[ee,it]=c.useState("all"),[pe,rt]=c.useState(""),F=((Te=a.data)==null?void 0:Te.models)??{},nt=((Le=a.data)==null?void 0:Le.available)??!1,Se=c.useMemo(()=>{var l;return new Set((((l=n.data)==null?void 0:l.providers)??[]).flatMap(m=>m.models.map(o=>o.key)))},[n.data]),lt=l=>{u(l),j(0)},R=l=>m=>{l(m),j(0)},te=c.useMemo(()=>{var M,v,_,$,L,z,$e;const l=new Map($t(s.data??[]).map(d=>[d.model_key,d])),m=[],o=new Set,g=(d,ve,Ee,x)=>{if(o.has(d))return;o.add(d);const C=l.get(d);m.push({key:d,model:Be(ve,Ee),provider:Ee,isDiscovered:Se.has(d),contextWindow:(x==null?void 0:x.contextWindow)??null,inputPrice:C?C.input_price_per_million:(x==null?void 0:x.inputPrice)??null,outputPrice:C?C.output_price_per_million:(x==null?void 0:x.outputPrice)??null,cacheReadPrice:C?C.cache_read_price_per_million:(x==null?void 0:x.cacheReadPrice)??null,cacheWritePrice:C?C.cache_write_price_per_million:(x==null?void 0:x.cacheWritePrice)??null,cacheWrite1hPrice:C?C.cache_write_1h_price_per_million??null:(x==null?void 0:x.cacheWrite1hPrice)??null,pricingTiers:C?C.pricing_tiers??[]:(x==null?void 0:x.pricingTiers)??[],source:C?"configured":(x==null?void 0:x.source)??"none"})};for(const d of((M=r.data)==null?void 0:M.data)??[]){if(d.owned_by===Et)continue;const ve=d.pricing_source==="default"?"default":d.pricing?"configured":"none";g(d.id,d.id,d.owned_by||Oe(d.id),{key:d.id,model:d.id,provider:d.owned_by,contextWindow:d.context_window,inputPrice:((v=d.pricing)==null?void 0:v.input_price_per_million)??null,outputPrice:((_=d.pricing)==null?void 0:_.output_price_per_million)??null,cacheReadPrice:(($=d.pricing)==null?void 0:$.cache_read_price_per_million)??null,cacheWritePrice:((L=d.pricing)==null?void 0:L.cache_write_price_per_million)??null,cacheWrite1hPrice:((z=d.pricing)==null?void 0:z.cache_write_1h_price_per_million)??null,pricingTiers:(($e=d.pricing)==null?void 0:$e.pricing_tiers)??[],source:ve})}for(const d of l.keys())g(d,d,Oe(d));return m},[r.data,s.data,Se]),Ce=c.useMemo(()=>new Map(te.map(l=>[l.key,l])),[te]),ie=c.useMemo(()=>{var o,g,M;const l=te.map(v=>{var _,$;return{...v,contextWindow:v.contextWindow??((_=F[v.key])==null?void 0:_.context_window)??null,releaseDate:(($=F[v.key])==null?void 0:$.release_date)??null}}),m=new Set(l.map(v=>v.key));for(const v of((o=n.data)==null?void 0:o.providers)??[])for(const _ of v.models)m.has(_.key)||(m.add(_.key),l.push({key:_.key,model:Be(_.key,v.provider),provider:v.provider,isDiscovered:!0,contextWindow:((g=F[_.key])==null?void 0:g.context_window)??null,releaseDate:((M=F[_.key])==null?void 0:M.release_date)??null,inputPrice:null,outputPrice:null,cacheReadPrice:null,cacheWritePrice:null,cacheWrite1hPrice:null,pricingTiers:[],source:"none"}));return l},[te,n.data,F]),at=(((Ae=n.data)==null?void 0:Ae.providers)??[]).filter(l=>!l.ok),re=c.useMemo(()=>{const l=Array.from(new Set(ie.map(m=>m.provider))).sort((m,o)=>m.localeCompare(o));return[{value:"all",label:"All providers"},...l.map(m=>({value:m,label:m}))]},[ie]);c.useEffect(()=>{D==="all"||re.length<=1||re.some(l=>l.value===D)||Ne("all")},[re,D]);const U=p.trim().toLowerCase(),he=Number(de)||0,me=Q===""?Number.POSITIVE_INFINITY:Number(Q),st=pe===""?null:Number(pe),xe=ee==="all"?null:Date.now()-Number(ee)*Rt,G=c.useMemo(()=>{const l=o=>{if(U&&!o.key.toLowerCase().includes(U)&&!o.provider.toLowerCase().includes(U)||D!=="all"&&o.provider!==D||K==="configured"&&o.source!=="configured"||K==="default"&&o.source!=="default"||K==="priced"&&o.inputPrice==null||K==="unpriced"&&o.inputPrice!=null||H==="discovered"&&!o.isDiscovered||H==="custom"&&o.isDiscovered)return!1;if(q!=="all"){const g=De.find(v=>v.value===q),M=F[o.key];if(!g||!M||!g.test(M))return!1}if(he>0&&(o.contextWindow==null||o.contextWindowme))return!1;if(xe!=null){const g=o.releaseDate?Date.parse(o.releaseDate):Number.NaN;if(Number.isNaN(g)||g{const M=S.dir==="asc"?1:-1;if(S.col==="model")return o.model.localeCompare(g.model)*M;if(S.col==="released"){const L=o.releaseDate??null,z=g.releaseDate??null;return!L&&!z?o.model.localeCompare(g.model):L?z?(Lz?1:0)*M||o.model.localeCompare(g.model):-1:1}const v=L=>S.col==="input"?L.inputPrice:L.outputPrice,_=v(o),$=v(g);return _==null&&$==null?o.model.localeCompare(g.model):_==null?1:$==null?-1:(_-$)*M||o.model.localeCompare(g.model)};return ie.filter(l).sort(m)},[ie,U,D,K,H,q,he,me,xe,F,S]),J=G.length,ct=Math.max(1,Math.ceil(J/k)),ke=Math.min(P,ct-1),Me=ke*k,fe=G.slice(Me,Me+k),ot={column:S.col,direction:S.dir==="asc"?"ascending":"descending"},ut=l=>{Z({col:String(l.column),dir:l.direction==="ascending"?"asc":"desc"}),j(0)},dt=c.useCallback(l=>h(m=>m===l?null:l),[]),ge=fe.map(l=>l.key),X=Wt(W.selectedKeys,ge),pt=ge.length>0&&X.length===ge.length&&J>X.length,ht=W.allMatching?G.map(l=>l.key):X,We=W.allMatching?J:X.length,Ie=y?G.find(l=>l.key===y)??Ce.get(y)??null:null,mt=async l=>{ye(!0),Pe(void 0);try{for(const m of ht)await f.mutateAsync({model_key:m,input_price_per_million:l.input_price_per_million,output_price_per_million:l.output_price_per_million,cache_read_price_per_million:l.cache_read_price_per_million??null,cache_write_price_per_million:l.cache_write_price_per_million??null,cache_write_1h_price_per_million:null,pricing_tiers:[]});W.clear(),ue(!1)}catch(m){Pe(m)}finally{ye(!1)}},xt=r.isLoading||s.isLoading||n.isLoading,ft=U!==""||D!=="all"||K!=="all"||H!=="all"||q!=="all"||de!=="0"||Q!==""||ee!=="all"?"No models match your filters.":"No models yet. Add a provider on the Providers page, or price a model below.",ne=N?G.find(l=>l.key===N)??Ce.get(N)??null:null;return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(Pt,{title:"Models",description:"Every model your providers can serve. Set a price on any model so budgets and usage tracking work."}),e.jsx(Nt,{error:r.error??s.error??n.error??a.error}),e.jsxs("div",{className:`grid gap-4 lg:items-start ${ne?"lg:grid-cols-[minmax(0,1fr)_360px]":"grid-cols-1"}`,children:[e.jsxs("div",{className:"flex min-w-0 flex-col gap-3",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(Ut,{value:p,onChange:lt,placeholder:"Search models…"}),e.jsx(B,{ariaLabel:"Filter by provider",value:D,onChange:R(Ne),options:re}),e.jsx(B,{ariaLabel:"Filter by pricing",value:K,onChange:R(Xe),options:[{value:"all",label:"Any pricing"},{value:"configured",label:"Custom price"},{value:"default",label:"Default price"},{value:"priced",label:"Priced"},{value:"unpriced",label:"Unpriced"}]}),e.jsx(B,{ariaLabel:"Filter by source",value:H,onChange:R(Ze),options:[{value:"all",label:"Any source"},{value:"discovered",label:"Discovered"},{value:"custom",label:"Custom (not discovered)"}]}),e.jsx(B,{ariaLabel:"Filter by capability",value:q,onChange:R(Qe),options:[{value:"all",label:"Any capability"},...De.map(l=>({value:l.value,label:l.label}))]}),e.jsx(B,{ariaLabel:"Minimum context window",value:de,onChange:R(et),options:Dt}),e.jsx(B,{ariaLabel:"Maximum input price",value:Q,onChange:R(tt),options:Ft}),e.jsx(B,{ariaLabel:"Compare prices at context",value:pe,onChange:rt,options:Bt}),e.jsx(B,{ariaLabel:"Filter by release date",value:ee,onChange:R(it),options:Kt})]}),e.jsx(ii,{providers:at}),X.length>0?e.jsx(It,{selectedCount:We,allMatching:W.allMatching,matchingTotal:J,canSelectAllMatching:pt,onSelectAllMatching:W.enableAllMatching,onClear:W.clear,children:e.jsx(A,{size:"sm",variant:"primary",onPress:()=>ue(!0),children:"Set pricing"})}):null,e.jsx(ti,{rows:fe,isLoading:xt,empty:ft,sortDescriptor:ot,onSortChange:ut,selectedKey:N,onSelect:O,onEditPricing:dt,comparisonContextTokens:st,selectedKeys:W.selectedKeys,onSelectionChange:W.onSelectionChange}),Ie?e.jsx(se,{children:e.jsxs(se.Content,{className:"p-0",children:[e.jsxs("div",{className:"flex items-center justify-between border-b border-[var(--otari-line)] px-4 py-2",children:[e.jsx("span",{className:"text-sm font-medium text-[var(--otari-ink)]",children:"Edit pricing"}),e.jsx(A,{size:"sm",variant:"ghost",onPress:()=>h(null),children:"Close"})]}),e.jsx(Xt,{row:Ie,onClose:()=>h(null)})]})}):null,e.jsx(Lt,{page:ke,pageSize:k,total:J,rowsOnPage:fe.length,onPageChange:j,onPageSizeChange:l=>{T(l),j(0)},pageSizeOptions:[15,25,50]})]}),ne?e.jsx("aside",{className:"lg:sticky lg:top-4",children:e.jsx(Ht,{row:ne,metadata:F[ne.key],metadataAvailable:nt,onMakeAlias:l=>t(`/aliases?target=${encodeURIComponent(l)}`),onClose:()=>O(null)})}):null]}),e.jsx(At,{isOpen:Ue,onOpenChange:ue,targetCount:We,isPending:Ge,error:Je,onSubmit:mt,title:"Set pricing",description:l=>`Apply these per-1M rates to ${l.toLocaleString()} selected ${l===1?"model":"models"}. This replaces each model's price; pricing tiers and the 1h cache rate are cleared. Edit a single model for tiers.`})]})}export{pi as ModelsPage}; diff --git a/src/gateway/static/dashboard/assets/OverviewPage-CNyNgkDA.js b/src/gateway/static/dashboard/assets/OverviewPage-D2MB34d0.js similarity index 99% rename from src/gateway/static/dashboard/assets/OverviewPage-CNyNgkDA.js rename to src/gateway/static/dashboard/assets/OverviewPage-D2MB34d0.js index c8ad88be..d41d3abe 100644 --- a/src/gateway/static/dashboard/assets/OverviewPage-CNyNgkDA.js +++ b/src/gateway/static/dashboard/assets/OverviewPage-D2MB34d0.js @@ -1 +1 @@ -import{j as t}from"./tanstack-query-1t81HyiD.js";import{r as b,i as rt,N as G}from"./react-dgEcD0HR.js";import{L as at,M as st,d as j,N as nt,l as ot,a as it,u as lt,b as dt,O as w,P as ct,R as ut,E as I,S as g,Q as _,T as N,U as R,V as D,W as mt}from"./index-JlWCttWt.js";import{S as q}from"./charts-DIsd9m--.js";import{D as vt}from"./DataTable-Bmn_eYSV.js";import{d as H,B as ht}from"./heroui-BI50yK5B.js";import"./recharts-C4kRDmvS.js";function M(e){return e==="neutral"?void 0:e}const xt=.02,ft=.1;function B(e){if(!e||e.request_count===0)return{rate:null,status:"neutral"};const i=e.error_count/e.request_count,a=i>=ft?"alert":i>=xt?"warn":"ok";return{rate:i,status:a}}function gt(e){return!e||e.total===0?"neutral":e.healthy>=e.total?"ok":e.healthy===0?"alert":"warn"}const pt=.8;function bt(e){if(e.length===0)return{status:"neutral",label:"No budgets configured",overCount:0,nearCount:0,cappedCount:0};const i=e.filter(r=>r.max_budget!==null&&r.user_count>0);if(i.length===0)return{status:"neutral",label:"No capped budgets",overCount:0,nearCount:0,cappedCount:0};let a=0,s=0,n,c=-1;for(const r of i){const o=r.max_budget*r.user_count,l=o>0?r.total_spend/o:0;l>=1?a+=1:l>=pt&&(s+=1),l>c&&(c=l,n={name:r.name??r.budget_id,spent:r.total_spend,allocated:o,pct:l})}const d=a>0?"alert":s>0?"warn":"ok",p=a>0?`${a} over limit`:s>0?`${s} near limit`:"All within budget";return{status:d,label:p,overCount:a,nearCount:s,cappedCount:i.length,worst:n}}const W=864e5,K=30;function T(){const e=new Date;return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}function yt(){const[e,i]=b.useState(T);return b.useEffect(()=>{const a=()=>{if(document.visibilityState==="visible"){const s=T();i(n=>n===s?n:s)}};return document.addEventListener("visibilitychange",a),window.addEventListener("focus",a),()=>{document.removeEventListener("visibilitychange",a),window.removeEventListener("focus",a)}},[]),b.useMemo(()=>{const a=Date.now(),s=new Date(a);return{today:new Date(s.getFullYear(),s.getMonth(),s.getDate()).toISOString(),periodStart:new Date(a-K*W).toISOString(),prevStart:new Date(a-2*K*W).toISOString()}},[e])}const St={ok:"Healthy",warn:"Elevated",alert:"High"},jt={ok:"On track",warn:"Near limit",alert:"Over budget"};function Pt(){const e=at();return e.isLoading?t.jsx(st,{}):t.jsx(wt,{needsSetup:e.isSuccess&&e.data.providers.length===0})}function wt({needsSetup:e=!1}){var L,O,A,$,F,P,U;const i=yt(),a=b.useMemo(()=>({start_date:i.today}),[i]),s=b.useMemo(()=>({start_date:i.periodStart}),[i]),n=b.useMemo(()=>({start_date:i.prevStart,end_date:i.periodStart}),[i]),c=j(a,"hour"),d=j(s,"day"),p=j(n,"day"),r=nt(),o=ot(),l=it(),y=lt(),h=dt({},0,5),E=(L=c.data)==null?void 0:L.totals,v=(O=d.data)==null?void 0:O.totals,x=(A=p.data)==null?void 0:A.totals,S=(($=d.data)==null?void 0:$.series)??[],C=S.length>1,u=B(v),k=B(x),Y=u.rate!==null&&k.rate!==null?w(u.rate,k.rate):null,m=bt(o.data??[]),V=gt(r.data),Q=(l.data??[]).filter(f=>f.is_active).length,z=(y.data??[]).filter(f=>!f.blocked).length,J=(((F=h.data)==null?void 0:F.length)??0)>0,X=e&&h.isSuccess&&!J,Z=c.error??d.error??r.error??o.error??l.error??y.error,tt=()=>{c.refetch(),d.refetch(),p.refetch(),r.refetch(),o.refetch(),l.refetch(),y.refetch(),h.refetch()},et=c.isFetching||d.isFetching||r.isFetching||o.isFetching||l.isFetching||y.isFetching||h.isFetching;return t.jsxs("div",{className:"flex flex-col gap-6",children:[t.jsx(ct,{title:"Overview",description:"At-a-glance spend, traffic, and health across the gateway.",action:t.jsx(ut,{onRefresh:tt,isFetching:et,updatedAt:d.dataUpdatedAt})}),X?t.jsx(Nt,{}):null,t.jsx(I,{error:Z}),t.jsx(_t,{providerHealth:V,healthy:((P=r.data)==null?void 0:P.healthy)??0,total:((U=r.data)==null?void 0:U.total)??0,budget:m,errStatus:u.status,errRate:u.rate,ready:r.isSuccess&&o.isSuccess&&d.isSuccess,failed:r.isError||o.isError||d.isError}),t.jsxs("div",{className:"grid grid-cols-2 gap-4 sm:grid-cols-3 xl:grid-cols-4",children:[t.jsx(g,{label:"Spend today",value:E?_(E.cost):"—"}),t.jsx(g,{label:"Spend, last 30 days",value:v?_(v.cost):"—",hint:v?t.jsx(N,{fraction:w(v.cost,x==null?void 0:x.cost)}):null,chart:C?t.jsx(q,{values:S.map(f=>f.cost),ariaLabel:"Spend trend over the last 30 days"}):void 0}),t.jsx(g,{label:"Requests, last 30 days",value:v?R(v.request_count):"—",hint:v?t.jsx(N,{fraction:w(v.request_count,x==null?void 0:x.request_count)}):null,chart:C?t.jsx(q,{values:S.map(f=>f.requests),ariaLabel:"Request volume trend over the last 30 days"}):void 0}),t.jsx(g,{label:"Error rate, last 30 days",value:u.rate===null?"—":D(u.rate),status:M(u.status),statusLabel:u.status==="neutral"?void 0:St[u.status],hint:u.rate!==null?t.jsx(N,{fraction:Y}):null}),t.jsx(g,{label:"Budget health",value:o.data&&m.worst?D(m.worst.pct):"—",status:o.data?M(m.status):void 0,statusLabel:o.data&&m.status!=="neutral"?jt[m.status]:void 0,hint:o.data?m.worst?`${m.label} · worst: ${m.worst.name}`:m.label:void 0,to:"/budgets"}),t.jsx(g,{label:"Active keys",value:l.data?R(Q):"—",to:"/keys"}),t.jsx(g,{label:"Active users",value:y.data?R(z):"—",to:"/users"})]}),t.jsx(Et,{entries:h.data??[],loading:h.isLoading,error:h.error})]})}function Nt(){const e=rt();return t.jsx(H,{children:t.jsxs(H.Content,{className:"flex flex-col gap-3 p-6",children:[t.jsxs("div",{children:[t.jsx("h2",{className:"text-lg font-semibold text-[var(--otari-ink)]",children:"Get started with Otari"}),t.jsx("p",{className:"mt-1 text-sm text-[var(--otari-muted)]",children:"Add a provider to begin serving models. Once it is configured, this page will show your gateway’s traffic, spend, and health."})]}),t.jsx("div",{children:t.jsx(ht,{variant:"primary",onPress:()=>e("/providers"),children:"Add your first provider"})})]})})}function Rt({text:e}){return t.jsx("div",{role:"status",className:"flex items-center gap-2 rounded-xl border border-[var(--otari-line)] bg-[var(--otari-bg)] px-4 py-3 text-sm text-[var(--otari-muted)]",children:e})}function _t({providerHealth:e,healthy:i,total:a,budget:s,errStatus:n,errRate:c,ready:d,failed:p}){if(p)return t.jsx(Rt,{text:"Some status data could not be loaded."});if(!d)return null;const r=[];if((e==="warn"||e==="alert")&&a>0){const o=a-i;r.push({text:`${o} provider${o===1?"":"s"} unreachable`,to:"/providers"})}return s.overCount>0?r.push({text:`${s.overCount} budget${s.overCount===1?"":"s"} over limit`,to:"/budgets"}):s.nearCount>0&&r.push({text:`${s.nearCount} budget${s.nearCount===1?"":"s"} near limit`,to:"/budgets"}),n==="alert"&&c!==null&&r.push({text:`error rate ${D(c)}`,to:"/activity?status=error"}),r.length===0?null:t.jsxs("div",{role:"alert",className:"flex flex-col gap-2 rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-900 sm:flex-row sm:flex-wrap sm:items-center",children:[t.jsx("span",{className:"font-medium",children:"Needs attention:"}),r.map((o,l)=>t.jsxs("span",{className:"flex items-center gap-2",children:[l>0?t.jsx("span",{"aria-hidden":!0,className:"text-amber-400",children:"·"}):null,t.jsx(G,{to:o.to,className:"underline underline-offset-2 hover:text-amber-950",children:o.text})]},o.to+o.text))]})}function Dt(e){return e==="error"?"error":"ok"}function Et({entries:e,loading:i,error:a}){const s=[{id:"time",header:"Time",cell:n=>t.jsx("span",{className:"text-[var(--otari-muted)]",title:new Date(n.timestamp).toLocaleString(),children:mt(n.timestamp)})},{id:"model",header:"Model",isRowHeader:!0,cell:n=>t.jsx("span",{className:"text-[var(--otari-ink)]",children:n.model})},{id:"cost",header:"Cost",align:"end",cell:n=>n.cost===null?"—":_(n.cost)},{id:"status",header:"Status",cell:n=>t.jsx("span",{className:`inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium ${n.status==="error"?"border-red-200 bg-red-50 text-red-700":"border-[var(--otari-line)] bg-[var(--otari-brand-tint)] text-[var(--otari-brand-dark)]"}`,children:Dt(n.status)})}];return t.jsxs("div",{className:"flex flex-col gap-3",children:[t.jsxs("div",{className:"flex items-center justify-between",children:[t.jsx("h2",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:"Recent activity"}),t.jsx(G,{to:"/activity",className:"text-sm text-[var(--otari-brand-dark)] hover:underline",children:"View all →"})]}),t.jsx(I,{error:a}),t.jsx(vt,{ariaLabel:"Recent activity",columns:s,rows:e,getRowKey:n=>n.id,isLoading:i,emptyContent:"No requests yet. Once the gateway serves traffic, it appears here."})]})}export{Pt as OverviewIndex,wt as OverviewPage,T as localDayKey}; +import{j as t}from"./tanstack-query-1t81HyiD.js";import{r as b,i as rt,N as G}from"./react-dgEcD0HR.js";import{L as at,M as st,d as j,N as nt,l as ot,a as it,u as lt,b as dt,O as w,P as ct,R as ut,E as I,S as g,Q as _,T as N,U as R,V as D,W as mt}from"./index-BP-wLuMr.js";import{S as q}from"./charts-DIsd9m--.js";import{D as vt}from"./DataTable-Bmn_eYSV.js";import{d as H,B as ht}from"./heroui-BI50yK5B.js";import"./recharts-C4kRDmvS.js";function M(e){return e==="neutral"?void 0:e}const xt=.02,ft=.1;function B(e){if(!e||e.request_count===0)return{rate:null,status:"neutral"};const i=e.error_count/e.request_count,a=i>=ft?"alert":i>=xt?"warn":"ok";return{rate:i,status:a}}function gt(e){return!e||e.total===0?"neutral":e.healthy>=e.total?"ok":e.healthy===0?"alert":"warn"}const pt=.8;function bt(e){if(e.length===0)return{status:"neutral",label:"No budgets configured",overCount:0,nearCount:0,cappedCount:0};const i=e.filter(r=>r.max_budget!==null&&r.user_count>0);if(i.length===0)return{status:"neutral",label:"No capped budgets",overCount:0,nearCount:0,cappedCount:0};let a=0,s=0,n,c=-1;for(const r of i){const o=r.max_budget*r.user_count,l=o>0?r.total_spend/o:0;l>=1?a+=1:l>=pt&&(s+=1),l>c&&(c=l,n={name:r.name??r.budget_id,spent:r.total_spend,allocated:o,pct:l})}const d=a>0?"alert":s>0?"warn":"ok",p=a>0?`${a} over limit`:s>0?`${s} near limit`:"All within budget";return{status:d,label:p,overCount:a,nearCount:s,cappedCount:i.length,worst:n}}const W=864e5,K=30;function T(){const e=new Date;return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}function yt(){const[e,i]=b.useState(T);return b.useEffect(()=>{const a=()=>{if(document.visibilityState==="visible"){const s=T();i(n=>n===s?n:s)}};return document.addEventListener("visibilitychange",a),window.addEventListener("focus",a),()=>{document.removeEventListener("visibilitychange",a),window.removeEventListener("focus",a)}},[]),b.useMemo(()=>{const a=Date.now(),s=new Date(a);return{today:new Date(s.getFullYear(),s.getMonth(),s.getDate()).toISOString(),periodStart:new Date(a-K*W).toISOString(),prevStart:new Date(a-2*K*W).toISOString()}},[e])}const St={ok:"Healthy",warn:"Elevated",alert:"High"},jt={ok:"On track",warn:"Near limit",alert:"Over budget"};function Pt(){const e=at();return e.isLoading?t.jsx(st,{}):t.jsx(wt,{needsSetup:e.isSuccess&&e.data.providers.length===0})}function wt({needsSetup:e=!1}){var L,O,A,$,F,P,U;const i=yt(),a=b.useMemo(()=>({start_date:i.today}),[i]),s=b.useMemo(()=>({start_date:i.periodStart}),[i]),n=b.useMemo(()=>({start_date:i.prevStart,end_date:i.periodStart}),[i]),c=j(a,"hour"),d=j(s,"day"),p=j(n,"day"),r=nt(),o=ot(),l=it(),y=lt(),h=dt({},0,5),E=(L=c.data)==null?void 0:L.totals,v=(O=d.data)==null?void 0:O.totals,x=(A=p.data)==null?void 0:A.totals,S=(($=d.data)==null?void 0:$.series)??[],C=S.length>1,u=B(v),k=B(x),Y=u.rate!==null&&k.rate!==null?w(u.rate,k.rate):null,m=bt(o.data??[]),V=gt(r.data),Q=(l.data??[]).filter(f=>f.is_active).length,z=(y.data??[]).filter(f=>!f.blocked).length,J=(((F=h.data)==null?void 0:F.length)??0)>0,X=e&&h.isSuccess&&!J,Z=c.error??d.error??r.error??o.error??l.error??y.error,tt=()=>{c.refetch(),d.refetch(),p.refetch(),r.refetch(),o.refetch(),l.refetch(),y.refetch(),h.refetch()},et=c.isFetching||d.isFetching||r.isFetching||o.isFetching||l.isFetching||y.isFetching||h.isFetching;return t.jsxs("div",{className:"flex flex-col gap-6",children:[t.jsx(ct,{title:"Overview",description:"At-a-glance spend, traffic, and health across the gateway.",action:t.jsx(ut,{onRefresh:tt,isFetching:et,updatedAt:d.dataUpdatedAt})}),X?t.jsx(Nt,{}):null,t.jsx(I,{error:Z}),t.jsx(_t,{providerHealth:V,healthy:((P=r.data)==null?void 0:P.healthy)??0,total:((U=r.data)==null?void 0:U.total)??0,budget:m,errStatus:u.status,errRate:u.rate,ready:r.isSuccess&&o.isSuccess&&d.isSuccess,failed:r.isError||o.isError||d.isError}),t.jsxs("div",{className:"grid grid-cols-2 gap-4 sm:grid-cols-3 xl:grid-cols-4",children:[t.jsx(g,{label:"Spend today",value:E?_(E.cost):"—"}),t.jsx(g,{label:"Spend, last 30 days",value:v?_(v.cost):"—",hint:v?t.jsx(N,{fraction:w(v.cost,x==null?void 0:x.cost)}):null,chart:C?t.jsx(q,{values:S.map(f=>f.cost),ariaLabel:"Spend trend over the last 30 days"}):void 0}),t.jsx(g,{label:"Requests, last 30 days",value:v?R(v.request_count):"—",hint:v?t.jsx(N,{fraction:w(v.request_count,x==null?void 0:x.request_count)}):null,chart:C?t.jsx(q,{values:S.map(f=>f.requests),ariaLabel:"Request volume trend over the last 30 days"}):void 0}),t.jsx(g,{label:"Error rate, last 30 days",value:u.rate===null?"—":D(u.rate),status:M(u.status),statusLabel:u.status==="neutral"?void 0:St[u.status],hint:u.rate!==null?t.jsx(N,{fraction:Y}):null}),t.jsx(g,{label:"Budget health",value:o.data&&m.worst?D(m.worst.pct):"—",status:o.data?M(m.status):void 0,statusLabel:o.data&&m.status!=="neutral"?jt[m.status]:void 0,hint:o.data?m.worst?`${m.label} · worst: ${m.worst.name}`:m.label:void 0,to:"/budgets"}),t.jsx(g,{label:"Active keys",value:l.data?R(Q):"—",to:"/keys"}),t.jsx(g,{label:"Active users",value:y.data?R(z):"—",to:"/users"})]}),t.jsx(Et,{entries:h.data??[],loading:h.isLoading,error:h.error})]})}function Nt(){const e=rt();return t.jsx(H,{children:t.jsxs(H.Content,{className:"flex flex-col gap-3 p-6",children:[t.jsxs("div",{children:[t.jsx("h2",{className:"text-lg font-semibold text-[var(--otari-ink)]",children:"Get started with Otari"}),t.jsx("p",{className:"mt-1 text-sm text-[var(--otari-muted)]",children:"Add a provider to begin serving models. Once it is configured, this page will show your gateway’s traffic, spend, and health."})]}),t.jsx("div",{children:t.jsx(ht,{variant:"primary",onPress:()=>e("/providers"),children:"Add your first provider"})})]})})}function Rt({text:e}){return t.jsx("div",{role:"status",className:"flex items-center gap-2 rounded-xl border border-[var(--otari-line)] bg-[var(--otari-bg)] px-4 py-3 text-sm text-[var(--otari-muted)]",children:e})}function _t({providerHealth:e,healthy:i,total:a,budget:s,errStatus:n,errRate:c,ready:d,failed:p}){if(p)return t.jsx(Rt,{text:"Some status data could not be loaded."});if(!d)return null;const r=[];if((e==="warn"||e==="alert")&&a>0){const o=a-i;r.push({text:`${o} provider${o===1?"":"s"} unreachable`,to:"/providers"})}return s.overCount>0?r.push({text:`${s.overCount} budget${s.overCount===1?"":"s"} over limit`,to:"/budgets"}):s.nearCount>0&&r.push({text:`${s.nearCount} budget${s.nearCount===1?"":"s"} near limit`,to:"/budgets"}),n==="alert"&&c!==null&&r.push({text:`error rate ${D(c)}`,to:"/activity?status=error"}),r.length===0?null:t.jsxs("div",{role:"alert",className:"flex flex-col gap-2 rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-900 sm:flex-row sm:flex-wrap sm:items-center",children:[t.jsx("span",{className:"font-medium",children:"Needs attention:"}),r.map((o,l)=>t.jsxs("span",{className:"flex items-center gap-2",children:[l>0?t.jsx("span",{"aria-hidden":!0,className:"text-amber-400",children:"·"}):null,t.jsx(G,{to:o.to,className:"underline underline-offset-2 hover:text-amber-950",children:o.text})]},o.to+o.text))]})}function Dt(e){return e==="error"?"error":"ok"}function Et({entries:e,loading:i,error:a}){const s=[{id:"time",header:"Time",cell:n=>t.jsx("span",{className:"text-[var(--otari-muted)]",title:new Date(n.timestamp).toLocaleString(),children:mt(n.timestamp)})},{id:"model",header:"Model",isRowHeader:!0,cell:n=>t.jsx("span",{className:"text-[var(--otari-ink)]",children:n.model})},{id:"cost",header:"Cost",align:"end",cell:n=>n.cost===null?"—":_(n.cost)},{id:"status",header:"Status",cell:n=>t.jsx("span",{className:`inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium ${n.status==="error"?"border-red-200 bg-red-50 text-red-700":"border-[var(--otari-line)] bg-[var(--otari-brand-tint)] text-[var(--otari-brand-dark)]"}`,children:Dt(n.status)})}];return t.jsxs("div",{className:"flex flex-col gap-3",children:[t.jsxs("div",{className:"flex items-center justify-between",children:[t.jsx("h2",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:"Recent activity"}),t.jsx(G,{to:"/activity",className:"text-sm text-[var(--otari-brand-dark)] hover:underline",children:"View all →"})]}),t.jsx(I,{error:a}),t.jsx(vt,{ariaLabel:"Recent activity",columns:s,rows:e,getRowKey:n=>n.id,isLoading:i,emptyContent:"No requests yet. Once the gateway serves traffic, it appears here."})]})}export{Pt as OverviewIndex,wt as OverviewPage,T as localDayKey}; diff --git a/src/gateway/static/dashboard/assets/ProvidersPage-DueCtyY7.js b/src/gateway/static/dashboard/assets/ProvidersPage-Los10ECT.js similarity index 99% rename from src/gateway/static/dashboard/assets/ProvidersPage-DueCtyY7.js rename to src/gateway/static/dashboard/assets/ProvidersPage-Los10ECT.js index 93cccb6d..dc34f44c 100644 --- a/src/gateway/static/dashboard/assets/ProvidersPage-DueCtyY7.js +++ b/src/gateway/static/dashboard/assets/ProvidersPage-Los10ECT.js @@ -1 +1 @@ -import{j as e}from"./tanstack-query-1t81HyiD.js";import{r as x,L as M}from"./react-dgEcD0HR.js";import{L as Y,X as G,J as V,N as W,Y as J,Z as X,_ as Z,P as Q,E as I,I as ee,$ as te,a0 as se,W as $,C as ae,a1 as O,a2 as ne,G as q,a3 as re,a4 as ie}from"./index-JlWCttWt.js";import{F as S}from"./Field-Dwp6u3t8.js";import{D as oe}from"./DataTable-Bmn_eYSV.js";import{B as f,d as _,f as de,T as le,L as F,I as H,D as ce,S as me,C as T,a as ue,b as xe}from"./heroui-BI50yK5B.js";function R({value:s,onChange:a,label:t,placeholder:r,description:i}){return e.jsxs(le,{value:s,onChange:a,className:"flex max-w-md flex-col gap-1",children:[e.jsx(F,{className:"text-sm font-medium text-[var(--otari-ink)]",children:t}),e.jsx(H,{type:"password",placeholder:r??"sk-…",autoComplete:"off",autoCorrect:"off",autoCapitalize:"off",spellCheck:!1,"data-1p-ignore":!0,"data-lpignore":"true"}),i?e.jsx(ce,{className:"text-xs text-[var(--otari-muted)]",children:i}):null]})}function z({label:s,value:a,onChange:t,description:r,placeholder:i,extra:l=[],includeCatalog:m=!0}){var k;const g=re(),u=x.useMemo(()=>m?[...l,...(g.data??[]).map(o=>({id:o.id,name:o.name}))]:l,[g.data,l,m]),[p,c]=x.useState(()=>{var o;return((o=u.find(y=>y.id===a))==null?void 0:o.name)??""}),j=((k=u.find(o=>o.id===a))==null?void 0:k.name)??"",h=p.trim()===j.trim()?"":p.trim().toLowerCase(),d=u.filter(o=>!h||o.name.toLowerCase().includes(h)||o.id.toLowerCase().includes(h)).slice(0,50);return e.jsxs(T.Root,{allowsEmptyCollection:!0,menuTrigger:"focus",inputValue:p,onInputChange:c,onSelectionChange:o=>{var y;o!=null?(t(String(o)),c(((y=u.find(N=>N.id===String(o)))==null?void 0:y.name)??"")):(t(""),c(""))},className:"flex max-w-md flex-col gap-1",children:[e.jsx(F,{className:"text-sm font-medium text-[var(--otari-ink)]",children:s}),e.jsxs(T.InputGroup,{children:[e.jsx(H,{placeholder:i??"Search providers…",autoComplete:"off","data-1p-ignore":!0,"data-lpignore":"true",onFocus:o=>o.currentTarget.select()}),e.jsx(T.Trigger,{})]}),e.jsx(T.Popover,{children:e.jsx(ue,{items:d,className:"max-h-72 overflow-auto",children:o=>e.jsx(xe,{id:o.id,textValue:o.name,children:o.name})})}),r?e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:r}):null]})}function U({getPayload:s}){const a=ie(),t=s();return e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx(f,{variant:"outline",isDisabled:t===null||a.isPending,onPress:()=>{t&&a.mutate(t)},children:a.isPending?"Testing…":"Test connection"}),e.jsx("span",{role:"status","aria-live":"polite",children:a.isPending?null:a.error?e.jsx("span",{className:"text-xs text-red-700",children:q(a.error)}):a.data?a.data.ok?e.jsxs("span",{className:"text-xs font-medium text-green-700",children:["Connected. ",a.data.model_count," model",a.data.model_count===1?"":"s"," available."]}):e.jsx("span",{className:"block max-w-md break-words text-xs text-red-700",children:a.data.error??"Connection failed."}):null})]})}function pe({onClose:s}){var w;const a=O(),[t,r]=x.useState(""),[i,l]=x.useState(""),[m,g]=x.useState(!1),[u,p]=x.useState(""),[c,j]=x.useState(""),h=ne(t),d=((w=h.data)==null?void 0:w.id)===t?h.data:void 0;x.useEffect(()=>{d&&p(d.default_api_base??"")},[d]);const k=(d==null?void 0:d.env_key_present)??!1,o=((d==null?void 0:d.requires_api_key)??!0)&&!k,y=c.trim()!==""&&c.trim()!==t,N=/[:/]/.test(c),P=t!==""&&!N&&(!o||i.trim()!=="")&&!a.isPending,C=()=>{P&&a.mutate({instance:y?c.trim():t,provider_type:y?t:null,api_base:u.trim()||null,api_key:i.trim()||null},{onSuccess:s})};return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx(I,{error:a.error}),e.jsx(z,{label:"Provider",value:t,onChange:A=>{r(A),j(""),p("")},description:"Its endpoint is built in."}),e.jsx(R,{value:i,onChange:l,label:d&&!o?"API key (optional)":"API key",description:d?o?`${d.name}'s endpoint is built in — just add your key.`:k?`${d.env_key} is set on the server, so a key is optional here. Paste one to override it.`:`${d.name} needs no API key.`:"Stored encrypted. Requires OTARI_SECRET_KEY on the server."}),e.jsx("button",{type:"button",className:"self-start text-xs font-medium text-[var(--otari-brand-dark)]",onClick:()=>g(A=>!A),children:m?"Hide advanced":"Advanced (API base, rename)"}),m?e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsx(S,{label:"API base",value:u,onChange:p,placeholder:(d==null?void 0:d.default_api_base)??"https://…/v1",description:"Only if you route through a proxy. Blank uses the built-in default."}),e.jsx(S,{label:"Name",value:c,onChange:j,placeholder:t||"instance name",description:N?e.jsx("span",{className:"text-red-700",children:"A name cannot contain “:” or “/”."}):"Rename to run two instances of the same provider."})]}):null,e.jsxs("div",{className:"flex flex-wrap items-start gap-2",children:[e.jsx(f,{variant:"primary",isDisabled:!P,onPress:C,children:a.isPending?"Adding…":"Add provider"}),e.jsx(f,{variant:"ghost",onPress:s,children:"Cancel"}),e.jsx(U,{getPayload:()=>t===""?null:{instance:y?c.trim():t,provider_type:y?t:null,api_base:u.trim()||null,api_key:i.trim()||null}})]})]})}function he({onClose:s}){const a=O(),[t,r]=x.useState(""),[i,l]=x.useState("openai-compatible"),[m,g]=x.useState(""),[u,p]=x.useState(""),c=/[:/]/.test(t),j=t.trim()!==""&&!c&&m.trim()!==""&&!a.isPending,h=()=>{j&&a.mutate({instance:t.trim(),provider_type:i||"openai-compatible",api_base:m.trim(),api_key:u.trim()||null},{onSuccess:s})};return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx(I,{error:a.error}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsx(S,{label:"Name",value:t,onChange:r,placeholder:"my-local-llm",isRequired:!0,autoFocus:!0,description:c?e.jsx("span",{className:"text-red-700",children:"A name cannot contain “:” or “/”."}):"Call it whatever you want."}),e.jsx(z,{label:"Compatible with",value:i,onChange:l,includeCatalog:!1,description:"The API this endpoint speaks.",extra:[{id:"openai-compatible",name:"OpenAI"},{id:"anthropic-compatible",name:"Anthropic"}]})]}),e.jsx(S,{label:"API base",value:m,onChange:g,placeholder:"http://localhost:8000/v1",isRequired:!0,description:"The endpoint URL of your server."}),e.jsx(R,{value:u,onChange:p,label:"API key (optional)",description:"Many local backends need none. Stored encrypted."}),e.jsxs("div",{className:"flex flex-wrap items-start gap-2",children:[e.jsx(f,{variant:"primary",isDisabled:!j,onPress:h,children:a.isPending?"Adding…":"Add provider"}),e.jsx(f,{variant:"ghost",onPress:s,children:"Cancel"}),e.jsx(U,{getPayload:()=>t.trim()===""||m.trim()===""?null:{instance:t.trim(),provider_type:i||"openai-compatible",api_base:m.trim(),api_key:u.trim()||null}})]})]})}function ve({onClose:s}){const[a,t]=x.useState("known");return e.jsx(_,{children:e.jsxs(_.Content,{className:"flex flex-col gap-4 p-5",children:[e.jsx("div",{className:"flex items-center justify-between",children:e.jsx("div",{className:"flex items-center gap-1 rounded-lg bg-[var(--otari-bg)] p-1",children:[["known","Known provider"],["custom","Custom endpoint"]].map(([r,i])=>e.jsx("button",{type:"button","aria-pressed":a===r,onClick:()=>t(r),className:a===r?"rounded-md bg-white px-3 py-1.5 text-sm font-medium text-[var(--otari-ink)] shadow-sm":"rounded-md px-3 py-1.5 text-sm text-[var(--otari-muted)] hover:text-[var(--otari-ink)]",children:i},r))})}),a==="known"?e.jsx(pe,{onClose:s}):e.jsx(he,{onClose:s})]})})}function ge({provider:s,onClose:a}){const t=te(),[r,i]=x.useState(s.provider_type??""),[l,m]=x.useState(s.api_base??""),[g,u]=x.useState(!1),[p,c]=x.useState(""),j=()=>{if(t.isPending)return;const h={provider_type:r.trim()||null,api_base:l.trim()||null,expected_updated_at:s.updated_at};g&&p.trim()&&(h.api_key=p.trim()),t.mutate({instance:s.instance,body:h},{onSuccess:a})};return e.jsx(_,{children:e.jsxs(_.Content,{className:"flex flex-col gap-4 p-5",children:[e.jsxs("div",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:["Edit ",e.jsx("code",{children:s.instance})]}),e.jsx(I,{error:t.error}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsx(S,{label:"Provider type",value:r,onChange:i,placeholder:"openai"}),e.jsx(S,{label:"API base",value:l,onChange:m,placeholder:"https://api.openai.com/v1"})]}),e.jsx("div",{className:"flex flex-col gap-2",children:g?e.jsxs(e.Fragment,{children:[e.jsx(R,{value:p,onChange:c,label:"New API key",description:"Stored encrypted. The old key is replaced when you save."}),e.jsx("button",{type:"button",className:"self-start text-xs font-medium text-[var(--otari-brand-dark)]",onClick:()=>{u(!1),c("")},children:"Keep the current key"})]}):e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("span",{className:"text-sm text-[var(--otari-muted)]",children:["API key: ",e.jsx("code",{children:s.last4?`••••${s.last4}`:"none set"})]}),e.jsx(f,{size:"sm",variant:"outline",onPress:()=>u(!0),children:"Replace key"})]})}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(f,{variant:"primary",isDisabled:t.isPending,onPress:j,children:t.isPending?"Saving…":"Save changes"}),e.jsx(f,{variant:"ghost",onPress:a,children:"Cancel"})]})]})})}function fe(s,a){const t=new Map((a??[]).map(l=>[l.instance,l])),r=new Map((s??[]).map(l=>[l.instance,l]));return[...new Set([...t.keys(),...r.keys()])].sort().map(l=>{const m=t.get(l);return{instance:l,source:m?"stored":"config",stored:m,meta:r.get(l)}})}function je({state:s}){return s?s.status==="pending"?e.jsxs("span",{className:"inline-flex items-center gap-1.5 text-xs text-[var(--otari-muted)]",children:[e.jsx(me,{size:"sm"})," Testing…"]}):s.ok?e.jsxs("span",{className:"text-xs font-medium text-green-700",children:["Connected. ",s.model_count," model",s.model_count===1?"":"s"," available."]}):e.jsx("span",{className:"block max-w-xs break-words text-xs text-red-700",children:s.error??"Connection failed."}):null}function ye({health:s}){if(!s)return e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"—"});const a=s.ok?"border-green-200 bg-green-50 text-green-700":"border-red-200 bg-red-50 text-red-700",t=s.checked_at?`Last checked ${$(s.checked_at)}`:"Not checked yet",r=s.ok?t:`${s.error??"Unreachable"} · ${t}`;return e.jsxs("span",{title:r,className:`inline-flex items-center gap-1.5 rounded-full border px-2.5 py-0.5 text-xs font-medium ${a}`,children:[e.jsx("span",{"aria-hidden":!0,className:`h-1.5 w-1.5 rounded-full ${s.ok?"bg-green-500":"bg-red-500"}`}),s.ok?"Reachable":"Unreachable"]})}function be({healthy:s,total:a,checkedAt:t}){const r=s===a,i=se();return e.jsxs("div",{className:"flex flex-wrap items-center gap-3 rounded-xl border border-[var(--otari-line)] bg-[var(--otari-surface)] px-4 py-2.5 text-sm",children:[e.jsx("span",{"aria-hidden":!0,className:`h-2 w-2 rounded-full ${r?"bg-green-500":"bg-red-500"}`}),e.jsxs("span",{className:"font-medium text-[var(--otari-ink)]",children:[s," of ",a," provider",a===1?"":"s"," reachable"]}),t?e.jsxs("span",{className:"text-[var(--otari-muted)]",children:["Last checked ",$(t)]}):null,e.jsx(f,{size:"sm",variant:"ghost",className:"ml-auto",isDisabled:i.isPending,onPress:()=>i.mutate(),children:i.isPending?"Re-checking…":"Re-check all"})]})}function E({n:s,title:a,children:t}){return e.jsxs("li",{className:"flex gap-3",children:[e.jsx("span",{className:"flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-[var(--otari-brand-tint)] text-xs font-semibold text-[var(--otari-brand-dark)]",children:s}),e.jsxs("div",{className:"text-sm",children:[e.jsx("div",{className:"font-medium text-[var(--otari-ink)]",children:a}),e.jsx("div",{className:"text-[var(--otari-muted)]",children:t})]})]})}function ke({onAddProvider:s,needsPricing:a,onEnablePricing:t,enabling:r,secretKeyConfigured:i}){return e.jsx(_,{children:e.jsxs(_.Content,{className:"flex flex-col gap-4 p-6",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-semibold text-[var(--otari-ink)]",children:"Welcome to Otari"}),e.jsx("p",{className:"mt-1 text-sm text-[var(--otari-muted)]",children:"You are signed in. Add a provider to start serving models: three quick steps."})]}),e.jsxs("ol",{className:"flex flex-col gap-3",children:[e.jsxs(E,{n:1,title:"Add a provider",children:["Enter a provider name (like ",e.jsx("code",{children:"openai"}),") and its API key. Keys are encrypted at rest."]}),e.jsxs(E,{n:2,title:"Test the connection",children:["Use ",e.jsx("strong",{children:"Test"})," on the provider row to confirm the key works and see how many models it serves."]}),e.jsxs(E,{n:3,title:"Send your first request",children:["Point your app at ",e.jsx("code",{children:"/v1"})," on this gateway with the API key printed in the server logs (",e.jsx("code",{children:"gw-…"}),"). See the"," ",e.jsx("a",{href:"/welcome",className:"font-medium text-[var(--otari-brand-dark)]",children:"quickstart"}),"."]})]}),a?e.jsxs("p",{className:"text-sm text-[var(--otari-muted)]",children:["Tip: ",e.jsx("code",{children:"require_pricing"})," is on, so requests are rejected until pricing is set."," ",e.jsx("button",{type:"button",className:"font-medium text-[var(--otari-brand-dark)] disabled:opacity-50",disabled:r,onClick:t,children:"Enable default pricing"})," ","to meter new models with public rates."]}):null,e.jsx("div",{children:e.jsx(f,{variant:"primary",isDisabled:!i,onPress:s,children:"Add your first provider"})})]})})}function we(){var K,B,D,L;const s=Y(),a=G(),t=V(),r=W(),i=J(),l=X(),m=Z(),[g,u]=x.useState(!1),[p,c]=x.useState(null),[j,h]=x.useState({}),d=fe((K=s.data)==null?void 0:K.providers,a.data),k=new Map((((B=r.data)==null?void 0:B.providers)??[]).map(n=>[n.instance,n])),o=s.isLoading||a.isLoading,y=((D=a.data)==null?void 0:D.find(n=>n.instance===p))??null,N=((L=t.data)==null?void 0:L.require_pricing)===!0&&t.data.default_pricing===!1,P=t.data?t.data.secret_key_configured!==!1:!t.isError,C=!o&&d.length===0&&!g,w=n=>{h(v=>({...v,[n]:{status:"pending"}})),l.mutate(n,{onSuccess:v=>h(b=>({...b,[n]:{status:"done",...v}})),onError:v=>h(b=>({...b,[n]:{status:"done",ok:!1,model_count:0,error:q(v)}}))})},A=[{id:"provider",header:"Provider",isRowHeader:!0,cell:n=>e.jsx(M,{to:`/models?provider=${encodeURIComponent(n.instance)}`,className:"font-medium text-[var(--otari-ink)] hover:text-[var(--otari-brand-dark)] hover:underline",children:n.instance})},{id:"type",header:"Type",cell:n=>{var v,b;return e.jsx("span",{className:"text-[var(--otari-muted)]",children:((v=n.meta)==null?void 0:v.provider_type)??((b=n.stored)==null?void 0:b.provider_type)??n.instance})}},{id:"source",header:"Source",cell:n=>e.jsx(de,{size:"sm",color:n.source==="stored"?"accent":"default",children:n.source==="stored"?"stored":"config"})},{id:"api_key",header:"API key",cell:n=>{var v,b;return e.jsx("span",{className:"text-[var(--otari-muted)]",children:n.source==="stored"?n.stored&&!n.stored.decryptable?e.jsx("span",{className:"text-amber-700",title:"This key can't be decrypted with the current OTARI_SECRET_KEY. Replace the key, or restore the original OTARI_SECRET_KEY.",children:"⚠ key unreadable"}):e.jsx("code",{children:(v=n.stored)!=null&&v.last4?`••••${n.stored.last4}`:"none set"}):(b=n.meta)!=null&&b.env_key?e.jsxs("span",{children:["via ",e.jsx("code",{children:n.meta.env_key})]}):"config.yml"})}},{id:"status",header:"Status",cell:n=>e.jsx(ye,{health:k.get(n.instance)})},{id:"actions",header:"Actions",align:"end",cell:n=>{var v,b;return n.source==="stored"?e.jsxs("div",{className:"flex flex-col items-end gap-1.5",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(f,{size:"sm",variant:"outline",isDisabled:((v=j[n.instance])==null?void 0:v.status)==="pending"||((b=n.stored)==null?void 0:b.decryptable)===!1,onPress:()=>w(n.instance),children:"Test"}),e.jsx(f,{size:"sm",variant:"ghost",onPress:()=>{u(!1),c(n.instance)},children:"Edit"}),e.jsx(ae,{confirmLabel:"Delete",isPending:i.isPending,onConfirm:()=>i.mutate(n.instance),children:"Delete"})]}),e.jsx(je,{state:j[n.instance]})]}):e.jsx("span",{className:"block text-right text-xs text-[var(--otari-muted)]",children:"managed in config.yml"})}}];return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(Q,{title:"Providers",description:"Add provider API keys here to serve models without editing config.yml. Keys are encrypted at rest.",action:g||C?null:e.jsx(f,{variant:"primary",isDisabled:!P,onPress:()=>{c(null),u(!0)},children:"Add provider"})}),e.jsx(I,{error:s.error??a.error??t.error??r.error??m.error??i.error}),P?null:e.jsxs(ee,{tone:"warning",children:[e.jsx("code",{children:"OTARI_SECRET_KEY"})," is not set, so provider keys can't be encrypted at rest and adding providers from the dashboard is disabled. Set it on the server and restart to add providers here. Providers defined in"," ",e.jsx("code",{children:"config.yml"})," keep working without it."]}),C?e.jsx(ke,{onAddProvider:()=>{c(null),u(!0)},needsPricing:N,onEnablePricing:()=>m.mutate({default_pricing:!0}),enabling:m.isPending,secretKeyConfigured:P}):null,g&&P?e.jsx(ve,{onClose:()=>u(!1)}):null,y?e.jsx(ge,{provider:y,onClose:()=>c(null)}):null,!o&&d.length>0&&r.data&&r.data.total>0?e.jsx(be,{healthy:r.data.healthy,total:r.data.total,checkedAt:r.data.checked_at}):null,C?null:e.jsx(oe,{ariaLabel:"Providers",columns:A,rows:d,getRowKey:n=>n.instance,isLoading:o,emptyContent:"No providers yet. Add your first provider to start serving models."})]})}export{we as ProvidersPage}; +import{j as e}from"./tanstack-query-1t81HyiD.js";import{r as x,L as M}from"./react-dgEcD0HR.js";import{L as Y,X as G,J as V,N as W,Y as J,Z as X,_ as Z,P as Q,E as I,I as ee,$ as te,a0 as se,W as $,C as ae,a1 as O,a2 as ne,G as q,a3 as re,a4 as ie}from"./index-BP-wLuMr.js";import{F as S}from"./Field-Dwp6u3t8.js";import{D as oe}from"./DataTable-Bmn_eYSV.js";import{B as f,d as _,f as de,T as le,L as F,I as H,D as ce,S as me,C as T,a as ue,b as xe}from"./heroui-BI50yK5B.js";function R({value:s,onChange:a,label:t,placeholder:r,description:i}){return e.jsxs(le,{value:s,onChange:a,className:"flex max-w-md flex-col gap-1",children:[e.jsx(F,{className:"text-sm font-medium text-[var(--otari-ink)]",children:t}),e.jsx(H,{type:"password",placeholder:r??"sk-…",autoComplete:"off",autoCorrect:"off",autoCapitalize:"off",spellCheck:!1,"data-1p-ignore":!0,"data-lpignore":"true"}),i?e.jsx(ce,{className:"text-xs text-[var(--otari-muted)]",children:i}):null]})}function z({label:s,value:a,onChange:t,description:r,placeholder:i,extra:l=[],includeCatalog:m=!0}){var k;const g=re(),u=x.useMemo(()=>m?[...l,...(g.data??[]).map(o=>({id:o.id,name:o.name}))]:l,[g.data,l,m]),[p,c]=x.useState(()=>{var o;return((o=u.find(y=>y.id===a))==null?void 0:o.name)??""}),j=((k=u.find(o=>o.id===a))==null?void 0:k.name)??"",h=p.trim()===j.trim()?"":p.trim().toLowerCase(),d=u.filter(o=>!h||o.name.toLowerCase().includes(h)||o.id.toLowerCase().includes(h)).slice(0,50);return e.jsxs(T.Root,{allowsEmptyCollection:!0,menuTrigger:"focus",inputValue:p,onInputChange:c,onSelectionChange:o=>{var y;o!=null?(t(String(o)),c(((y=u.find(N=>N.id===String(o)))==null?void 0:y.name)??"")):(t(""),c(""))},className:"flex max-w-md flex-col gap-1",children:[e.jsx(F,{className:"text-sm font-medium text-[var(--otari-ink)]",children:s}),e.jsxs(T.InputGroup,{children:[e.jsx(H,{placeholder:i??"Search providers…",autoComplete:"off","data-1p-ignore":!0,"data-lpignore":"true",onFocus:o=>o.currentTarget.select()}),e.jsx(T.Trigger,{})]}),e.jsx(T.Popover,{children:e.jsx(ue,{items:d,className:"max-h-72 overflow-auto",children:o=>e.jsx(xe,{id:o.id,textValue:o.name,children:o.name})})}),r?e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:r}):null]})}function U({getPayload:s}){const a=ie(),t=s();return e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx(f,{variant:"outline",isDisabled:t===null||a.isPending,onPress:()=>{t&&a.mutate(t)},children:a.isPending?"Testing…":"Test connection"}),e.jsx("span",{role:"status","aria-live":"polite",children:a.isPending?null:a.error?e.jsx("span",{className:"text-xs text-red-700",children:q(a.error)}):a.data?a.data.ok?e.jsxs("span",{className:"text-xs font-medium text-green-700",children:["Connected. ",a.data.model_count," model",a.data.model_count===1?"":"s"," available."]}):e.jsx("span",{className:"block max-w-md break-words text-xs text-red-700",children:a.data.error??"Connection failed."}):null})]})}function pe({onClose:s}){var w;const a=O(),[t,r]=x.useState(""),[i,l]=x.useState(""),[m,g]=x.useState(!1),[u,p]=x.useState(""),[c,j]=x.useState(""),h=ne(t),d=((w=h.data)==null?void 0:w.id)===t?h.data:void 0;x.useEffect(()=>{d&&p(d.default_api_base??"")},[d]);const k=(d==null?void 0:d.env_key_present)??!1,o=((d==null?void 0:d.requires_api_key)??!0)&&!k,y=c.trim()!==""&&c.trim()!==t,N=/[:/]/.test(c),P=t!==""&&!N&&(!o||i.trim()!=="")&&!a.isPending,C=()=>{P&&a.mutate({instance:y?c.trim():t,provider_type:y?t:null,api_base:u.trim()||null,api_key:i.trim()||null},{onSuccess:s})};return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx(I,{error:a.error}),e.jsx(z,{label:"Provider",value:t,onChange:A=>{r(A),j(""),p("")},description:"Its endpoint is built in."}),e.jsx(R,{value:i,onChange:l,label:d&&!o?"API key (optional)":"API key",description:d?o?`${d.name}'s endpoint is built in — just add your key.`:k?`${d.env_key} is set on the server, so a key is optional here. Paste one to override it.`:`${d.name} needs no API key.`:"Stored encrypted. Requires OTARI_SECRET_KEY on the server."}),e.jsx("button",{type:"button",className:"self-start text-xs font-medium text-[var(--otari-brand-dark)]",onClick:()=>g(A=>!A),children:m?"Hide advanced":"Advanced (API base, rename)"}),m?e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsx(S,{label:"API base",value:u,onChange:p,placeholder:(d==null?void 0:d.default_api_base)??"https://…/v1",description:"Only if you route through a proxy. Blank uses the built-in default."}),e.jsx(S,{label:"Name",value:c,onChange:j,placeholder:t||"instance name",description:N?e.jsx("span",{className:"text-red-700",children:"A name cannot contain “:” or “/”."}):"Rename to run two instances of the same provider."})]}):null,e.jsxs("div",{className:"flex flex-wrap items-start gap-2",children:[e.jsx(f,{variant:"primary",isDisabled:!P,onPress:C,children:a.isPending?"Adding…":"Add provider"}),e.jsx(f,{variant:"ghost",onPress:s,children:"Cancel"}),e.jsx(U,{getPayload:()=>t===""?null:{instance:y?c.trim():t,provider_type:y?t:null,api_base:u.trim()||null,api_key:i.trim()||null}})]})]})}function he({onClose:s}){const a=O(),[t,r]=x.useState(""),[i,l]=x.useState("openai-compatible"),[m,g]=x.useState(""),[u,p]=x.useState(""),c=/[:/]/.test(t),j=t.trim()!==""&&!c&&m.trim()!==""&&!a.isPending,h=()=>{j&&a.mutate({instance:t.trim(),provider_type:i||"openai-compatible",api_base:m.trim(),api_key:u.trim()||null},{onSuccess:s})};return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx(I,{error:a.error}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsx(S,{label:"Name",value:t,onChange:r,placeholder:"my-local-llm",isRequired:!0,autoFocus:!0,description:c?e.jsx("span",{className:"text-red-700",children:"A name cannot contain “:” or “/”."}):"Call it whatever you want."}),e.jsx(z,{label:"Compatible with",value:i,onChange:l,includeCatalog:!1,description:"The API this endpoint speaks.",extra:[{id:"openai-compatible",name:"OpenAI"},{id:"anthropic-compatible",name:"Anthropic"}]})]}),e.jsx(S,{label:"API base",value:m,onChange:g,placeholder:"http://localhost:8000/v1",isRequired:!0,description:"The endpoint URL of your server."}),e.jsx(R,{value:u,onChange:p,label:"API key (optional)",description:"Many local backends need none. Stored encrypted."}),e.jsxs("div",{className:"flex flex-wrap items-start gap-2",children:[e.jsx(f,{variant:"primary",isDisabled:!j,onPress:h,children:a.isPending?"Adding…":"Add provider"}),e.jsx(f,{variant:"ghost",onPress:s,children:"Cancel"}),e.jsx(U,{getPayload:()=>t.trim()===""||m.trim()===""?null:{instance:t.trim(),provider_type:i||"openai-compatible",api_base:m.trim(),api_key:u.trim()||null}})]})]})}function ve({onClose:s}){const[a,t]=x.useState("known");return e.jsx(_,{children:e.jsxs(_.Content,{className:"flex flex-col gap-4 p-5",children:[e.jsx("div",{className:"flex items-center justify-between",children:e.jsx("div",{className:"flex items-center gap-1 rounded-lg bg-[var(--otari-bg)] p-1",children:[["known","Known provider"],["custom","Custom endpoint"]].map(([r,i])=>e.jsx("button",{type:"button","aria-pressed":a===r,onClick:()=>t(r),className:a===r?"rounded-md bg-white px-3 py-1.5 text-sm font-medium text-[var(--otari-ink)] shadow-sm":"rounded-md px-3 py-1.5 text-sm text-[var(--otari-muted)] hover:text-[var(--otari-ink)]",children:i},r))})}),a==="known"?e.jsx(pe,{onClose:s}):e.jsx(he,{onClose:s})]})})}function ge({provider:s,onClose:a}){const t=te(),[r,i]=x.useState(s.provider_type??""),[l,m]=x.useState(s.api_base??""),[g,u]=x.useState(!1),[p,c]=x.useState(""),j=()=>{if(t.isPending)return;const h={provider_type:r.trim()||null,api_base:l.trim()||null,expected_updated_at:s.updated_at};g&&p.trim()&&(h.api_key=p.trim()),t.mutate({instance:s.instance,body:h},{onSuccess:a})};return e.jsx(_,{children:e.jsxs(_.Content,{className:"flex flex-col gap-4 p-5",children:[e.jsxs("div",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:["Edit ",e.jsx("code",{children:s.instance})]}),e.jsx(I,{error:t.error}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsx(S,{label:"Provider type",value:r,onChange:i,placeholder:"openai"}),e.jsx(S,{label:"API base",value:l,onChange:m,placeholder:"https://api.openai.com/v1"})]}),e.jsx("div",{className:"flex flex-col gap-2",children:g?e.jsxs(e.Fragment,{children:[e.jsx(R,{value:p,onChange:c,label:"New API key",description:"Stored encrypted. The old key is replaced when you save."}),e.jsx("button",{type:"button",className:"self-start text-xs font-medium text-[var(--otari-brand-dark)]",onClick:()=>{u(!1),c("")},children:"Keep the current key"})]}):e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("span",{className:"text-sm text-[var(--otari-muted)]",children:["API key: ",e.jsx("code",{children:s.last4?`••••${s.last4}`:"none set"})]}),e.jsx(f,{size:"sm",variant:"outline",onPress:()=>u(!0),children:"Replace key"})]})}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(f,{variant:"primary",isDisabled:t.isPending,onPress:j,children:t.isPending?"Saving…":"Save changes"}),e.jsx(f,{variant:"ghost",onPress:a,children:"Cancel"})]})]})})}function fe(s,a){const t=new Map((a??[]).map(l=>[l.instance,l])),r=new Map((s??[]).map(l=>[l.instance,l]));return[...new Set([...t.keys(),...r.keys()])].sort().map(l=>{const m=t.get(l);return{instance:l,source:m?"stored":"config",stored:m,meta:r.get(l)}})}function je({state:s}){return s?s.status==="pending"?e.jsxs("span",{className:"inline-flex items-center gap-1.5 text-xs text-[var(--otari-muted)]",children:[e.jsx(me,{size:"sm"})," Testing…"]}):s.ok?e.jsxs("span",{className:"text-xs font-medium text-green-700",children:["Connected. ",s.model_count," model",s.model_count===1?"":"s"," available."]}):e.jsx("span",{className:"block max-w-xs break-words text-xs text-red-700",children:s.error??"Connection failed."}):null}function ye({health:s}){if(!s)return e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"—"});const a=s.ok?"border-green-200 bg-green-50 text-green-700":"border-red-200 bg-red-50 text-red-700",t=s.checked_at?`Last checked ${$(s.checked_at)}`:"Not checked yet",r=s.ok?t:`${s.error??"Unreachable"} · ${t}`;return e.jsxs("span",{title:r,className:`inline-flex items-center gap-1.5 rounded-full border px-2.5 py-0.5 text-xs font-medium ${a}`,children:[e.jsx("span",{"aria-hidden":!0,className:`h-1.5 w-1.5 rounded-full ${s.ok?"bg-green-500":"bg-red-500"}`}),s.ok?"Reachable":"Unreachable"]})}function be({healthy:s,total:a,checkedAt:t}){const r=s===a,i=se();return e.jsxs("div",{className:"flex flex-wrap items-center gap-3 rounded-xl border border-[var(--otari-line)] bg-[var(--otari-surface)] px-4 py-2.5 text-sm",children:[e.jsx("span",{"aria-hidden":!0,className:`h-2 w-2 rounded-full ${r?"bg-green-500":"bg-red-500"}`}),e.jsxs("span",{className:"font-medium text-[var(--otari-ink)]",children:[s," of ",a," provider",a===1?"":"s"," reachable"]}),t?e.jsxs("span",{className:"text-[var(--otari-muted)]",children:["Last checked ",$(t)]}):null,e.jsx(f,{size:"sm",variant:"ghost",className:"ml-auto",isDisabled:i.isPending,onPress:()=>i.mutate(),children:i.isPending?"Re-checking…":"Re-check all"})]})}function E({n:s,title:a,children:t}){return e.jsxs("li",{className:"flex gap-3",children:[e.jsx("span",{className:"flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-[var(--otari-brand-tint)] text-xs font-semibold text-[var(--otari-brand-dark)]",children:s}),e.jsxs("div",{className:"text-sm",children:[e.jsx("div",{className:"font-medium text-[var(--otari-ink)]",children:a}),e.jsx("div",{className:"text-[var(--otari-muted)]",children:t})]})]})}function ke({onAddProvider:s,needsPricing:a,onEnablePricing:t,enabling:r,secretKeyConfigured:i}){return e.jsx(_,{children:e.jsxs(_.Content,{className:"flex flex-col gap-4 p-6",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-semibold text-[var(--otari-ink)]",children:"Welcome to Otari"}),e.jsx("p",{className:"mt-1 text-sm text-[var(--otari-muted)]",children:"You are signed in. Add a provider to start serving models: three quick steps."})]}),e.jsxs("ol",{className:"flex flex-col gap-3",children:[e.jsxs(E,{n:1,title:"Add a provider",children:["Enter a provider name (like ",e.jsx("code",{children:"openai"}),") and its API key. Keys are encrypted at rest."]}),e.jsxs(E,{n:2,title:"Test the connection",children:["Use ",e.jsx("strong",{children:"Test"})," on the provider row to confirm the key works and see how many models it serves."]}),e.jsxs(E,{n:3,title:"Send your first request",children:["Point your app at ",e.jsx("code",{children:"/v1"})," on this gateway with the API key printed in the server logs (",e.jsx("code",{children:"gw-…"}),"). See the"," ",e.jsx("a",{href:"/welcome",className:"font-medium text-[var(--otari-brand-dark)]",children:"quickstart"}),"."]})]}),a?e.jsxs("p",{className:"text-sm text-[var(--otari-muted)]",children:["Tip: ",e.jsx("code",{children:"require_pricing"})," is on, so requests are rejected until pricing is set."," ",e.jsx("button",{type:"button",className:"font-medium text-[var(--otari-brand-dark)] disabled:opacity-50",disabled:r,onClick:t,children:"Enable default pricing"})," ","to meter new models with public rates."]}):null,e.jsx("div",{children:e.jsx(f,{variant:"primary",isDisabled:!i,onPress:s,children:"Add your first provider"})})]})})}function we(){var K,B,D,L;const s=Y(),a=G(),t=V(),r=W(),i=J(),l=X(),m=Z(),[g,u]=x.useState(!1),[p,c]=x.useState(null),[j,h]=x.useState({}),d=fe((K=s.data)==null?void 0:K.providers,a.data),k=new Map((((B=r.data)==null?void 0:B.providers)??[]).map(n=>[n.instance,n])),o=s.isLoading||a.isLoading,y=((D=a.data)==null?void 0:D.find(n=>n.instance===p))??null,N=((L=t.data)==null?void 0:L.require_pricing)===!0&&t.data.default_pricing===!1,P=t.data?t.data.secret_key_configured!==!1:!t.isError,C=!o&&d.length===0&&!g,w=n=>{h(v=>({...v,[n]:{status:"pending"}})),l.mutate(n,{onSuccess:v=>h(b=>({...b,[n]:{status:"done",...v}})),onError:v=>h(b=>({...b,[n]:{status:"done",ok:!1,model_count:0,error:q(v)}}))})},A=[{id:"provider",header:"Provider",isRowHeader:!0,cell:n=>e.jsx(M,{to:`/models?provider=${encodeURIComponent(n.instance)}`,className:"font-medium text-[var(--otari-ink)] hover:text-[var(--otari-brand-dark)] hover:underline",children:n.instance})},{id:"type",header:"Type",cell:n=>{var v,b;return e.jsx("span",{className:"text-[var(--otari-muted)]",children:((v=n.meta)==null?void 0:v.provider_type)??((b=n.stored)==null?void 0:b.provider_type)??n.instance})}},{id:"source",header:"Source",cell:n=>e.jsx(de,{size:"sm",color:n.source==="stored"?"accent":"default",children:n.source==="stored"?"stored":"config"})},{id:"api_key",header:"API key",cell:n=>{var v,b;return e.jsx("span",{className:"text-[var(--otari-muted)]",children:n.source==="stored"?n.stored&&!n.stored.decryptable?e.jsx("span",{className:"text-amber-700",title:"This key can't be decrypted with the current OTARI_SECRET_KEY. Replace the key, or restore the original OTARI_SECRET_KEY.",children:"⚠ key unreadable"}):e.jsx("code",{children:(v=n.stored)!=null&&v.last4?`••••${n.stored.last4}`:"none set"}):(b=n.meta)!=null&&b.env_key?e.jsxs("span",{children:["via ",e.jsx("code",{children:n.meta.env_key})]}):"config.yml"})}},{id:"status",header:"Status",cell:n=>e.jsx(ye,{health:k.get(n.instance)})},{id:"actions",header:"Actions",align:"end",cell:n=>{var v,b;return n.source==="stored"?e.jsxs("div",{className:"flex flex-col items-end gap-1.5",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(f,{size:"sm",variant:"outline",isDisabled:((v=j[n.instance])==null?void 0:v.status)==="pending"||((b=n.stored)==null?void 0:b.decryptable)===!1,onPress:()=>w(n.instance),children:"Test"}),e.jsx(f,{size:"sm",variant:"ghost",onPress:()=>{u(!1),c(n.instance)},children:"Edit"}),e.jsx(ae,{confirmLabel:"Delete",isPending:i.isPending,onConfirm:()=>i.mutate(n.instance),children:"Delete"})]}),e.jsx(je,{state:j[n.instance]})]}):e.jsx("span",{className:"block text-right text-xs text-[var(--otari-muted)]",children:"managed in config.yml"})}}];return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(Q,{title:"Providers",description:"Add provider API keys here to serve models without editing config.yml. Keys are encrypted at rest.",action:g||C?null:e.jsx(f,{variant:"primary",isDisabled:!P,onPress:()=>{c(null),u(!0)},children:"Add provider"})}),e.jsx(I,{error:s.error??a.error??t.error??r.error??m.error??i.error}),P?null:e.jsxs(ee,{tone:"warning",children:[e.jsx("code",{children:"OTARI_SECRET_KEY"})," is not set, so provider keys can't be encrypted at rest and adding providers from the dashboard is disabled. Set it on the server and restart to add providers here. Providers defined in"," ",e.jsx("code",{children:"config.yml"})," keep working without it."]}),C?e.jsx(ke,{onAddProvider:()=>{c(null),u(!0)},needsPricing:N,onEnablePricing:()=>m.mutate({default_pricing:!0}),enabling:m.isPending,secretKeyConfigured:P}):null,g&&P?e.jsx(ve,{onClose:()=>u(!1)}):null,y?e.jsx(ge,{provider:y,onClose:()=>c(null)}):null,!o&&d.length>0&&r.data&&r.data.total>0?e.jsx(be,{healthy:r.data.healthy,total:r.data.total,checkedAt:r.data.checked_at}):null,C?null:e.jsx(oe,{ariaLabel:"Providers",columns:A,rows:d,getRowKey:n=>n.instance,isLoading:o,emptyContent:"No providers yet. Add your first provider to start serving models."})]})}export{we as ProvidersPage}; diff --git a/src/gateway/static/dashboard/assets/SettingsPage-BVUWlkda.js b/src/gateway/static/dashboard/assets/SettingsPage-DJbI5U1N.js similarity index 99% rename from src/gateway/static/dashboard/assets/SettingsPage-BVUWlkda.js rename to src/gateway/static/dashboard/assets/SettingsPage-DJbI5U1N.js index 77f1c7d6..f09eaa29 100644 --- a/src/gateway/static/dashboard/assets/SettingsPage-BVUWlkda.js +++ b/src/gateway/static/dashboard/assets/SettingsPage-DJbI5U1N.js @@ -1 +1 @@ -import{j as e}from"./tanstack-query-1t81HyiD.js";import{r as u}from"./react-dgEcD0HR.js";import{J as R,_ as C,P,E as y,M as E,a5 as T,a6 as _,a7 as D,F as A,a8 as O,X as F,a9 as I,I as w}from"./index-JlWCttWt.js";import{d as v,B as h,A as d,g as K,I as M}from"./heroui-BI50yK5B.js";function b(t,r){return{[t]:r}}function z(t,r){let s=0;for(const a of r)if(a===t[s]&&(s+=1),s===t.length)return!0;return t.length===0}function L(t,r){const s=r.trim().toLowerCase();if(s==="")return!0;const a=`${t.key} ${t.description??""} ${t.group}`.toLowerCase(),n=t.key.toLowerCase().replace(/[^a-z0-9]/g,"");return s.split(/\s+/).every(i=>a.includes(i)||z(i,n))}function B({checked:t,onChange:r,label:s,disabled:a}){return e.jsx("button",{type:"button",role:"switch","aria-checked":t,"aria-label":s,disabled:a,onClick:()=>r(!t),className:`relative inline-flex h-6 w-11 shrink-0 items-center rounded-full transition-colors disabled:opacity-50 ${t?"bg-[var(--otari-brand)]":"bg-[var(--otari-line)]"}`,children:e.jsx("span",{className:`inline-block h-5 w-5 transform rounded-full bg-white shadow transition-transform ${t?"translate-x-5":"translate-x-0.5"}`})})}function $({field:t,onSave:r,disabled:s}){const a=typeof t.value=="number"?t.value:0,[n,i]=u.useState(String(a)),o=t.type==="float";u.useEffect(()=>{i(String(a))},[a]);const c=Number(n),p=n.trim()!==""&&Number.isFinite(c)&&(o||Number.isInteger(c)),m=t.minimum??void 0,x=t.exclusive_minimum??void 0,g=x!==void 0?c>x:m!==void 0?c>=m:c>=0,l=p&&g&&c!==a;return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(M,{type:"number",min:"0",step:o?"any":"1",inputMode:o?"decimal":"numeric","aria-label":t.key,value:n,disabled:s,onChange:f=>i(f.target.value),className:"w-28 rounded-md border border-[var(--otari-line)] bg-white px-2 py-1 text-right text-sm tabular-nums focus:border-[var(--otari-brand)] focus:outline-none disabled:opacity-50"}),e.jsx(h,{size:"sm",variant:"primary","aria-label":`Save ${t.key}`,isDisabled:s||!l,onPress:()=>r(c),children:"Save"})]})}function H({field:t,onSave:r,disabled:s}){const a=typeof t.value=="string"?t.value:"",[n,i]=u.useState(a);u.useEffect(()=>{i(a)},[a]);const o=n!==a;return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"text","aria-label":t.key,value:n,disabled:s,placeholder:"unset",onChange:c=>i(c.target.value),className:"w-56 rounded-md border border-[var(--otari-line)] bg-white px-2 py-1 text-sm focus:border-[var(--otari-brand)] focus:outline-none disabled:opacity-50"}),e.jsx(h,{size:"sm",variant:"primary","aria-label":`Save ${t.key}`,isDisabled:s||!o,onPress:()=>r(n.trim()===""?null:n),children:"Save"})]})}function Y(t){const{value:r}=t;return r==null?"unset":typeof r=="boolean"?r?"on":"off":Array.isArray(r)?r.length?r.join(", "):"none":String(r)}function q({field:t,patch:r,disabled:s}){return t.settable?t.type==="bool"?e.jsx(B,{checked:t.value===!0,onChange:a=>r(b(t.key,a)),label:t.key,disabled:s}):t.options&&t.options.length>0?e.jsx(A,{ariaLabel:t.key,value:String(t.value??""),onChange:a=>r(b(t.key,a)),options:t.options.map(a=>({value:a,label:a}))}):t.type==="int"||t.type==="float"?e.jsx($,{field:t,onSave:a=>r(b(t.key,a)),disabled:s}):e.jsx(H,{field:t,onSave:a=>r(b(t.key,a)),disabled:s}):e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-sm tabular-nums text-[var(--otari-ink)]",children:Y(t)}),e.jsx("span",{className:"rounded-full border border-[var(--otari-line)] px-2 py-0.5 text-xs text-[var(--otari-muted)]",children:"startup-only"})]})}function U({field:t,patch:r,disabled:s}){return e.jsxs("div",{className:"flex items-start justify-between gap-6 py-4",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("code",{className:"text-sm font-medium text-[var(--otari-ink)]",children:t.key}),t.description?e.jsx("p",{className:"mt-1 text-sm text-[var(--otari-muted)]",children:t.description}):null]}),e.jsx("div",{className:"shrink-0 pt-0.5",children:e.jsx(q,{field:t,patch:r,disabled:s})})]})}function V({value:t,fieldRef:r}){const s=u.useRef(null),a=r??s,[n,i]=u.useState(!1),[o,c]=u.useState(!1),p=async()=>{var m,x,g;(m=a.current)==null||m.focus(),(x=a.current)==null||x.select();try{if((g=navigator.clipboard)!=null&&g.writeText){await navigator.clipboard.writeText(t),i(!0),c(!1),window.setTimeout(()=>i(!1),2e3);return}}catch{}c(!0)};return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-xs font-medium text-[var(--otari-muted)]",children:"New master key"}),e.jsx(h,{size:"sm",variant:"outline",onPress:p,children:n?"Copied":"Copy"})]}),e.jsx("input",{ref:a,readOnly:!0,value:t,onFocus:m=>m.currentTarget.select(),autoComplete:"off",autoCorrect:"off",autoCapitalize:"off",spellCheck:!1,"data-1p-ignore":!0,"data-lpignore":"true"}),e.jsx("span",{"aria-live":"polite",className:"text-xs text-[var(--otari-brand-dark)]",children:n?"Copied to clipboard.":""}),o?e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"Selected. Press Ctrl/Cmd-C to copy."}):null]})}function G({masterKey:t,error:r,isPending:s,onRegenerate:a,onClose:n}){const i=u.useRef(null);return u.useEffect(()=>{var o,c;t!==void 0&&((o=i.current)==null||o.focus(),(c=i.current)==null||c.select())},[t]),e.jsx(d.Backdrop,{children:e.jsx(d.Container,{placement:"center",size:"lg",children:e.jsxs(d.Dialog,{children:[e.jsx(d.Header,{children:e.jsx(d.Heading,{children:t!==void 0?"Master key regenerated":"Regenerate master key?"})}),e.jsx(d.Body,{className:"flex flex-col gap-4",children:t!==void 0?e.jsxs(e.Fragment,{children:[e.jsx(w,{tone:"warning",children:"Copy this key now. It is shown once and cannot be retrieved again after you close this dialog."}),e.jsx("p",{className:"text-sm text-[var(--otari-muted)]",children:"The previous master key has stopped working. This browser tab now uses the new key."}),e.jsx(V,{value:t,fieldRef:i})]}):e.jsxs(e.Fragment,{children:[e.jsx(w,{tone:"warning",children:"This immediately invalidates the current dashboard master key. Other signed-in dashboard sessions will need the new key to continue."}),e.jsx("p",{className:"text-sm text-[var(--otari-muted)]",children:"The replacement key will be shown once. Save it before closing the next screen."}),e.jsx(y,{error:r})]})}),e.jsx(d.Footer,{children:t!==void 0?e.jsx(h,{variant:"primary",onPress:n,children:"I’ve saved this key"}):e.jsxs(e.Fragment,{children:[e.jsx(h,{variant:"ghost",isDisabled:s,onPress:n,children:"Cancel"}),e.jsx(h,{variant:"danger",isPending:s,onPress:a,children:"Regenerate key"})]})})]})})})}function X({source:t}){const r=O(),[s,a]=u.useState(!1),[n,i]=u.useState(),o=t==="generated",c=()=>r.mutate(void 0,{onSuccess:x=>{i(x.master_key)}}),p=()=>{a(!1),i(void 0),r.reset()},m=x=>{x?(r.reset(),a(!0)):n===void 0&&p()};return e.jsx("div",{className:"flex flex-col gap-4 py-4",children:e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("code",{className:"text-sm font-medium text-[var(--otari-ink)]",children:"master_key"}),e.jsx("p",{className:"mt-1 max-w-3xl text-sm text-[var(--otari-muted)]",children:o?"This gateway uses its first-run generated dashboard key. Regeneration invalidates the current key immediately.":"This gateway uses a key managed through OTARI_MASTER_KEY or config.yml. Rotate it in configuration, then restart the gateway."})]}),e.jsxs(d,{isOpen:s,onOpenChange:m,children:[o?e.jsx(d.Trigger,{className:K({size:"sm",variant:"danger-soft"}),children:"Regenerate"}):e.jsx(h,{size:"sm",variant:"danger-soft",isDisabled:!0,children:"Managed in configuration"}),s?e.jsx(G,{masterKey:n,error:r.error,isPending:r.isPending,onRegenerate:c,onClose:p}):null]})]})})}function J(){var o;const t=F(),r=I(),s=r.data,a=((o=t.data)==null?void 0:o.length)??0,n=(t.data??[]).filter(c=>!c.decryptable).length,i=a>0;return e.jsxs("div",{className:"flex flex-col gap-4 py-4",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("code",{className:"text-sm font-medium text-[var(--otari-ink)]",children:"OTARI_SECRET_KEY"}),e.jsxs("p",{className:"mt-1 max-w-3xl text-sm text-[var(--otari-muted)]",children:["Generate a new key with ",e.jsx("code",{children:"uv run otari gen-secret-key"}),", then restart with"," ",e.jsx("code",{children:"OTARI_SECRET_KEY=,"}),". Re-encrypt the stored provider keys, then restart with ",e.jsx("code",{children:"OTARI_SECRET_KEY="})," once none are unreadable."]})]}),e.jsx("div",{className:"shrink-0",children:e.jsx(h,{size:"sm",variant:"outline",isDisabled:!i||r.isPending,onPress:()=>r.mutate(),children:r.isPending?"Re-encrypting…":"Re-encrypt provider keys"})})]}),e.jsx(y,{error:t.error??r.error}),n>0?e.jsxs(w,{tone:"warning",children:[n," stored provider key",n===1?"":"s"," cannot be decrypted with the current"," ",e.jsx("code",{children:"OTARI_SECRET_KEY"}),". Restore the old secret key and re-encrypt, or edit each affected provider and replace its key."]}):null,s?e.jsxs("p",{className:"text-sm text-[var(--otari-muted)]",role:"status","aria-live":"polite",children:["Re-encrypted ",s.reencrypted," provider key",s.reencrypted===1?"":"s",".",s.unreadable>0?` ${s.unreadable} still need replacement.`:" All decryptable stored keys now use the primary secret key."]}):!t.isLoading&&!i?e.jsx("p",{className:"text-sm text-[var(--otari-muted)]",children:"No stored provider keys need re-encryption."}):null]})}function Q({masterKeySource:t}){return e.jsxs("section",{className:"flex flex-col gap-2",children:[e.jsxs("h2",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:["Credential security ",e.jsx("span",{className:"font-normal text-[var(--otari-muted)]",children:"(2)"})]}),e.jsx(v,{children:e.jsxs(v.Content,{className:"flex flex-col divide-y divide-[var(--otari-line)] px-5 py-1",children:[e.jsx(X,{source:t}),e.jsx(J,{})]})})]})}function W({preview:t,error:r,isPending:s,onAccept:a,onReject:n}){return e.jsx(d.Backdrop,{children:e.jsx(d.Container,{placement:"center",size:"lg",children:e.jsxs(d.Dialog,{children:[e.jsx(d.Header,{children:e.jsx(d.Heading,{children:"Review default price updates"})}),e.jsxs(d.Body,{className:"flex flex-col gap-4",children:[e.jsxs("p",{className:"text-sm text-[var(--otari-muted)]",children:[t.added_count," added, ",t.changed_count," changed, and ",t.removed_count," removed upstream model prices. The accepted catalog is saved in the database with source ",e.jsx("code",{children:"genai-prices"})," and reloads after a restart. Your ",t.protected_model_count," custom model price",t.protected_model_count===1?"":"s"," remain unchanged."]}),t.changes.length>0?e.jsx("ul",{className:"max-h-60 list-disc overflow-auto pl-5 text-sm text-[var(--otari-ink)]",children:t.changes.map(i=>e.jsxs("li",{children:[i.model_key,": ",i.change]},i.model_key))}):null,t.changes_truncated?e.jsx("p",{className:"text-xs text-[var(--otari-muted)]",children:"Only the first 100 changes are shown."}):null,e.jsx(y,{error:r})]}),e.jsxs(d.Footer,{children:[e.jsx(h,{variant:"ghost",isDisabled:s,onPress:n,children:"Reject changes"}),e.jsx(h,{variant:"primary",isPending:s,onPress:a,children:"Accept price updates"})]})]})})})}function Z(){const t=T(),r=_(),s=D(),a=t.data,n=r.isPending||s.isPending,i=()=>{a===void 0||n||s.mutate(void 0,{onSuccess:t.reset})};return e.jsxs("section",{className:"flex flex-col gap-2",children:[e.jsx("h2",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:"Default pricing catalog"}),e.jsx(v,{children:e.jsxs(v.Content,{className:"flex flex-col gap-4 p-5",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"text-sm font-medium text-[var(--otari-ink)]",children:"genai-prices defaults"}),e.jsxs("p",{className:"mt-1 max-w-3xl text-sm text-[var(--otari-muted)]",children:["Fetch the latest upstream catalog, review the proposed change summary, then accept or reject it. Accepted data is stored as ",e.jsx("code",{children:"genai-prices"}),"; custom prices remain separate and always take precedence."]})]}),e.jsx(h,{size:"sm",variant:"outline",isDisabled:t.isPending||n,onPress:()=>t.mutate(),children:t.isPending?"Checking prices…":"Check for price updates"})]}),e.jsx(y,{error:t.error})]})}),e.jsxs(d,{isOpen:a!==void 0,onOpenChange:o=>o?void 0:i(),children:[e.jsx(d.Trigger,{className:"hidden",children:"Review price updates"}),a?e.jsx(W,{preview:a,error:r.error??s.error,isPending:n,onAccept:()=>r.mutate(void 0,{onSuccess:t.reset}),onReject:i}):null]})]})}function ee(t){const r=[],s=new Map;for(const a of t){let n=s.get(a.group);n||(n={name:a.group,fields:[]},s.set(a.group,n),r.push(n)),n.fields.push(a)}return r}function ne(){const t=R(),r=C(),s=t.data,a=r.isPending,[n,i]=u.useState(""),[o,c]=u.useState(!1),p=u.useRef(null);u.useEffect(()=>{function l(f){var N;const j=f.target,S=j&&(j.tagName==="INPUT"||j.tagName==="TEXTAREA"||j.tagName==="SELECT");f.key==="/"&&!S&&(f.preventDefault(),(N=p.current)==null||N.focus())}return window.addEventListener("keydown",l),()=>window.removeEventListener("keydown",l)},[]);const m=l=>r.mutate(l),x=(s==null?void 0:s.config)??[],g=x.filter(l=>(o?l.settable:!0)&&L(l,n)),k=ee(g);return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(P,{title:"Settings",description:"Every effective gateway setting. Settable fields apply immediately and persist across restarts; startup-only fields are shown for reference and change only via config.yml or environment variables (then a restart)."}),e.jsx(y,{error:t.error??r.error}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("input",{ref:p,type:"search","aria-label":"Search settings",placeholder:"Search settings (press / to focus)…",value:n,onChange:l=>i(l.target.value),onKeyDown:l=>{l.key==="Escape"&&i("")},className:"min-w-0 flex-1 rounded-lg border border-[var(--otari-line)] bg-[var(--otari-bg)] px-3 py-2 text-sm text-[var(--otari-ink)] focus:border-[var(--otari-brand)] focus:outline-none"}),e.jsxs("label",{className:"flex items-center gap-2 text-sm text-[var(--otari-muted)]",children:[e.jsx("input",{type:"checkbox",checked:o,onChange:l=>c(l.target.checked),className:"h-4 w-4 accent-[var(--otari-brand)]"}),"Settable only"]})]}),s?e.jsxs("p",{className:"text-xs text-[var(--otari-muted)]",children:["Showing ",g.length," of ",x.length," settings"]}):null,s&&g.length===0?e.jsx("p",{className:"text-sm text-[var(--otari-muted)]",children:"No settings match your search."}):null,t.isLoading?e.jsx(E,{}):null,k.map(l=>e.jsxs("section",{className:"flex flex-col gap-2",children:[e.jsxs("h2",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:[l.name," ",e.jsxs("span",{className:"font-normal text-[var(--otari-muted)]",children:["(",l.fields.length,")"]})]}),e.jsx(v,{children:e.jsx(v.Content,{className:"flex flex-col divide-y divide-[var(--otari-line)] px-5 py-1",children:l.fields.map(f=>e.jsx(U,{field:f,patch:m,disabled:!s||a},f.key))})})]},l.name)),s?e.jsx(Z,{}):null,s?e.jsx(Q,{masterKeySource:s.master_key_source}):null,s?e.jsxs("p",{className:"text-xs text-[var(--otari-muted)]",children:["Mode: ",s.mode," · Version ",s.version,s.require_pricing?" · require_pricing on":""]}):null]})}export{ne as SettingsPage,L as fieldMatches}; +import{j as e}from"./tanstack-query-1t81HyiD.js";import{r as u}from"./react-dgEcD0HR.js";import{J as R,_ as C,P,E as y,M as E,a5 as T,a6 as _,a7 as D,F as A,a8 as O,X as F,a9 as I,I as w}from"./index-BP-wLuMr.js";import{d as v,B as h,A as d,g as K,I as M}from"./heroui-BI50yK5B.js";function b(t,r){return{[t]:r}}function z(t,r){let s=0;for(const a of r)if(a===t[s]&&(s+=1),s===t.length)return!0;return t.length===0}function L(t,r){const s=r.trim().toLowerCase();if(s==="")return!0;const a=`${t.key} ${t.description??""} ${t.group}`.toLowerCase(),n=t.key.toLowerCase().replace(/[^a-z0-9]/g,"");return s.split(/\s+/).every(i=>a.includes(i)||z(i,n))}function B({checked:t,onChange:r,label:s,disabled:a}){return e.jsx("button",{type:"button",role:"switch","aria-checked":t,"aria-label":s,disabled:a,onClick:()=>r(!t),className:`relative inline-flex h-6 w-11 shrink-0 items-center rounded-full transition-colors disabled:opacity-50 ${t?"bg-[var(--otari-brand)]":"bg-[var(--otari-line)]"}`,children:e.jsx("span",{className:`inline-block h-5 w-5 transform rounded-full bg-white shadow transition-transform ${t?"translate-x-5":"translate-x-0.5"}`})})}function $({field:t,onSave:r,disabled:s}){const a=typeof t.value=="number"?t.value:0,[n,i]=u.useState(String(a)),o=t.type==="float";u.useEffect(()=>{i(String(a))},[a]);const c=Number(n),p=n.trim()!==""&&Number.isFinite(c)&&(o||Number.isInteger(c)),m=t.minimum??void 0,x=t.exclusive_minimum??void 0,g=x!==void 0?c>x:m!==void 0?c>=m:c>=0,l=p&&g&&c!==a;return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(M,{type:"number",min:"0",step:o?"any":"1",inputMode:o?"decimal":"numeric","aria-label":t.key,value:n,disabled:s,onChange:f=>i(f.target.value),className:"w-28 rounded-md border border-[var(--otari-line)] bg-white px-2 py-1 text-right text-sm tabular-nums focus:border-[var(--otari-brand)] focus:outline-none disabled:opacity-50"}),e.jsx(h,{size:"sm",variant:"primary","aria-label":`Save ${t.key}`,isDisabled:s||!l,onPress:()=>r(c),children:"Save"})]})}function H({field:t,onSave:r,disabled:s}){const a=typeof t.value=="string"?t.value:"",[n,i]=u.useState(a);u.useEffect(()=>{i(a)},[a]);const o=n!==a;return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"text","aria-label":t.key,value:n,disabled:s,placeholder:"unset",onChange:c=>i(c.target.value),className:"w-56 rounded-md border border-[var(--otari-line)] bg-white px-2 py-1 text-sm focus:border-[var(--otari-brand)] focus:outline-none disabled:opacity-50"}),e.jsx(h,{size:"sm",variant:"primary","aria-label":`Save ${t.key}`,isDisabled:s||!o,onPress:()=>r(n.trim()===""?null:n),children:"Save"})]})}function Y(t){const{value:r}=t;return r==null?"unset":typeof r=="boolean"?r?"on":"off":Array.isArray(r)?r.length?r.join(", "):"none":String(r)}function q({field:t,patch:r,disabled:s}){return t.settable?t.type==="bool"?e.jsx(B,{checked:t.value===!0,onChange:a=>r(b(t.key,a)),label:t.key,disabled:s}):t.options&&t.options.length>0?e.jsx(A,{ariaLabel:t.key,value:String(t.value??""),onChange:a=>r(b(t.key,a)),options:t.options.map(a=>({value:a,label:a}))}):t.type==="int"||t.type==="float"?e.jsx($,{field:t,onSave:a=>r(b(t.key,a)),disabled:s}):e.jsx(H,{field:t,onSave:a=>r(b(t.key,a)),disabled:s}):e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-sm tabular-nums text-[var(--otari-ink)]",children:Y(t)}),e.jsx("span",{className:"rounded-full border border-[var(--otari-line)] px-2 py-0.5 text-xs text-[var(--otari-muted)]",children:"startup-only"})]})}function U({field:t,patch:r,disabled:s}){return e.jsxs("div",{className:"flex items-start justify-between gap-6 py-4",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("code",{className:"text-sm font-medium text-[var(--otari-ink)]",children:t.key}),t.description?e.jsx("p",{className:"mt-1 text-sm text-[var(--otari-muted)]",children:t.description}):null]}),e.jsx("div",{className:"shrink-0 pt-0.5",children:e.jsx(q,{field:t,patch:r,disabled:s})})]})}function V({value:t,fieldRef:r}){const s=u.useRef(null),a=r??s,[n,i]=u.useState(!1),[o,c]=u.useState(!1),p=async()=>{var m,x,g;(m=a.current)==null||m.focus(),(x=a.current)==null||x.select();try{if((g=navigator.clipboard)!=null&&g.writeText){await navigator.clipboard.writeText(t),i(!0),c(!1),window.setTimeout(()=>i(!1),2e3);return}}catch{}c(!0)};return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-xs font-medium text-[var(--otari-muted)]",children:"New master key"}),e.jsx(h,{size:"sm",variant:"outline",onPress:p,children:n?"Copied":"Copy"})]}),e.jsx("input",{ref:a,readOnly:!0,value:t,onFocus:m=>m.currentTarget.select(),autoComplete:"off",autoCorrect:"off",autoCapitalize:"off",spellCheck:!1,"data-1p-ignore":!0,"data-lpignore":"true"}),e.jsx("span",{"aria-live":"polite",className:"text-xs text-[var(--otari-brand-dark)]",children:n?"Copied to clipboard.":""}),o?e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"Selected. Press Ctrl/Cmd-C to copy."}):null]})}function G({masterKey:t,error:r,isPending:s,onRegenerate:a,onClose:n}){const i=u.useRef(null);return u.useEffect(()=>{var o,c;t!==void 0&&((o=i.current)==null||o.focus(),(c=i.current)==null||c.select())},[t]),e.jsx(d.Backdrop,{children:e.jsx(d.Container,{placement:"center",size:"lg",children:e.jsxs(d.Dialog,{children:[e.jsx(d.Header,{children:e.jsx(d.Heading,{children:t!==void 0?"Master key regenerated":"Regenerate master key?"})}),e.jsx(d.Body,{className:"flex flex-col gap-4",children:t!==void 0?e.jsxs(e.Fragment,{children:[e.jsx(w,{tone:"warning",children:"Copy this key now. It is shown once and cannot be retrieved again after you close this dialog."}),e.jsx("p",{className:"text-sm text-[var(--otari-muted)]",children:"The previous master key has stopped working. This browser tab now uses the new key."}),e.jsx(V,{value:t,fieldRef:i})]}):e.jsxs(e.Fragment,{children:[e.jsx(w,{tone:"warning",children:"This immediately invalidates the current dashboard master key. Other signed-in dashboard sessions will need the new key to continue."}),e.jsx("p",{className:"text-sm text-[var(--otari-muted)]",children:"The replacement key will be shown once. Save it before closing the next screen."}),e.jsx(y,{error:r})]})}),e.jsx(d.Footer,{children:t!==void 0?e.jsx(h,{variant:"primary",onPress:n,children:"I’ve saved this key"}):e.jsxs(e.Fragment,{children:[e.jsx(h,{variant:"ghost",isDisabled:s,onPress:n,children:"Cancel"}),e.jsx(h,{variant:"danger",isPending:s,onPress:a,children:"Regenerate key"})]})})]})})})}function X({source:t}){const r=O(),[s,a]=u.useState(!1),[n,i]=u.useState(),o=t==="generated",c=()=>r.mutate(void 0,{onSuccess:x=>{i(x.master_key)}}),p=()=>{a(!1),i(void 0),r.reset()},m=x=>{x?(r.reset(),a(!0)):n===void 0&&p()};return e.jsx("div",{className:"flex flex-col gap-4 py-4",children:e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("code",{className:"text-sm font-medium text-[var(--otari-ink)]",children:"master_key"}),e.jsx("p",{className:"mt-1 max-w-3xl text-sm text-[var(--otari-muted)]",children:o?"This gateway uses its first-run generated dashboard key. Regeneration invalidates the current key immediately.":"This gateway uses a key managed through OTARI_MASTER_KEY or config.yml. Rotate it in configuration, then restart the gateway."})]}),e.jsxs(d,{isOpen:s,onOpenChange:m,children:[o?e.jsx(d.Trigger,{className:K({size:"sm",variant:"danger-soft"}),children:"Regenerate"}):e.jsx(h,{size:"sm",variant:"danger-soft",isDisabled:!0,children:"Managed in configuration"}),s?e.jsx(G,{masterKey:n,error:r.error,isPending:r.isPending,onRegenerate:c,onClose:p}):null]})]})})}function J(){var o;const t=F(),r=I(),s=r.data,a=((o=t.data)==null?void 0:o.length)??0,n=(t.data??[]).filter(c=>!c.decryptable).length,i=a>0;return e.jsxs("div",{className:"flex flex-col gap-4 py-4",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("code",{className:"text-sm font-medium text-[var(--otari-ink)]",children:"OTARI_SECRET_KEY"}),e.jsxs("p",{className:"mt-1 max-w-3xl text-sm text-[var(--otari-muted)]",children:["Generate a new key with ",e.jsx("code",{children:"uv run otari gen-secret-key"}),", then restart with"," ",e.jsx("code",{children:"OTARI_SECRET_KEY=,"}),". Re-encrypt the stored provider keys, then restart with ",e.jsx("code",{children:"OTARI_SECRET_KEY="})," once none are unreadable."]})]}),e.jsx("div",{className:"shrink-0",children:e.jsx(h,{size:"sm",variant:"outline",isDisabled:!i||r.isPending,onPress:()=>r.mutate(),children:r.isPending?"Re-encrypting…":"Re-encrypt provider keys"})})]}),e.jsx(y,{error:t.error??r.error}),n>0?e.jsxs(w,{tone:"warning",children:[n," stored provider key",n===1?"":"s"," cannot be decrypted with the current"," ",e.jsx("code",{children:"OTARI_SECRET_KEY"}),". Restore the old secret key and re-encrypt, or edit each affected provider and replace its key."]}):null,s?e.jsxs("p",{className:"text-sm text-[var(--otari-muted)]",role:"status","aria-live":"polite",children:["Re-encrypted ",s.reencrypted," provider key",s.reencrypted===1?"":"s",".",s.unreadable>0?` ${s.unreadable} still need replacement.`:" All decryptable stored keys now use the primary secret key."]}):!t.isLoading&&!i?e.jsx("p",{className:"text-sm text-[var(--otari-muted)]",children:"No stored provider keys need re-encryption."}):null]})}function Q({masterKeySource:t}){return e.jsxs("section",{className:"flex flex-col gap-2",children:[e.jsxs("h2",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:["Credential security ",e.jsx("span",{className:"font-normal text-[var(--otari-muted)]",children:"(2)"})]}),e.jsx(v,{children:e.jsxs(v.Content,{className:"flex flex-col divide-y divide-[var(--otari-line)] px-5 py-1",children:[e.jsx(X,{source:t}),e.jsx(J,{})]})})]})}function W({preview:t,error:r,isPending:s,onAccept:a,onReject:n}){return e.jsx(d.Backdrop,{children:e.jsx(d.Container,{placement:"center",size:"lg",children:e.jsxs(d.Dialog,{children:[e.jsx(d.Header,{children:e.jsx(d.Heading,{children:"Review default price updates"})}),e.jsxs(d.Body,{className:"flex flex-col gap-4",children:[e.jsxs("p",{className:"text-sm text-[var(--otari-muted)]",children:[t.added_count," added, ",t.changed_count," changed, and ",t.removed_count," removed upstream model prices. The accepted catalog is saved in the database with source ",e.jsx("code",{children:"genai-prices"})," and reloads after a restart. Your ",t.protected_model_count," custom model price",t.protected_model_count===1?"":"s"," remain unchanged."]}),t.changes.length>0?e.jsx("ul",{className:"max-h-60 list-disc overflow-auto pl-5 text-sm text-[var(--otari-ink)]",children:t.changes.map(i=>e.jsxs("li",{children:[i.model_key,": ",i.change]},i.model_key))}):null,t.changes_truncated?e.jsx("p",{className:"text-xs text-[var(--otari-muted)]",children:"Only the first 100 changes are shown."}):null,e.jsx(y,{error:r})]}),e.jsxs(d.Footer,{children:[e.jsx(h,{variant:"ghost",isDisabled:s,onPress:n,children:"Reject changes"}),e.jsx(h,{variant:"primary",isPending:s,onPress:a,children:"Accept price updates"})]})]})})})}function Z(){const t=T(),r=_(),s=D(),a=t.data,n=r.isPending||s.isPending,i=()=>{a===void 0||n||s.mutate(void 0,{onSuccess:t.reset})};return e.jsxs("section",{className:"flex flex-col gap-2",children:[e.jsx("h2",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:"Default pricing catalog"}),e.jsx(v,{children:e.jsxs(v.Content,{className:"flex flex-col gap-4 p-5",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"text-sm font-medium text-[var(--otari-ink)]",children:"genai-prices defaults"}),e.jsxs("p",{className:"mt-1 max-w-3xl text-sm text-[var(--otari-muted)]",children:["Fetch the latest upstream catalog, review the proposed change summary, then accept or reject it. Accepted data is stored as ",e.jsx("code",{children:"genai-prices"}),"; custom prices remain separate and always take precedence."]})]}),e.jsx(h,{size:"sm",variant:"outline",isDisabled:t.isPending||n,onPress:()=>t.mutate(),children:t.isPending?"Checking prices…":"Check for price updates"})]}),e.jsx(y,{error:t.error})]})}),e.jsxs(d,{isOpen:a!==void 0,onOpenChange:o=>o?void 0:i(),children:[e.jsx(d.Trigger,{className:"hidden",children:"Review price updates"}),a?e.jsx(W,{preview:a,error:r.error??s.error,isPending:n,onAccept:()=>r.mutate(void 0,{onSuccess:t.reset}),onReject:i}):null]})]})}function ee(t){const r=[],s=new Map;for(const a of t){let n=s.get(a.group);n||(n={name:a.group,fields:[]},s.set(a.group,n),r.push(n)),n.fields.push(a)}return r}function ne(){const t=R(),r=C(),s=t.data,a=r.isPending,[n,i]=u.useState(""),[o,c]=u.useState(!1),p=u.useRef(null);u.useEffect(()=>{function l(f){var N;const j=f.target,S=j&&(j.tagName==="INPUT"||j.tagName==="TEXTAREA"||j.tagName==="SELECT");f.key==="/"&&!S&&(f.preventDefault(),(N=p.current)==null||N.focus())}return window.addEventListener("keydown",l),()=>window.removeEventListener("keydown",l)},[]);const m=l=>r.mutate(l),x=(s==null?void 0:s.config)??[],g=x.filter(l=>(o?l.settable:!0)&&L(l,n)),k=ee(g);return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(P,{title:"Settings",description:"Every effective gateway setting. Settable fields apply immediately and persist across restarts; startup-only fields are shown for reference and change only via config.yml or environment variables (then a restart)."}),e.jsx(y,{error:t.error??r.error}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("input",{ref:p,type:"search","aria-label":"Search settings",placeholder:"Search settings (press / to focus)…",value:n,onChange:l=>i(l.target.value),onKeyDown:l=>{l.key==="Escape"&&i("")},className:"min-w-0 flex-1 rounded-lg border border-[var(--otari-line)] bg-[var(--otari-bg)] px-3 py-2 text-sm text-[var(--otari-ink)] focus:border-[var(--otari-brand)] focus:outline-none"}),e.jsxs("label",{className:"flex items-center gap-2 text-sm text-[var(--otari-muted)]",children:[e.jsx("input",{type:"checkbox",checked:o,onChange:l=>c(l.target.checked),className:"h-4 w-4 accent-[var(--otari-brand)]"}),"Settable only"]})]}),s?e.jsxs("p",{className:"text-xs text-[var(--otari-muted)]",children:["Showing ",g.length," of ",x.length," settings"]}):null,s&&g.length===0?e.jsx("p",{className:"text-sm text-[var(--otari-muted)]",children:"No settings match your search."}):null,t.isLoading?e.jsx(E,{}):null,k.map(l=>e.jsxs("section",{className:"flex flex-col gap-2",children:[e.jsxs("h2",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:[l.name," ",e.jsxs("span",{className:"font-normal text-[var(--otari-muted)]",children:["(",l.fields.length,")"]})]}),e.jsx(v,{children:e.jsx(v.Content,{className:"flex flex-col divide-y divide-[var(--otari-line)] px-5 py-1",children:l.fields.map(f=>e.jsx(U,{field:f,patch:m,disabled:!s||a},f.key))})})]},l.name)),s?e.jsx(Z,{}):null,s?e.jsx(Q,{masterKeySource:s.master_key_source}):null,s?e.jsxs("p",{className:"text-xs text-[var(--otari-muted)]",children:["Mode: ",s.mode," · Version ",s.version,s.require_pricing?" · require_pricing on":""]}):null]})}export{ne as SettingsPage,L as fieldMatches}; diff --git a/src/gateway/static/dashboard/assets/TablePagination-CfsjgA8s.js b/src/gateway/static/dashboard/assets/TablePagination-BtDO5gaH.js similarity index 98% rename from src/gateway/static/dashboard/assets/TablePagination-CfsjgA8s.js rename to src/gateway/static/dashboard/assets/TablePagination-BtDO5gaH.js index 431d7f9f..46ce9867 100644 --- a/src/gateway/static/dashboard/assets/TablePagination-CfsjgA8s.js +++ b/src/gateway/static/dashboard/assets/TablePagination-BtDO5gaH.js @@ -1 +1 @@ -import{j as e}from"./tanstack-query-1t81HyiD.js";import{r as u}from"./react-dgEcD0HR.js";import{I as w,E as M,F as D}from"./index-JlWCttWt.js";import{A as o,B as x,T as F,L as $,I as T,S as y}from"./heroui-BI50yK5B.js";function _({label:t,value:r,onChange:a,isRequired:c,autoFocus:i}){return e.jsxs(F,{value:r,onChange:a,isRequired:c,className:"flex flex-col gap-1",children:[e.jsx($,{className:"text-sm font-medium text-[var(--otari-ink)]",children:t}),e.jsx(T,{inputMode:"decimal",placeholder:"0.00",autoFocus:i})]})}function R(t){const r=t.trim();if(r==="")return null;const a=Number(r);return Number.isFinite(a)&&a>=0?a:Number.NaN}const C=t=>`Recompute cost for ${t.toLocaleString()} imported ${t===1?"row":"rows"} from each row's own token counts at these per-1M rates. Enforced gateway rows are never affected.`;function W({isOpen:t,onOpenChange:r,targetCount:a,isPending:c,error:i,onSubmit:E,title:I="Set price",description:L=C}){const[j,p]=u.useState(""),[n,h]=u.useState(""),[b,N]=u.useState(""),[f,v]=u.useState("");u.useEffect(()=>{t&&(p(""),h(""),N(""),v(""))},[t]);const m=R(j),l=R(n),d=R(b),s=R(f),g=m===null||Number.isNaN(m)||l===null||Number.isNaN(l)||Number.isNaN(d??0)||Number.isNaN(s??0),S=()=>{g||m===null||l===null||E({input_price_per_million:m,output_price_per_million:l,...d!==null&&!Number.isNaN(d)?{cache_read_price_per_million:d}:{},...s!==null&&!Number.isNaN(s)?{cache_write_price_per_million:s}:{}})};return e.jsx(o,{isOpen:t,onOpenChange:r,children:t?e.jsx(o.Backdrop,{children:e.jsx(o.Container,{placement:"center",size:"lg",children:e.jsxs(o.Dialog,{children:[e.jsx(o.Header,{children:e.jsx(o.Heading,{children:I})}),e.jsxs(o.Body,{className:"flex flex-col gap-4",children:[e.jsx("p",{className:"text-sm text-[var(--otari-muted)]",children:L(a)}),e.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[e.jsx(_,{label:"Input $ / 1M",value:j,onChange:p,isRequired:!0,autoFocus:!0}),e.jsx(_,{label:"Output $ / 1M",value:n,onChange:h,isRequired:!0}),e.jsx(_,{label:"Cache read $ / 1M",value:b,onChange:N}),e.jsx(_,{label:"Cache write $ / 1M",value:f,onChange:v})]}),e.jsx(w,{tone:"info",children:"Leave a cache rate blank to bill those tokens at the input rate."}),e.jsx(M,{error:i})]}),e.jsxs(o.Footer,{children:[e.jsx(x,{variant:"ghost",isDisabled:c,onPress:()=>r(!1),children:"Cancel"}),e.jsx(x,{variant:"primary",isDisabled:g,isPending:c,onPress:S,children:"Set price"})]})]})})}):null})}const P=[25,50,100];function q({page:t,pageSize:r,total:a,rowsOnPage:c,onPageChange:i,onPageSizeChange:E,pageSizeOptions:I=P,isFetching:L=!1,hasNextFallback:j=!1}){const p=u.useId(),n=a!=null?Math.max(1,Math.ceil(a/r)):null,h=t===0,b=n!=null?t>=n-1:!j,N=c>0?t*r+1:0,f=t*r+c,v=a!=null?a===0?"0 of 0":`${N.toLocaleString()}–${f.toLocaleString()} of ${a.toLocaleString()}`:c>0?`${N.toLocaleString()}–${f.toLocaleString()}`:"0",[m,l]=u.useState(String(t+1));u.useEffect(()=>{l(String(t+1))},[t]);const d=()=>{const s=Number.parseInt(m,10);if(Number.isNaN(s)){l(String(t+1));return}const g=n??Number.MAX_SAFE_INTEGER,S=Math.min(Math.max(s,1),g);S-1!==t?i(S-1):l(String(t+1))};return e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("label",{htmlFor:p,className:"text-sm text-[var(--otari-muted)]",children:"Rows"}),e.jsx(D,{id:p,ariaLabel:"Rows per page",value:String(r),onChange:s=>E(Number.parseInt(s,10)),options:I.map(s=>({value:String(s),label:String(s)}))}),L?e.jsx(y,{size:"sm"}):null]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"text-sm text-[var(--otari-muted)] tabular-nums",children:v}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(x,{size:"sm",variant:"outline","aria-label":"First page",isDisabled:h,onPress:()=>i(0),children:"«"}),e.jsx(x,{size:"sm",variant:"outline","aria-label":"Previous page",isDisabled:h,onPress:()=>i(t-1),children:"‹"}),e.jsxs("span",{className:"inline-flex items-center gap-1 text-sm text-[var(--otari-muted)]",children:[e.jsx("input",{"aria-label":"Page number",inputMode:"numeric",value:m,onChange:s=>l(s.target.value.replace(/[^0-9]/g,"")),onKeyDown:s=>{s.key==="Enter"&&s.currentTarget.blur()},onBlur:d,className:"w-12 rounded-lg border border-[var(--otari-line)] bg-[var(--otari-bg)] px-2 py-1 text-center text-sm text-[var(--otari-ink)] tabular-nums focus:border-[var(--otari-brand)] focus:outline-none"}),n!=null?e.jsxs("span",{className:"tabular-nums",children:["/ ",n.toLocaleString()]}):null]}),e.jsx(x,{size:"sm",variant:"outline","aria-label":"Next page",isDisabled:b,onPress:()=>i(t+1),children:"›"}),e.jsx(x,{size:"sm",variant:"outline","aria-label":"Last page",isDisabled:n==null||b,onPress:()=>n!=null&&i(n-1),children:"»"})]})]})]})}export{P,W as S,q as T}; +import{j as e}from"./tanstack-query-1t81HyiD.js";import{r as u}from"./react-dgEcD0HR.js";import{I as w,E as M,F as D}from"./index-BP-wLuMr.js";import{A as o,B as x,T as F,L as $,I as T,S as y}from"./heroui-BI50yK5B.js";function _({label:t,value:r,onChange:a,isRequired:c,autoFocus:i}){return e.jsxs(F,{value:r,onChange:a,isRequired:c,className:"flex flex-col gap-1",children:[e.jsx($,{className:"text-sm font-medium text-[var(--otari-ink)]",children:t}),e.jsx(T,{inputMode:"decimal",placeholder:"0.00",autoFocus:i})]})}function R(t){const r=t.trim();if(r==="")return null;const a=Number(r);return Number.isFinite(a)&&a>=0?a:Number.NaN}const C=t=>`Recompute cost for ${t.toLocaleString()} imported ${t===1?"row":"rows"} from each row's own token counts at these per-1M rates. Enforced gateway rows are never affected.`;function W({isOpen:t,onOpenChange:r,targetCount:a,isPending:c,error:i,onSubmit:E,title:I="Set price",description:L=C}){const[j,p]=u.useState(""),[n,h]=u.useState(""),[b,N]=u.useState(""),[f,v]=u.useState("");u.useEffect(()=>{t&&(p(""),h(""),N(""),v(""))},[t]);const m=R(j),l=R(n),d=R(b),s=R(f),g=m===null||Number.isNaN(m)||l===null||Number.isNaN(l)||Number.isNaN(d??0)||Number.isNaN(s??0),S=()=>{g||m===null||l===null||E({input_price_per_million:m,output_price_per_million:l,...d!==null&&!Number.isNaN(d)?{cache_read_price_per_million:d}:{},...s!==null&&!Number.isNaN(s)?{cache_write_price_per_million:s}:{}})};return e.jsx(o,{isOpen:t,onOpenChange:r,children:t?e.jsx(o.Backdrop,{children:e.jsx(o.Container,{placement:"center",size:"lg",children:e.jsxs(o.Dialog,{children:[e.jsx(o.Header,{children:e.jsx(o.Heading,{children:I})}),e.jsxs(o.Body,{className:"flex flex-col gap-4",children:[e.jsx("p",{className:"text-sm text-[var(--otari-muted)]",children:L(a)}),e.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[e.jsx(_,{label:"Input $ / 1M",value:j,onChange:p,isRequired:!0,autoFocus:!0}),e.jsx(_,{label:"Output $ / 1M",value:n,onChange:h,isRequired:!0}),e.jsx(_,{label:"Cache read $ / 1M",value:b,onChange:N}),e.jsx(_,{label:"Cache write $ / 1M",value:f,onChange:v})]}),e.jsx(w,{tone:"info",children:"Leave a cache rate blank to bill those tokens at the input rate."}),e.jsx(M,{error:i})]}),e.jsxs(o.Footer,{children:[e.jsx(x,{variant:"ghost",isDisabled:c,onPress:()=>r(!1),children:"Cancel"}),e.jsx(x,{variant:"primary",isDisabled:g,isPending:c,onPress:S,children:"Set price"})]})]})})}):null})}const P=[25,50,100];function q({page:t,pageSize:r,total:a,rowsOnPage:c,onPageChange:i,onPageSizeChange:E,pageSizeOptions:I=P,isFetching:L=!1,hasNextFallback:j=!1}){const p=u.useId(),n=a!=null?Math.max(1,Math.ceil(a/r)):null,h=t===0,b=n!=null?t>=n-1:!j,N=c>0?t*r+1:0,f=t*r+c,v=a!=null?a===0?"0 of 0":`${N.toLocaleString()}–${f.toLocaleString()} of ${a.toLocaleString()}`:c>0?`${N.toLocaleString()}–${f.toLocaleString()}`:"0",[m,l]=u.useState(String(t+1));u.useEffect(()=>{l(String(t+1))},[t]);const d=()=>{const s=Number.parseInt(m,10);if(Number.isNaN(s)){l(String(t+1));return}const g=n??Number.MAX_SAFE_INTEGER,S=Math.min(Math.max(s,1),g);S-1!==t?i(S-1):l(String(t+1))};return e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("label",{htmlFor:p,className:"text-sm text-[var(--otari-muted)]",children:"Rows"}),e.jsx(D,{id:p,ariaLabel:"Rows per page",value:String(r),onChange:s=>E(Number.parseInt(s,10)),options:I.map(s=>({value:String(s),label:String(s)}))}),L?e.jsx(y,{size:"sm"}):null]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"text-sm text-[var(--otari-muted)] tabular-nums",children:v}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(x,{size:"sm",variant:"outline","aria-label":"First page",isDisabled:h,onPress:()=>i(0),children:"«"}),e.jsx(x,{size:"sm",variant:"outline","aria-label":"Previous page",isDisabled:h,onPress:()=>i(t-1),children:"‹"}),e.jsxs("span",{className:"inline-flex items-center gap-1 text-sm text-[var(--otari-muted)]",children:[e.jsx("input",{"aria-label":"Page number",inputMode:"numeric",value:m,onChange:s=>l(s.target.value.replace(/[^0-9]/g,"")),onKeyDown:s=>{s.key==="Enter"&&s.currentTarget.blur()},onBlur:d,className:"w-12 rounded-lg border border-[var(--otari-line)] bg-[var(--otari-bg)] px-2 py-1 text-center text-sm text-[var(--otari-ink)] tabular-nums focus:border-[var(--otari-brand)] focus:outline-none"}),n!=null?e.jsxs("span",{className:"tabular-nums",children:["/ ",n.toLocaleString()]}):null]}),e.jsx(x,{size:"sm",variant:"outline","aria-label":"Next page",isDisabled:b,onPress:()=>i(t+1),children:"›"}),e.jsx(x,{size:"sm",variant:"outline","aria-label":"Last page",isDisabled:n==null||b,onPress:()=>n!=null&&i(n-1),children:"»"})]})]})]})}export{P,W as S,q as T}; diff --git a/src/gateway/static/dashboard/assets/ToolsGuardrailsPage-5txNsDJk.js b/src/gateway/static/dashboard/assets/ToolsGuardrailsPage-BuyJANrn.js similarity index 99% rename from src/gateway/static/dashboard/assets/ToolsGuardrailsPage-5txNsDJk.js rename to src/gateway/static/dashboard/assets/ToolsGuardrailsPage-BuyJANrn.js index 39bfe287..fafe7120 100644 --- a/src/gateway/static/dashboard/assets/ToolsGuardrailsPage-5txNsDJk.js +++ b/src/gateway/static/dashboard/assets/ToolsGuardrailsPage-BuyJANrn.js @@ -1 +1 @@ -import{j as e}from"./tanstack-query-1t81HyiD.js";import{r as x}from"./react-dgEcD0HR.js";import{aa as L,ab as C,P,E,M as R,G as w,ac as D,F as M}from"./index-JlWCttWt.js";import{d as N,B as g}from"./heroui-BI50yK5B.js";function U(s,t){return{[s]:t}}const B=[{key:"web_search",label:"Web search",blurb:"Backend for otari_web_search tools (a SearXNG instance or a search adapter).",order:["web_search_url","web_search_engines","web_search_max_results","web_search_extract","web_search_purpose_hint"]},{key:"sandbox",label:"Code execution",blurb:"Backend for otari_code_execution tools (the sandbox that runs generated code).",order:["sandbox_url","sandbox_purpose_hint"]},{key:"guardrails",label:"Guardrails",blurb:"Default input-guardrails service used when a request does not pass its own guardrail URL.",order:["guardrails_url"]}];function $(){const[s,t]=x.useState(null),a=x.useRef(void 0),n=r=>{t(r),window.clearTimeout(a.current),a.current=window.setTimeout(()=>t(null),2500)};return x.useEffect(()=>()=>window.clearTimeout(a.current),[]),[s,n]}function G({message:s}){return s?e.jsxs("div",{role:"status","aria-live":"polite",className:"fixed right-4 bottom-4 z-50 flex items-center gap-2 rounded-lg border border-green-200 bg-green-50 px-4 py-3 text-sm font-medium text-green-700 shadow-lg",children:[e.jsx("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2","aria-hidden":!0,className:"h-5 w-5",children:e.jsx("path",{d:"M20 6 9 17l-5-5",strokeLinecap:"round",strokeLinejoin:"round"})}),s]}):null}const S="rounded-md border border-[var(--otari-line)] bg-[var(--otari-surface)] px-2 py-1 text-sm focus:border-[var(--otari-brand)] focus:outline-none disabled:opacity-50",b="grid gap-x-4 gap-y-1.5 py-4 sm:grid-cols-[minmax(0,1fr)_16rem_10rem] sm:items-start",_=`w-full sm:col-start-2 ${S}`,k="flex items-center gap-2 sm:col-start-3",f="flex flex-col gap-1 sm:col-span-2 sm:col-start-2";function j({message:s}){return s?e.jsx("span",{className:"break-words text-xs text-red-700",children:s}):null}function y({field:s,help:t}){return e.jsxs("div",{className:"min-w-0 sm:col-start-1",children:[e.jsx("code",{className:"text-sm font-medium text-[var(--otari-ink)]",children:s.key}),s.description?e.jsx("p",{className:"mt-1 text-sm text-[var(--otari-muted)]",children:s.description}):null,t?e.jsx("p",{className:"mt-1 text-xs text-[var(--otari-muted)]",children:t}):null]})}function z({field:s,onSave:t,saveError:a,disabled:n}){const r=typeof s.value=="string"?s.value:"",[l,i]=x.useState(r),[m,p]=x.useState(null),c=D();x.useEffect(()=>{i(r)},[r]);const o=l.trim()!==r,d=l.trim(),h=m!==null&&m===d;return e.jsxs("div",{className:b,children:[e.jsx(y,{field:s,help:"Leave blank and Save to fall back to the configured default."}),e.jsx("input",{type:"text",inputMode:"url","aria-label":s.key,value:l,disabled:n,placeholder:"unset",onChange:v=>{i(v.target.value),c.reset()},className:_}),e.jsxs("div",{className:k,children:[e.jsx(g,{size:"sm",variant:"primary","aria-label":`Save ${s.key}`,isDisabled:n||!o,onPress:()=>t(d===""?null:d),children:"Save"}),e.jsx(g,{size:"sm",variant:"outline","aria-label":`Test ${s.service}`,isDisabled:d===""||c.isPending,onPress:()=>{p(d),c.mutate({service:s.service,url:d})},children:c.isPending?"Testing…":"Test"})]}),e.jsxs("div",{className:f,children:[e.jsx("span",{role:"status","aria-live":"polite",className:"block break-words text-xs",children:c.isPending||!h?null:c.error?e.jsx("span",{className:"text-red-700",children:w(c.error)}):c.data?e.jsx("span",{className:c.data.ok?"font-medium text-green-700":"text-red-700",children:c.data.reason}):null}),e.jsx(j,{message:a})]})]})}function I({field:s,onSave:t,saveError:a,disabled:n}){const r=typeof s.value=="string"?s.value:"",[l,i]=x.useState(r);x.useEffect(()=>{i(r)},[r]);const m=l!==r;return e.jsxs("div",{className:b,children:[e.jsx(y,{field:s}),e.jsx("input",{type:"text","aria-label":s.key,value:l,disabled:n,placeholder:"default",onChange:p=>i(p.target.value),className:_}),e.jsx("div",{className:k,children:e.jsx(g,{size:"sm",variant:"primary","aria-label":`Save ${s.key}`,isDisabled:n||!m,onPress:()=>t(l.trim()===""?null:l.trim()),children:"Save"})}),a?e.jsx("div",{className:f,children:e.jsx(j,{message:a})}):null]})}function A({field:s,onSave:t,saveError:a,disabled:n}){const r=typeof s.value=="number"?String(s.value):"",[l,i]=x.useState(r);x.useEffect(()=>{i(r)},[r]);const m=l.trim(),p=Number(m),o=(m===""||Number.isInteger(p)&&p>=1)&&m!==r;return e.jsxs("div",{className:b,children:[e.jsx(y,{field:s,help:"Leave blank to use the backend default."}),e.jsx("input",{type:"number",min:"1",step:"1",inputMode:"numeric","aria-label":s.key,value:l,disabled:n,placeholder:"default",onChange:d=>i(d.target.value),className:`w-full text-right tabular-nums sm:col-start-2 sm:w-28 sm:justify-self-end ${S}`}),e.jsx("div",{className:k,children:e.jsx(g,{size:"sm",variant:"primary","aria-label":`Save ${s.key}`,isDisabled:n||!o,onPress:()=>t(m===""?null:p),children:"Save"})}),a?e.jsx("div",{className:f,children:e.jsx(j,{message:a})}):null]})}function F({field:s,onSave:t,saveError:a,disabled:n}){const r=s.value===!0?"on":s.value===!1?"off":"default";return e.jsxs("div",{className:b,children:[e.jsx(y,{field:s}),e.jsx("div",{className:"sm:col-start-2 sm:justify-self-start",children:e.jsx(M,{ariaLabel:s.key,value:r,onChange:l=>t(l==="default"?null:l==="on"),options:[{value:"default",label:"Default"},{value:"on",label:"On"},{value:"off",label:"Off"}],disabled:n})}),a?e.jsx("div",{className:f,children:e.jsx(j,{message:a})}):null]})}function O({field:s,onSave:t,saveError:a,disabled:n}){return s.type==="url"?e.jsx(z,{field:s,onSave:t,saveError:a,disabled:n}):s.type==="int"?e.jsx(A,{field:s,onSave:t,saveError:a,disabled:n}):s.type==="bool"?e.jsx(F,{field:s,onSave:t,saveError:a,disabled:n}):e.jsx(I,{field:s,onSave:t,saveError:a,disabled:n})}function V(){const s=L(),t=C(),[a,n]=$(),[r,l]=x.useState({}),i=s.data,m=!i||t.isPending,p=new Map(((i==null?void 0:i.fields)??[]).map(o=>[o.key,o])),c=(o,d)=>{l(h=>{const{[o.key]:v,...u}=h;return u}),t.mutate(U(o.key,d),{onSuccess:()=>n(`${o.key} saved`),onError:h=>l(v=>({...v,[o.key]:w(h)}))})};return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(P,{title:"Tools & Guardrails",description:"Configure the built-in tool and guardrail service endpoints without a restart. Changes apply immediately and persist. URLs are validated for shape (http/https) and can be tested for reachability before saving; the network-safety gates for these services live on the Settings page."}),e.jsx(E,{error:s.error}),s.isLoading?e.jsx(R,{}):null,B.map(o=>{const d=o.order.map(u=>p.get(u)).filter(u=>u!==void 0),h=((i==null?void 0:i.fields)??[]).filter(u=>u.service===o.key&&!o.order.includes(u.key)),v=[...d,...h];return v.length===0?null:e.jsxs("section",{className:"flex flex-col gap-2",children:[e.jsx("h2",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:o.label}),e.jsx("p",{className:"text-sm text-[var(--otari-muted)]",children:o.blurb}),e.jsx(N,{children:e.jsx(N.Content,{className:"flex flex-col divide-y divide-[var(--otari-line)] px-5 py-1",children:v.map(u=>e.jsx(O,{field:u,onSave:T=>c(u,T),saveError:r[u.key],disabled:m},u.key))})})]},o.key)}),e.jsx(G,{message:a})]})}export{V as ToolsGuardrailsPage}; +import{j as e}from"./tanstack-query-1t81HyiD.js";import{r as x}from"./react-dgEcD0HR.js";import{aa as L,ab as C,P,E,M as R,G as w,ac as D,F as M}from"./index-BP-wLuMr.js";import{d as N,B as g}from"./heroui-BI50yK5B.js";function U(s,t){return{[s]:t}}const B=[{key:"web_search",label:"Web search",blurb:"Backend for otari_web_search tools (a SearXNG instance or a search adapter).",order:["web_search_url","web_search_engines","web_search_max_results","web_search_extract","web_search_purpose_hint"]},{key:"sandbox",label:"Code execution",blurb:"Backend for otari_code_execution tools (the sandbox that runs generated code).",order:["sandbox_url","sandbox_purpose_hint"]},{key:"guardrails",label:"Guardrails",blurb:"Default input-guardrails service used when a request does not pass its own guardrail URL.",order:["guardrails_url"]}];function $(){const[s,t]=x.useState(null),a=x.useRef(void 0),n=r=>{t(r),window.clearTimeout(a.current),a.current=window.setTimeout(()=>t(null),2500)};return x.useEffect(()=>()=>window.clearTimeout(a.current),[]),[s,n]}function G({message:s}){return s?e.jsxs("div",{role:"status","aria-live":"polite",className:"fixed right-4 bottom-4 z-50 flex items-center gap-2 rounded-lg border border-green-200 bg-green-50 px-4 py-3 text-sm font-medium text-green-700 shadow-lg",children:[e.jsx("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2","aria-hidden":!0,className:"h-5 w-5",children:e.jsx("path",{d:"M20 6 9 17l-5-5",strokeLinecap:"round",strokeLinejoin:"round"})}),s]}):null}const S="rounded-md border border-[var(--otari-line)] bg-[var(--otari-surface)] px-2 py-1 text-sm focus:border-[var(--otari-brand)] focus:outline-none disabled:opacity-50",b="grid gap-x-4 gap-y-1.5 py-4 sm:grid-cols-[minmax(0,1fr)_16rem_10rem] sm:items-start",_=`w-full sm:col-start-2 ${S}`,k="flex items-center gap-2 sm:col-start-3",f="flex flex-col gap-1 sm:col-span-2 sm:col-start-2";function j({message:s}){return s?e.jsx("span",{className:"break-words text-xs text-red-700",children:s}):null}function y({field:s,help:t}){return e.jsxs("div",{className:"min-w-0 sm:col-start-1",children:[e.jsx("code",{className:"text-sm font-medium text-[var(--otari-ink)]",children:s.key}),s.description?e.jsx("p",{className:"mt-1 text-sm text-[var(--otari-muted)]",children:s.description}):null,t?e.jsx("p",{className:"mt-1 text-xs text-[var(--otari-muted)]",children:t}):null]})}function z({field:s,onSave:t,saveError:a,disabled:n}){const r=typeof s.value=="string"?s.value:"",[l,i]=x.useState(r),[m,p]=x.useState(null),c=D();x.useEffect(()=>{i(r)},[r]);const o=l.trim()!==r,d=l.trim(),h=m!==null&&m===d;return e.jsxs("div",{className:b,children:[e.jsx(y,{field:s,help:"Leave blank and Save to fall back to the configured default."}),e.jsx("input",{type:"text",inputMode:"url","aria-label":s.key,value:l,disabled:n,placeholder:"unset",onChange:v=>{i(v.target.value),c.reset()},className:_}),e.jsxs("div",{className:k,children:[e.jsx(g,{size:"sm",variant:"primary","aria-label":`Save ${s.key}`,isDisabled:n||!o,onPress:()=>t(d===""?null:d),children:"Save"}),e.jsx(g,{size:"sm",variant:"outline","aria-label":`Test ${s.service}`,isDisabled:d===""||c.isPending,onPress:()=>{p(d),c.mutate({service:s.service,url:d})},children:c.isPending?"Testing…":"Test"})]}),e.jsxs("div",{className:f,children:[e.jsx("span",{role:"status","aria-live":"polite",className:"block break-words text-xs",children:c.isPending||!h?null:c.error?e.jsx("span",{className:"text-red-700",children:w(c.error)}):c.data?e.jsx("span",{className:c.data.ok?"font-medium text-green-700":"text-red-700",children:c.data.reason}):null}),e.jsx(j,{message:a})]})]})}function I({field:s,onSave:t,saveError:a,disabled:n}){const r=typeof s.value=="string"?s.value:"",[l,i]=x.useState(r);x.useEffect(()=>{i(r)},[r]);const m=l!==r;return e.jsxs("div",{className:b,children:[e.jsx(y,{field:s}),e.jsx("input",{type:"text","aria-label":s.key,value:l,disabled:n,placeholder:"default",onChange:p=>i(p.target.value),className:_}),e.jsx("div",{className:k,children:e.jsx(g,{size:"sm",variant:"primary","aria-label":`Save ${s.key}`,isDisabled:n||!m,onPress:()=>t(l.trim()===""?null:l.trim()),children:"Save"})}),a?e.jsx("div",{className:f,children:e.jsx(j,{message:a})}):null]})}function A({field:s,onSave:t,saveError:a,disabled:n}){const r=typeof s.value=="number"?String(s.value):"",[l,i]=x.useState(r);x.useEffect(()=>{i(r)},[r]);const m=l.trim(),p=Number(m),o=(m===""||Number.isInteger(p)&&p>=1)&&m!==r;return e.jsxs("div",{className:b,children:[e.jsx(y,{field:s,help:"Leave blank to use the backend default."}),e.jsx("input",{type:"number",min:"1",step:"1",inputMode:"numeric","aria-label":s.key,value:l,disabled:n,placeholder:"default",onChange:d=>i(d.target.value),className:`w-full text-right tabular-nums sm:col-start-2 sm:w-28 sm:justify-self-end ${S}`}),e.jsx("div",{className:k,children:e.jsx(g,{size:"sm",variant:"primary","aria-label":`Save ${s.key}`,isDisabled:n||!o,onPress:()=>t(m===""?null:p),children:"Save"})}),a?e.jsx("div",{className:f,children:e.jsx(j,{message:a})}):null]})}function F({field:s,onSave:t,saveError:a,disabled:n}){const r=s.value===!0?"on":s.value===!1?"off":"default";return e.jsxs("div",{className:b,children:[e.jsx(y,{field:s}),e.jsx("div",{className:"sm:col-start-2 sm:justify-self-start",children:e.jsx(M,{ariaLabel:s.key,value:r,onChange:l=>t(l==="default"?null:l==="on"),options:[{value:"default",label:"Default"},{value:"on",label:"On"},{value:"off",label:"Off"}],disabled:n})}),a?e.jsx("div",{className:f,children:e.jsx(j,{message:a})}):null]})}function O({field:s,onSave:t,saveError:a,disabled:n}){return s.type==="url"?e.jsx(z,{field:s,onSave:t,saveError:a,disabled:n}):s.type==="int"?e.jsx(A,{field:s,onSave:t,saveError:a,disabled:n}):s.type==="bool"?e.jsx(F,{field:s,onSave:t,saveError:a,disabled:n}):e.jsx(I,{field:s,onSave:t,saveError:a,disabled:n})}function V(){const s=L(),t=C(),[a,n]=$(),[r,l]=x.useState({}),i=s.data,m=!i||t.isPending,p=new Map(((i==null?void 0:i.fields)??[]).map(o=>[o.key,o])),c=(o,d)=>{l(h=>{const{[o.key]:v,...u}=h;return u}),t.mutate(U(o.key,d),{onSuccess:()=>n(`${o.key} saved`),onError:h=>l(v=>({...v,[o.key]:w(h)}))})};return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(P,{title:"Tools & Guardrails",description:"Configure the built-in tool and guardrail service endpoints without a restart. Changes apply immediately and persist. URLs are validated for shape (http/https) and can be tested for reachability before saving; the network-safety gates for these services live on the Settings page."}),e.jsx(E,{error:s.error}),s.isLoading?e.jsx(R,{}):null,B.map(o=>{const d=o.order.map(u=>p.get(u)).filter(u=>u!==void 0),h=((i==null?void 0:i.fields)??[]).filter(u=>u.service===o.key&&!o.order.includes(u.key)),v=[...d,...h];return v.length===0?null:e.jsxs("section",{className:"flex flex-col gap-2",children:[e.jsx("h2",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:o.label}),e.jsx("p",{className:"text-sm text-[var(--otari-muted)]",children:o.blurb}),e.jsx(N,{children:e.jsx(N.Content,{className:"flex flex-col divide-y divide-[var(--otari-line)] px-5 py-1",children:v.map(u=>e.jsx(O,{field:u,onSave:T=>c(u,T),saveError:r[u.key],disabled:m},u.key))})})]},o.key)}),e.jsx(G,{message:a})]})}export{V as ToolsGuardrailsPage}; diff --git a/src/gateway/static/dashboard/assets/UsagePage-B19CFPzF.js b/src/gateway/static/dashboard/assets/UsagePage-D99w-NDh.js similarity index 98% rename from src/gateway/static/dashboard/assets/UsagePage-B19CFPzF.js rename to src/gateway/static/dashboard/assets/UsagePage-D99w-NDh.js index 8daed9c4..dab160f8 100644 --- a/src/gateway/static/dashboard/assets/UsagePage-B19CFPzF.js +++ b/src/gateway/static/dashboard/assets/UsagePage-D99w-NDh.js @@ -1 +1 @@ -import{j as e}from"./tanstack-query-1t81HyiD.js";import{i as Ue,r as i}from"./react-dgEcD0HR.js";import{u as Ae,a as Re,d as Y,O as T,P as Oe,E as ye,R as Ke,g as te,q as $e,S as q,T as U,Q as W,V as Be,ad as B,e as Ie,f as ze,b as He,c as xe}from"./index-JlWCttWt.js";import{i as se,b as Ge,U as ke,A as Qe,d as je,F as Ve,f as Ye}from"./FilterChips-DZjxf-ot.js";import{u as Ze,r as We,B as Je}from"./tableSelection-9hV37uhu.js";import{S as ae,B as Xe}from"./charts-DIsd9m--.js";import{C as et}from"./ConfirmDialog-DXR8OubG.js";import{D as we}from"./DataTable-Bmn_eYSV.js";import{T as tt,S as st}from"./TablePagination-CfsjgA8s.js";import{B as I,S as pe}from"./heroui-BI50yK5B.js";import"./recharts-C4kRDmvS.js";function Z(t){return t.toLocaleString()}function at(t){return t===null?"—":t<1e3?`${Math.round(t)} ms`:`${(t/1e3).toFixed(2)} s`}const fe=Ye(je,ke),ne=15,_e="__other__",ve="__unknown__";function Se({title:t,rows:r,totalCost:h,emptyLabel:n,onDrill:v,loading:m}){const[c,x]=i.useState(!1),j=c?r:r.slice(0,ne),A=r.length-j.length,N=o=>o.is_other?_e:o.key??ve,R=[{id:"name",header:t.replace("Spend by ",""),isRowHeader:!0,cell:o=>{const d=h>0?o.cost/h:0;return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("span",{className:"truncate text-[var(--otari-ink)]",children:o.is_other?`Other (${o.requests.toLocaleString()} req)`:o.key===null?"(unknown)":o.key}),e.jsx("span",{className:"h-1 w-full overflow-hidden rounded-full bg-[var(--otari-line)]",children:e.jsx("span",{className:"block h-full rounded-full bg-[var(--otari-brand)]",style:{width:`${Math.min(100,d*100)}%`}})})]})}},{id:"requests",header:"Requests",align:"end",cell:o=>e.jsx("span",{className:"text-[var(--otari-muted)]",children:Z(o.requests)})},{id:"spend",header:"Spend",align:"end",cell:o=>e.jsx("span",{className:"text-[var(--otari-ink)]",children:W(o.cost)})}];return e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx("h2",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:t}),e.jsx(we,{ariaLabel:t,columns:R,rows:j,getRowKey:N,isLoading:m,emptyContent:n,onRowAction:o=>{o!==_e&&o!==ve&&v(o)}}),!m&&A>0?e.jsxs(I,{size:"sm",variant:"ghost",onPress:()=>x(!0),children:["Show all ",r.length]}):null,!m&&c&&r.length>ne?e.jsxs(I,{size:"sm",variant:"ghost",onPress:()=>x(!1),children:["Show top ",ne]}):null]})}const nt=[{key:"cost",label:"Cost"},{key:"tokens",label:"Tokens"},{key:"requests",label:"Requests"}];function ot(t,r){return r==="cost"?t.cost:r==="tokens"?t.tokens:t.requests}function be(t,r){return r==="cost"?W(t):r==="tokens"?B(t):Z(t)}function rt(t,r){const h=new Date(t);return Number.isNaN(h.getTime())?t:r==="hour"?h.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit",timeZone:"UTC"}):h.toLocaleDateString(void 0,{month:"short",day:"numeric",timeZone:"UTC"})}function lt(t,r,h){const n=t.map(m=>({label:rt(m.bucket_start,h),value:ot(m,r)})),v=n.length?Math.max(...n.map(m=>m.value)):0;return{points:n,peak:v,count:t.length}}const it=50;function ct(t){const r=new Date(t).getTime();if(Number.isNaN(r))return t;const h=Math.max(0,Math.round((Date.now()-r)/1e3));if(h<60)return`${h}s ago`;const n=Math.round(h/60);if(n<60)return`${n}m ago`;const v=Math.round(n/60);return v<24?`${v}h ago`:`${Math.round(v/24)}d ago`}function dt({status:t}){return e.jsx("span",{className:`inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium ${t==="error"?"border-red-200 bg-red-50 text-red-700":"border-[var(--otari-line)] bg-[var(--otari-brand-tint)] text-[var(--otari-brand-dark)]"}`,children:t})}const ut=[{id:"time",header:"Time",isRowHeader:!0,cell:t=>e.jsx("span",{className:"text-[var(--otari-muted)]",title:new Date(t.timestamp).toLocaleString(),children:ct(t.timestamp)})},{id:"model",header:"Model",cell:t=>e.jsx("span",{className:"text-[var(--otari-ink)]",children:t.model})},{id:"user",header:"User",cell:t=>e.jsx("span",{className:"text-[var(--otari-muted)]",children:t.user_id??"—"})},{id:"tokens",header:"Tokens",align:"end",cell:t=>t.total_tokens===null?"—":t.total_tokens.toLocaleString()},{id:"cost",header:"Cost",align:"end",cell:t=>t.cost===null?"—":W(t.cost)},{id:"status",header:"Status",cell:t=>e.jsx(dt,{status:t.status})}],mt=t=>t.id;function ht({filters:t,anyFilter:r}){var $,H;const[h,n]=i.useState(0),[v,m]=i.useState(it),c=Ze(),x=Ie(),j=ze(),[A,N]=i.useState(!1),[R,o]=i.useState(!1),d=JSON.stringify(t),L=i.useRef(d);i.useEffect(()=>{L.current!==d&&(L.current=d,n(0),c.clear())},[d,c]);const p=He(t,h,v),C=xe(t),g=p.data??[],P=C.isSuccess&&!C.isPlaceholderData?(($=C.data)==null?void 0:$.total)??0:null,O=g.filter(_=>!_.counts_toward_budget).map(_=>_.id),f=g.filter(_=>_.counts_toward_budget).map(_=>_.id),S=We(c.selectedKeys,O),b=S.length,k=c.allMatching||b>0,D=i.useMemo(()=>({...t,counts_toward_budget:!1}),[t]),y=xe(D,k),E=y.isSuccess?((H=y.data)==null?void 0:H.total)??null:null,K=O.length>0&&b===O.length&&E!=null&&E>b,F=c.allMatching?E??b:b,l=()=>c.allMatching?{by_filter:!0,model:t.model,user_id:t.user_id,api_key_id:t.api_key_id,start_date:t.start_date,end_date:t.end_date,priced:t.priced}:{ids:S},a=()=>x.mutate(l(),{onSuccess:()=>{N(!1),c.clear()}}),u=_=>j.mutate({...l(),..._},{onSuccess:()=>{o(!1),c.clear()}});return e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsx("h2",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:"Individual requests"}),e.jsx(ye,{error:p.error??C.error}),k?e.jsxs(Je,{selectedCount:F,allMatching:c.allMatching,matchingTotal:E,canSelectAllMatching:K,onSelectAllMatching:c.enableAllMatching,onClear:c.clear,children:[e.jsx(I,{size:"sm",variant:"primary",onPress:()=>o(!0),children:"Set price"}),e.jsx(I,{size:"sm",variant:"danger",onPress:()=>N(!0),children:"Delete"})]}):null,e.jsx(we,{ariaLabel:"Individual requests",columns:ut,rows:g,getRowKey:mt,isLoading:p.isLoading,emptyContent:r?"No requests match these filters.":"No requests recorded yet.",selectionMode:"multiple",selectedKeys:c.selectedKeys,onSelectionChange:c.onSelectionChange,disabledKeys:f}),e.jsx(tt,{page:h,pageSize:v,total:P,rowsOnPage:g.length,onPageChange:n,onPageSizeChange:_=>{m(_),n(0)},isFetching:p.isFetching,hasNextFallback:g.length===v}),e.jsx(et,{isOpen:A,onOpenChange:N,heading:"Delete usage rows",body:`Delete ${F.toLocaleString()} imported ${F===1?"row":"rows"}? Only imported rows are removed, and this cannot be undone.`,confirmLabel:"Delete",isPending:x.isPending,error:x.error,onConfirm:a}),e.jsx(st,{isOpen:R,onOpenChange:o,targetCount:F,isPending:j.isPending,error:j.error,onSubmit:u})]})}function wt(){var ue,me,he,ge;const t=Ue(),r=Ae(),h=Re(),[n,v]=i.useState(fe),[m,c]=i.useState(()=>se(fe.seconds??0)),[x,j]=i.useState(!1),[A,N]=i.useState(),[R,o]=i.useState(),[d,L]=i.useState(""),[p,C]=i.useState(""),[g,z]=i.useState(""),[P,O]=i.useState("cost"),f=x?A:m,S=x?R:void 0,b=x?f?Ge(f,S):"day":n.bucket,k=i.useMemo(()=>({start_date:f,end_date:S,model:d.trim()||void 0,user_id:p||void 0,api_key_id:g||void 0}),[f,S,d,p,g]),D=i.useMemo(()=>{if(x){if(!f||!S)return null;const s=new Date(S).getTime()-new Date(f).getTime();return s>0?{...k,start_date:new Date(new Date(f).getTime()-s).toISOString(),end_date:f}:null}return!m||n.seconds===null?null:{...k,start_date:new Date(new Date(m).getTime()-n.seconds*1e3).toISOString(),end_date:m}},[x,f,S,k,n.seconds,m]),y=Y(k,b),E=Y(D??k,b,D!==null),oe=i.useMemo(()=>({start_date:m,model:d.trim()||void 0,user_id:p||void 0,api_key_id:g||void 0}),[m,d,p,g]),K=Y(oe,n.bucket),F=(((ue=K.data)==null?void 0:ue.series)??[]).map(s=>({bucketStart:s.bucket_start,requests:s.requests})),l=y.data,a=l==null?void 0:l.totals,u=D!==null?(me=E.data)==null?void 0:me.totals:void 0,$=a?T(a.cost,u==null?void 0:u.cost):null,H=i.useMemo(()=>({...k,model:void 0}),[k]),_=Y(H,b),J=((ge=(he=_.data)==null?void 0:he.by_model)==null?void 0:ge.filter(s=>!s.is_other&&s.key!==null).map(s=>s.key))??[],re=(r.data??[]).map(s=>({value:s.user_id,label:s.alias?`${s.alias} (${s.user_id})`:s.user_id})),le=(h.data??[]).map(s=>({value:s.id,label:s.key_name??`${s.id.slice(0,8)}…`})),Ne=(d&&!J.includes(d)?[d,...J]:J).map(s=>({value:s,label:s})),Ce=x||n.key!==ke,G=!!(d.trim()||p||g||Ce),ie=(s,w)=>{var Q;return((Q=s.find(V=>V.value===w))==null?void 0:Q.label)??w},Pe=()=>{L(""),C(""),z("")},Ee=[...p?[{key:"user",label:"User",value:ie(re,p),onClear:()=>C("")}]:[],...d.trim()?[{key:"model",label:"Model",value:d.trim(),onClear:()=>L("")}]:[],...g?[{key:"key",label:"API key",value:ie(le,g),onClear:()=>z("")}]:[]],qe=!!(l&&a&&a.request_count===0&&!G),Le=(l==null?void 0:l.start_date)??f,De=(l==null?void 0:l.end_date)??S,ce=s=>{j(!1),v(s),c(se(s.seconds??0)),N(void 0),o(void 0)},Fe=(s,w)=>{j(!0),N(s),o(w)},Me=()=>{x||c(se(n.seconds??0)),y.refetch(),K.refetch(),_.refetch(),D!==null&&E.refetch()},de=s=>{const w=new URLSearchParams;f&&w.set("start_date",f),S&&w.set("end_date",S);for(const[Q,V]of Object.entries(s))V&&w.set(Q,V);t(`/activity?${w.toString()}`)},Te=a&&a.request_count>0?a.error_count/a.request_count:0,M=(l==null?void 0:l.series)??[],X=M.length>1,ee=lt(M,P,b);return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(Oe,{title:"Usage & analytics",description:"Aggregate spend, tokens, and request volume over time. Click a model or user to drill into the request log."}),e.jsx(ye,{error:y.error}),e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsx(Qe,{presets:je,extentKey:n.key,onPreset:ce,onSelectRange:Fe,onSelectFull:()=>ce(n),series:F,bucket:n.bucket,windowStart:Le,windowEnd:De,loading:K.isLoading,ariaLabel:"Usage request volume over the selected window",action:e.jsx(Ke,{onRefresh:Me,isFetching:y.isFetching,updatedAt:y.dataUpdatedAt})}),e.jsxs(Ve,{chips:Ee,onClearAll:Pe,children:[e.jsx(te,{label:"User",value:p,onChange:C,options:re,placeholder:"All users"}),e.jsx(te,{label:"Model",value:d,onChange:L,options:Ne,placeholder:"All models"}),e.jsx(te,{label:"API key",value:g,onChange:z,options:le,placeholder:"All keys"})]})]}),qe?e.jsx($e,{title:"No usage yet",description:"Once the gateway serves requests, spend and volume appear here."}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4 sm:grid-cols-3 xl:grid-cols-4",children:[e.jsx(q,{label:"Tracked cost",value:a?W(a.cost):"—",hint:a?e.jsxs("span",{className:"text-[var(--otari-muted)]",children:[e.jsx(U,{fraction:$}),a.unpriced_requests?`${$!==null?" · ":""}${Z(a.unpriced_requests)} unpriced`:null]}):null,chart:X?e.jsx(ae,{values:M.map(s=>s.cost),ariaLabel:"Spend trend over the selected window"}):void 0}),e.jsx(q,{label:"Requests",value:a?Z(a.request_count):"—",hint:a?e.jsxs("span",{className:"text-[var(--otari-muted)]",children:[Be(Te)," errors",u?e.jsxs(e.Fragment,{children:[" · ",e.jsx(U,{fraction:T(a.request_count,u.request_count)})]}):null]}):null,chart:X?e.jsx(ae,{values:M.map(s=>s.requests),ariaLabel:"Request volume trend over the selected window"}):void 0}),e.jsx(q,{label:"Tokens",value:a?B(a.total_tokens):"—",hint:a?e.jsx(U,{fraction:T(a.total_tokens,u==null?void 0:u.total_tokens)}):null,chart:X?e.jsx(ae,{values:M.map(s=>s.tokens),ariaLabel:"Token usage trend over the selected window"}):void 0}),e.jsx(q,{label:"Cache read",value:a?B(a.cache_read_tokens):"—",hint:a?e.jsx(U,{fraction:T(a.cache_read_tokens,u==null?void 0:u.cache_read_tokens)}):null}),e.jsx(q,{label:"Cache write",value:a?B(a.cache_write_tokens):"—",hint:a?e.jsx(U,{fraction:T(a.cache_write_tokens,u==null?void 0:u.cache_write_tokens)}):null}),e.jsx(q,{label:"1h cache write",value:a?B(a.cache_write_1h_tokens??0):"—",hint:a?e.jsx(U,{fraction:T(a.cache_write_1h_tokens??0,(u==null?void 0:u.cache_write_1h_tokens)??0)}):null}),e.jsx(q,{label:"Avg latency",value:a?at(a.avg_latency_ms):"—"})]}),e.jsxs("div",{className:"grid gap-6 lg:grid-cols-2",children:[e.jsx(Se,{title:"Spend by model",rows:(l==null?void 0:l.by_model)??[],totalCost:(a==null?void 0:a.cost)??0,emptyLabel:G?"No usage matches these filters.":"No usage recorded yet.",onDrill:s=>de({model:s,user_id:p||void 0,api_key_id:g||void 0}),loading:y.isLoading}),e.jsx(Se,{title:"Spend by user",rows:(l==null?void 0:l.by_user)??[],totalCost:(a==null?void 0:a.cost)??0,emptyLabel:G?"No usage matches these filters.":"No usage recorded yet.",onDrill:s=>de({user_id:s,model:d.trim()||void 0,api_key_id:g||void 0}),loading:y.isLoading})]}),e.jsx(ht,{filters:k,anyFilter:G}),e.jsxs("div",{className:"flex flex-col gap-3 rounded-xl border border-[var(--otari-line)] bg-[var(--otari-surface)] p-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("h2",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:"Over time"}),e.jsxs("div",{className:"inline-flex gap-1.5",children:[nt.map(s=>e.jsx(I,{size:"sm",variant:P===s.key?"primary":"outline",onPress:()=>O(s.key),children:s.label},s.key)),y.isFetching?e.jsx(pe,{size:"sm"}):null]})]}),y.isLoading?e.jsx("div",{className:"flex h-48 items-center justify-center",children:e.jsx(pe,{size:"sm"})}):M.length===0?e.jsx("div",{className:"flex h-48 items-center justify-center text-sm text-[var(--otari-muted)]",children:"No data in this range."}):e.jsxs("figure",{className:"flex flex-col gap-2",children:[e.jsx(Xe,{data:ee.points,formatValue:s=>be(s,P),ariaLabel:`${P} per ${b}`}),e.jsxs("figcaption",{className:"text-xs text-[var(--otari-muted)]",children:[be(ee.peak,P)," peak · ",ee.count," ",b==="hour"?"hours":"days"," (times in UTC)"]})]})]})]})]})}export{wt as UsagePage}; +import{j as e}from"./tanstack-query-1t81HyiD.js";import{i as Ue,r as i}from"./react-dgEcD0HR.js";import{u as Ae,a as Re,d as Y,O as T,P as Oe,E as ye,R as Ke,g as te,q as $e,S as q,T as U,Q as W,V as Be,ad as B,e as Ie,f as ze,b as He,c as xe}from"./index-BP-wLuMr.js";import{i as se,b as Ge,U as ke,A as Qe,d as je,F as Ve,f as Ye}from"./FilterChips-DZjxf-ot.js";import{u as Ze,r as We,B as Je}from"./tableSelection-9hV37uhu.js";import{S as ae,B as Xe}from"./charts-DIsd9m--.js";import{C as et}from"./ConfirmDialog-BFS2k4X_.js";import{D as we}from"./DataTable-Bmn_eYSV.js";import{T as tt,S as st}from"./TablePagination-BtDO5gaH.js";import{B as I,S as pe}from"./heroui-BI50yK5B.js";import"./recharts-C4kRDmvS.js";function Z(t){return t.toLocaleString()}function at(t){return t===null?"—":t<1e3?`${Math.round(t)} ms`:`${(t/1e3).toFixed(2)} s`}const fe=Ye(je,ke),ne=15,_e="__other__",ve="__unknown__";function Se({title:t,rows:r,totalCost:h,emptyLabel:n,onDrill:v,loading:m}){const[c,x]=i.useState(!1),j=c?r:r.slice(0,ne),A=r.length-j.length,N=o=>o.is_other?_e:o.key??ve,R=[{id:"name",header:t.replace("Spend by ",""),isRowHeader:!0,cell:o=>{const d=h>0?o.cost/h:0;return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("span",{className:"truncate text-[var(--otari-ink)]",children:o.is_other?`Other (${o.requests.toLocaleString()} req)`:o.key===null?"(unknown)":o.key}),e.jsx("span",{className:"h-1 w-full overflow-hidden rounded-full bg-[var(--otari-line)]",children:e.jsx("span",{className:"block h-full rounded-full bg-[var(--otari-brand)]",style:{width:`${Math.min(100,d*100)}%`}})})]})}},{id:"requests",header:"Requests",align:"end",cell:o=>e.jsx("span",{className:"text-[var(--otari-muted)]",children:Z(o.requests)})},{id:"spend",header:"Spend",align:"end",cell:o=>e.jsx("span",{className:"text-[var(--otari-ink)]",children:W(o.cost)})}];return e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx("h2",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:t}),e.jsx(we,{ariaLabel:t,columns:R,rows:j,getRowKey:N,isLoading:m,emptyContent:n,onRowAction:o=>{o!==_e&&o!==ve&&v(o)}}),!m&&A>0?e.jsxs(I,{size:"sm",variant:"ghost",onPress:()=>x(!0),children:["Show all ",r.length]}):null,!m&&c&&r.length>ne?e.jsxs(I,{size:"sm",variant:"ghost",onPress:()=>x(!1),children:["Show top ",ne]}):null]})}const nt=[{key:"cost",label:"Cost"},{key:"tokens",label:"Tokens"},{key:"requests",label:"Requests"}];function ot(t,r){return r==="cost"?t.cost:r==="tokens"?t.tokens:t.requests}function be(t,r){return r==="cost"?W(t):r==="tokens"?B(t):Z(t)}function rt(t,r){const h=new Date(t);return Number.isNaN(h.getTime())?t:r==="hour"?h.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit",timeZone:"UTC"}):h.toLocaleDateString(void 0,{month:"short",day:"numeric",timeZone:"UTC"})}function lt(t,r,h){const n=t.map(m=>({label:rt(m.bucket_start,h),value:ot(m,r)})),v=n.length?Math.max(...n.map(m=>m.value)):0;return{points:n,peak:v,count:t.length}}const it=50;function ct(t){const r=new Date(t).getTime();if(Number.isNaN(r))return t;const h=Math.max(0,Math.round((Date.now()-r)/1e3));if(h<60)return`${h}s ago`;const n=Math.round(h/60);if(n<60)return`${n}m ago`;const v=Math.round(n/60);return v<24?`${v}h ago`:`${Math.round(v/24)}d ago`}function dt({status:t}){return e.jsx("span",{className:`inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium ${t==="error"?"border-red-200 bg-red-50 text-red-700":"border-[var(--otari-line)] bg-[var(--otari-brand-tint)] text-[var(--otari-brand-dark)]"}`,children:t})}const ut=[{id:"time",header:"Time",isRowHeader:!0,cell:t=>e.jsx("span",{className:"text-[var(--otari-muted)]",title:new Date(t.timestamp).toLocaleString(),children:ct(t.timestamp)})},{id:"model",header:"Model",cell:t=>e.jsx("span",{className:"text-[var(--otari-ink)]",children:t.model})},{id:"user",header:"User",cell:t=>e.jsx("span",{className:"text-[var(--otari-muted)]",children:t.user_id??"—"})},{id:"tokens",header:"Tokens",align:"end",cell:t=>t.total_tokens===null?"—":t.total_tokens.toLocaleString()},{id:"cost",header:"Cost",align:"end",cell:t=>t.cost===null?"—":W(t.cost)},{id:"status",header:"Status",cell:t=>e.jsx(dt,{status:t.status})}],mt=t=>t.id;function ht({filters:t,anyFilter:r}){var $,H;const[h,n]=i.useState(0),[v,m]=i.useState(it),c=Ze(),x=Ie(),j=ze(),[A,N]=i.useState(!1),[R,o]=i.useState(!1),d=JSON.stringify(t),L=i.useRef(d);i.useEffect(()=>{L.current!==d&&(L.current=d,n(0),c.clear())},[d,c]);const p=He(t,h,v),C=xe(t),g=p.data??[],P=C.isSuccess&&!C.isPlaceholderData?(($=C.data)==null?void 0:$.total)??0:null,O=g.filter(_=>!_.counts_toward_budget).map(_=>_.id),f=g.filter(_=>_.counts_toward_budget).map(_=>_.id),S=We(c.selectedKeys,O),b=S.length,k=c.allMatching||b>0,D=i.useMemo(()=>({...t,counts_toward_budget:!1}),[t]),y=xe(D,k),E=y.isSuccess?((H=y.data)==null?void 0:H.total)??null:null,K=O.length>0&&b===O.length&&E!=null&&E>b,F=c.allMatching?E??b:b,l=()=>c.allMatching?{by_filter:!0,model:t.model,user_id:t.user_id,api_key_id:t.api_key_id,start_date:t.start_date,end_date:t.end_date,priced:t.priced}:{ids:S},a=()=>x.mutate(l(),{onSuccess:()=>{N(!1),c.clear()}}),u=_=>j.mutate({...l(),..._},{onSuccess:()=>{o(!1),c.clear()}});return e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsx("h2",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:"Individual requests"}),e.jsx(ye,{error:p.error??C.error}),k?e.jsxs(Je,{selectedCount:F,allMatching:c.allMatching,matchingTotal:E,canSelectAllMatching:K,onSelectAllMatching:c.enableAllMatching,onClear:c.clear,children:[e.jsx(I,{size:"sm",variant:"primary",onPress:()=>o(!0),children:"Set price"}),e.jsx(I,{size:"sm",variant:"danger",onPress:()=>N(!0),children:"Delete"})]}):null,e.jsx(we,{ariaLabel:"Individual requests",columns:ut,rows:g,getRowKey:mt,isLoading:p.isLoading,emptyContent:r?"No requests match these filters.":"No requests recorded yet.",selectionMode:"multiple",selectedKeys:c.selectedKeys,onSelectionChange:c.onSelectionChange,disabledKeys:f}),e.jsx(tt,{page:h,pageSize:v,total:P,rowsOnPage:g.length,onPageChange:n,onPageSizeChange:_=>{m(_),n(0)},isFetching:p.isFetching,hasNextFallback:g.length===v}),e.jsx(et,{isOpen:A,onOpenChange:N,heading:"Delete usage rows",body:`Delete ${F.toLocaleString()} imported ${F===1?"row":"rows"}? Only imported rows are removed, and this cannot be undone.`,confirmLabel:"Delete",isPending:x.isPending,error:x.error,onConfirm:a}),e.jsx(st,{isOpen:R,onOpenChange:o,targetCount:F,isPending:j.isPending,error:j.error,onSubmit:u})]})}function wt(){var ue,me,he,ge;const t=Ue(),r=Ae(),h=Re(),[n,v]=i.useState(fe),[m,c]=i.useState(()=>se(fe.seconds??0)),[x,j]=i.useState(!1),[A,N]=i.useState(),[R,o]=i.useState(),[d,L]=i.useState(""),[p,C]=i.useState(""),[g,z]=i.useState(""),[P,O]=i.useState("cost"),f=x?A:m,S=x?R:void 0,b=x?f?Ge(f,S):"day":n.bucket,k=i.useMemo(()=>({start_date:f,end_date:S,model:d.trim()||void 0,user_id:p||void 0,api_key_id:g||void 0}),[f,S,d,p,g]),D=i.useMemo(()=>{if(x){if(!f||!S)return null;const s=new Date(S).getTime()-new Date(f).getTime();return s>0?{...k,start_date:new Date(new Date(f).getTime()-s).toISOString(),end_date:f}:null}return!m||n.seconds===null?null:{...k,start_date:new Date(new Date(m).getTime()-n.seconds*1e3).toISOString(),end_date:m}},[x,f,S,k,n.seconds,m]),y=Y(k,b),E=Y(D??k,b,D!==null),oe=i.useMemo(()=>({start_date:m,model:d.trim()||void 0,user_id:p||void 0,api_key_id:g||void 0}),[m,d,p,g]),K=Y(oe,n.bucket),F=(((ue=K.data)==null?void 0:ue.series)??[]).map(s=>({bucketStart:s.bucket_start,requests:s.requests})),l=y.data,a=l==null?void 0:l.totals,u=D!==null?(me=E.data)==null?void 0:me.totals:void 0,$=a?T(a.cost,u==null?void 0:u.cost):null,H=i.useMemo(()=>({...k,model:void 0}),[k]),_=Y(H,b),J=((ge=(he=_.data)==null?void 0:he.by_model)==null?void 0:ge.filter(s=>!s.is_other&&s.key!==null).map(s=>s.key))??[],re=(r.data??[]).map(s=>({value:s.user_id,label:s.alias?`${s.alias} (${s.user_id})`:s.user_id})),le=(h.data??[]).map(s=>({value:s.id,label:s.key_name??`${s.id.slice(0,8)}…`})),Ne=(d&&!J.includes(d)?[d,...J]:J).map(s=>({value:s,label:s})),Ce=x||n.key!==ke,G=!!(d.trim()||p||g||Ce),ie=(s,w)=>{var Q;return((Q=s.find(V=>V.value===w))==null?void 0:Q.label)??w},Pe=()=>{L(""),C(""),z("")},Ee=[...p?[{key:"user",label:"User",value:ie(re,p),onClear:()=>C("")}]:[],...d.trim()?[{key:"model",label:"Model",value:d.trim(),onClear:()=>L("")}]:[],...g?[{key:"key",label:"API key",value:ie(le,g),onClear:()=>z("")}]:[]],qe=!!(l&&a&&a.request_count===0&&!G),Le=(l==null?void 0:l.start_date)??f,De=(l==null?void 0:l.end_date)??S,ce=s=>{j(!1),v(s),c(se(s.seconds??0)),N(void 0),o(void 0)},Fe=(s,w)=>{j(!0),N(s),o(w)},Me=()=>{x||c(se(n.seconds??0)),y.refetch(),K.refetch(),_.refetch(),D!==null&&E.refetch()},de=s=>{const w=new URLSearchParams;f&&w.set("start_date",f),S&&w.set("end_date",S);for(const[Q,V]of Object.entries(s))V&&w.set(Q,V);t(`/activity?${w.toString()}`)},Te=a&&a.request_count>0?a.error_count/a.request_count:0,M=(l==null?void 0:l.series)??[],X=M.length>1,ee=lt(M,P,b);return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(Oe,{title:"Usage & analytics",description:"Aggregate spend, tokens, and request volume over time. Click a model or user to drill into the request log."}),e.jsx(ye,{error:y.error}),e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsx(Qe,{presets:je,extentKey:n.key,onPreset:ce,onSelectRange:Fe,onSelectFull:()=>ce(n),series:F,bucket:n.bucket,windowStart:Le,windowEnd:De,loading:K.isLoading,ariaLabel:"Usage request volume over the selected window",action:e.jsx(Ke,{onRefresh:Me,isFetching:y.isFetching,updatedAt:y.dataUpdatedAt})}),e.jsxs(Ve,{chips:Ee,onClearAll:Pe,children:[e.jsx(te,{label:"User",value:p,onChange:C,options:re,placeholder:"All users"}),e.jsx(te,{label:"Model",value:d,onChange:L,options:Ne,placeholder:"All models"}),e.jsx(te,{label:"API key",value:g,onChange:z,options:le,placeholder:"All keys"})]})]}),qe?e.jsx($e,{title:"No usage yet",description:"Once the gateway serves requests, spend and volume appear here."}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4 sm:grid-cols-3 xl:grid-cols-4",children:[e.jsx(q,{label:"Tracked cost",value:a?W(a.cost):"—",hint:a?e.jsxs("span",{className:"text-[var(--otari-muted)]",children:[e.jsx(U,{fraction:$}),a.unpriced_requests?`${$!==null?" · ":""}${Z(a.unpriced_requests)} unpriced`:null]}):null,chart:X?e.jsx(ae,{values:M.map(s=>s.cost),ariaLabel:"Spend trend over the selected window"}):void 0}),e.jsx(q,{label:"Requests",value:a?Z(a.request_count):"—",hint:a?e.jsxs("span",{className:"text-[var(--otari-muted)]",children:[Be(Te)," errors",u?e.jsxs(e.Fragment,{children:[" · ",e.jsx(U,{fraction:T(a.request_count,u.request_count)})]}):null]}):null,chart:X?e.jsx(ae,{values:M.map(s=>s.requests),ariaLabel:"Request volume trend over the selected window"}):void 0}),e.jsx(q,{label:"Tokens",value:a?B(a.total_tokens):"—",hint:a?e.jsx(U,{fraction:T(a.total_tokens,u==null?void 0:u.total_tokens)}):null,chart:X?e.jsx(ae,{values:M.map(s=>s.tokens),ariaLabel:"Token usage trend over the selected window"}):void 0}),e.jsx(q,{label:"Cache read",value:a?B(a.cache_read_tokens):"—",hint:a?e.jsx(U,{fraction:T(a.cache_read_tokens,u==null?void 0:u.cache_read_tokens)}):null}),e.jsx(q,{label:"Cache write",value:a?B(a.cache_write_tokens):"—",hint:a?e.jsx(U,{fraction:T(a.cache_write_tokens,u==null?void 0:u.cache_write_tokens)}):null}),e.jsx(q,{label:"1h cache write",value:a?B(a.cache_write_1h_tokens??0):"—",hint:a?e.jsx(U,{fraction:T(a.cache_write_1h_tokens??0,(u==null?void 0:u.cache_write_1h_tokens)??0)}):null}),e.jsx(q,{label:"Avg latency",value:a?at(a.avg_latency_ms):"—"})]}),e.jsxs("div",{className:"grid gap-6 lg:grid-cols-2",children:[e.jsx(Se,{title:"Spend by model",rows:(l==null?void 0:l.by_model)??[],totalCost:(a==null?void 0:a.cost)??0,emptyLabel:G?"No usage matches these filters.":"No usage recorded yet.",onDrill:s=>de({model:s,user_id:p||void 0,api_key_id:g||void 0}),loading:y.isLoading}),e.jsx(Se,{title:"Spend by user",rows:(l==null?void 0:l.by_user)??[],totalCost:(a==null?void 0:a.cost)??0,emptyLabel:G?"No usage matches these filters.":"No usage recorded yet.",onDrill:s=>de({user_id:s,model:d.trim()||void 0,api_key_id:g||void 0}),loading:y.isLoading})]}),e.jsx(ht,{filters:k,anyFilter:G}),e.jsxs("div",{className:"flex flex-col gap-3 rounded-xl border border-[var(--otari-line)] bg-[var(--otari-surface)] p-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("h2",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:"Over time"}),e.jsxs("div",{className:"inline-flex gap-1.5",children:[nt.map(s=>e.jsx(I,{size:"sm",variant:P===s.key?"primary":"outline",onPress:()=>O(s.key),children:s.label},s.key)),y.isFetching?e.jsx(pe,{size:"sm"}):null]})]}),y.isLoading?e.jsx("div",{className:"flex h-48 items-center justify-center",children:e.jsx(pe,{size:"sm"})}):M.length===0?e.jsx("div",{className:"flex h-48 items-center justify-center text-sm text-[var(--otari-muted)]",children:"No data in this range."}):e.jsxs("figure",{className:"flex flex-col gap-2",children:[e.jsx(Xe,{data:ee.points,formatValue:s=>be(s,P),ariaLabel:`${P} per ${b}`}),e.jsxs("figcaption",{className:"text-xs text-[var(--otari-muted)]",children:[be(ee.peak,P)," peak · ",ee.count," ",b==="hour"?"hours":"days"," (times in UTC)"]})]})]})]})]})}export{wt as UsagePage}; diff --git a/src/gateway/static/dashboard/assets/UsersPage-8qOL-FQs.js b/src/gateway/static/dashboard/assets/UsersPage-m0ebv2w3.js similarity index 98% rename from src/gateway/static/dashboard/assets/UsersPage-8qOL-FQs.js rename to src/gateway/static/dashboard/assets/UsersPage-m0ebv2w3.js index fee9148a..32723fcd 100644 --- a/src/gateway/static/dashboard/assets/UsersPage-8qOL-FQs.js +++ b/src/gateway/static/dashboard/assets/UsersPage-m0ebv2w3.js @@ -1 +1 @@ -import{j as e}from"./tanstack-query-1t81HyiD.js";import{r}from"./react-dgEcD0HR.js";import{u as Q,l as M,p as K,ae as X,P as Y,E as A,q as Z,af as ee,F as se}from"./index-JlWCttWt.js";import{u as te,r as ae,B as ne}from"./tableSelection-9hV37uhu.js";import{C as re}from"./ConfirmDialog-DXR8OubG.js";import{D as le}from"./DataTable-Bmn_eYSV.js";import{F as B}from"./Field-Dwp6u3t8.js";import{a as ie,M as R}from"./ModelScopeControl-Bcam0tnJ.js";import{f as I,B as d,d as S,A as f}from"./heroui-BI50yK5B.js";const de=new Intl.NumberFormat(void 0,{style:"currency",currency:"USD",maximumFractionDigits:4});function U(t){return de.format(t)}const oe=t=>t.user_id,D=t=>t.startsWith("apikey-");function H(t){return t.split("-")[0]}function E(t){return t.name??H(t.budget_id)}function $({value:t,onChange:l,budgets:n}){return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{htmlFor:"user-budget",className:"text-sm font-medium text-[var(--otari-ink)]",children:"Budget"}),e.jsxs("select",{id:"user-budget",value:t??"",onChange:a=>l(a.target.value||null),className:"w-full rounded-lg border border-[var(--otari-line)] bg-[var(--otari-bg)] px-3 py-2 text-sm text-[var(--otari-ink)]",children:[e.jsx("option",{value:"",children:"No budget (unlimited)"}),n.map(a=>e.jsxs("option",{value:a.budget_id,children:[E(a),a.max_budget===null?" · no limit":` · ${U(a.max_budget)}`]},a.budget_id))]}),e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"The spending limit this user is held to. Manage budgets on the Budgets page."})]})}function ce({onClose:t}){const l=ee(),n=M(),[a,i]=r.useState(""),[o,u]=r.useState(""),[c,g]=r.useState(null),[p,m]=r.useState(null),[b,j]=r.useState(!0),x=()=>{if(l.isPending||!b||a.trim()==="")return;const h={user_id:a.trim(),alias:o.trim()||null,budget_id:c,allowed_models:p};l.mutate(h,{onSuccess:t})};return e.jsx(S,{children:e.jsxs(S.Content,{className:"flex flex-col gap-4 p-5",children:[e.jsx("div",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:"Create user"}),e.jsx(A,{error:l.error}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsx(B,{label:"User ID",value:a,onChange:i,placeholder:"alice@example.com",isRequired:!0,autoFocus:!0,description:"The identifier callers send as the `user` field; spend and budgets track against it."}),e.jsx(B,{label:"Alias (optional)",value:o,onChange:u,placeholder:"Alice"})]}),e.jsx($,{value:c,onChange:g,budgets:n.data??[]}),e.jsx(R,{title:"Model access (default for this user's keys)",description:"The models this user's keys may list and call by default. A key can narrow this, but never exceed it.",initial:null,onChange:(h,C)=>{m(h),j(C)}}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(d,{variant:"primary",isDisabled:l.isPending||!b||a.trim()==="",onPress:x,children:l.isPending?"Creating…":"Create user"}),e.jsx(d,{variant:"ghost",onPress:t,children:"Cancel"})]})]})})}function ue({user:t,onClose:l}){const n=K(),a=M(),[i,o]=r.useState(t.alias??""),[u,c]=r.useState(t.budget_id),[g,p]=r.useState(t.allowed_models),[m,b]=r.useState(!0),j=()=>{if(n.isPending||!m)return;const x={alias:i.trim()||null,budget_id:u,allowed_models:g};n.mutate({id:t.user_id,body:x},{onSuccess:l})};return e.jsx(S,{children:e.jsxs(S.Content,{className:"flex flex-col gap-4 p-5",children:[e.jsxs("div",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:["Edit ",e.jsx("code",{children:t.user_id})]}),e.jsx(A,{error:n.error}),e.jsx(B,{label:"Alias",value:i,onChange:o,placeholder:"Alice"}),e.jsx($,{value:u,onChange:c,budgets:a.data??[]}),e.jsx(R,{title:"Model access (default for this user's keys)",description:"The models this user's keys may list and call by default. A key can narrow this, but never exceed it.",initial:t.allowed_models,onChange:(x,h)=>{p(x),b(h)}}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(d,{variant:"primary",isDisabled:n.isPending||!m,onPress:j,children:n.isPending?"Saving…":"Save changes"}),e.jsx(d,{variant:"ghost",onPress:l,children:"Cancel"})]})]})})}function ge({trigger:t,message:l,confirmLabel:n,isPending:a,onConfirm:i}){const[o,u]=r.useState(!1);return o?e.jsxs("div",{className:"flex flex-col items-end gap-1.5 rounded-lg border border-amber-200 bg-amber-50 p-2 text-right",children:[e.jsx("span",{className:"max-w-xs text-xs text-amber-800",children:l}),e.jsxs("span",{className:"inline-flex gap-1",children:[e.jsx(d,{size:"sm",variant:"danger",isDisabled:a,onPress:i,children:n}),e.jsx(d,{size:"sm",variant:"ghost",isDisabled:a,onPress:()=>u(!1),children:"Cancel"})]})]}):e.jsx(d,{size:"sm",variant:"danger-soft",onPress:()=>u(!0),children:t})}function me({user:t}){return t.blocked?e.jsx(I,{size:"sm",color:"warning",children:"Blocked"}):e.jsx(I,{size:"sm",color:"accent",children:"Active"})}function xe({allowed:t}){const{text:l,tone:n}=ie(t),a=n==="danger"?"text-red-700 font-medium":n==="muted"?"text-[var(--otari-muted)]":"text-[var(--otari-brand-dark)] font-medium",i=t&&t.length>0?t.join(", "):void 0;return e.jsx("span",{className:`text-xs ${a}`,title:i,children:l})}function he({isOpen:t,onOpenChange:l,budgets:n,count:a,isPending:i,error:o,onAssign:u}){const[c,g]=r.useState("");return r.useEffect(()=>{t&&g("")},[t]),e.jsx(f,{isOpen:t,onOpenChange:l,children:t?e.jsx(f.Backdrop,{children:e.jsx(f.Container,{placement:"center",size:"md",children:e.jsxs(f.Dialog,{children:[e.jsx(f.Header,{children:e.jsx(f.Heading,{children:"Assign budget"})}),e.jsxs(f.Body,{className:"flex flex-col gap-4",children:[e.jsxs("p",{className:"text-sm text-[var(--otari-muted)]",children:["Assign a budget to ",a," selected ",a===1?"user":"users","."]}),e.jsx(se,{label:"Budget",value:c,onChange:g,options:[{value:"",label:"Select a budget…"},...n.map(p=>({value:p.budget_id,label:E(p)}))]}),e.jsx(A,{error:o})]}),e.jsxs(f.Footer,{children:[e.jsx(d,{variant:"ghost",isDisabled:i,onPress:()=>l(!1),children:"Cancel"}),e.jsx(d,{variant:"primary",isDisabled:!c,isPending:i,onPress:()=>u(c),children:"Assign"})]})]})})}):null})}function Ae(){const t=Q(),l=M(),n=K(),a=X(),[i,o]=r.useState(!1),[u,c]=r.useState(null),[g,p]=r.useState(!1),m=t.data??[],b=t.isLoading,j=m.filter(s=>D(s.user_id)).length,x=g?m:m.filter(s=>!D(s.user_id)),h=m.find(s=>s.user_id===u)??null,C=!b&&x.length===0&&!i,P=r.useMemo(()=>new Map((l.data??[]).map(s=>[s.budget_id,s])),[l.data]),y=te(),[q,_]=r.useState(!1),[W,N]=r.useState(!1),[F,z]=r.useState(void 0),[T,L]=r.useState(!1),G=x.map(s=>s.user_id),v=ae(y.selectedKeys,G),O=r.useCallback((s,k)=>n.mutate({id:s.user_id,body:{blocked:k}}),[n.mutate]),V=async(s,k)=>{L(!0),z(void 0);try{for(const w of v)await s(w);y.clear(),k()}catch(w){z(w)}finally{L(!1)}},J=r.useMemo(()=>[{id:"user",header:"User",isRowHeader:!0,cell:s=>e.jsxs("div",{className:"flex flex-col gap-0.5",children:[e.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[e.jsx("code",{className:"text-xs font-medium text-[var(--otari-ink)]",children:s.user_id}),D(s.user_id)?e.jsx(I,{size:"sm",color:"default",children:"virtual"}):null]}),s.alias?e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:s.alias}):null]})},{id:"status",header:"Status",cell:s=>e.jsx(me,{user:s})},{id:"budget",header:"Budget",cell:s=>s.budget_id?e.jsx("span",{className:"text-[var(--otari-muted)]",title:s.budget_id,children:P.get(s.budget_id)?E(P.get(s.budget_id)):H(s.budget_id)}):e.jsx("span",{className:"text-[var(--otari-muted)]",children:"—"})},{id:"spend",header:"Spend",cell:s=>e.jsxs("span",{className:"text-[var(--otari-muted)]",children:[U(s.spend),s.reserved>0?e.jsxs("span",{children:[" (+",U(s.reserved)," held)"]}):null]})},{id:"access",header:"Model access",cell:s=>e.jsx(xe,{allowed:s.allowed_models})},{id:"actions",header:"Actions",align:"end",cell:s=>e.jsxs("div",{className:"flex items-center justify-end gap-1.5",children:[e.jsx(d,{size:"sm",variant:"outline",isDisabled:n.isPending,onPress:()=>O(s,!s.blocked),children:s.blocked?"Unblock":"Block"}),e.jsx(d,{size:"sm",variant:"ghost",onPress:()=>{o(!1),c(s.user_id)},children:"Edit"}),e.jsx(ge,{trigger:"Delete",confirmLabel:"Delete user",isPending:a.isPending,message:e.jsxs(e.Fragment,{children:["Delete ",e.jsx("strong",{children:s.user_id}),"? This deactivates its API keys and hides the user; usage history is preserved."]}),onConfirm:()=>a.mutate(s.user_id)})]})}],[P,n.isPending,a.isPending,a.mutate,O]);return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(Y,{title:"Users",description:"People and teams that own API keys. Set each one's budget and default model access here; issue their keys on the API keys page.",action:i?null:e.jsx(d,{variant:"primary",onPress:()=>{c(null),o(!0)},children:"Create user"})}),e.jsx(A,{error:t.error??n.error??a.error}),C?e.jsx(Z,{title:"No users yet",description:"A user owns API keys and carries the budget and default model access those keys inherit. Create a user here, then issue its keys on the API keys page.",actionLabel:"Create your first user",onAction:()=>{c(null),o(!0)}}):null,j>0?e.jsxs("label",{className:"flex w-fit items-center gap-2 text-xs text-[var(--otari-muted)]",children:[e.jsx("input",{type:"checkbox",checked:g,onChange:s=>p(s.target.checked)}),"Show auto-created (virtual) users (",j,")"]}):null,i?e.jsx(ce,{onClose:()=>o(!1)}):null,h?e.jsx(ue,{user:h,onClose:()=>c(null)},h.user_id):null,v.length>0?e.jsxs(ne,{selectedCount:v.length,allMatching:!1,matchingTotal:null,canSelectAllMatching:!1,onSelectAllMatching:()=>{},onClear:y.clear,children:[e.jsx(d,{size:"sm",variant:"primary",onPress:()=>N(!0),children:"Assign budget"}),e.jsx(d,{size:"sm",variant:"danger",onPress:()=>_(!0),children:"Delete"})]}):null,C?null:e.jsx(le,{ariaLabel:"Users",columns:J,rows:x,getRowKey:oe,isLoading:b,emptyContent:"No users yet. Create one, or create an API key to auto-create one.",selectionMode:"multiple",selectedKeys:y.selectedKeys,onSelectionChange:y.onSelectionChange}),e.jsx(re,{isOpen:q,onOpenChange:_,heading:"Delete users",body:`Delete ${v.length} ${v.length===1?"user":"users"}? This deactivates their API keys and hides them; usage history is preserved.`,confirmLabel:"Delete",isPending:T,error:F,onConfirm:()=>V(s=>a.mutateAsync(s),()=>_(!1))}),e.jsx(he,{isOpen:W,onOpenChange:N,budgets:l.data??[],count:v.length,isPending:T,error:F,onAssign:s=>V(k=>n.mutateAsync({id:k,body:{budget_id:s}}),()=>N(!1))})]})}export{Ae as UsersPage}; +import{j as e}from"./tanstack-query-1t81HyiD.js";import{r}from"./react-dgEcD0HR.js";import{u as Q,l as M,p as K,ae as X,P as Y,E as A,q as Z,af as ee,F as se}from"./index-BP-wLuMr.js";import{u as te,r as ae,B as ne}from"./tableSelection-9hV37uhu.js";import{C as re}from"./ConfirmDialog-BFS2k4X_.js";import{D as le}from"./DataTable-Bmn_eYSV.js";import{F as B}from"./Field-Dwp6u3t8.js";import{a as ie,M as R}from"./ModelScopeControl-hWii6vSv.js";import{f as I,B as d,d as S,A as f}from"./heroui-BI50yK5B.js";const de=new Intl.NumberFormat(void 0,{style:"currency",currency:"USD",maximumFractionDigits:4});function U(t){return de.format(t)}const oe=t=>t.user_id,D=t=>t.startsWith("apikey-");function H(t){return t.split("-")[0]}function E(t){return t.name??H(t.budget_id)}function $({value:t,onChange:l,budgets:n}){return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{htmlFor:"user-budget",className:"text-sm font-medium text-[var(--otari-ink)]",children:"Budget"}),e.jsxs("select",{id:"user-budget",value:t??"",onChange:a=>l(a.target.value||null),className:"w-full rounded-lg border border-[var(--otari-line)] bg-[var(--otari-bg)] px-3 py-2 text-sm text-[var(--otari-ink)]",children:[e.jsx("option",{value:"",children:"No budget (unlimited)"}),n.map(a=>e.jsxs("option",{value:a.budget_id,children:[E(a),a.max_budget===null?" · no limit":` · ${U(a.max_budget)}`]},a.budget_id))]}),e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:"The spending limit this user is held to. Manage budgets on the Budgets page."})]})}function ce({onClose:t}){const l=ee(),n=M(),[a,i]=r.useState(""),[o,u]=r.useState(""),[c,g]=r.useState(null),[p,m]=r.useState(null),[b,j]=r.useState(!0),x=()=>{if(l.isPending||!b||a.trim()==="")return;const h={user_id:a.trim(),alias:o.trim()||null,budget_id:c,allowed_models:p};l.mutate(h,{onSuccess:t})};return e.jsx(S,{children:e.jsxs(S.Content,{className:"flex flex-col gap-4 p-5",children:[e.jsx("div",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:"Create user"}),e.jsx(A,{error:l.error}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsx(B,{label:"User ID",value:a,onChange:i,placeholder:"alice@example.com",isRequired:!0,autoFocus:!0,description:"The identifier callers send as the `user` field; spend and budgets track against it."}),e.jsx(B,{label:"Alias (optional)",value:o,onChange:u,placeholder:"Alice"})]}),e.jsx($,{value:c,onChange:g,budgets:n.data??[]}),e.jsx(R,{title:"Model access (default for this user's keys)",description:"The models this user's keys may list and call by default. A key can narrow this, but never exceed it.",initial:null,onChange:(h,C)=>{m(h),j(C)}}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(d,{variant:"primary",isDisabled:l.isPending||!b||a.trim()==="",onPress:x,children:l.isPending?"Creating…":"Create user"}),e.jsx(d,{variant:"ghost",onPress:t,children:"Cancel"})]})]})})}function ue({user:t,onClose:l}){const n=K(),a=M(),[i,o]=r.useState(t.alias??""),[u,c]=r.useState(t.budget_id),[g,p]=r.useState(t.allowed_models),[m,b]=r.useState(!0),j=()=>{if(n.isPending||!m)return;const x={alias:i.trim()||null,budget_id:u,allowed_models:g};n.mutate({id:t.user_id,body:x},{onSuccess:l})};return e.jsx(S,{children:e.jsxs(S.Content,{className:"flex flex-col gap-4 p-5",children:[e.jsxs("div",{className:"text-sm font-semibold text-[var(--otari-ink)]",children:["Edit ",e.jsx("code",{children:t.user_id})]}),e.jsx(A,{error:n.error}),e.jsx(B,{label:"Alias",value:i,onChange:o,placeholder:"Alice"}),e.jsx($,{value:u,onChange:c,budgets:a.data??[]}),e.jsx(R,{title:"Model access (default for this user's keys)",description:"The models this user's keys may list and call by default. A key can narrow this, but never exceed it.",initial:t.allowed_models,onChange:(x,h)=>{p(x),b(h)}}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(d,{variant:"primary",isDisabled:n.isPending||!m,onPress:j,children:n.isPending?"Saving…":"Save changes"}),e.jsx(d,{variant:"ghost",onPress:l,children:"Cancel"})]})]})})}function ge({trigger:t,message:l,confirmLabel:n,isPending:a,onConfirm:i}){const[o,u]=r.useState(!1);return o?e.jsxs("div",{className:"flex flex-col items-end gap-1.5 rounded-lg border border-amber-200 bg-amber-50 p-2 text-right",children:[e.jsx("span",{className:"max-w-xs text-xs text-amber-800",children:l}),e.jsxs("span",{className:"inline-flex gap-1",children:[e.jsx(d,{size:"sm",variant:"danger",isDisabled:a,onPress:i,children:n}),e.jsx(d,{size:"sm",variant:"ghost",isDisabled:a,onPress:()=>u(!1),children:"Cancel"})]})]}):e.jsx(d,{size:"sm",variant:"danger-soft",onPress:()=>u(!0),children:t})}function me({user:t}){return t.blocked?e.jsx(I,{size:"sm",color:"warning",children:"Blocked"}):e.jsx(I,{size:"sm",color:"accent",children:"Active"})}function xe({allowed:t}){const{text:l,tone:n}=ie(t),a=n==="danger"?"text-red-700 font-medium":n==="muted"?"text-[var(--otari-muted)]":"text-[var(--otari-brand-dark)] font-medium",i=t&&t.length>0?t.join(", "):void 0;return e.jsx("span",{className:`text-xs ${a}`,title:i,children:l})}function he({isOpen:t,onOpenChange:l,budgets:n,count:a,isPending:i,error:o,onAssign:u}){const[c,g]=r.useState("");return r.useEffect(()=>{t&&g("")},[t]),e.jsx(f,{isOpen:t,onOpenChange:l,children:t?e.jsx(f.Backdrop,{children:e.jsx(f.Container,{placement:"center",size:"md",children:e.jsxs(f.Dialog,{children:[e.jsx(f.Header,{children:e.jsx(f.Heading,{children:"Assign budget"})}),e.jsxs(f.Body,{className:"flex flex-col gap-4",children:[e.jsxs("p",{className:"text-sm text-[var(--otari-muted)]",children:["Assign a budget to ",a," selected ",a===1?"user":"users","."]}),e.jsx(se,{label:"Budget",value:c,onChange:g,options:[{value:"",label:"Select a budget…"},...n.map(p=>({value:p.budget_id,label:E(p)}))]}),e.jsx(A,{error:o})]}),e.jsxs(f.Footer,{children:[e.jsx(d,{variant:"ghost",isDisabled:i,onPress:()=>l(!1),children:"Cancel"}),e.jsx(d,{variant:"primary",isDisabled:!c,isPending:i,onPress:()=>u(c),children:"Assign"})]})]})})}):null})}function Ae(){const t=Q(),l=M(),n=K(),a=X(),[i,o]=r.useState(!1),[u,c]=r.useState(null),[g,p]=r.useState(!1),m=t.data??[],b=t.isLoading,j=m.filter(s=>D(s.user_id)).length,x=g?m:m.filter(s=>!D(s.user_id)),h=m.find(s=>s.user_id===u)??null,C=!b&&x.length===0&&!i,P=r.useMemo(()=>new Map((l.data??[]).map(s=>[s.budget_id,s])),[l.data]),y=te(),[q,_]=r.useState(!1),[W,N]=r.useState(!1),[F,z]=r.useState(void 0),[T,L]=r.useState(!1),G=x.map(s=>s.user_id),v=ae(y.selectedKeys,G),O=r.useCallback((s,k)=>n.mutate({id:s.user_id,body:{blocked:k}}),[n.mutate]),V=async(s,k)=>{L(!0),z(void 0);try{for(const w of v)await s(w);y.clear(),k()}catch(w){z(w)}finally{L(!1)}},J=r.useMemo(()=>[{id:"user",header:"User",isRowHeader:!0,cell:s=>e.jsxs("div",{className:"flex flex-col gap-0.5",children:[e.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[e.jsx("code",{className:"text-xs font-medium text-[var(--otari-ink)]",children:s.user_id}),D(s.user_id)?e.jsx(I,{size:"sm",color:"default",children:"virtual"}):null]}),s.alias?e.jsx("span",{className:"text-xs text-[var(--otari-muted)]",children:s.alias}):null]})},{id:"status",header:"Status",cell:s=>e.jsx(me,{user:s})},{id:"budget",header:"Budget",cell:s=>s.budget_id?e.jsx("span",{className:"text-[var(--otari-muted)]",title:s.budget_id,children:P.get(s.budget_id)?E(P.get(s.budget_id)):H(s.budget_id)}):e.jsx("span",{className:"text-[var(--otari-muted)]",children:"—"})},{id:"spend",header:"Spend",cell:s=>e.jsxs("span",{className:"text-[var(--otari-muted)]",children:[U(s.spend),s.reserved>0?e.jsxs("span",{children:[" (+",U(s.reserved)," held)"]}):null]})},{id:"access",header:"Model access",cell:s=>e.jsx(xe,{allowed:s.allowed_models})},{id:"actions",header:"Actions",align:"end",cell:s=>e.jsxs("div",{className:"flex items-center justify-end gap-1.5",children:[e.jsx(d,{size:"sm",variant:"outline",isDisabled:n.isPending,onPress:()=>O(s,!s.blocked),children:s.blocked?"Unblock":"Block"}),e.jsx(d,{size:"sm",variant:"ghost",onPress:()=>{o(!1),c(s.user_id)},children:"Edit"}),e.jsx(ge,{trigger:"Delete",confirmLabel:"Delete user",isPending:a.isPending,message:e.jsxs(e.Fragment,{children:["Delete ",e.jsx("strong",{children:s.user_id}),"? This deactivates its API keys and hides the user; usage history is preserved."]}),onConfirm:()=>a.mutate(s.user_id)})]})}],[P,n.isPending,a.isPending,a.mutate,O]);return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(Y,{title:"Users",description:"People and teams that own API keys. Set each one's budget and default model access here; issue their keys on the API keys page.",action:i?null:e.jsx(d,{variant:"primary",onPress:()=>{c(null),o(!0)},children:"Create user"})}),e.jsx(A,{error:t.error??n.error??a.error}),C?e.jsx(Z,{title:"No users yet",description:"A user owns API keys and carries the budget and default model access those keys inherit. Create a user here, then issue its keys on the API keys page.",actionLabel:"Create your first user",onAction:()=>{c(null),o(!0)}}):null,j>0?e.jsxs("label",{className:"flex w-fit items-center gap-2 text-xs text-[var(--otari-muted)]",children:[e.jsx("input",{type:"checkbox",checked:g,onChange:s=>p(s.target.checked)}),"Show auto-created (virtual) users (",j,")"]}):null,i?e.jsx(ce,{onClose:()=>o(!1)}):null,h?e.jsx(ue,{user:h,onClose:()=>c(null)},h.user_id):null,v.length>0?e.jsxs(ne,{selectedCount:v.length,allMatching:!1,matchingTotal:null,canSelectAllMatching:!1,onSelectAllMatching:()=>{},onClear:y.clear,children:[e.jsx(d,{size:"sm",variant:"primary",onPress:()=>N(!0),children:"Assign budget"}),e.jsx(d,{size:"sm",variant:"danger",onPress:()=>_(!0),children:"Delete"})]}):null,C?null:e.jsx(le,{ariaLabel:"Users",columns:J,rows:x,getRowKey:oe,isLoading:b,emptyContent:"No users yet. Create one, or create an API key to auto-create one.",selectionMode:"multiple",selectedKeys:y.selectedKeys,onSelectionChange:y.onSelectionChange}),e.jsx(re,{isOpen:q,onOpenChange:_,heading:"Delete users",body:`Delete ${v.length} ${v.length===1?"user":"users"}? This deactivates their API keys and hides them; usage history is preserved.`,confirmLabel:"Delete",isPending:T,error:F,onConfirm:()=>V(s=>a.mutateAsync(s),()=>_(!1))}),e.jsx(he,{isOpen:W,onOpenChange:N,budgets:l.data??[],count:v.length,isPending:T,error:F,onAssign:s=>V(k=>n.mutateAsync({id:k,body:{budget_id:s}}),()=>N(!1))})]})}export{Ae as UsersPage}; diff --git a/src/gateway/static/dashboard/assets/index-JlWCttWt.js b/src/gateway/static/dashboard/assets/index-BP-wLuMr.js similarity index 96% rename from src/gateway/static/dashboard/assets/index-JlWCttWt.js rename to src/gateway/static/dashboard/assets/index-BP-wLuMr.js index a0a1572f..636c90a0 100644 --- a/src/gateway/static/dashboard/assets/index-JlWCttWt.js +++ b/src/gateway/static/dashboard/assets/index-BP-wLuMr.js @@ -1,2 +1,2 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ActivityPage-lcRQhBAw.js","assets/tanstack-query-1t81HyiD.js","assets/react-dgEcD0HR.js","assets/FilterChips-DZjxf-ot.js","assets/heroui-BI50yK5B.js","assets/recharts-C4kRDmvS.js","assets/tableSelection-9hV37uhu.js","assets/ConfirmDialog-DXR8OubG.js","assets/DataTable-Bmn_eYSV.js","assets/TablePagination-CfsjgA8s.js","assets/AliasesPage-CPjhdIJQ.js","assets/Field-Dwp6u3t8.js","assets/BudgetsPage-BuN1cg5q.js","assets/DocsPage-Bw1czoYN.js","assets/KeysPage-DHZEligd.js","assets/ModelScopeControl-Bcam0tnJ.js","assets/ModelsPage-avB5ycpT.js","assets/OverviewPage-CNyNgkDA.js","assets/charts-DIsd9m--.js","assets/ProvidersPage-DueCtyY7.js","assets/SettingsPage-BVUWlkda.js","assets/ToolsGuardrailsPage-5txNsDJk.js","assets/UsagePage-B19CFPzF.js","assets/UsersPage-8qOL-FQs.js"])))=>i.map(i=>d[i]); -var Le=Object.defineProperty;var Ie=(e,r,n)=>r in e?Le(e,r,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[r]=n;var ie=(e,r,n)=>Ie(e,typeof r!="symbol"?r+"":r,n);import{u as y,j as t,a as g,b as h,k as X,Q as Ae,c as qe}from"./tanstack-query-1t81HyiD.js";import{d as Re,r as a,N as G,O as De,H as Oe,e as Me,f as w,h as Fe}from"./react-dgEcD0HR.js";import{B as C,C as M,L as me,I as fe,a as Ue,b as Ke,d as I,S as Be,c as _,T as ze,e as $e}from"./heroui-BI50yK5B.js";(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))s(i);new MutationObserver(i=>{for(const o of i)if(o.type==="childList")for(const d of o.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&s(d)}).observe(document,{childList:!0,subtree:!0});function n(i){const o={};return i.integrity&&(o.integrity=i.integrity),i.referrerPolicy&&(o.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?o.credentials="include":i.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function s(i){if(i.ep)return;i.ep=!0;const o=n(i);fetch(i.href,o)}})();var Qe=Re();const Ve="modulepreload",We=function(e){return"/"+e},oe={},P=function(r,n,s){let i=Promise.resolve();if(n&&n.length>0){let d=function(x){return Promise.all(x.map(f=>Promise.resolve(f).then(b=>({status:"fulfilled",value:b}),b=>({status:"rejected",reason:b}))))};document.getElementsByTagName("link");const m=document.querySelector("meta[property=csp-nonce]"),p=(m==null?void 0:m.nonce)||(m==null?void 0:m.getAttribute("nonce"));i=d(n.map(x=>{if(x=We(x),x in oe)return;oe[x]=!0;const f=x.endsWith(".css"),b=f?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${x}"]${b}`))return;const u=document.createElement("link");if(u.rel=f?"stylesheet":Ve,f||(u.as="script"),u.crossOrigin="",u.href=x,p&&u.setAttribute("nonce",p),document.head.appendChild(u),f)return new Promise((N,R)=>{u.addEventListener("load",N),u.addEventListener("error",()=>R(new Error(`Unable to preload CSS for ${x}`)))})}))}function o(d){const m=new Event("vite:preloadError",{cancelable:!0});if(m.payload=d,window.dispatchEvent(m),!m.defaultPrevented)throw d}return i.then(d=>{for(const m of d||[])m.status==="rejected"&&o(m.reason);return r().catch(o)})};class T extends Error{constructor(n,s){super(s);ie(this,"status");this.name="ApiError",this.status=n}}let F=null;function le(e){F=e}async function J(e){try{const r=await e.json();if(typeof r.detail=="string")return r.detail;if(r.detail!=null)return JSON.stringify(r.detail)}catch{}return e.statusText||`Request failed (${e.status})`}async function He(e){let r;try{r=await fetch("/v1/auth/session",{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify({master_key:e})})}catch{throw new T(0,"Network error: could not reach the gateway.")}if(r.status===401||r.status===403)return!1;if(!r.ok)throw new T(r.status,await J(r));return!0}async function Ge(){try{await fetch("/v1/auth/session",{method:"DELETE"})}catch{}}async function c(e,r={}){const n=new Headers(r.headers);n.set("Accept","application/json"),r.body!=null&&!n.has("Content-Type")&&n.set("Content-Type","application/json");let s;try{s=await fetch(e,{...r,headers:n})}catch{throw new T(0,"Network error: could not reach the gateway.")}if(s.status===401||s.status===403)throw F==null||F(),new T(s.status,await J(s));if(!s.ok)throw new T(s.status,await J(s));if(s.status!==204)return await s.json()}const Y="otari.dashboard.hasSession",he=a.createContext(null);function Je(){try{return window.localStorage.getItem(Y)==="1"}catch{return!1}}function Ye({children:e}){const r=y(),[n,s]=a.useState(Je),i=a.useCallback(()=>{Ge(),s(!1),r.clear();try{window.localStorage.removeItem(Y)}catch{}},[r]),o=a.useCallback(()=>{r.clear(),s(!0);try{window.localStorage.setItem(Y,"1")}catch{}},[r]);a.useEffect(()=>(le(i),()=>le(null)),[i]);const d=a.useMemo(()=>({isAuthenticated:n,login:o,logout:i}),[n,o,i]);return t.jsx(he.Provider,{value:d,children:e})}function Z(){const e=a.useContext(he);if(!e)throw new Error("useAuth must be used within an AuthProvider");return e}function Xe(e){return e instanceof T&&e.status===0}function Ze(){const e=y(),[r,n]=a.useState(!1);return a.useEffect(()=>{const s=e.getQueryCache(),i=()=>s.getAll().some(o=>o.state.status==="error"&&Xe(o.state.error));return n(i()),s.subscribe(()=>n(i()))},[e]),r}function et(){return Ze()?t.jsxs("div",{role:"alert","aria-live":"assertive",className:"fixed right-4 bottom-4 z-50 flex max-w-sm items-start gap-2.5 rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700 shadow-lg",children:[t.jsxs("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2","aria-hidden":!0,className:"mt-0.5 h-5 w-5 shrink-0",children:[t.jsx("path",{d:"M12 9v4M12 17h.01",strokeLinecap:"round",strokeLinejoin:"round"}),t.jsx("path",{d:"M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z",strokeLinejoin:"round"})]}),t.jsxs("span",{children:[t.jsx("strong",{className:"font-semibold",children:"Can’t reach the gateway."})," The backend isn’t responding; data won’t load or save until the connection is restored."]})]}):null}const L="models",K="pricing",xe="settings",ve="tool-settings",ee="aliases",te="discoverable",re="providers",ne="provider-health",ye="stored-providers",tt="model-metadata",rt="build",A="keys",q="budgets",pe="users",O="usage",nt=6e4,ce=60*6e4;function tr(){return g({queryKey:[L],queryFn:()=>c("/v1/models"),staleTime:6e4})}function st(){return g({queryKey:[rt],queryFn:()=>c("/dashboard-build.json"),refetchInterval:nt,refetchOnWindowFocus:!0,staleTime:0,retry:!1})}function rr(){return g({queryKey:[te],queryFn:()=>c("/v1/models/discoverable"),staleTime:5*6e4})}function nr(){return g({queryKey:[re],queryFn:()=>c("/v1/providers"),staleTime:5*6e4})}function sr(){return g({queryKey:["provider-catalog"],queryFn:()=>c("/v1/providers/catalog"),staleTime:1/0})}function ar(e){return g({queryKey:["provider-catalog",e],queryFn:()=>c(`/v1/providers/catalog/${encodeURIComponent(e)}`),enabled:e!=="",staleTime:1/0})}function ir(){return g({queryKey:[ne],queryFn:()=>c("/v1/providers/health"),staleTime:ce,refetchInterval:ce})}function or(){const e=y();return h({mutationFn:()=>c("/v1/providers/health?refresh=true"),onSuccess:r=>e.setQueryData([ne],r)})}function lr(){return g({queryKey:[ye],queryFn:()=>c("/v1/provider-credentials"),staleTime:6e4})}function B(e){e.invalidateQueries({queryKey:[ye]}),e.invalidateQueries({queryKey:[re]}),e.invalidateQueries({queryKey:[L]}),e.invalidateQueries({queryKey:[te]}),e.invalidateQueries({queryKey:[ne]})}function cr(){const e=y();return h({mutationFn:r=>c("/v1/provider-credentials",{method:"POST",body:JSON.stringify(r)}),onSuccess:()=>B(e)})}function ur(){const e=y();return h({mutationFn:({instance:r,body:n})=>c(`/v1/provider-credentials/${encodeURIComponent(r)}`,{method:"PATCH",body:JSON.stringify(n)}),onSuccess:()=>B(e)})}function dr(){const e=y();return h({mutationFn:r=>c(`/v1/provider-credentials/${encodeURIComponent(r)}`,{method:"DELETE"}),onSuccess:()=>B(e)})}function mr(){const e=y();return h({mutationFn:()=>c("/v1/provider-credentials/reencrypt",{method:"POST"}),onSuccess:()=>B(e)})}function fr(){return h({mutationFn:e=>c(`/v1/provider-credentials/${encodeURIComponent(e)}/test`,{method:"POST"})})}function hr(){return h({mutationFn:e=>c("/v1/provider-credentials/test",{method:"POST",body:JSON.stringify(e)})})}function xr(){return g({queryKey:[tt],queryFn:()=>c("/v1/models/metadata"),staleTime:10*6e4})}function vr(){return g({queryKey:[ee],queryFn:()=>c("/v1/aliases"),staleTime:6e4})}function yr(){const e=y();return h({mutationFn:r=>c("/v1/aliases",{method:"POST",body:JSON.stringify(r)}),onSuccess:()=>{e.invalidateQueries({queryKey:[ee]}),e.invalidateQueries({queryKey:[L]})}})}function pr(){const e=y();return h({mutationFn:r=>c(`/v1/aliases/${encodeURIComponent(r)}`,{method:"DELETE"}),onSuccess:()=>{e.invalidateQueries({queryKey:[ee]}),e.invalidateQueries({queryKey:[L]})}})}function at(){return g({queryKey:[xe],queryFn:()=>c("/v1/settings"),staleTime:6e4})}function it(){const e=y();return h({mutationFn:r=>c("/v1/settings",{method:"PATCH",body:JSON.stringify(r)}),onSuccess:r=>{e.setQueryData([xe],r),e.invalidateQueries({queryKey:[L]}),e.invalidateQueries({queryKey:[te]})}})}function gr(){return h({mutationFn:()=>c("/v1/settings/master-key/rotate",{method:"POST"})})}function br(){return g({queryKey:[ve],queryFn:()=>c("/v1/tool-settings"),staleTime:6e4})}function jr(){const e=y();return h({mutationFn:r=>c("/v1/tool-settings",{method:"PATCH",body:JSON.stringify(r)}),onSuccess:r=>{e.setQueryData([ve],r)}})}function wr(){return h({mutationFn:({service:e,url:r})=>c(`/v1/tool-settings/${encodeURIComponent(e)}/test`,{method:"POST",body:JSON.stringify({url:r})})})}const $=1e3,ot=100;async function lt(){const e=[];for(let r=0;rc("/v1/pricing",{method:"POST",body:JSON.stringify(r)}),onSuccess:()=>{e.invalidateQueries({queryKey:[K]}),e.invalidateQueries({queryKey:[L]})}})}function Er(){const e=y();return h({mutationFn:r=>c(`/v1/pricing/${encodeURIComponent(r)}`,{method:"DELETE"}),onSuccess:()=>{e.invalidateQueries({queryKey:[K]}),e.invalidateQueries({queryKey:[L]})}})}function Pr(){return h({mutationFn:()=>c("/v1/pricing/refresh",{method:"POST"})})}function Nr(){const e=y();return h({mutationFn:()=>c("/v1/pricing/refresh/confirm",{method:"POST"}),onSuccess:()=>{e.invalidateQueries({queryKey:[K]}),e.invalidateQueries({queryKey:[L]}),e.invalidateQueries({queryKey:[re]})}})}function Cr(){return h({mutationFn:()=>c("/v1/pricing/refresh/reject",{method:"POST"})})}const Q=1e3,ct=100;async function ut(){const e=[];for(let r=0;rc("/v1/keys",{method:"POST",body:JSON.stringify(r)}),onSuccess:()=>void e.invalidateQueries({queryKey:[A]})})}function Lr(){const e=y();return h({mutationFn:({id:r,body:n})=>c(`/v1/keys/${encodeURIComponent(r)}`,{method:"PATCH",body:JSON.stringify(n)}),onSuccess:()=>void e.invalidateQueries({queryKey:[A]})})}function Ir(){const e=y();return h({mutationFn:r=>c(`/v1/keys/${encodeURIComponent(r)}/rotate`,{method:"POST"}),onSuccess:()=>void e.invalidateQueries({queryKey:[A]})})}function Ar(){const e=y();return h({mutationFn:r=>c(`/v1/keys/${encodeURIComponent(r)}`,{method:"DELETE"}),onSuccess:()=>void e.invalidateQueries({queryKey:[A]})})}const V=1e3,dt=100;async function mt(){const e=[];for(let r=0;rc(`/v1/budgets/${encodeURIComponent(e)}/reset-logs`),enabled:e!==null,staleTime:6e4})}function Dr(){const e=y();return h({mutationFn:r=>c("/v1/budgets",{method:"POST",body:JSON.stringify(r)}),onSuccess:()=>void e.invalidateQueries({queryKey:[q]})})}function Or(){const e=y();return h({mutationFn:({id:r,body:n})=>c(`/v1/budgets/${encodeURIComponent(r)}`,{method:"PATCH",body:JSON.stringify(n)}),onSuccess:()=>void e.invalidateQueries({queryKey:[q]})})}function Mr(){const e=y();return h({mutationFn:r=>c(`/v1/budgets/${encodeURIComponent(r)}`,{method:"DELETE"}),onSuccess:()=>void e.invalidateQueries({queryKey:[q]})})}const W=1e3,ft=100;async function ht(){const e=[];for(let r=0;rc("/v1/users",{method:"POST",body:JSON.stringify(r)}),onSuccess:()=>se(e)})}function Kr(){const e=y();return h({mutationFn:({id:r,body:n})=>c(`/v1/users/${encodeURIComponent(r)}`,{method:"PATCH",body:JSON.stringify(n)}),onSuccess:()=>se(e)})}function Br(){const e=y();return h({mutationFn:r=>c(`/v1/users/${encodeURIComponent(r)}`,{method:"DELETE"}),onSuccess:()=>{se(e),e.invalidateQueries({queryKey:[A]})}})}function ae(e){const r=new URLSearchParams;return e.start_date&&r.set("start_date",e.start_date),e.end_date&&r.set("end_date",e.end_date),e.status&&r.set("status",e.status),e.model&&r.set("model",e.model),e.endpoint&&r.set("endpoint",e.endpoint),e.user_id&&r.set("user_id",e.user_id),e.api_key_id&&r.set("api_key_id",e.api_key_id),e.source&&r.set("source",e.source),e.priced!==void 0&&r.set("priced",String(e.priced)),e.counts_toward_budget!==void 0&&r.set("counts_toward_budget",String(e.counts_toward_budget)),r}function zr(e,r,n){return g({queryKey:[O,"list",e,r,n],queryFn:()=>{const s=ae(e);return s.set("skip",String(r*n)),s.set("limit",String(n)),c(`/v1/usage?${s.toString()}`)},placeholderData:X,staleTime:1e4})}function $r(e,r=!0){return g({queryKey:[O,"count",e],queryFn:()=>c(`/v1/usage/count?${ae(e).toString()}`),enabled:r,placeholderData:X,staleTime:1e4})}function Qr(){const e=y();return h({mutationFn:r=>c("/v1/usage",{method:"DELETE",body:JSON.stringify(r)}),onSuccess:()=>{e.invalidateQueries({queryKey:[O]})}})}function Vr(){const e=y();return h({mutationFn:r=>c("/v1/usage/set-price",{method:"POST",body:JSON.stringify(r)}),onSuccess:()=>{e.invalidateQueries({queryKey:[O]})}})}function Wr(e,r,n=!0){return g({queryKey:[O,"summary",e,r],queryFn:()=>{const s=ae(e);return s.set("bucket",r),c(`/v1/usage/summary?${s.toString()}`)},enabled:n,placeholderData:X,staleTime:3e4})}function Hr(e){return e==null?"0":new Intl.NumberFormat("en-US").format(e)}function Gr(e){if(e==null)return"$0.00";const r=e!==0&&Math.abs(e)<.01?4:2;return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:r}).format(e)}function Jr(e){if(e==null)return"—";if(e>=1e6){const r=e/1e6;return`${Number.isInteger(r)?r:r.toFixed(1)}M`}if(e>=1e3){const r=Math.round(e/1e3);return r>=1e3?"1M":`${r}K`}return String(e)}const xt=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function Yr(e){if(!e)return"—";const r=/^(\d{4})-(\d{2})/.exec(e);if(!r)return e;const n=Number(r[2])-1;return n<0||n>11?r[1]:`${xt[n]} ${r[1]}`}const vt=new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",maximumFractionDigits:2});function Xr(e){return vt.format(e)}function Zr(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e)}function yt(e){return`${(e*100).toFixed(1)}%`}function en(e,r){return r===void 0||r===0?null:(e-r)/r}function pt(e,r=Date.now()){if(!e)return"never";const n=new Date(e);if(Number.isNaN(n.getTime()))return e;const s=Math.round((r-n.getTime())/1e3),i=s<0,o=Math.abs(s),d=[["second",60],["minute",60],["hour",24],["day",30],["month",12],["year",Number.POSITIVE_INFINITY]];let m=o,p="second";for(const[f,b]of d){if(p=f,m0?"▲":e<0?"▼":"•";return t.jsxs("span",{className:"text-[var(--otari-muted)]",children:[r," ",yt(Math.abs(e))," vs prev"]})}function gt(e){return e instanceof T||e instanceof Error?e.message:"Something went wrong."}function bt({error:e}){return e?t.jsx("div",{role:"alert",className:"rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700",children:gt(e)}):null}function jt({tone:e="info",children:r}){const n=e==="warning"?"border-amber-200 bg-amber-50 text-amber-800":"border-[var(--otari-brand)] bg-[var(--otari-brand-tint)] text-[var(--otari-brand-dark)]";return t.jsx("div",{className:`rounded-lg border px-4 py-3 text-sm ${n}`,children:r})}function nn({title:e,description:r,action:n}){return t.jsxs("div",{className:"flex flex-col gap-3",children:[t.jsxs("div",{children:[t.jsx("h1",{className:"text-xl font-semibold text-[var(--otari-ink)]",children:e}),r?t.jsx("p",{className:"mt-1 text-sm text-[var(--otari-muted)]",children:r}):null]}),n?t.jsx("div",{className:"flex flex-wrap gap-2",children:n}):null]})}function wt(e){const[r,n]=a.useState(()=>Date.now());return a.useEffect(()=>{let s;const i=()=>{s===void 0&&(s=setInterval(()=>n(Date.now()),e))},o=()=>{s!==void 0&&(clearInterval(s),s=void 0)},d=()=>{n(Date.now()),document.visibilityState==="visible"?i():o()};return d(),document.addEventListener("visibilitychange",d),()=>{o(),document.removeEventListener("visibilitychange",d)}},[e]),r}function sn({onRefresh:e,isFetching:r=!1,updatedAt:n,label:s="Refresh"}){const i=wt(15e3),o=n?pt(new Date(n).toISOString(),i):null;return t.jsxs("span",{className:"inline-flex items-center gap-2",children:[o?t.jsxs("span",{className:"text-xs text-[var(--otari-muted)]",children:["Updated ",o]}):null,t.jsx(C,{variant:"outline",size:"sm",isIconOnly:!0,isDisabled:r,onPress:e,"aria-label":s,children:t.jsxs("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:`h-4 w-4 ${r?"animate-spin":""}`,"aria-hidden":"true",children:[t.jsx("path",{d:"M20 11a8 8 0 1 0-.5 4",strokeLinecap:"round",strokeLinejoin:"round"}),t.jsx("path",{d:"M20 4v5h-5",strokeLinecap:"round",strokeLinejoin:"round"})]})})]})}function an({title:e,description:r,actionLabel:n,onAction:s,isActionDisabled:i,children:o}){return t.jsx(I,{children:t.jsxs(I.Content,{className:"flex flex-col gap-4 p-6",children:[t.jsxs("div",{children:[t.jsx("h2",{className:"text-lg font-semibold text-[var(--otari-ink)]",children:e}),r?t.jsx("p",{className:"mt-1 text-sm text-[var(--otari-muted)]",children:r}):null]}),o,n&&s?t.jsx("div",{children:t.jsx(C,{variant:"primary",isDisabled:i,onPress:s,children:n})}):null]})})}function on({label:e="Loading…"}){return t.jsxs("div",{role:"status",className:"flex items-center justify-center gap-2 px-4 py-10 text-sm text-[var(--otari-muted)]",children:[t.jsx(Be,{size:"sm"}),t.jsx("span",{children:e})]})}function ln({children:e,confirmLabel:r,onConfirm:n,isPending:s}){const[i,o]=a.useState(!1);return i?t.jsxs("span",{className:"inline-flex items-center gap-1",children:[t.jsx(C,{size:"sm",variant:"danger",isDisabled:s,onPress:n,children:r}),t.jsx(C,{size:"sm",variant:"ghost",isDisabled:s,onPress:()=>o(!1),children:"Cancel"})]}):t.jsx(C,{size:"sm",variant:"danger-soft",onPress:()=>o(!0),children:e})}const St="rounded-lg border border-[var(--otari-line)] bg-[var(--otari-bg)] px-3 py-2 text-sm text-[var(--otari-ink)] focus:border-[var(--otari-brand)] focus:outline-none";function cn({id:e,label:r,ariaLabel:n,value:s,onChange:i,options:o,children:d,disabled:m}){const p=a.useId(),x=e??(r?p:void 0),f=t.jsx("select",{id:x,"aria-label":r?void 0:n,value:s,disabled:m,onChange:b=>i(b.target.value),className:St,children:o?o.map(b=>t.jsx("option",{value:b.value,children:b.label},b.value)):d});return r?t.jsxs("div",{className:"flex flex-col gap-1",children:[t.jsx("label",{htmlFor:x,className:"text-xs font-medium text-[var(--otari-muted)]",children:r}),f]}):f}function un({label:e,value:r,onChange:n,options:s,placeholder:i,maxVisible:o=50,allowsCustom:d=!1}){const m=u=>{var N;return((N=s.find(R=>R.value===u))==null?void 0:N.label)??u},[p,x]=a.useState(()=>m(r));a.useEffect(()=>{x(m(r))},[r]);const f=p.trim().toLowerCase(),b=s.filter(u=>!f||u.value.toLowerCase().includes(f)||u.label.toLowerCase().includes(f)).slice(0,o);return t.jsxs(M.Root,{allowsEmptyCollection:!0,allowsCustomValue:d,menuTrigger:"focus",inputValue:p,onInputChange:u=>{x(u),d?n(u.trim()):u.trim()===""&&n("")},onSelectionChange:u=>{u!=null&&n(String(u))},className:"flex flex-col gap-1",children:[t.jsx(me,{className:"text-xs font-medium text-[var(--otari-muted)]",children:e}),t.jsxs(M.InputGroup,{children:[t.jsx(fe,{placeholder:i,autoComplete:"off",onFocus:u=>u.currentTarget.select()}),t.jsx(M.Trigger,{})]}),t.jsx(M.Popover,{children:t.jsx(Ue,{items:b,className:"max-h-72 overflow-auto",children:u=>t.jsx(Ke,{id:u.value,textValue:u.label,children:u.label})})})]})}function kt(){var o;const e=at(),r=it(),[n,s]=a.useState(!1);return!(((o=e.data)==null?void 0:o.require_pricing)===!0&&e.data.default_pricing===!1)||n?null:t.jsx("div",{className:"shrink-0 px-6 pt-3",children:t.jsx(jt,{tone:"warning",children:t.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[t.jsxs("span",{children:["Requests are rejected until pricing is set (",t.jsx("code",{children:"require_pricing"})," is on). Enable default pricing to meter new models with public rates right away."]}),t.jsxs("span",{className:"flex items-center gap-2",children:[t.jsx(C,{size:"sm",variant:"primary",isDisabled:r.isPending,onPress:()=>r.mutate({default_pricing:!0}),children:r.isPending?"Enabling…":"Enable default pricing"}),t.jsx(C,{size:"sm",variant:"ghost",onPress:()=>s(!0),children:"Dismiss"})]})]})})})}function Et(){const{data:e}=st(),r=a.useRef(null);return e&&r.current===null&&(r.current=e.build),e!=null&&r.current!=null&&e.build!==r.current}function Pt(){const e=Et(),[r,n]=a.useState(!1);return!e||r?null:t.jsx("div",{className:"pointer-events-none absolute inset-x-0 top-0 z-50 flex justify-center",children:t.jsxs("div",{role:"status",className:"pointer-events-auto mt-1.5 flex items-center gap-3 rounded-full border border-[var(--otari-brand)] bg-[var(--otari-brand-tint)] py-1.5 pr-1.5 pl-4 text-sm text-[var(--otari-brand-dark)] shadow-md",children:[t.jsxs("span",{children:[t.jsx("strong",{className:"font-semibold",children:"An update is available."})," Reloading keeps you signed in."]}),t.jsx(C,{size:"sm",variant:"primary",onPress:()=>window.location.reload(),children:"Update now"}),t.jsx(C,{size:"sm",variant:"ghost",onPress:()=>n(!0),children:"Later"})]})})}const ge=200,be=480,H=240,Nt=60,je="otari.dashboard.sidebarWidth",we="otari.dashboard.sidebarCollapsed",de=16,Se="(max-width: 767px)",U=e=>Math.min(be,Math.max(ge,e));function Ct(){return typeof window>"u"||typeof window.matchMedia!="function"?!1:window.matchMedia(Se).matches}const _t='a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])';function Tt(e){return e?Array.from(e.querySelectorAll(_t)).filter(r=>r.offsetParent!==null||r===document.activeElement):[]}function Lt(){if(typeof window>"u")return H;try{const e=window.localStorage.getItem(je),r=e?Number.parseInt(e,10):Number.NaN;return Number.isNaN(r)?H:U(r)}catch{return H}}function It(){if(typeof window>"u")return!1;try{return window.localStorage.getItem(we)==="1"}catch{return!1}}const At=[{key:"home"},{key:"observability",label:"Observability"},{key:"catalog",label:"Catalog"},{key:"access",label:"Access"},{key:"system"}],qt=[{to:"/",section:"home",label:"Overview",end:!0,icon:t.jsxs("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("rect",{x:"3.5",y:"3.5",width:"7",height:"7",rx:"1.5",strokeLinejoin:"round"}),t.jsx("rect",{x:"13.5",y:"3.5",width:"7",height:"7",rx:"1.5",strokeLinejoin:"round"}),t.jsx("rect",{x:"3.5",y:"13.5",width:"7",height:"7",rx:"1.5",strokeLinejoin:"round"}),t.jsx("rect",{x:"13.5",y:"13.5",width:"7",height:"7",rx:"1.5",strokeLinejoin:"round"})]})},{to:"/activity",section:"observability",label:"Activity",icon:t.jsx("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:t.jsx("path",{d:"M3 12h4l2.5-6 4 12 2.5-6H21",strokeLinecap:"round",strokeLinejoin:"round"})})},{to:"/usage",section:"observability",label:"Usage",icon:t.jsx("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:t.jsx("path",{d:"M4 20V10M10 20V4M16 20v-7M22 20H2",strokeLinecap:"round",strokeLinejoin:"round"})})},{to:"/providers",section:"catalog",label:"Providers",icon:t.jsxs("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("rect",{x:"3.5",y:"4.5",width:"17",height:"6",rx:"1.5",strokeLinejoin:"round"}),t.jsx("rect",{x:"3.5",y:"13.5",width:"17",height:"6",rx:"1.5",strokeLinejoin:"round"}),t.jsx("path",{d:"M7 7.5h.01M7 16.5h.01",strokeLinecap:"round",strokeLinejoin:"round"})]})},{to:"/users",section:"access",label:"Users",icon:t.jsxs("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("circle",{cx:"9",cy:"8",r:"3.2",strokeLinejoin:"round"}),t.jsx("path",{d:"M3.5 19a5.5 5.5 0 0 1 11 0",strokeLinecap:"round",strokeLinejoin:"round"}),t.jsx("path",{d:"M16 5.2a3.2 3.2 0 0 1 0 5.6M17.5 19a5.5 5.5 0 0 0-3-4.9",strokeLinecap:"round",strokeLinejoin:"round"})]})},{to:"/keys",section:"access",label:"API keys",icon:t.jsxs("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("circle",{cx:"7.5",cy:"15.5",r:"3.5"}),t.jsx("path",{d:"M10 13l7-7M14 5l3 3M16.5 7.5l2-2",strokeLinecap:"round",strokeLinejoin:"round"})]})},{to:"/budgets",section:"access",label:"Budgets",icon:t.jsxs("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("path",{d:"M3 7.5A1.5 1.5 0 0 1 4.5 6H18a1.5 1.5 0 0 1 1.5 1.5V9",strokeLinejoin:"round"}),t.jsx("rect",{x:"3",y:"7.5",width:"18",height:"12",rx:"1.5",strokeLinejoin:"round"}),t.jsx("path",{d:"M16 13.5h.01",strokeLinecap:"round",strokeLinejoin:"round"}),t.jsx("path",{d:"M21 12v3h-3.5a1.5 1.5 0 0 1 0-3H21z",strokeLinejoin:"round"})]})},{to:"/models",section:"catalog",label:"Models",icon:t.jsxs("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("path",{d:"M12 3l8 4.5v9L12 21l-8-4.5v-9L12 3z",strokeLinejoin:"round"}),t.jsx("path",{d:"M12 12l8-4.5M12 12v9M12 12L4 7.5",strokeLinejoin:"round"})]})},{to:"/aliases",section:"catalog",label:"Aliases",icon:t.jsxs("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("path",{d:"M20.6 13.4L13.4 20.6a2 2 0 0 1-2.8 0l-7-7A2 2 0 0 1 3 12.2V5a2 2 0 0 1 2-2h7.2a2 2 0 0 1 1.4.6l7 7a2 2 0 0 1 0 2.8z",strokeLinejoin:"round"}),t.jsx("circle",{cx:"7.5",cy:"7.5",r:"1.5"})]})},{to:"/tools",section:"system",label:"Tools & Guardrails",icon:t.jsxs("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("path",{d:"M14.7 6.3a4 4 0 0 1 5 5l-8.4 8.4a2 2 0 0 1-2.8 0l-2.2-2.2a2 2 0 0 1 0-2.8z",strokeLinejoin:"round"}),t.jsx("path",{d:"M12 9 5 16",strokeLinecap:"round"})]})},{to:"/settings",section:"system",label:"Settings",icon:t.jsxs("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("circle",{cx:"12",cy:"12",r:"3"}),t.jsx("path",{d:"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z",strokeLinejoin:"round"})]})}];function Rt(){const{logout:e}=Z(),r=a.useRef(null),n=a.useRef(null),s=a.useRef(null),[i,o]=a.useState(Lt),[d,m]=a.useState(It),[p,x]=a.useState(!1),[f,b]=a.useState(Ct),[u,N]=a.useState(!1);a.useEffect(()=>{if(typeof window>"u"||typeof window.matchMedia!="function")return;const l=window.matchMedia(Se),v=j=>{b(j.matches),j.matches||N(!1)};return typeof l.addEventListener=="function"?(l.addEventListener("change",v),()=>l.removeEventListener("change",v)):(l.addListener(v),()=>l.removeListener(v))},[]),a.useEffect(()=>{if(!u)return;const l=v=>{v.key==="Escape"&&N(!1)};return window.addEventListener("keydown",l),()=>window.removeEventListener("keydown",l)},[u]),a.useEffect(()=>{var l,v,j;f&&(u?(l=r.current)==null||l.focus():(v=r.current)!=null&&v.contains(document.activeElement)&&((j=s.current)==null||j.focus()))},[f,u]);const R=a.useCallback(l=>{if(l.key!=="Tab")return;const v=Tt(r.current);if(v.length===0)return;const j=v[0],k=v[v.length-1],D=document.activeElement;l.shiftKey&&(D===j||D===r.current)?(l.preventDefault(),k.focus()):!l.shiftKey&&D===k&&(l.preventDefault(),j.focus())},[]);a.useEffect(()=>{const l=window.setTimeout(()=>{try{window.localStorage.setItem(je,String(Math.round(i)))}catch{}},200);return()=>window.clearTimeout(l)},[i]),a.useEffect(()=>{try{window.localStorage.setItem(we,d?"1":"0")}catch{}},[d]);const Ee=a.useCallback(l=>{l.preventDefault(),l.currentTarget.setPointerCapture(l.pointerId),x(!0)},[]),Pe=a.useCallback(l=>{var j;if(!l.currentTarget.hasPointerCapture(l.pointerId))return;const v=((j=r.current)==null?void 0:j.getBoundingClientRect().left)??0;o(U(l.clientX-v))},[]),Ne=a.useCallback(l=>{l.currentTarget.hasPointerCapture(l.pointerId)&&l.currentTarget.releasePointerCapture(l.pointerId),x(!1)},[]),Ce=a.useCallback(l=>{var v;l.preventDefault(),(v=n.current)==null||v.focus()},[]),_e=a.useCallback(l=>{l.key==="ArrowLeft"?(l.preventDefault(),o(v=>U(v-de))):l.key==="ArrowRight"&&(l.preventDefault(),o(v=>U(v+de)))},[]),Te=d?Nt:i,S=f?!1:d,z=f&&u?!0:void 0;return t.jsxs("div",{className:_("relative flex h-full flex-col overflow-hidden",p&&"cursor-col-resize select-none"),children:[t.jsx("button",{type:"button",inert:z,onClick:Ce,className:"sr-only focus:not-sr-only focus:absolute focus:top-3 focus:left-3 focus:z-50 focus:rounded-lg focus:border focus:border-[var(--otari-brand)] focus:bg-[var(--otari-surface)] focus:px-4 focus:py-2 focus:text-sm focus:font-medium focus:text-[var(--otari-brand-dark)] focus:shadow-md focus:outline-none",children:"Skip to main content"}),t.jsxs("header",{inert:z,className:"flex shrink-0 items-center justify-between border-b border-[var(--otari-line)] bg-[var(--otari-surface)] px-5 py-3",children:[t.jsxs("div",{className:"flex items-center gap-2.5",children:[t.jsx("button",{type:"button",ref:s,onClick:()=>N(l=>!l),"aria-label":u?"Close navigation":"Open navigation","aria-expanded":u,"aria-controls":"app-sidebar",className:"-ml-1 flex h-8 w-8 items-center justify-center rounded-lg text-[var(--otari-muted)] transition-colors hover:bg-[var(--otari-bg)] hover:text-[var(--otari-ink)] md:hidden",children:t.jsx("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5",children:t.jsx("path",{d:"M4 6h16M4 12h16M4 18h16",strokeLinecap:"round",strokeLinejoin:"round"})})}),t.jsx("img",{src:"/favicon.svg",alt:"",className:"h-7 w-7 shrink-0"}),t.jsx("span",{className:"text-base font-semibold text-[var(--otari-ink)]",children:"Otari"})]}),t.jsx(C,{size:"sm",variant:"outline",onPress:e,"aria-label":"Sign out",children:"Sign out"})]}),t.jsx(Pt,{}),t.jsx(et,{}),t.jsx(kt,{}),t.jsxs("div",{className:"flex min-h-0 flex-1",children:[f&&u?t.jsx("div",{"aria-hidden":"true",onClick:()=>N(!1),className:"fixed inset-0 z-30 bg-black/40 md:hidden"}):null,t.jsxs("aside",{ref:r,id:"app-sidebar",role:f?"dialog":void 0,"aria-modal":f&&u?!0:void 0,"aria-label":f?"Navigation":void 0,tabIndex:f?-1:void 0,inert:f&&!u?!0:void 0,onKeyDown:f&&u?R:void 0,style:f?void 0:{width:Te},className:_("flex flex-col border-r border-[var(--otari-line)] bg-[var(--otari-surface)] focus:outline-none",f?_("fixed inset-y-0 left-0 z-40 w-[17rem] shadow-xl transition-transform duration-200",u?"translate-x-0":"-translate-x-full"):_("relative shrink-0",!p&&"transition-[width] duration-150")),children:[t.jsx("button",{type:"button",onClick:()=>m(l=>!l),"aria-label":d?"Expand sidebar":"Collapse sidebar","aria-pressed":d,title:d?"Expand sidebar":"Collapse sidebar",className:"absolute -right-3 top-4 z-30 hidden h-6 w-6 items-center justify-center rounded-full border border-[var(--otari-line)] bg-[var(--otari-surface)] text-[var(--otari-muted)] shadow-sm transition-colors hover:border-[var(--otari-brand)] hover:text-[var(--otari-brand-dark)] md:flex",children:t.jsx("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",className:_("h-3.5 w-3.5 transition-transform",d&&"rotate-180"),children:t.jsx("path",{d:"M15 6l-6 6 6 6",strokeLinecap:"round",strokeLinejoin:"round"})})}),t.jsx("nav",{className:_("flex flex-col py-4",S?"px-2":"px-3"),children:At.map((l,v)=>{const j=qt.filter(k=>k.section===l.key);return j.length===0?null:t.jsxs("div",{className:v>0?"mt-4":void 0,children:[!S&&l.label?t.jsx("div",{className:"px-3 pb-1 text-[11px] font-semibold tracking-wider text-[var(--otari-muted)] uppercase",children:l.label}):null,v>0&&(S||!l.label)?t.jsx("div",{className:"mx-1 mb-2 border-t border-[var(--otari-line)]"}):null,t.jsx("div",{className:"flex flex-col gap-1",children:j.map(k=>t.jsxs(G,{to:k.to,end:k.end,onClick:()=>N(!1),"aria-label":S?k.label:void 0,title:S?k.label:void 0,className:({isActive:D})=>_("flex items-center rounded-lg py-2 text-sm font-medium transition-colors",S?"justify-center px-0":"gap-3 px-3",D?"bg-[var(--otari-brand-tint)] text-[var(--otari-brand-dark)]":"text-[var(--otari-muted)] hover:bg-[var(--otari-bg)] hover:text-[var(--otari-ink)]"),children:[k.icon,S?null:k.label]},k.to))})]},l.key)})}),t.jsxs("div",{className:"mt-auto flex flex-col gap-1 pb-3",children:[t.jsxs(G,{to:"/docs",onClick:()=>N(!1),"aria-label":S?"User guide":void 0,title:S?"User guide":void 0,className:({isActive:l})=>_("flex items-center rounded-lg py-2 text-sm font-medium transition-colors",S?"mx-2 justify-center px-0":"mx-3 gap-3 px-3",l?"bg-[var(--otari-brand-tint)] text-[var(--otari-brand-dark)]":"text-[var(--otari-muted)] hover:bg-[var(--otari-bg)] hover:text-[var(--otari-ink)]"),children:[t.jsxs("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("path",{d:"M12 6.5C10.5 5 8 4.5 4 4.5V18c4 0 6.5.5 8 2 1.5-1.5 4-2 8-2V4.5c-4 0-6.5.5-8 2z",strokeLinejoin:"round"}),t.jsx("path",{d:"M12 6.5V20",strokeLinecap:"round"})]}),S?null:"User guide"]}),t.jsxs("a",{href:"https://otari.ai",target:"_blank",rel:"noreferrer",title:"otari.ai: the hosted Otari gateway",className:_("flex items-center rounded-lg py-2 text-xs font-medium text-[var(--otari-muted)] transition-colors hover:bg-[var(--otari-bg)] hover:text-[var(--otari-brand-dark)]",S?"mx-2 justify-center px-0":"mx-3 gap-2 px-3"),children:[t.jsx("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-4 w-4 shrink-0",children:t.jsx("path",{d:"M18 10h-1.26A8 8 0 1 0 9 20h9a5 5 0 0 0 0-10z",strokeLinejoin:"round"})}),S?null:t.jsxs("span",{className:"flex-1",children:["otari.ai ",t.jsx("span",{"aria-hidden":!0,children:"↗"})]})]})]}),d||f?null:t.jsx("div",{role:"separator","aria-orientation":"vertical","aria-label":"Resize sidebar","aria-valuenow":Math.round(i),"aria-valuemin":ge,"aria-valuemax":be,tabIndex:0,onPointerDown:Ee,onPointerMove:Pe,onPointerUp:Ne,onKeyDown:_e,className:_("absolute top-0 right-0 z-10 h-full w-1.5 cursor-col-resize touch-none transition-colors","hover:bg-[var(--otari-brand)] focus-visible:bg-[var(--otari-brand)] focus:outline-none",p?"bg-[var(--otari-brand)]":"bg-transparent")})]}),t.jsx("main",{ref:n,id:"main-content",tabIndex:-1,inert:z,className:"flex-1 overflow-y-auto focus:outline-none",children:t.jsx("div",{className:"mx-auto flex max-w-[1800px] flex-col gap-6 px-4 py-5 md:px-6 md:py-6",children:t.jsx(De,{})})})]})]})}function Dt(){const{login:e}=Z(),[r,n]=a.useState(""),[s,i]=a.useState(null),[o,d]=a.useState(!1),m=async()=>{const p=r.trim();if(!(!p||o)){d(!0),i(null);try{await He(p)?e():i(new Error("Invalid master key."))}catch(x){i(x)}finally{d(!1)}}};return t.jsx("div",{className:"flex min-h-full items-center justify-center p-6",children:t.jsx(I,{className:"w-full max-w-md",children:t.jsxs(I.Content,{className:"flex flex-col gap-5 p-7",children:[t.jsxs("div",{className:"flex flex-col items-center gap-3 text-center",children:[t.jsx("img",{src:"/favicon.svg",alt:"Otari",className:"h-12 w-12"}),t.jsxs("div",{children:[t.jsx("h1",{className:"text-lg font-semibold text-[var(--otari-ink)]",children:"Otari Dashboard"}),t.jsx("p",{className:"mt-1 text-sm text-[var(--otari-muted)]",children:"Sign in with your master key to browse models, set pricing, and manage settings."})]})]}),t.jsxs("form",{className:"flex flex-col gap-4",onSubmit:p=>{p.preventDefault(),m()},children:[t.jsxs(ze,{value:r,onChange:p=>{n(p),s&&i(null)},type:"password",isRequired:!0,className:"flex flex-col gap-1",children:[t.jsx(me,{className:"text-sm font-medium text-[var(--otari-ink)]",children:"Master key"}),t.jsx(fe,{placeholder:"otari-mk-… or your master key",autoFocus:!0,autoComplete:"off"})]}),t.jsxs("details",{className:"text-xs text-[var(--otari-muted)]",children:[t.jsx("summary",{className:"cursor-pointer font-medium text-[var(--otari-brand-dark)]",children:"First run? Where to find your key"}),t.jsxs("p",{className:"mt-2 leading-relaxed",children:["If you did not set ",t.jsx("code",{children:"OTARI_MASTER_KEY"}),", Otari generated one and printed it to the server logs on startup. Look for the line ",t.jsx("code",{children:"Your master key:"})," (for example, run"," ",t.jsx("code",{children:"docker logs "}),") and paste it above."]})]}),t.jsx(bt,{error:s}),t.jsx(C,{type:"submit",variant:"primary",fullWidth:!0,isDisabled:!r.trim()||o,children:o?"Signing in…":"Sign in"})]}),t.jsx("p",{className:"text-center text-xs text-[var(--otari-muted)]",children:"The key is sent once to this gateway and exchanged for a session cookie; it is never stored in the browser."}),t.jsx("div",{className:"border-t border-[var(--otari-line)] pt-4 text-center",children:t.jsx($e,{href:"/welcome",className:"text-sm font-medium text-[var(--otari-brand-dark)]",children:"New to Otari? Open the welcome guide"})})]})})})}const Ot=a.lazy(async()=>({default:(await P(async()=>{const{ActivityPage:e}=await import("./ActivityPage-lcRQhBAw.js");return{ActivityPage:e}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9]))).ActivityPage})),Mt=a.lazy(async()=>({default:(await P(async()=>{const{AliasesPage:e}=await import("./AliasesPage-CPjhdIJQ.js");return{AliasesPage:e}},__vite__mapDeps([10,1,2,6,4,7,8,11]))).AliasesPage})),Ft=a.lazy(async()=>({default:(await P(async()=>{const{BudgetsPage:e}=await import("./BudgetsPage-BuN1cg5q.js");return{BudgetsPage:e}},__vite__mapDeps([12,1,2,6,4,7,8,11]))).BudgetsPage})),Ut=a.lazy(async()=>({default:(await P(async()=>{const{DocsPage:e}=await import("./DocsPage-Bw1czoYN.js");return{DocsPage:e}},__vite__mapDeps([13,1,2,4]))).DocsPage})),Kt=a.lazy(async()=>({default:(await P(async()=>{const{KeysPage:e}=await import("./KeysPage-DHZEligd.js");return{KeysPage:e}},__vite__mapDeps([14,1,2,6,4,7,8,11,15]))).KeysPage})),Bt=a.lazy(async()=>({default:(await P(async()=>{const{ModelsPage:e}=await import("./ModelsPage-avB5ycpT.js");return{ModelsPage:e}},__vite__mapDeps([16,1,2,6,4,8,9]))).ModelsPage})),zt=a.lazy(async()=>({default:(await P(async()=>{const{OverviewIndex:e}=await import("./OverviewPage-CNyNgkDA.js");return{OverviewIndex:e}},__vite__mapDeps([17,1,2,18,5,4,8]))).OverviewIndex})),$t=a.lazy(async()=>({default:(await P(async()=>{const{ProvidersPage:e}=await import("./ProvidersPage-DueCtyY7.js");return{ProvidersPage:e}},__vite__mapDeps([19,1,2,11,4,8]))).ProvidersPage})),Qt=a.lazy(async()=>({default:(await P(async()=>{const{SettingsPage:e}=await import("./SettingsPage-BVUWlkda.js");return{SettingsPage:e}},__vite__mapDeps([20,1,2,4]))).SettingsPage})),Vt=a.lazy(async()=>({default:(await P(async()=>{const{ToolsGuardrailsPage:e}=await import("./ToolsGuardrailsPage-5txNsDJk.js");return{ToolsGuardrailsPage:e}},__vite__mapDeps([21,1,2,4]))).ToolsGuardrailsPage})),Wt=a.lazy(async()=>({default:(await P(async()=>{const{UsagePage:e}=await import("./UsagePage-B19CFPzF.js");return{UsagePage:e}},__vite__mapDeps([22,1,2,3,4,5,6,18,7,8,9]))).UsagePage})),Ht=a.lazy(async()=>({default:(await P(async()=>{const{UsersPage:e}=await import("./UsersPage-8qOL-FQs.js");return{UsersPage:e}},__vite__mapDeps([23,1,2,6,4,7,8,11,15]))).UsersPage}));function E(e){return t.jsx(a.Suspense,{fallback:t.jsx("div",{role:"status",children:"Loading page…"}),children:e})}function Gt(){const{isAuthenticated:e}=Z();return e?t.jsx(Oe,{children:t.jsx(Me,{children:t.jsxs(w,{element:t.jsx(Rt,{}),children:[t.jsx(w,{index:!0,element:E(t.jsx(zt,{}))}),t.jsx(w,{path:"providers",element:E(t.jsx($t,{}))}),t.jsx(w,{path:"keys",element:E(t.jsx(Kt,{}))}),t.jsx(w,{path:"users",element:E(t.jsx(Ht,{}))}),t.jsx(w,{path:"budgets",element:E(t.jsx(Ft,{}))}),t.jsx(w,{path:"activity",element:E(t.jsx(Ot,{}))}),t.jsx(w,{path:"usage",element:E(t.jsx(Wt,{}))}),t.jsx(w,{path:"models",element:E(t.jsx(Bt,{}))}),t.jsx(w,{path:"aliases",element:E(t.jsx(Mt,{}))}),t.jsx(w,{path:"tools",element:E(t.jsx(Vt,{}))}),t.jsx(w,{path:"settings",element:E(t.jsx(Qt,{}))}),t.jsx(w,{path:"docs",element:E(t.jsx(Ut,{}))}),t.jsx(w,{path:"*",element:t.jsx(Fe,{to:"/",replace:!0})})]})})}):t.jsx(Dt,{})}function Jt({children:e}){const[r]=a.useState(()=>new Ae({defaultOptions:{queries:{refetchOnWindowFocus:!1,retry:(n,s)=>s instanceof T&&(s.status===401||s.status===403)?!1:n<2}}}));return t.jsx(qe,{client:r,children:t.jsx(Ye,{children:e})})}const ke=document.getElementById("root");if(!ke)throw new Error("Root element #root not found");Qe.createRoot(ke).render(t.jsx(a.StrictMode,{children:t.jsx(Jt,{children:t.jsx(Gt,{})})}));export{ur as $,kr as A,Jr as B,ln as C,Er as D,bt as E,cn as F,gt as G,Yr as H,jt as I,at as J,Gr as K,nr as L,on as M,ir as N,en as O,nn as P,Xr as Q,sn as R,tn as S,rn as T,Hr as U,yt as V,pt as W,lr as X,dr as Y,fr as Z,it as _,_r as a,or as a0,cr as a1,ar as a2,sr as a3,hr as a4,Pr as a5,Nr as a6,Cr as a7,gr as a8,mr as a9,br as aa,jr as ab,wr as ac,Zr as ad,Br as ae,Ur as af,zr as b,$r as c,Wr as d,Qr as e,Vr as f,un as g,rr as h,vr as i,pr as j,yr as k,qr as l,Dr as m,Or as n,Mr as o,Kr as p,an as q,Rr as r,Lr as s,Ir as t,Fr as u,Ar as v,Tr as w,tr as x,Sr as y,xr as z}; +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ActivityPage-BngVFI4f.js","assets/tanstack-query-1t81HyiD.js","assets/react-dgEcD0HR.js","assets/FilterChips-DZjxf-ot.js","assets/heroui-BI50yK5B.js","assets/recharts-C4kRDmvS.js","assets/tableSelection-9hV37uhu.js","assets/ConfirmDialog-BFS2k4X_.js","assets/DataTable-Bmn_eYSV.js","assets/TablePagination-BtDO5gaH.js","assets/AliasesPage-0BMZtDwo.js","assets/Field-Dwp6u3t8.js","assets/BudgetsPage-DSFlTi1s.js","assets/DocsPage-DneryjqV.js","assets/KeysPage-C0dFnjAw.js","assets/ModelScopeControl-hWii6vSv.js","assets/ModelsPage-CDwjz2Xn.js","assets/OverviewPage-D2MB34d0.js","assets/charts-DIsd9m--.js","assets/ProvidersPage-Los10ECT.js","assets/SettingsPage-DJbI5U1N.js","assets/ToolsGuardrailsPage-BuyJANrn.js","assets/UsagePage-D99w-NDh.js","assets/UsersPage-m0ebv2w3.js"])))=>i.map(i=>d[i]); +var Le=Object.defineProperty;var Ie=(e,r,n)=>r in e?Le(e,r,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[r]=n;var ie=(e,r,n)=>Ie(e,typeof r!="symbol"?r+"":r,n);import{u as y,j as t,a as g,b as h,k as X,Q as Ae,c as qe}from"./tanstack-query-1t81HyiD.js";import{d as Re,r as a,N as G,O as De,H as Oe,e as Me,f as w,h as Fe}from"./react-dgEcD0HR.js";import{B as C,C as M,L as me,I as fe,a as Ue,b as Ke,d as I,S as Be,c as _,T as ze,e as $e}from"./heroui-BI50yK5B.js";(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))s(i);new MutationObserver(i=>{for(const o of i)if(o.type==="childList")for(const d of o.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&s(d)}).observe(document,{childList:!0,subtree:!0});function n(i){const o={};return i.integrity&&(o.integrity=i.integrity),i.referrerPolicy&&(o.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?o.credentials="include":i.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function s(i){if(i.ep)return;i.ep=!0;const o=n(i);fetch(i.href,o)}})();var Qe=Re();const Ve="modulepreload",We=function(e){return"/"+e},oe={},P=function(r,n,s){let i=Promise.resolve();if(n&&n.length>0){let d=function(x){return Promise.all(x.map(f=>Promise.resolve(f).then(b=>({status:"fulfilled",value:b}),b=>({status:"rejected",reason:b}))))};document.getElementsByTagName("link");const m=document.querySelector("meta[property=csp-nonce]"),p=(m==null?void 0:m.nonce)||(m==null?void 0:m.getAttribute("nonce"));i=d(n.map(x=>{if(x=We(x),x in oe)return;oe[x]=!0;const f=x.endsWith(".css"),b=f?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${x}"]${b}`))return;const u=document.createElement("link");if(u.rel=f?"stylesheet":Ve,f||(u.as="script"),u.crossOrigin="",u.href=x,p&&u.setAttribute("nonce",p),document.head.appendChild(u),f)return new Promise((N,R)=>{u.addEventListener("load",N),u.addEventListener("error",()=>R(new Error(`Unable to preload CSS for ${x}`)))})}))}function o(d){const m=new Event("vite:preloadError",{cancelable:!0});if(m.payload=d,window.dispatchEvent(m),!m.defaultPrevented)throw d}return i.then(d=>{for(const m of d||[])m.status==="rejected"&&o(m.reason);return r().catch(o)})};class T extends Error{constructor(n,s){super(s);ie(this,"status");this.name="ApiError",this.status=n}}let F=null;function le(e){F=e}async function J(e){try{const r=await e.json();if(typeof r.detail=="string")return r.detail;if(r.detail!=null)return JSON.stringify(r.detail)}catch{}return e.statusText||`Request failed (${e.status})`}async function He(e){let r;try{r=await fetch("/v1/auth/session",{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify({master_key:e})})}catch{throw new T(0,"Network error: could not reach the gateway.")}if(r.status===401||r.status===403)return!1;if(!r.ok)throw new T(r.status,await J(r));return!0}async function Ge(){try{await fetch("/v1/auth/session",{method:"DELETE"})}catch{}}async function c(e,r={}){const n=new Headers(r.headers);n.set("Accept","application/json"),r.body!=null&&!n.has("Content-Type")&&n.set("Content-Type","application/json");let s;try{s=await fetch(e,{...r,headers:n})}catch{throw new T(0,"Network error: could not reach the gateway.")}if(s.status===401||s.status===403)throw F==null||F(),new T(s.status,await J(s));if(!s.ok)throw new T(s.status,await J(s));if(s.status!==204)return await s.json()}const Y="otari.dashboard.hasSession",he=a.createContext(null);function Je(){try{return window.localStorage.getItem(Y)==="1"}catch{return!1}}function Ye({children:e}){const r=y(),[n,s]=a.useState(Je),i=a.useCallback(()=>{Ge(),s(!1),r.clear();try{window.localStorage.removeItem(Y)}catch{}},[r]),o=a.useCallback(()=>{r.clear(),s(!0);try{window.localStorage.setItem(Y,"1")}catch{}},[r]);a.useEffect(()=>(le(i),()=>le(null)),[i]);const d=a.useMemo(()=>({isAuthenticated:n,login:o,logout:i}),[n,o,i]);return t.jsx(he.Provider,{value:d,children:e})}function Z(){const e=a.useContext(he);if(!e)throw new Error("useAuth must be used within an AuthProvider");return e}function Xe(e){return e instanceof T&&e.status===0}function Ze(){const e=y(),[r,n]=a.useState(!1);return a.useEffect(()=>{const s=e.getQueryCache(),i=()=>s.getAll().some(o=>o.state.status==="error"&&Xe(o.state.error));return n(i()),s.subscribe(()=>n(i()))},[e]),r}function et(){return Ze()?t.jsxs("div",{role:"alert","aria-live":"assertive",className:"fixed right-4 bottom-4 z-50 flex max-w-sm items-start gap-2.5 rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700 shadow-lg",children:[t.jsxs("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2","aria-hidden":!0,className:"mt-0.5 h-5 w-5 shrink-0",children:[t.jsx("path",{d:"M12 9v4M12 17h.01",strokeLinecap:"round",strokeLinejoin:"round"}),t.jsx("path",{d:"M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z",strokeLinejoin:"round"})]}),t.jsxs("span",{children:[t.jsx("strong",{className:"font-semibold",children:"Can’t reach the gateway."})," The backend isn’t responding; data won’t load or save until the connection is restored."]})]}):null}const L="models",K="pricing",xe="settings",ve="tool-settings",ee="aliases",te="discoverable",re="providers",ne="provider-health",ye="stored-providers",tt="model-metadata",rt="build",A="keys",q="budgets",pe="users",O="usage",nt=6e4,ce=60*6e4;function tr(){return g({queryKey:[L],queryFn:()=>c("/v1/models"),staleTime:6e4})}function st(){return g({queryKey:[rt],queryFn:()=>c("/dashboard-build.json"),refetchInterval:nt,refetchOnWindowFocus:!0,staleTime:0,retry:!1})}function rr(){return g({queryKey:[te],queryFn:()=>c("/v1/models/discoverable"),staleTime:5*6e4})}function nr(){return g({queryKey:[re],queryFn:()=>c("/v1/providers"),staleTime:5*6e4})}function sr(){return g({queryKey:["provider-catalog"],queryFn:()=>c("/v1/providers/catalog"),staleTime:1/0})}function ar(e){return g({queryKey:["provider-catalog",e],queryFn:()=>c(`/v1/providers/catalog/${encodeURIComponent(e)}`),enabled:e!=="",staleTime:1/0})}function ir(){return g({queryKey:[ne],queryFn:()=>c("/v1/providers/health"),staleTime:ce,refetchInterval:ce})}function or(){const e=y();return h({mutationFn:()=>c("/v1/providers/health?refresh=true"),onSuccess:r=>e.setQueryData([ne],r)})}function lr(){return g({queryKey:[ye],queryFn:()=>c("/v1/provider-credentials"),staleTime:6e4})}function B(e){e.invalidateQueries({queryKey:[ye]}),e.invalidateQueries({queryKey:[re]}),e.invalidateQueries({queryKey:[L]}),e.invalidateQueries({queryKey:[te]}),e.invalidateQueries({queryKey:[ne]})}function cr(){const e=y();return h({mutationFn:r=>c("/v1/provider-credentials",{method:"POST",body:JSON.stringify(r)}),onSuccess:()=>B(e)})}function ur(){const e=y();return h({mutationFn:({instance:r,body:n})=>c(`/v1/provider-credentials/${encodeURIComponent(r)}`,{method:"PATCH",body:JSON.stringify(n)}),onSuccess:()=>B(e)})}function dr(){const e=y();return h({mutationFn:r=>c(`/v1/provider-credentials/${encodeURIComponent(r)}`,{method:"DELETE"}),onSuccess:()=>B(e)})}function mr(){const e=y();return h({mutationFn:()=>c("/v1/provider-credentials/reencrypt",{method:"POST"}),onSuccess:()=>B(e)})}function fr(){return h({mutationFn:e=>c(`/v1/provider-credentials/${encodeURIComponent(e)}/test`,{method:"POST"})})}function hr(){return h({mutationFn:e=>c("/v1/provider-credentials/test",{method:"POST",body:JSON.stringify(e)})})}function xr(){return g({queryKey:[tt],queryFn:()=>c("/v1/models/metadata"),staleTime:10*6e4})}function vr(){return g({queryKey:[ee],queryFn:()=>c("/v1/aliases"),staleTime:6e4})}function yr(){const e=y();return h({mutationFn:r=>c("/v1/aliases",{method:"POST",body:JSON.stringify(r)}),onSuccess:()=>{e.invalidateQueries({queryKey:[ee]}),e.invalidateQueries({queryKey:[L]})}})}function pr(){const e=y();return h({mutationFn:r=>c(`/v1/aliases/${encodeURIComponent(r)}`,{method:"DELETE"}),onSuccess:()=>{e.invalidateQueries({queryKey:[ee]}),e.invalidateQueries({queryKey:[L]})}})}function at(){return g({queryKey:[xe],queryFn:()=>c("/v1/settings"),staleTime:6e4})}function it(){const e=y();return h({mutationFn:r=>c("/v1/settings",{method:"PATCH",body:JSON.stringify(r)}),onSuccess:r=>{e.setQueryData([xe],r),e.invalidateQueries({queryKey:[L]}),e.invalidateQueries({queryKey:[te]})}})}function gr(){return h({mutationFn:()=>c("/v1/settings/master-key/rotate",{method:"POST"})})}function br(){return g({queryKey:[ve],queryFn:()=>c("/v1/tool-settings"),staleTime:6e4})}function jr(){const e=y();return h({mutationFn:r=>c("/v1/tool-settings",{method:"PATCH",body:JSON.stringify(r)}),onSuccess:r=>{e.setQueryData([ve],r)}})}function wr(){return h({mutationFn:({service:e,url:r})=>c(`/v1/tool-settings/${encodeURIComponent(e)}/test`,{method:"POST",body:JSON.stringify({url:r})})})}const $=1e3,ot=100;async function lt(){const e=[];for(let r=0;rc("/v1/pricing",{method:"POST",body:JSON.stringify(r)}),onSuccess:()=>{e.invalidateQueries({queryKey:[K]}),e.invalidateQueries({queryKey:[L]})}})}function Er(){const e=y();return h({mutationFn:r=>c(`/v1/pricing/${encodeURIComponent(r)}`,{method:"DELETE"}),onSuccess:()=>{e.invalidateQueries({queryKey:[K]}),e.invalidateQueries({queryKey:[L]})}})}function Pr(){return h({mutationFn:()=>c("/v1/pricing/refresh",{method:"POST"})})}function Nr(){const e=y();return h({mutationFn:()=>c("/v1/pricing/refresh/confirm",{method:"POST"}),onSuccess:()=>{e.invalidateQueries({queryKey:[K]}),e.invalidateQueries({queryKey:[L]}),e.invalidateQueries({queryKey:[re]})}})}function Cr(){return h({mutationFn:()=>c("/v1/pricing/refresh/reject",{method:"POST"})})}const Q=1e3,ct=100;async function ut(){const e=[];for(let r=0;rc("/v1/keys",{method:"POST",body:JSON.stringify(r)}),onSuccess:()=>void e.invalidateQueries({queryKey:[A]})})}function Lr(){const e=y();return h({mutationFn:({id:r,body:n})=>c(`/v1/keys/${encodeURIComponent(r)}`,{method:"PATCH",body:JSON.stringify(n)}),onSuccess:()=>void e.invalidateQueries({queryKey:[A]})})}function Ir(){const e=y();return h({mutationFn:r=>c(`/v1/keys/${encodeURIComponent(r)}/rotate`,{method:"POST"}),onSuccess:()=>void e.invalidateQueries({queryKey:[A]})})}function Ar(){const e=y();return h({mutationFn:r=>c(`/v1/keys/${encodeURIComponent(r)}`,{method:"DELETE"}),onSuccess:()=>void e.invalidateQueries({queryKey:[A]})})}const V=1e3,dt=100;async function mt(){const e=[];for(let r=0;rc(`/v1/budgets/${encodeURIComponent(e)}/reset-logs`),enabled:e!==null,staleTime:6e4})}function Dr(){const e=y();return h({mutationFn:r=>c("/v1/budgets",{method:"POST",body:JSON.stringify(r)}),onSuccess:()=>void e.invalidateQueries({queryKey:[q]})})}function Or(){const e=y();return h({mutationFn:({id:r,body:n})=>c(`/v1/budgets/${encodeURIComponent(r)}`,{method:"PATCH",body:JSON.stringify(n)}),onSuccess:()=>void e.invalidateQueries({queryKey:[q]})})}function Mr(){const e=y();return h({mutationFn:r=>c(`/v1/budgets/${encodeURIComponent(r)}`,{method:"DELETE"}),onSuccess:()=>void e.invalidateQueries({queryKey:[q]})})}const W=1e3,ft=100;async function ht(){const e=[];for(let r=0;rc("/v1/users",{method:"POST",body:JSON.stringify(r)}),onSuccess:()=>se(e)})}function Kr(){const e=y();return h({mutationFn:({id:r,body:n})=>c(`/v1/users/${encodeURIComponent(r)}`,{method:"PATCH",body:JSON.stringify(n)}),onSuccess:()=>se(e)})}function Br(){const e=y();return h({mutationFn:r=>c(`/v1/users/${encodeURIComponent(r)}`,{method:"DELETE"}),onSuccess:()=>{se(e),e.invalidateQueries({queryKey:[A]})}})}function ae(e){const r=new URLSearchParams;return e.start_date&&r.set("start_date",e.start_date),e.end_date&&r.set("end_date",e.end_date),e.status&&r.set("status",e.status),e.model&&r.set("model",e.model),e.endpoint&&r.set("endpoint",e.endpoint),e.user_id&&r.set("user_id",e.user_id),e.api_key_id&&r.set("api_key_id",e.api_key_id),e.source&&r.set("source",e.source),e.priced!==void 0&&r.set("priced",String(e.priced)),e.counts_toward_budget!==void 0&&r.set("counts_toward_budget",String(e.counts_toward_budget)),r}function zr(e,r,n){return g({queryKey:[O,"list",e,r,n],queryFn:()=>{const s=ae(e);return s.set("skip",String(r*n)),s.set("limit",String(n)),c(`/v1/usage?${s.toString()}`)},placeholderData:X,staleTime:1e4})}function $r(e,r=!0){return g({queryKey:[O,"count",e],queryFn:()=>c(`/v1/usage/count?${ae(e).toString()}`),enabled:r,placeholderData:X,staleTime:1e4})}function Qr(){const e=y();return h({mutationFn:r=>c("/v1/usage",{method:"DELETE",body:JSON.stringify(r)}),onSuccess:()=>{e.invalidateQueries({queryKey:[O]})}})}function Vr(){const e=y();return h({mutationFn:r=>c("/v1/usage/set-price",{method:"POST",body:JSON.stringify(r)}),onSuccess:()=>{e.invalidateQueries({queryKey:[O]})}})}function Wr(e,r,n=!0){return g({queryKey:[O,"summary",e,r],queryFn:()=>{const s=ae(e);return s.set("bucket",r),c(`/v1/usage/summary?${s.toString()}`)},enabled:n,placeholderData:X,staleTime:3e4})}function Hr(e){return e==null?"0":new Intl.NumberFormat("en-US").format(e)}function Gr(e){if(e==null)return"$0.00";const r=e!==0&&Math.abs(e)<.01?4:2;return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:r}).format(e)}function Jr(e){if(e==null)return"—";if(e>=1e6){const r=e/1e6;return`${Number.isInteger(r)?r:r.toFixed(1)}M`}if(e>=1e3){const r=Math.round(e/1e3);return r>=1e3?"1M":`${r}K`}return String(e)}const xt=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function Yr(e){if(!e)return"—";const r=/^(\d{4})-(\d{2})/.exec(e);if(!r)return e;const n=Number(r[2])-1;return n<0||n>11?r[1]:`${xt[n]} ${r[1]}`}const vt=new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",maximumFractionDigits:2});function Xr(e){return vt.format(e)}function Zr(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e)}function yt(e){return`${(e*100).toFixed(1)}%`}function en(e,r){return r===void 0||r===0?null:(e-r)/r}function pt(e,r=Date.now()){if(!e)return"never";const n=new Date(e);if(Number.isNaN(n.getTime()))return e;const s=Math.round((r-n.getTime())/1e3),i=s<0,o=Math.abs(s),d=[["second",60],["minute",60],["hour",24],["day",30],["month",12],["year",Number.POSITIVE_INFINITY]];let m=o,p="second";for(const[f,b]of d){if(p=f,m0?"▲":e<0?"▼":"•";return t.jsxs("span",{className:"text-[var(--otari-muted)]",children:[r," ",yt(Math.abs(e))," vs prev"]})}function gt(e){return e instanceof T||e instanceof Error?e.message:"Something went wrong."}function bt({error:e}){return e?t.jsx("div",{role:"alert",className:"rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700",children:gt(e)}):null}function jt({tone:e="info",children:r}){const n=e==="warning"?"border-amber-200 bg-amber-50 text-amber-800":"border-[var(--otari-brand)] bg-[var(--otari-brand-tint)] text-[var(--otari-brand-dark)]";return t.jsx("div",{className:`rounded-lg border px-4 py-3 text-sm ${n}`,children:r})}function nn({title:e,description:r,action:n}){return t.jsxs("div",{className:"flex flex-col gap-3",children:[t.jsxs("div",{children:[t.jsx("h1",{className:"text-xl font-semibold text-[var(--otari-ink)]",children:e}),r?t.jsx("p",{className:"mt-1 text-sm text-[var(--otari-muted)]",children:r}):null]}),n?t.jsx("div",{className:"flex flex-wrap gap-2",children:n}):null]})}function wt(e){const[r,n]=a.useState(()=>Date.now());return a.useEffect(()=>{let s;const i=()=>{s===void 0&&(s=setInterval(()=>n(Date.now()),e))},o=()=>{s!==void 0&&(clearInterval(s),s=void 0)},d=()=>{n(Date.now()),document.visibilityState==="visible"?i():o()};return d(),document.addEventListener("visibilitychange",d),()=>{o(),document.removeEventListener("visibilitychange",d)}},[e]),r}function sn({onRefresh:e,isFetching:r=!1,updatedAt:n,label:s="Refresh"}){const i=wt(15e3),o=n?pt(new Date(n).toISOString(),i):null;return t.jsxs("span",{className:"inline-flex items-center gap-2",children:[o?t.jsxs("span",{className:"text-xs text-[var(--otari-muted)]",children:["Updated ",o]}):null,t.jsx(C,{variant:"outline",size:"sm",isIconOnly:!0,isDisabled:r,onPress:e,"aria-label":s,children:t.jsxs("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:`h-4 w-4 ${r?"animate-spin":""}`,"aria-hidden":"true",children:[t.jsx("path",{d:"M20 11a8 8 0 1 0-.5 4",strokeLinecap:"round",strokeLinejoin:"round"}),t.jsx("path",{d:"M20 4v5h-5",strokeLinecap:"round",strokeLinejoin:"round"})]})})]})}function an({title:e,description:r,actionLabel:n,onAction:s,isActionDisabled:i,children:o}){return t.jsx(I,{children:t.jsxs(I.Content,{className:"flex flex-col gap-4 p-6",children:[t.jsxs("div",{children:[t.jsx("h2",{className:"text-lg font-semibold text-[var(--otari-ink)]",children:e}),r?t.jsx("p",{className:"mt-1 text-sm text-[var(--otari-muted)]",children:r}):null]}),o,n&&s?t.jsx("div",{children:t.jsx(C,{variant:"primary",isDisabled:i,onPress:s,children:n})}):null]})})}function on({label:e="Loading…"}){return t.jsxs("div",{role:"status",className:"flex items-center justify-center gap-2 px-4 py-10 text-sm text-[var(--otari-muted)]",children:[t.jsx(Be,{size:"sm"}),t.jsx("span",{children:e})]})}function ln({children:e,confirmLabel:r,onConfirm:n,isPending:s}){const[i,o]=a.useState(!1);return i?t.jsxs("span",{className:"inline-flex items-center gap-1",children:[t.jsx(C,{size:"sm",variant:"danger",isDisabled:s,onPress:n,children:r}),t.jsx(C,{size:"sm",variant:"ghost",isDisabled:s,onPress:()=>o(!1),children:"Cancel"})]}):t.jsx(C,{size:"sm",variant:"danger-soft",onPress:()=>o(!0),children:e})}const St="rounded-lg border border-[var(--otari-line)] bg-[var(--otari-bg)] px-3 py-2 text-sm text-[var(--otari-ink)] focus:border-[var(--otari-brand)] focus:outline-none";function cn({id:e,label:r,ariaLabel:n,value:s,onChange:i,options:o,children:d,disabled:m}){const p=a.useId(),x=e??(r?p:void 0),f=t.jsx("select",{id:x,"aria-label":r?void 0:n,value:s,disabled:m,onChange:b=>i(b.target.value),className:St,children:o?o.map(b=>t.jsx("option",{value:b.value,children:b.label},b.value)):d});return r?t.jsxs("div",{className:"flex flex-col gap-1",children:[t.jsx("label",{htmlFor:x,className:"text-xs font-medium text-[var(--otari-muted)]",children:r}),f]}):f}function un({label:e,value:r,onChange:n,options:s,placeholder:i,maxVisible:o=50,allowsCustom:d=!1}){const m=u=>{var N;return((N=s.find(R=>R.value===u))==null?void 0:N.label)??u},[p,x]=a.useState(()=>m(r));a.useEffect(()=>{x(m(r))},[r]);const f=p.trim().toLowerCase(),b=s.filter(u=>!f||u.value.toLowerCase().includes(f)||u.label.toLowerCase().includes(f)).slice(0,o);return t.jsxs(M.Root,{allowsEmptyCollection:!0,allowsCustomValue:d,menuTrigger:"focus",inputValue:p,onInputChange:u=>{x(u),d?n(u.trim()):u.trim()===""&&n("")},onSelectionChange:u=>{u!=null&&n(String(u))},className:"flex flex-col gap-1",children:[t.jsx(me,{className:"text-xs font-medium text-[var(--otari-muted)]",children:e}),t.jsxs(M.InputGroup,{children:[t.jsx(fe,{placeholder:i,autoComplete:"off",onFocus:u=>u.currentTarget.select()}),t.jsx(M.Trigger,{})]}),t.jsx(M.Popover,{children:t.jsx(Ue,{items:b,className:"max-h-72 overflow-auto",children:u=>t.jsx(Ke,{id:u.value,textValue:u.label,children:u.label})})})]})}function kt(){var o;const e=at(),r=it(),[n,s]=a.useState(!1);return!(((o=e.data)==null?void 0:o.require_pricing)===!0&&e.data.default_pricing===!1)||n?null:t.jsx("div",{className:"shrink-0 px-6 pt-3",children:t.jsx(jt,{tone:"warning",children:t.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[t.jsxs("span",{children:["Requests are rejected until pricing is set (",t.jsx("code",{children:"require_pricing"})," is on). Enable default pricing to meter new models with public rates right away."]}),t.jsxs("span",{className:"flex items-center gap-2",children:[t.jsx(C,{size:"sm",variant:"primary",isDisabled:r.isPending,onPress:()=>r.mutate({default_pricing:!0}),children:r.isPending?"Enabling…":"Enable default pricing"}),t.jsx(C,{size:"sm",variant:"ghost",onPress:()=>s(!0),children:"Dismiss"})]})]})})})}function Et(){const{data:e}=st(),r=a.useRef(null);return e&&r.current===null&&(r.current=e.build),e!=null&&r.current!=null&&e.build!==r.current}function Pt(){const e=Et(),[r,n]=a.useState(!1);return!e||r?null:t.jsx("div",{className:"pointer-events-none absolute inset-x-0 top-0 z-50 flex justify-center",children:t.jsxs("div",{role:"status",className:"pointer-events-auto mt-1.5 flex items-center gap-3 rounded-full border border-[var(--otari-brand)] bg-[var(--otari-brand-tint)] py-1.5 pr-1.5 pl-4 text-sm text-[var(--otari-brand-dark)] shadow-md",children:[t.jsxs("span",{children:[t.jsx("strong",{className:"font-semibold",children:"An update is available."})," Reloading keeps you signed in."]}),t.jsx(C,{size:"sm",variant:"primary",onPress:()=>window.location.reload(),children:"Update now"}),t.jsx(C,{size:"sm",variant:"ghost",onPress:()=>n(!0),children:"Later"})]})})}const ge=200,be=480,H=240,Nt=60,je="otari.dashboard.sidebarWidth",we="otari.dashboard.sidebarCollapsed",de=16,Se="(max-width: 767px)",U=e=>Math.min(be,Math.max(ge,e));function Ct(){return typeof window>"u"||typeof window.matchMedia!="function"?!1:window.matchMedia(Se).matches}const _t='a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])';function Tt(e){return e?Array.from(e.querySelectorAll(_t)).filter(r=>r.offsetParent!==null||r===document.activeElement):[]}function Lt(){if(typeof window>"u")return H;try{const e=window.localStorage.getItem(je),r=e?Number.parseInt(e,10):Number.NaN;return Number.isNaN(r)?H:U(r)}catch{return H}}function It(){if(typeof window>"u")return!1;try{return window.localStorage.getItem(we)==="1"}catch{return!1}}const At=[{key:"home"},{key:"observability",label:"Observability"},{key:"catalog",label:"Catalog"},{key:"access",label:"Access"},{key:"system"}],qt=[{to:"/",section:"home",label:"Overview",end:!0,icon:t.jsxs("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("rect",{x:"3.5",y:"3.5",width:"7",height:"7",rx:"1.5",strokeLinejoin:"round"}),t.jsx("rect",{x:"13.5",y:"3.5",width:"7",height:"7",rx:"1.5",strokeLinejoin:"round"}),t.jsx("rect",{x:"3.5",y:"13.5",width:"7",height:"7",rx:"1.5",strokeLinejoin:"round"}),t.jsx("rect",{x:"13.5",y:"13.5",width:"7",height:"7",rx:"1.5",strokeLinejoin:"round"})]})},{to:"/activity",section:"observability",label:"Activity",icon:t.jsx("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:t.jsx("path",{d:"M3 12h4l2.5-6 4 12 2.5-6H21",strokeLinecap:"round",strokeLinejoin:"round"})})},{to:"/usage",section:"observability",label:"Usage",icon:t.jsx("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:t.jsx("path",{d:"M4 20V10M10 20V4M16 20v-7M22 20H2",strokeLinecap:"round",strokeLinejoin:"round"})})},{to:"/providers",section:"catalog",label:"Providers",icon:t.jsxs("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("rect",{x:"3.5",y:"4.5",width:"17",height:"6",rx:"1.5",strokeLinejoin:"round"}),t.jsx("rect",{x:"3.5",y:"13.5",width:"17",height:"6",rx:"1.5",strokeLinejoin:"round"}),t.jsx("path",{d:"M7 7.5h.01M7 16.5h.01",strokeLinecap:"round",strokeLinejoin:"round"})]})},{to:"/users",section:"access",label:"Users",icon:t.jsxs("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("circle",{cx:"9",cy:"8",r:"3.2",strokeLinejoin:"round"}),t.jsx("path",{d:"M3.5 19a5.5 5.5 0 0 1 11 0",strokeLinecap:"round",strokeLinejoin:"round"}),t.jsx("path",{d:"M16 5.2a3.2 3.2 0 0 1 0 5.6M17.5 19a5.5 5.5 0 0 0-3-4.9",strokeLinecap:"round",strokeLinejoin:"round"})]})},{to:"/keys",section:"access",label:"API keys",icon:t.jsxs("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("circle",{cx:"7.5",cy:"15.5",r:"3.5"}),t.jsx("path",{d:"M10 13l7-7M14 5l3 3M16.5 7.5l2-2",strokeLinecap:"round",strokeLinejoin:"round"})]})},{to:"/budgets",section:"access",label:"Budgets",icon:t.jsxs("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("path",{d:"M3 7.5A1.5 1.5 0 0 1 4.5 6H18a1.5 1.5 0 0 1 1.5 1.5V9",strokeLinejoin:"round"}),t.jsx("rect",{x:"3",y:"7.5",width:"18",height:"12",rx:"1.5",strokeLinejoin:"round"}),t.jsx("path",{d:"M16 13.5h.01",strokeLinecap:"round",strokeLinejoin:"round"}),t.jsx("path",{d:"M21 12v3h-3.5a1.5 1.5 0 0 1 0-3H21z",strokeLinejoin:"round"})]})},{to:"/models",section:"catalog",label:"Models",icon:t.jsxs("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("path",{d:"M12 3l8 4.5v9L12 21l-8-4.5v-9L12 3z",strokeLinejoin:"round"}),t.jsx("path",{d:"M12 12l8-4.5M12 12v9M12 12L4 7.5",strokeLinejoin:"round"})]})},{to:"/aliases",section:"catalog",label:"Aliases",icon:t.jsxs("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("path",{d:"M20.6 13.4L13.4 20.6a2 2 0 0 1-2.8 0l-7-7A2 2 0 0 1 3 12.2V5a2 2 0 0 1 2-2h7.2a2 2 0 0 1 1.4.6l7 7a2 2 0 0 1 0 2.8z",strokeLinejoin:"round"}),t.jsx("circle",{cx:"7.5",cy:"7.5",r:"1.5"})]})},{to:"/tools",section:"system",label:"Tools & Guardrails",icon:t.jsxs("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("path",{d:"M14.7 6.3a4 4 0 0 1 5 5l-8.4 8.4a2 2 0 0 1-2.8 0l-2.2-2.2a2 2 0 0 1 0-2.8z",strokeLinejoin:"round"}),t.jsx("path",{d:"M12 9 5 16",strokeLinecap:"round"})]})},{to:"/settings",section:"system",label:"Settings",icon:t.jsxs("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("circle",{cx:"12",cy:"12",r:"3"}),t.jsx("path",{d:"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z",strokeLinejoin:"round"})]})}];function Rt(){const{logout:e}=Z(),r=a.useRef(null),n=a.useRef(null),s=a.useRef(null),[i,o]=a.useState(Lt),[d,m]=a.useState(It),[p,x]=a.useState(!1),[f,b]=a.useState(Ct),[u,N]=a.useState(!1);a.useEffect(()=>{if(typeof window>"u"||typeof window.matchMedia!="function")return;const l=window.matchMedia(Se),v=j=>{b(j.matches),j.matches||N(!1)};return typeof l.addEventListener=="function"?(l.addEventListener("change",v),()=>l.removeEventListener("change",v)):(l.addListener(v),()=>l.removeListener(v))},[]),a.useEffect(()=>{if(!u)return;const l=v=>{v.key==="Escape"&&N(!1)};return window.addEventListener("keydown",l),()=>window.removeEventListener("keydown",l)},[u]),a.useEffect(()=>{var l,v,j;f&&(u?(l=r.current)==null||l.focus():(v=r.current)!=null&&v.contains(document.activeElement)&&((j=s.current)==null||j.focus()))},[f,u]);const R=a.useCallback(l=>{if(l.key!=="Tab")return;const v=Tt(r.current);if(v.length===0)return;const j=v[0],k=v[v.length-1],D=document.activeElement;l.shiftKey&&(D===j||D===r.current)?(l.preventDefault(),k.focus()):!l.shiftKey&&D===k&&(l.preventDefault(),j.focus())},[]);a.useEffect(()=>{const l=window.setTimeout(()=>{try{window.localStorage.setItem(je,String(Math.round(i)))}catch{}},200);return()=>window.clearTimeout(l)},[i]),a.useEffect(()=>{try{window.localStorage.setItem(we,d?"1":"0")}catch{}},[d]);const Ee=a.useCallback(l=>{l.preventDefault(),l.currentTarget.setPointerCapture(l.pointerId),x(!0)},[]),Pe=a.useCallback(l=>{var j;if(!l.currentTarget.hasPointerCapture(l.pointerId))return;const v=((j=r.current)==null?void 0:j.getBoundingClientRect().left)??0;o(U(l.clientX-v))},[]),Ne=a.useCallback(l=>{l.currentTarget.hasPointerCapture(l.pointerId)&&l.currentTarget.releasePointerCapture(l.pointerId),x(!1)},[]),Ce=a.useCallback(l=>{var v;l.preventDefault(),(v=n.current)==null||v.focus()},[]),_e=a.useCallback(l=>{l.key==="ArrowLeft"?(l.preventDefault(),o(v=>U(v-de))):l.key==="ArrowRight"&&(l.preventDefault(),o(v=>U(v+de)))},[]),Te=d?Nt:i,S=f?!1:d,z=f&&u?!0:void 0;return t.jsxs("div",{className:_("relative flex h-full flex-col overflow-hidden",p&&"cursor-col-resize select-none"),children:[t.jsx("button",{type:"button",inert:z,onClick:Ce,className:"sr-only focus:not-sr-only focus:absolute focus:top-3 focus:left-3 focus:z-50 focus:rounded-lg focus:border focus:border-[var(--otari-brand)] focus:bg-[var(--otari-surface)] focus:px-4 focus:py-2 focus:text-sm focus:font-medium focus:text-[var(--otari-brand-dark)] focus:shadow-md focus:outline-none",children:"Skip to main content"}),t.jsxs("header",{inert:z,className:"flex shrink-0 items-center justify-between border-b border-[var(--otari-line)] bg-[var(--otari-surface)] px-5 py-3",children:[t.jsxs("div",{className:"flex items-center gap-2.5",children:[t.jsx("button",{type:"button",ref:s,onClick:()=>N(l=>!l),"aria-label":u?"Close navigation":"Open navigation","aria-expanded":u,"aria-controls":"app-sidebar",className:"-ml-1 flex h-8 w-8 items-center justify-center rounded-lg text-[var(--otari-muted)] transition-colors hover:bg-[var(--otari-bg)] hover:text-[var(--otari-ink)] md:hidden",children:t.jsx("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5",children:t.jsx("path",{d:"M4 6h16M4 12h16M4 18h16",strokeLinecap:"round",strokeLinejoin:"round"})})}),t.jsx("img",{src:"/favicon.svg",alt:"",className:"h-7 w-7 shrink-0"}),t.jsx("span",{className:"text-base font-semibold text-[var(--otari-ink)]",children:"Otari"})]}),t.jsx(C,{size:"sm",variant:"outline",onPress:e,"aria-label":"Sign out",children:"Sign out"})]}),t.jsx(Pt,{}),t.jsx(et,{}),t.jsx(kt,{}),t.jsxs("div",{className:"flex min-h-0 flex-1",children:[f&&u?t.jsx("div",{"aria-hidden":"true",onClick:()=>N(!1),className:"fixed inset-0 z-30 bg-black/40 md:hidden"}):null,t.jsxs("aside",{ref:r,id:"app-sidebar",role:f?"dialog":void 0,"aria-modal":f&&u?!0:void 0,"aria-label":f?"Navigation":void 0,tabIndex:f?-1:void 0,inert:f&&!u?!0:void 0,onKeyDown:f&&u?R:void 0,style:f?void 0:{width:Te},className:_("flex flex-col border-r border-[var(--otari-line)] bg-[var(--otari-surface)] focus:outline-none",f?_("fixed inset-y-0 left-0 z-40 w-[17rem] shadow-xl transition-transform duration-200",u?"translate-x-0":"-translate-x-full"):_("relative shrink-0",!p&&"transition-[width] duration-150")),children:[t.jsx("button",{type:"button",onClick:()=>m(l=>!l),"aria-label":d?"Expand sidebar":"Collapse sidebar","aria-pressed":d,title:d?"Expand sidebar":"Collapse sidebar",className:"absolute -right-3 top-4 z-30 hidden h-6 w-6 items-center justify-center rounded-full border border-[var(--otari-line)] bg-[var(--otari-surface)] text-[var(--otari-muted)] shadow-sm transition-colors hover:border-[var(--otari-brand)] hover:text-[var(--otari-brand-dark)] md:flex",children:t.jsx("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",className:_("h-3.5 w-3.5 transition-transform",d&&"rotate-180"),children:t.jsx("path",{d:"M15 6l-6 6 6 6",strokeLinecap:"round",strokeLinejoin:"round"})})}),t.jsx("nav",{className:_("flex flex-col py-4",S?"px-2":"px-3"),children:At.map((l,v)=>{const j=qt.filter(k=>k.section===l.key);return j.length===0?null:t.jsxs("div",{className:v>0?"mt-4":void 0,children:[!S&&l.label?t.jsx("div",{className:"px-3 pb-1 text-[11px] font-semibold tracking-wider text-[var(--otari-muted)] uppercase",children:l.label}):null,v>0&&(S||!l.label)?t.jsx("div",{className:"mx-1 mb-2 border-t border-[var(--otari-line)]"}):null,t.jsx("div",{className:"flex flex-col gap-1",children:j.map(k=>t.jsxs(G,{to:k.to,end:k.end,onClick:()=>N(!1),"aria-label":S?k.label:void 0,title:S?k.label:void 0,className:({isActive:D})=>_("flex items-center rounded-lg py-2 text-sm font-medium transition-colors",S?"justify-center px-0":"gap-3 px-3",D?"bg-[var(--otari-brand-tint)] text-[var(--otari-brand-dark)]":"text-[var(--otari-muted)] hover:bg-[var(--otari-bg)] hover:text-[var(--otari-ink)]"),children:[k.icon,S?null:k.label]},k.to))})]},l.key)})}),t.jsxs("div",{className:"mt-auto flex flex-col gap-1 pb-3",children:[t.jsxs(G,{to:"/docs",onClick:()=>N(!1),"aria-label":S?"User guide":void 0,title:S?"User guide":void 0,className:({isActive:l})=>_("flex items-center rounded-lg py-2 text-sm font-medium transition-colors",S?"mx-2 justify-center px-0":"mx-3 gap-3 px-3",l?"bg-[var(--otari-brand-tint)] text-[var(--otari-brand-dark)]":"text-[var(--otari-muted)] hover:bg-[var(--otari-bg)] hover:text-[var(--otari-ink)]"),children:[t.jsxs("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-5 w-5 shrink-0",children:[t.jsx("path",{d:"M12 6.5C10.5 5 8 4.5 4 4.5V18c4 0 6.5.5 8 2 1.5-1.5 4-2 8-2V4.5c-4 0-6.5.5-8 2z",strokeLinejoin:"round"}),t.jsx("path",{d:"M12 6.5V20",strokeLinecap:"round"})]}),S?null:"User guide"]}),t.jsxs("a",{href:"https://otari.ai",target:"_blank",rel:"noreferrer",title:"otari.ai: the hosted Otari gateway",className:_("flex items-center rounded-lg py-2 text-xs font-medium text-[var(--otari-muted)] transition-colors hover:bg-[var(--otari-bg)] hover:text-[var(--otari-brand-dark)]",S?"mx-2 justify-center px-0":"mx-3 gap-2 px-3"),children:[t.jsx("svg",{"aria-hidden":!0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"h-4 w-4 shrink-0",children:t.jsx("path",{d:"M18 10h-1.26A8 8 0 1 0 9 20h9a5 5 0 0 0 0-10z",strokeLinejoin:"round"})}),S?null:t.jsxs("span",{className:"flex-1",children:["otari.ai ",t.jsx("span",{"aria-hidden":!0,children:"↗"})]})]})]}),d||f?null:t.jsx("div",{role:"separator","aria-orientation":"vertical","aria-label":"Resize sidebar","aria-valuenow":Math.round(i),"aria-valuemin":ge,"aria-valuemax":be,tabIndex:0,onPointerDown:Ee,onPointerMove:Pe,onPointerUp:Ne,onKeyDown:_e,className:_("absolute top-0 right-0 z-10 h-full w-1.5 cursor-col-resize touch-none transition-colors","hover:bg-[var(--otari-brand)] focus-visible:bg-[var(--otari-brand)] focus:outline-none",p?"bg-[var(--otari-brand)]":"bg-transparent")})]}),t.jsx("main",{ref:n,id:"main-content",tabIndex:-1,inert:z,className:"flex-1 overflow-y-auto focus:outline-none",children:t.jsx("div",{className:"mx-auto flex max-w-[1800px] flex-col gap-6 px-4 py-5 md:px-6 md:py-6",children:t.jsx(De,{})})})]})]})}function Dt(){const{login:e}=Z(),[r,n]=a.useState(""),[s,i]=a.useState(null),[o,d]=a.useState(!1),m=async()=>{const p=r.trim();if(!(!p||o)){d(!0),i(null);try{await He(p)?e():i(new Error("Invalid master key."))}catch(x){i(x)}finally{d(!1)}}};return t.jsx("div",{className:"flex min-h-full items-center justify-center p-6",children:t.jsx(I,{className:"w-full max-w-md",children:t.jsxs(I.Content,{className:"flex flex-col gap-5 p-7",children:[t.jsxs("div",{className:"flex flex-col items-center gap-3 text-center",children:[t.jsx("img",{src:"/favicon.svg",alt:"Otari",className:"h-12 w-12"}),t.jsxs("div",{children:[t.jsx("h1",{className:"text-lg font-semibold text-[var(--otari-ink)]",children:"Otari Dashboard"}),t.jsx("p",{className:"mt-1 text-sm text-[var(--otari-muted)]",children:"Sign in with your master key to browse models, set pricing, and manage settings."})]})]}),t.jsxs("form",{className:"flex flex-col gap-4",onSubmit:p=>{p.preventDefault(),m()},children:[t.jsxs(ze,{value:r,onChange:p=>{n(p),s&&i(null)},type:"password",isRequired:!0,className:"flex flex-col gap-1",children:[t.jsx(me,{className:"text-sm font-medium text-[var(--otari-ink)]",children:"Master key"}),t.jsx(fe,{placeholder:"otari-mk-… or your master key",autoFocus:!0,autoComplete:"off"})]}),t.jsxs("details",{className:"text-xs text-[var(--otari-muted)]",children:[t.jsx("summary",{className:"cursor-pointer font-medium text-[var(--otari-brand-dark)]",children:"First run? Where to find your key"}),t.jsxs("p",{className:"mt-2 leading-relaxed",children:["If you did not set ",t.jsx("code",{children:"OTARI_MASTER_KEY"}),", Otari generated one and printed it to the server logs on startup. Look for the line ",t.jsx("code",{children:"Your master key:"})," (for example, run"," ",t.jsx("code",{children:"docker logs "}),") and paste it above."]})]}),t.jsx(bt,{error:s}),t.jsx(C,{type:"submit",variant:"primary",fullWidth:!0,isDisabled:!r.trim()||o,children:o?"Signing in…":"Sign in"})]}),t.jsx("p",{className:"text-center text-xs text-[var(--otari-muted)]",children:"The key is sent once to this gateway and exchanged for a session cookie; it is never stored in the browser."}),t.jsx("div",{className:"border-t border-[var(--otari-line)] pt-4 text-center",children:t.jsx($e,{href:"/welcome",className:"text-sm font-medium text-[var(--otari-brand-dark)]",children:"New to Otari? Open the welcome guide"})})]})})})}const Ot=a.lazy(async()=>({default:(await P(async()=>{const{ActivityPage:e}=await import("./ActivityPage-BngVFI4f.js");return{ActivityPage:e}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9]))).ActivityPage})),Mt=a.lazy(async()=>({default:(await P(async()=>{const{AliasesPage:e}=await import("./AliasesPage-0BMZtDwo.js");return{AliasesPage:e}},__vite__mapDeps([10,1,2,6,4,7,8,11]))).AliasesPage})),Ft=a.lazy(async()=>({default:(await P(async()=>{const{BudgetsPage:e}=await import("./BudgetsPage-DSFlTi1s.js");return{BudgetsPage:e}},__vite__mapDeps([12,1,2,6,4,7,8,11]))).BudgetsPage})),Ut=a.lazy(async()=>({default:(await P(async()=>{const{DocsPage:e}=await import("./DocsPage-DneryjqV.js");return{DocsPage:e}},__vite__mapDeps([13,1,2,4]))).DocsPage})),Kt=a.lazy(async()=>({default:(await P(async()=>{const{KeysPage:e}=await import("./KeysPage-C0dFnjAw.js");return{KeysPage:e}},__vite__mapDeps([14,1,2,6,4,7,8,11,15]))).KeysPage})),Bt=a.lazy(async()=>({default:(await P(async()=>{const{ModelsPage:e}=await import("./ModelsPage-CDwjz2Xn.js");return{ModelsPage:e}},__vite__mapDeps([16,1,2,6,4,8,9]))).ModelsPage})),zt=a.lazy(async()=>({default:(await P(async()=>{const{OverviewIndex:e}=await import("./OverviewPage-D2MB34d0.js");return{OverviewIndex:e}},__vite__mapDeps([17,1,2,18,5,4,8]))).OverviewIndex})),$t=a.lazy(async()=>({default:(await P(async()=>{const{ProvidersPage:e}=await import("./ProvidersPage-Los10ECT.js");return{ProvidersPage:e}},__vite__mapDeps([19,1,2,11,4,8]))).ProvidersPage})),Qt=a.lazy(async()=>({default:(await P(async()=>{const{SettingsPage:e}=await import("./SettingsPage-DJbI5U1N.js");return{SettingsPage:e}},__vite__mapDeps([20,1,2,4]))).SettingsPage})),Vt=a.lazy(async()=>({default:(await P(async()=>{const{ToolsGuardrailsPage:e}=await import("./ToolsGuardrailsPage-BuyJANrn.js");return{ToolsGuardrailsPage:e}},__vite__mapDeps([21,1,2,4]))).ToolsGuardrailsPage})),Wt=a.lazy(async()=>({default:(await P(async()=>{const{UsagePage:e}=await import("./UsagePage-D99w-NDh.js");return{UsagePage:e}},__vite__mapDeps([22,1,2,3,4,5,6,18,7,8,9]))).UsagePage})),Ht=a.lazy(async()=>({default:(await P(async()=>{const{UsersPage:e}=await import("./UsersPage-m0ebv2w3.js");return{UsersPage:e}},__vite__mapDeps([23,1,2,6,4,7,8,11,15]))).UsersPage}));function E(e){return t.jsx(a.Suspense,{fallback:t.jsx("div",{role:"status",children:"Loading page…"}),children:e})}function Gt(){const{isAuthenticated:e}=Z();return e?t.jsx(Oe,{children:t.jsx(Me,{children:t.jsxs(w,{element:t.jsx(Rt,{}),children:[t.jsx(w,{index:!0,element:E(t.jsx(zt,{}))}),t.jsx(w,{path:"providers",element:E(t.jsx($t,{}))}),t.jsx(w,{path:"keys",element:E(t.jsx(Kt,{}))}),t.jsx(w,{path:"users",element:E(t.jsx(Ht,{}))}),t.jsx(w,{path:"budgets",element:E(t.jsx(Ft,{}))}),t.jsx(w,{path:"activity",element:E(t.jsx(Ot,{}))}),t.jsx(w,{path:"usage",element:E(t.jsx(Wt,{}))}),t.jsx(w,{path:"models",element:E(t.jsx(Bt,{}))}),t.jsx(w,{path:"aliases",element:E(t.jsx(Mt,{}))}),t.jsx(w,{path:"tools",element:E(t.jsx(Vt,{}))}),t.jsx(w,{path:"settings",element:E(t.jsx(Qt,{}))}),t.jsx(w,{path:"docs",element:E(t.jsx(Ut,{}))}),t.jsx(w,{path:"*",element:t.jsx(Fe,{to:"/",replace:!0})})]})})}):t.jsx(Dt,{})}function Jt({children:e}){const[r]=a.useState(()=>new Ae({defaultOptions:{queries:{refetchOnWindowFocus:!1,retry:(n,s)=>s instanceof T&&(s.status===401||s.status===403)?!1:n<2}}}));return t.jsx(qe,{client:r,children:t.jsx(Ye,{children:e})})}const ke=document.getElementById("root");if(!ke)throw new Error("Root element #root not found");Qe.createRoot(ke).render(t.jsx(a.StrictMode,{children:t.jsx(Jt,{children:t.jsx(Gt,{})})}));export{ur as $,kr as A,Jr as B,ln as C,Er as D,bt as E,cn as F,gt as G,Yr as H,jt as I,at as J,Gr as K,nr as L,on as M,ir as N,en as O,nn as P,Xr as Q,sn as R,tn as S,rn as T,Hr as U,yt as V,pt as W,lr as X,dr as Y,fr as Z,it as _,_r as a,or as a0,cr as a1,ar as a2,sr as a3,hr as a4,Pr as a5,Nr as a6,Cr as a7,gr as a8,mr as a9,br as aa,jr as ab,wr as ac,Zr as ad,Br as ae,Ur as af,zr as b,$r as c,Wr as d,Qr as e,Vr as f,un as g,rr as h,vr as i,pr as j,yr as k,qr as l,Dr as m,Or as n,Mr as o,Kr as p,an as q,Rr as r,Lr as s,Ir as t,Fr as u,Ar as v,Tr as w,tr as x,Sr as y,xr as z}; diff --git a/src/gateway/static/dashboard/index.html b/src/gateway/static/dashboard/index.html index 11ff74b0..c254392a 100644 --- a/src/gateway/static/dashboard/index.html +++ b/src/gateway/static/dashboard/index.html @@ -19,7 +19,7 @@ insets to sit out of the way. --> Otari Dashboard - +