omnigateway 0.4.7 → 0.4.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +53 -15
  2. package/bin/omni.js +11 -11
  3. package/gateway.js +10 -15
  4. package/package.json +1 -1
  5. package/public/assets/{CopyValue-BiiqC_Z2.js → CopyValue-CHZz2PLE.js} +1 -1
  6. package/public/assets/{Field-b0ohzqzR.js → Field-B79Yxdit.js} +1 -1
  7. package/public/assets/{Match-B2ZxNor3.js → Match-BWa6L0L1.js} +1 -1
  8. package/public/assets/Panel-CoulMx6R.js +25 -0
  9. package/public/assets/Rack-ziQuyb2l.js +314 -0
  10. package/public/assets/{Readout-VYnpaTMg.js → Readout-D1XEfywe.js} +1 -1
  11. package/public/assets/States-Shs8nZi1.js +54 -0
  12. package/public/assets/{Toggle-DMk46RX2.js → Toggle-CNnMgEU1.js} +1 -1
  13. package/public/assets/{TokenBreakdown-B9RanXin.js → TokenBreakdown-hkwYCWT3.js} +1 -1
  14. package/public/assets/_app-BD1K3SGD.js +1 -0
  15. package/public/assets/_app.accounts-BDBEn5vF.js +64 -0
  16. package/public/assets/{_app.console-eFiUh-OA.js → _app.console-BtLYkvSQ.js} +4 -4
  17. package/public/assets/_app.database-ByLAAKXX.js +24 -0
  18. package/public/assets/_app.index-3mAmJsCn.js +62 -0
  19. package/public/assets/_app.keys-Ce6Xd1RK.js +76 -0
  20. package/public/assets/{_app.logs-DV7O6ZUp.js → _app.logs-CmDNhsU4.js} +7 -7
  21. package/public/assets/_app.models-mqdU56d8.js +148 -0
  22. package/public/assets/_app.plugins._pluginId-C0VWWCD2.js +20 -0
  23. package/public/assets/{_app.settings-B8zjCira.js → _app.settings-BLJ-25xq.js} +3 -3
  24. package/public/assets/{_app.usage-C4GR06sI.js → _app.usage-BaB40kku.js} +4 -4
  25. package/public/assets/{index-B2twwe7y.js → index-C3Fp8XmZ.js} +3 -3
  26. package/public/assets/{login-CJz2YA-O.js → login-Bn1s6JI_.js} +2 -2
  27. package/public/assets/plus-Cdyfj4uP.js +1 -0
  28. package/public/assets/{queries-BOAAI06M.js → queries-CX9mStps.js} +5 -2
  29. package/public/assets/{shared-Rzhx6i7s.js → shared-DtfLcn24.js} +2 -2
  30. package/public/assets/{trash-2-C7-QrCg5.js → trash-2-B5fBDSkh.js} +1 -1
  31. package/public/index.html +4 -4
  32. package/public/shared/dashboard-sdk.js +1 -0
  33. package/public/assets/Confirm-BO1xS6uH.js +0 -4
  34. package/public/assets/Lamp-BDf7-dMa.js +0 -25
  35. package/public/assets/Modal-OALemCh6.js +0 -82
  36. package/public/assets/Rack-DhVnjAjC.js +0 -180
  37. package/public/assets/States-6G9NsYha.js +0 -54
  38. package/public/assets/_app-ChlUa_Ov.js +0 -1
  39. package/public/assets/_app.accounts-CJ6lFXIx.js +0 -64
  40. package/public/assets/_app.database-BHaMpXld.js +0 -39
  41. package/public/assets/_app.index-C1vtrxnM.js +0 -62
  42. package/public/assets/_app.keys-Bz6-VVJi.js +0 -76
  43. package/public/assets/_app.models-KIctkivt.js +0 -148
  44. package/public/assets/_app.plugins._pluginId-BbqXEJUB.js +0 -20
  45. package/public/assets/dist-9ps0Qd15.js +0 -1
  46. package/public/assets/plus-C7a0RuII.js +0 -1
@@ -1,76 +0,0 @@
1
- import{$ as e,C as t,O as n,P as r,R as i,at as a,et as o,lt as s,nt as c,ot as l,p as u,rt as d,ut as f}from"./queries-BOAAI06M.js";import{o as p,t as m}from"./Rack-DhVnjAjC.js";import{n as h,r as g,t as _}from"./CopyValue-BiiqC_Z2.js";import{t as v}from"./plus-C7a0RuII.js";import{t as y}from"./Modal-OALemCh6.js";import{t as b}from"./Toggle-DMk46RX2.js";import{t as x}from"./Confirm-BO1xS6uH.js";import{C as S}from"./Lamp-BDf7-dMa.js";import{t as C}from"./Chip-BltJSw8A.js";import{n as w,r as T,t as E}from"./Field-b0ohzqzR.js";import{t as D}from"./Meter-stpt3vQu.js";import{a as O,i as k,n as A,r as j,t as M}from"./States-6G9NsYha.js";import{i as N,n as P,r as F,t as I}from"./Table-CVDZ69Zx.js";import{Fragment as L,useState as R}from"react";import{Fragment as z,jsx as B,jsxs as V}from"react/jsx-runtime";import H from"styled-components";var U=[{dimension:`requests`,window:`1m`},{dimension:`requests`,window:`5h`},{dimension:`requests`,window:`1w`},{dimension:`tokens`,window:`1m`},{dimension:`tokens`,window:`5h`},{dimension:`tokens`,window:`1w`},{dimension:`spend`,window:`5h`},{dimension:`spend`,window:`1w`},{dimension:`concurrency`,window:null}];function W(e){return e.window===null?e.dimension:`${e.dimension}:${e.window}`}var G={requests:`Requests`,tokens:`Tokens`,spend:`Spend`,concurrency:`Concurrent`},K={"1m":`per minute`,"5h":`per 5 hours`,"1w":`per week`};function q(e){let t=G[e.dimension];return e.window===null?t:`${t} ${K[e.window]}`}function J(e,t){return e===`spend`?`$${t<1?t.toFixed(4):t.toFixed(2)}`:t.toLocaleString(`en-US`)}function Y(e){return e.used===null||e.limit<=0?null:Math.max(0,e.used/e.limit)}function X(e){let t=null,n=-1;for(let r of e){let e=Y(r);e!==null&&e>n&&(t=r,n=e)}return t}function Z(e){let t={};for(let e of U)t[W(e)]=``;if(e===null)return t;for(let n of U){let r=n.window===null?e.concurrency:n.dimension===`requests`?e.requests?.[n.window]:n.dimension===`tokens`?e.tokens?.[n.window]:n.window===`1m`?void 0:e.spend?.[n.window];r!=null&&(t[W(n)]=String(r))}return t}function Q(e){let t={},n={},r={},i;for(let a of U){let o=(e[W(a)]??``).trim();if(o.length===0)continue;let s=Number(o),c=a.dimension===`spend`;if(!Number.isFinite(s)||s<=0||!c&&!Number.isInteger(s))return{problem:c?`${q(a)} must be an amount above zero, or blank for no limit.`:`${q(a)} must be a whole number above zero, or blank for no limit.`};a.window===null?i=s:a.dimension===`requests`?t[a.window]=s:a.dimension===`tokens`?n[a.window]=s:a.window!==`1m`&&(r[a.window]=s)}return{limits:{...Object.keys(t).length>0?{requests:t}:{},...Object.keys(n).length>0?{tokens:n}:{},...Object.keys(r).length>0?{spend:r}:{},...i===void 0?{}:{concurrency:i}}}}var ee=H.div`
2
- display: grid;
3
- grid-template-columns: repeat(3, minmax(0, 1fr));
4
- gap: ${({theme:e})=>e.space(2)};
5
- `,te=H.p`
6
- font-size: 11px;
7
- color: ${({theme:e})=>e.color.inkDim};
8
- `;function $({draft:e,onChange:t,disabled:n=!1}){return V(a,{$gap:2,children:[B(ee,{children:U.map(r=>{let i=W(r);return B(E,{label:q(r),children:a=>B(T,{...a,min:r.dimension===`spend`?void 0:1,step:r.dimension===`spend`?`any`:1,disabled:n,value:e[i]??``,placeholder:`none`,onChange:n=>t({...e,[i]:n.target.value})})},i)})}),B(te,{children:`Blank means no limit. Token and spend ceilings are debited after a response completes, so a key at its ceiling is refused on its next request rather than its current one. Concurrency counts requests in flight right now and resets when the gateway restarts.`})]})}var ne=H.p`
9
- font-size: 12px;
10
- color: ${({theme:e})=>e.color.down};
11
- `,re=H.p`
12
- font-size: 12px;
13
- color: ${({theme:e})=>e.color.warn};
14
- `;function ie({apiKey:e,onOpenChange:t}){let n=i(),[r,o]=R(()=>Z(e?.limits??{})),[c,l]=R(null);return B(y,{open:e!==null,onOpenChange:t,title:`Edit limits`,description:e===null?void 0:`What "${e.label}" may do per minute, per five hours, and per week. Every field is a ceiling; blank is no limit.`,width:`640px`,footer:V(z,{children:[B(s,{type:`button`,onClick:()=>t(!1),children:`Cancel`}),B(s,{type:`button`,$variant:`primary`,disabled:n.isPending,onClick:()=>{if(e===null)return;let i=Q(r);if(`problem`in i){l(i.problem);return}l(null),n.mutate({id:e.id,limits:i.limits},{onSuccess:()=>t(!1),onError:e=>l(k(e))})},children:n.isPending?`Saving…`:`Save limits`})]}),children:V(a,{$gap:3,children:[e?.limits===null?B(re,{role:`status`,children:`The stored limits for this key cannot be read, so the gateway refuses it. Saving here replaces them.`}):null,B($,{draft:r,onChange:o,disabled:n.isPending}),c===null?null:B(ne,{role:`alert`,children:c})]})})}var ae=H.div`
15
- display: grid;
16
- grid-template-columns: minmax(0, 11rem) minmax(0, 12rem) minmax(0, 1fr) minmax(0, 3.5rem);
17
- align-items: center;
18
- gap: ${({theme:e})=>e.space(2)} ${({theme:e})=>e.space(4)};
19
- `,oe=H.span`
20
- font-size: 11.5px;
21
- color: ${({theme:e})=>e.color.inkDim};
22
- `,se=H.p`
23
- font-size: 11px;
24
- color: ${({theme:e})=>e.color.inkDim};
25
- `;function ce({label:t,readings:n}){return V(a,{$gap:3,children:[B(ae,{children:n.map(n=>{let r=q({dimension:n.dimension,window:n.window}),i=Y(n),a=J(n.dimension,n.limit);return V(L,{children:[B(e,{as:`span`,children:r}),B(o,{children:n.used===null?a:`${J(n.dimension,n.used)} of ${a}`}),i===null?B(oe,{children:`in flight now, counted in the gateway process`}):B(D,{fraction:Math.min(1,i),label:`${t}, ${r}, ${Math.round(i*100)}% used`}),B(o,{children:i===null?`—`:`${Math.round(i*100)}%`})]},r)})}),B(se,{children:`Usage counts completed requests still inside each window. Requests in flight are added by the gateway itself and are not shown here.`})]})}var le=H.div`
26
- display: flex;
27
- flex-direction: column;
28
- gap: 2px;
29
- max-height: 190px;
30
- overflow-y: auto;
31
- padding: ${({theme:e})=>e.space(1)};
32
- border: 1px solid ${({theme:e})=>e.color.ruleStrong};
33
- border-radius: ${({theme:e})=>e.radius.control};
34
- background: ${({theme:e})=>e.color.panelSunk};
35
- `,ue=H.label`
36
- display: flex;
37
- align-items: center;
38
- gap: ${({theme:e})=>e.space(2)};
39
- padding: 4px 6px;
40
- border-radius: 2px;
41
- cursor: pointer;
42
- font-family: ${({theme:e})=>e.font.mono};
43
- font-size: 12px;
44
-
45
- &:hover {
46
- background: ${({theme:e})=>e.color.panelRaised};
47
- }
48
- `,de=H.p`
49
- font-size: 12px;
50
- color: ${({theme:e})=>e.color.warn};
51
- `,fe=H.p`
52
- font-size: 12px;
53
- color: ${({theme:e})=>e.color.down};
54
- `,pe=H.p`
55
- font-size: 12px;
56
- color: ${({theme:e})=>e.color.inkDim};
57
- `,me=H(s)`
58
- gap: 4px;
59
- `,he=H.p`
60
- font-size: 11px;
61
- color: ${({theme:e})=>e.color.inkDim};
62
- `;function ge({open:t,onOpenChange:r}){let i=n(),l=u(),[d,f]=R(``),[p,m]=R(!0),[v,x]=R([]),[S,C]=R(()=>Z({})),[T,D]=R(!1),[O,A]=R(!1),[j,M]=R(null),[N,P]=R(null),F=()=>{f(``),m(!0),x([]),C(Z({})),D(!1),A(!1),M(null),P(null),l.reset()},I=e=>{e||F(),r(e)},L=Object.values(S).filter(e=>e.trim().length>0).length;return B(y,{open:t,onOpenChange:I,title:j===null?`Create an API key`:`Key created`,description:j===null?`Clients send this key as a bearer token or as x-api-key on every /v1 request.`:void 0,footer:j===null?V(z,{children:[B(s,{type:`button`,onClick:()=>I(!1),children:`Cancel`}),B(s,{type:`button`,$variant:`primary`,disabled:l.isPending,onClick:()=>{let e=Q(S);if(`problem`in e){D(!0),P(e.problem);return}P(null),l.mutate({label:d.trim().length===0?`api key`:d.trim(),modelAllowlist:p?null:v,limits:e.limits,bodyLoggingOptOut:O},{onSuccess:e=>M(e),onError:e=>P(k(e))})},children:l.isPending?`Creating…`:`Create key`})]}):B(s,{type:`button`,$variant:`primary`,onClick:()=>I(!1),children:`I have copied the key`}),children:j===null?V(a,{$gap:3,children:[B(E,{label:`Label`,hint:`Names the client this key belongs to, e.g. laptop or CI.`,children:e=>B(w,{...e,value:d,placeholder:`api key`,onChange:e=>f(e.target.value)})}),V(a,{$gap:2,children:[V(c,{$gap:2,children:[B(b,{checked:p,label:`Allow every model`,onCheckedChange:m}),B(e,{as:`span`,children:`Allow every model`})]}),p?null:V(z,{children:[B(le,{children:(i.data??[]).map(e=>V(ue,{children:[B(`input`,{type:`checkbox`,checked:v.includes(e.id),onChange:t=>x(n=>t.target.checked?[...n,e.id]:n.filter(t=>t!==e.id))}),e.id]},e.id))}),v.length===0?B(de,{children:`With no model selected this key is allowed nothing and every request it makes will be refused.`}):null]})]}),V(a,{$gap:2,children:[V(c,{$gap:2,children:[V(me,{type:`button`,$size:`sm`,"aria-expanded":T,onClick:()=>D(e=>!e),children:[B(T?g:h,{}),`Limits`]}),B(e,{as:`span`,children:L===0?`no limits; this key is unbounded`:`${L} limit${L===1?``:`s`} set`})]}),T?B($,{draft:S,onChange:C}):null]}),V(a,{$gap:2,children:[V(c,{$gap:2,children:[B(b,{checked:O,label:`Never record this key's bodies`,onCheckedChange:A}),B(e,{as:`span`,children:`Never record this key's bodies`})]}),B(he,{children:`Suppresses body capture for this key whatever the gateway setting says. Choose it for a client whose payloads must not be retained. It cannot be changed after the key is created — issue a new key instead.`})]}),N===null?null:B(fe,{role:`alert`,children:N})]}):V(a,{$gap:3,children:[B(pe,{children:`This is the only time the key is shown. The gateway keeps a hash, so a lost key has to be replaced rather than recovered.`}),B(_,{value:j.key,label:`Copy API key`}),V(c,{$gap:2,children:[B(e,{children:`Label`}),B(o,{children:j.label}),B(e,{children:`Prefix`}),B(o,{children:j.prefix})]})]})})}var _e=H(c)`
63
- gap: 4px;
64
- flex-wrap: wrap;
65
- max-width: 34ch;
66
- `,ve=H.span`
67
- color: ${({theme:e})=>e.color.inkFaint};
68
- `,ye=H.span`
69
- font-size: 11px;
70
- color: ${({theme:e})=>e.color.inkDim};
71
- `,be=H.div`
72
- display: flex;
73
- flex-direction: column;
74
- align-items: flex-end;
75
- gap: 2px;
76
- `;function xe(e){if(e===null)return`usage not counted here`;let t=Y(e);return`${q({dimension:e.dimension,window:e.window})} ${J(e.dimension,e.limit)}, ${t===null?`—`:Math.round(t*100)}% used`}function Se(){let n=t(),i=r(),[a,o]=R(!1),[u,_]=R(null),[y,b]=R(null),[w,T]=R(null),E=n.data??[],D=E.filter(e=>e.revokedAt===null),k=n.isLoading?`Reading issued keys…`:E.length===0?`No keys exist, so nothing can call this gateway yet.`:`${D.length} active key${D.length===1?``:`s`} of ${E.length} ever issued.`;return V(z,{children:[B(m,{legend:`Keys`,title:`Gateway API keys`,summary:k,actions:V(s,{type:`button`,$variant:`primary`,onClick:()=>o(!0),children:[B(v,{}),`Create a key`]})}),B(O,{legend:`Issued keys`,meta:`${E.length}`,flush:!0,children:n.isError?B(A,{error:n.error,onRetry:()=>void n.refetch()}):n.isLoading?B(`div`,{style:{padding:12},children:B(j,{rows:4})}):E.length===0?B(M,{legend:`No keys`,message:`Create a key and give it to a client. The key is shown once, at creation.`,action:B(s,{type:`button`,$variant:`primary`,$size:`sm`,onClick:()=>o(!0),children:`Create a key`})}):B(d,{children:V(I,{children:[B(`thead`,{children:V(`tr`,{children:[B(F,{children:`Label`}),B(F,{children:`Prefix`}),B(F,{children:`Allowed models`}),B(F,{$align:`right`,children:`Limits`}),B(F,{$align:`right`,children:`Created`}),B(F,{children:`Body capture`}),B(F,{children:`Status`}),B(F,{})]})}),B(`tbody`,{children:E.map(t=>{let n=y===t.id,r=X(t.limitUsage);return V(L,{children:[V(N,{children:[B(P,{children:B(l,{style:{maxWidth:`24ch`,display:`block`},children:t.label})}),V(P,{$mono:!0,children:[t.prefix,`…`]}),B(P,{children:t.modelAllowlist===null?B(e,{children:`every model`}):t.modelAllowlist.length===0?B(C,{$tone:`down`,children:`no models`}):B(_e,{children:t.modelAllowlist.map(e=>B(C,{children:e},e))})}),B(P,{$align:`right`,children:t.limits===null?B(C,{$tone:`down`,children:`unreadable`}):t.limitUsage.length===0?B(e,{children:`no limits`}):V(be,{children:[V(`span`,{children:[t.limitUsage.length,` limit`,t.limitUsage.length===1?``:`s`]}),B(ye,{children:xe(r)})]})}),B(P,{$align:`right`,$mono:!0,children:S(t.createdAt)}),B(P,{children:t.bodyLoggingOptOut?B(C,{children:`no bodies`}):B(e,{children:`—`})}),B(P,{children:t.revokedAt===null?B(C,{$tone:`ok`,children:`active`}):B(ve,{title:S(t.revokedAt),children:B(C,{children:`revoked`})})}),B(P,{$align:`right`,children:V(c,{$gap:1,$justify:`flex-end`,children:[t.limitUsage.length===0?null:B(f,{type:`button`,$variant:`ghost`,$size:`sm`,"aria-expanded":n,"aria-label":`${n?`Hide`:`Show`} limits for ${t.label}`,title:`${n?`Hide`:`Show`} limits for ${t.label}`,onClick:()=>b(n?null:t.id),children:B(n?g:h,{})}),t.revokedAt===null?V(z,{children:[B(f,{type:`button`,$variant:`ghost`,$size:`sm`,"aria-label":`Edit limits for ${t.label}`,title:`Edit limits for ${t.label}`,onClick:()=>_(t),children:B(p,{})}),B(s,{type:`button`,$variant:`danger`,$size:`sm`,onClick:()=>T(t),children:`Revoke`})]}):null]})})]}),n?B(N,{children:B(P,{colSpan:8,children:B(ce,{label:t.label,readings:t.limitUsage})})}):null]},t.id)})})]})})}),B(ge,{open:a,onOpenChange:o}),B(ie,{apiKey:u,onOpenChange:e=>{e||_(null)}},u?.id??`none`),B(x,{open:w!==null,onOpenChange:e=>{e||T(null)},title:`Revoke key`,body:w===null?``:`Revoking "${w.label}" refuses its next request. The key stays listed so past usage keeps its attribution, and it cannot be un-revoked.`,confirmLabel:`Revoke key`,busy:i.isPending,onConfirm:()=>{w!==null&&i.mutate(w.id,{onSettled:()=>T(null)})}})]})}var Ce=Se;export{Ce as component};
@@ -1,148 +0,0 @@
1
- import{$ as e,F as t,O as n,at as r,et as i,g as a,it as o,lt as s,nt as c,ot as l,ut as u,x as d,y as f,z as p}from"./queries-BOAAI06M.js";import{r as m}from"./index-B2twwe7y.js";import{c as h,t as g}from"./Rack-DhVnjAjC.js";import{t as _}from"./plus-C7a0RuII.js";import{t as v}from"./trash-2-C7-QrCg5.js";import{t as y}from"./Toggle-DMk46RX2.js";import{t as b}from"./Confirm-BO1xS6uH.js";import{n as x,t as S}from"./Chip-BltJSw8A.js";import{i as C,n as w,r as T,t as E}from"./Field-b0ohzqzR.js";import{t as D}from"./Meter-stpt3vQu.js";import{a as O,i as k,n as A,r as j,t as M}from"./States-6G9NsYha.js";import{i as N,n as ee,r as te,t as P}from"./catalog-BBKm8Ih8.js";import{useEffect as ne,useId as re,useState as F}from"react";import{Fragment as I,jsx as L,jsxs as R}from"react/jsx-runtime";import z from"styled-components";var ie=h(`play`,[[`path`,{d:`M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z`,key:`10ikf1`}]]),ae=h(`rotate-ccw`,[[`path`,{d:`M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8`,key:`1357e3`}],[`path`,{d:`M3 3v5h5`,key:`1xhq8a`}]]),B=[`tier`,`health`,`quota`,`cost`,`latency`,`load`],oe={tier:`How preferred this tier is`,health:`Consecutive failures and breaker state`,quota:`Headroom in the tightest window, against how much of it is left`,cost:`Price of this request against the other candidates`,latency:`Observed time to first token`,load:`Requests in flight on this pair right now`},se=z.li`
2
- padding: ${({theme:e})=>e.space(2)} 0;
3
- border-bottom: 1px solid ${({theme:e})=>e.color.rule};
4
-
5
- &:last-child {
6
- border-bottom: 0;
7
- }
8
- `,ce=z(i)`
9
- width: 22px;
10
- color: ${({theme:e})=>e.color.inkFaint};
11
- flex: none;
12
- `,le=z(S)`
13
- border-color: ${({theme:e})=>e.color.ok};
14
- color: ${({theme:e})=>e.color.ok};
15
- background: ${({theme:e})=>e.color.okWash};
16
- `,ue=z.div`
17
- display: grid;
18
- grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
19
- gap: ${({theme:e})=>e.space(2)};
20
- margin-top: ${({theme:e})=>e.space(2)};
21
- padding-left: 30px;
22
- `,de=z.div`
23
- display: flex;
24
- flex-direction: column;
25
- gap: 3px;
26
- min-width: 0;
27
- `,fe=z.div`
28
- display: flex;
29
- align-items: baseline;
30
- justify-content: space-between;
31
- gap: 6px;
32
- `,pe=z.li`
33
- display: flex;
34
- align-items: center;
35
- gap: ${({theme:e})=>e.space(2)};
36
- padding: 5px 0;
37
- `,me=z(c)`
38
- gap: ${({theme:e})=>e.space(3)};
39
- flex-wrap: wrap;
40
- `,V=z.label`
41
- display: flex;
42
- align-items: center;
43
- gap: 6px;
44
- cursor: pointer;
45
- font-size: 12.5px;
46
- `,he=z.p`
47
- font-size: 12px;
48
- color: ${({theme:e})=>e.color.down};
49
- `;function H(e,t,n){return(e[t]??0)*n[t]}function ge({modelId:t}){let[n,a]=F({tools:!1,images:!1,reasoning:!1}),[u,f]=F(null),[m,h]=F(null),g=p(),_=d(),v=g.data?.weights,b=()=>{t!==null&&(h(null),_.mutate({modelId:t,need:n},{onSuccess:e=>f(e),onError:e=>{f(null),h(k(e))}}))},C=new Map(B.map(e=>[e,Math.max(1e-4,...(u?.candidates??[]).map(t=>v===void 0?0:Math.abs(H(t.reasons,e,v))))]));return L(O,{legend:`Explain`,meta:t??`no model selected`,actions:R(s,{type:`button`,$size:`sm`,$variant:`primary`,disabled:t===null||_.isPending,onClick:b,children:[L(ie,{}),_.isPending?`Ranking…`:`Rank candidates`]}),children:R(r,{$gap:3,children:[R(r,{$gap:1,children:[L(e,{children:`Pretend the request needs`}),R(me,{children:[R(V,{children:[L(y,{checked:n.tools,label:`Probe request uses tools`,onCheckedChange:e=>a({...n,tools:e})}),`Tools`]}),R(V,{children:[L(y,{checked:n.images,label:`Probe request includes an image`,onCheckedChange:e=>a({...n,images:e})}),`Images`]}),R(V,{children:[L(y,{checked:n.reasoning,label:`Probe request asks for reasoning`,onCheckedChange:e=>a({...n,reasoning:e})}),`Reasoning`]})]})]}),m===null?null:L(he,{children:m}),u===null?L(M,{legend:`Not ranked yet`,message:t===null?`Select a model to see which account the router would pick for it.`:`Run the ranking to see which account wins, by how much, and what was filtered out.`}):R(r,{$gap:3,children:[R(c,{$gap:2,$wrap:!0,children:[L(S,{$tone:`accent`,children:u.strategy}),u.deterministic?null:L(S,{$tone:`warn`,children:`order varies per request`}),L(o,{}),R(e,{children:[u.candidates.length,` eligible · `,u.excluded.length,` filtered out`]})]}),u.candidates.length===0?L(M,{legend:`Nothing eligible`,message:`Every target was filtered out. The reasons below say which rule removed each one.`}):L(`ul`,{children:u.candidates.map((t,n)=>R(se,{children:[R(c,{$gap:2,children:[L(ce,{children:n+1}),L(x,{provider:t.provider}),L(l,{style:{maxWidth:`22ch`},children:t.credentialLabel}),L(i,{$dim:!0,children:t.model}),R(S,{children:[`tier `,t.tier]}),L(o,{}),n===0?L(le,{children:`would be used`}):null,L(i,{children:t.score.toFixed(2)})]}),v===void 0?null:L(ue,{children:B.map(n=>{let r=H(t.reasons,n,v),a=C.get(n)??1;return R(de,{title:oe[n],children:[R(fe,{children:[L(e,{children:n}),L(i,{$dim:!0,$size:`10.5px`,children:r.toFixed(2)})]}),L(D,{fraction:Math.abs(r)/a,height:4,tone:`var(--accent)`,label:`${n} contributes ${r.toFixed(2)} of ${t.score.toFixed(2)}`})]},n)})})]},`${t.credentialId}:${t.model}`))}),u.excluded.length===0?null:R(r,{$gap:1,children:[L(e,{children:`Filtered out`}),L(`ul`,{children:u.excluded.map(e=>R(pe,{children:[L(i,{$dim:!0,children:e.model}),L(o,{}),L(S,{$tone:e.reason.startsWith(`capability`)?`warn`:`down`,children:e.reason})]},`${e.credentialId}:${e.model}:${e.reason}`))})]})]})]})})}var U=[{id:`score`,label:`Best score`,blurb:`Rank every eligible target by the routing weights and take the best one.`},{id:`priority`,label:`Lowest tier`,blurb:`Always prefer the lowest tier. Score only breaks ties inside a tier.`},{id:`roundRobin`,label:`Round robin`,blurb:`Take whichever eligible target has been idle longest, to spread load evenly.`},{id:`weighted`,label:`Weighted draw`,blurb:`Pick at random, biased by weight. The order differs from request to request.`}],W=0;function G(){return W+=1,`target-${W}`}function K(e,t){let n=N(e,t);return n===null?null:{costInput:String(n.input),costOutput:String(n.output),costCacheRead:String(n.cacheRead),costCacheWrite5m:String(n.cacheWrite5m),costCacheWrite1h:String(n.cacheWrite1h)}}function _e(e,t){let n=ee(e,t);return n===null?null:{contextWindow:String(n.contextWindow),maxOutputTokens:String(n.maxOutputTokens)}}var ve={oauth:`OAuth`,apiKey:`an API key`};function q(e){return e.map(e=>ve[e]).join(` or `)}function ye(e){let t={};for(let n of e){let e=t[n.provider]??[];e.includes(n.authType)||e.push(n.authType),t[n.provider]=e}return t}function J(e,t,n){let r=n[e];return r===void 0||r.length===0||te(e,t).some(e=>r.includes(e))}function be(e,t){return P[e].models.filter(n=>J(e,n.id,t))}function xe(e,t,n){if(t.trim().length===0||J(e,t,n))return null;let r=n[e]??[];return`${e} serves this model to ${q(te(e,t))} only, and every ${e} account here is ${q(r)}. Requests routed here will fail.`}function Se(e,t){return{...e,...t,...K(t.provider,t.model)??{},contextWindow:``,maxOutputTokens:``}}function Y(e=`anthropic`){let t=P[e].defaultModel,n=K(e,t);return{key:G(),provider:e,endpointId:``,model:t,tier:`1`,weight:`1`,costInput:n?.costInput??`0`,costOutput:n?.costOutput??`0`,costCacheRead:n?.costCacheRead??``,costCacheWrite5m:n?.costCacheWrite5m??``,costCacheWrite1h:n?.costCacheWrite1h??``,contextWindow:``,maxOutputTokens:``,tools:!0,images:!0,reasoning:!0}}function X(){return{id:``,strategy:`score`,isAlias:!1,targets:[Y()]}}function Ce(e){return{id:e.id,strategy:e.strategy,isAlias:e.isAlias,targets:e.targets.map(e=>({key:G(),provider:e.provider,endpointId:e.provider===`custom`?e.endpointId??``:``,model:e.model,tier:String(e.tier),weight:String(e.weight),costInput:String(e.costPerMTok.input),costOutput:String(e.costPerMTok.output),costCacheRead:e.costPerMTok.cacheRead===void 0?``:String(e.costPerMTok.cacheRead),costCacheWrite5m:e.costPerMTok.cacheWrite5m===void 0?``:String(e.costPerMTok.cacheWrite5m),costCacheWrite1h:e.costPerMTok.cacheWrite1h===void 0?``:String(e.costPerMTok.cacheWrite1h),contextWindow:e.contextWindow===void 0?``:String(e.contextWindow),maxOutputTokens:e.maxOutputTokens===void 0?``:String(e.maxOutputTokens),tools:e.capabilities.tools,images:e.capabilities.images,reasoning:e.capabilities.reasoning}))}}function we(e){let t=e.id.trim();if(t.length===0)return{ok:!1,problem:`Give the model a name clients will ask for.`};if(e.targets.length===0)return{ok:!1,problem:`A model needs at least one target to route to.`};let n=[];for(let[t,r]of e.targets.entries()){let e=`Target ${t+1}`,i=r.endpointId.trim();if(r.provider===`custom`&&i.length===0)return{ok:!1,problem:`${e} needs a custom endpoint.`};let a=r.model.trim();if(a.length===0)return{ok:!1,problem:`${e} needs a provider model name.`};let o=Number(r.tier);if(!Number.isInteger(o)||o<1)return{ok:!1,problem:`${e}: tier must be a whole number of 1 or more.`};let s=Number(r.weight);if(!Number.isFinite(s)||s<=0)return{ok:!1,problem:`${e}: weight must be greater than zero.`};let c=Number(r.costInput),l=Number(r.costOutput);if(!Number.isFinite(c)||c<0||!Number.isFinite(l)||l<0)return{ok:!1,problem:`${e}: prices cannot be negative.`};let u=r.costCacheRead.trim().length>0,d=Number(r.costCacheRead);if(u&&(!Number.isFinite(d)||d<0))return{ok:!1,problem:`${e}: the cache-read price cannot be negative.`};let f=r.costCacheWrite5m.trim().length>0,p=Number(r.costCacheWrite5m);if(f&&(!Number.isFinite(p)||p<0))return{ok:!1,problem:`${e}: the 5m cache-write price must be a number of 0 or more.`};let m=r.costCacheWrite1h.trim().length>0,h=Number(r.costCacheWrite1h);if(m&&(!Number.isFinite(h)||h<0))return{ok:!1,problem:`${e}: the 1h cache-write price must be a number of 0 or more.`};let g=r.contextWindow.trim().length>0,_=Number(r.contextWindow);if(g&&(!Number.isInteger(_)||_<1))return{ok:!1,problem:`${e}: the context window must be a whole number of tokens.`};let v=r.maxOutputTokens.trim().length>0,y=Number(r.maxOutputTokens);if(v&&(!Number.isInteger(y)||y<1))return{ok:!1,problem:`${e}: the output limit must be a whole number of tokens.`};n.push({provider:r.provider,...r.provider===`custom`?{endpointId:i}:{},model:a,tier:o,weight:s,costPerMTok:{input:c,output:l,...u?{cacheRead:d}:{},...f?{cacheWrite5m:p}:{},...m?{cacheWrite1h:h}:{}},...g?{contextWindow:_}:{},...v?{maxOutputTokens:y}:{},capabilities:{tools:r.tools,images:r.images,reasoning:r.reasoning}})}return{ok:!0,model:{id:t,strategy:e.strategy,isAlias:e.isAlias,targets:n}}}var Te=Object.keys(P),Ee=z.fieldset`
50
- border: 1px solid ${({theme:e})=>e.color.rule};
51
- border-left: 3px solid ${({theme:e,$provider:t})=>e.provider[t]};
52
- border-radius: ${({theme:e})=>e.radius.control};
53
- padding: ${({theme:e})=>e.space(3)};
54
- margin: 0;
55
- background: ${({theme:e})=>e.color.panelSunk};
56
- display: flex;
57
- flex-direction: column;
58
- gap: ${({theme:e})=>e.space(3)};
59
- min-width: 0;
60
- `,De=z.div`
61
- display: grid;
62
- grid-template-columns: minmax(140px, 1.4fr) minmax(160px, 2fr) 72px 72px;
63
- gap: ${({theme:e})=>e.space(2)};
64
- align-items: end;
65
-
66
- @media (max-width: 720px) {
67
- grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
68
- }
69
- `,Oe=z.div`
70
- display: grid;
71
- grid-template-columns: repeat(3, minmax(0, 1fr));
72
- gap: ${({theme:e})=>e.space(2)};
73
- align-items: end;
74
- `,Z=z.div`
75
- display: flex;
76
- flex-direction: column;
77
- gap: 4px;
78
- min-width: 0;
79
- `,ke=z(c)`
80
- gap: ${({theme:e})=>e.space(3)};
81
- flex-wrap: wrap;
82
- `,Ae=z.p`
83
- font-size: 11.5px;
84
- color: ${({theme:e})=>e.color.down};
85
- margin: 0;
86
- `,Q=z.label`
87
- display: flex;
88
- align-items: center;
89
- gap: 6px;
90
- cursor: pointer;
91
- `;function je({target:t,index:n,onChange:i,onRemove:a,removable:l,endpoints:d,held:f}){let p=re(),h=P[t.provider],g=be(t.provider,f),_=xe(t.provider,t.model,f),b=(e,n)=>{i({...t,[e]:n})},x=K(t.provider,t.model),S=_e(t.provider,t.model),E=e=>{i(Se(t,e))};return R(Ee,{$provider:t.provider,children:[R(c,{$gap:2,children:[R(e,{as:`legend`,children:[`Target `,n+1]}),L(o,{}),L(u,{type:`button`,$variant:`ghost`,$size:`sm`,disabled:!l,"aria-label":`Remove target ${n+1}`,title:l?`Remove target ${n+1}`:`A model needs at least one target`,onClick:a,children:L(v,{})})]}),R(De,{children:[R(Z,{children:[L(e,{as:`label`,htmlFor:`${p}-provider`,children:`Provider`}),L(C,{id:`${p}-provider`,value:t.provider,onChange:e=>{let n=e.target.value,r=P[n].models.some(e=>e.id===t.model);E({provider:n,model:r?t.model:P[n].defaultModel})},children:Te.map(e=>L(`option`,{value:e,children:m[e]},e))})]}),t.provider===`custom`?R(Z,{children:[L(e,{as:`label`,htmlFor:`${p}-endpoint`,children:`Endpoint`}),R(C,{id:`${p}-endpoint`,value:t.endpointId,onChange:e=>b(`endpointId`,e.target.value),children:[L(`option`,{value:``,children:`Choose endpoint`}),d.map(e=>L(`option`,{value:e.id,children:e.label},e.id))]})]}):null,R(Z,{children:[L(e,{as:`label`,htmlFor:`${p}-model`,children:`Provider model`}),L(w,{id:`${p}-model`,list:`${p}-catalog`,value:t.model,placeholder:h.defaultModel,onChange:e=>E({provider:t.provider,model:e.target.value})}),L(`datalist`,{id:`${p}-catalog`,children:g.map(e=>L(`option`,{value:e.id,children:e.label},e.id))}),_===null?null:L(Ae,{role:`note`,children:_})]}),R(Z,{children:[L(e,{as:`label`,htmlFor:`${p}-tier`,children:`Tier`}),L(T,{id:`${p}-tier`,min:1,step:1,value:t.tier,onChange:e=>b(`tier`,e.target.value)})]}),R(Z,{children:[L(e,{as:`label`,htmlFor:`${p}-weight`,children:`Weight`}),L(T,{id:`${p}-weight`,min:0,step:.1,value:t.weight,onChange:e=>b(`weight`,e.target.value)})]})]}),R(r,{$gap:1,children:[R(c,{$gap:2,children:[L(e,{children:`Price per million tokens`}),L(o,{}),x===null?L(e,{as:`span`,children:`not in the catalog — price it yourself`}):R(s,{type:`button`,$size:`sm`,$variant:`ghost`,disabled:t.costInput===x.costInput&&t.costOutput===x.costOutput&&t.costCacheRead===x.costCacheRead&&t.costCacheWrite5m===x.costCacheWrite5m&&t.costCacheWrite1h===x.costCacheWrite1h,onClick:()=>i({...t,...x}),children:[L(ae,{}),`Use list price`]})]}),R(Oe,{children:[R(Z,{children:[L(e,{as:`label`,htmlFor:`${p}-in`,children:`Input`}),L(T,{id:`${p}-in`,min:0,step:.01,value:t.costInput,onChange:e=>b(`costInput`,e.target.value)})]}),R(Z,{children:[L(e,{as:`label`,htmlFor:`${p}-out`,children:`Output`}),L(T,{id:`${p}-out`,min:0,step:.01,value:t.costOutput,onChange:e=>b(`costOutput`,e.target.value)})]}),R(Z,{children:[L(e,{as:`label`,htmlFor:`${p}-cache`,children:`Cache read`}),L(T,{id:`${p}-cache`,min:0,step:.01,placeholder:`same as input`,value:t.costCacheRead,onChange:e=>b(`costCacheRead`,e.target.value)})]}),R(Z,{children:[L(e,{as:`label`,htmlFor:`${p}-write5m`,children:`Cache write 5m`}),L(T,{id:`${p}-write5m`,min:0,step:.01,placeholder:`1.25x input`,value:t.costCacheWrite5m,onChange:e=>b(`costCacheWrite5m`,e.target.value)})]}),R(Z,{children:[L(e,{as:`label`,htmlFor:`${p}-write1h`,children:`Cache write 1h`}),L(T,{id:`${p}-write1h`,min:0,step:.01,placeholder:`2x input`,value:t.costCacheWrite1h,onChange:e=>b(`costCacheWrite1h`,e.target.value)})]})]})]}),R(r,{$gap:1,children:[R(c,{$gap:2,children:[L(e,{children:`Token limits`}),L(o,{}),S===null?L(e,{as:`span`,children:`not in the catalog — state them yourself`}):L(e,{as:`span`,children:`left empty, the published figures are used — and for an OpenAI target, the narrower ones its OAuth backend allows`})]}),R(Oe,{children:[R(Z,{children:[L(e,{as:`label`,htmlFor:`${p}-context`,children:`Context window`}),L(T,{id:`${p}-context`,min:1,step:1024,placeholder:S?.contextWindow??`published`,value:t.contextWindow,onChange:e=>b(`contextWindow`,e.target.value)})]}),R(Z,{children:[L(e,{as:`label`,htmlFor:`${p}-maxout`,children:`Max output`}),L(T,{id:`${p}-maxout`,min:1,step:1024,placeholder:S?.maxOutputTokens??`published`,value:t.maxOutputTokens,onChange:e=>b(`maxOutputTokens`,e.target.value)})]})]})]}),R(r,{$gap:1,children:[L(e,{children:`Capabilities`}),R(ke,{children:[R(Q,{children:[L(y,{checked:t.tools,label:`Target ${n+1} supports tools`,onCheckedChange:e=>b(`tools`,e)}),`Tools`]}),R(Q,{children:[L(y,{checked:t.images,label:`Target ${n+1} supports images`,onCheckedChange:e=>b(`images`,e)}),`Images`]}),R(Q,{children:[L(y,{checked:t.reasoning,label:`Target ${n+1} supports reasoning`,onCheckedChange:e=>b(`reasoning`,e)}),`Reasoning`]})]})]})]})}var Me=z.p`
92
- font-size: 11.5px;
93
- color: ${({theme:e})=>e.color.inkDim};
94
- `,Ne=z.p`
95
- font-size: 12px;
96
- color: ${({theme:e})=>e.color.down};
97
- `,Pe=z.p`
98
- font-size: 12px;
99
- color: ${({theme:e})=>e.color.ok};
100
- `,Fe=z(c)`
101
- gap: 8px;
102
- `;function Ie({model:n,onSaved:i,onDeleted:l}){let[u,d]=F(()=>n===null?X():Ce(n)),[p,m]=F(null),[h,g]=F(!1),[v,x]=F(!1),S=t(),T=f(),D=a(),A=ye(D.data??[]),j=(D.data??[]).filter(e=>e.provider===`custom`).map(e=>({id:String(e.providerData.endpointId??``),label:String(e.providerData.endpointLabel??e.providerData.endpointId??``)})).filter((e,t,n)=>e.id.length>0&&n.findIndex(t=>t.id===e.id)===t),M=n?.id??null;ne(()=>{d(n===null?X():Ce(n)),m(null),g(!1)},[M]);let N=U.find(e=>e.id===u.strategy);return R(I,{children:[L(O,{legend:n===null?`New model`:`Edit model`,meta:n===null?void 0:n.id,actions:R(I,{children:[n===null?null:L(s,{type:`button`,$variant:`danger`,$size:`sm`,onClick:()=>x(!0),children:`Delete`}),L(s,{type:`button`,$variant:`primary`,$size:`sm`,disabled:S.isPending,onClick:()=>{g(!1);let e=we(u);if(!e.ok){m(e.problem);return}m(null),S.mutate(e.model,{onSuccess:()=>{g(!0),i(e.model.id)},onError:e=>m(k(e))})},children:S.isPending?`Saving…`:n===null?`Create model`:`Save changes`})]}),children:R(r,{$gap:3,children:[L(E,{label:`Model name`,hint:n===null?`What clients send as the model. Anything not listed here is rejected.`:`Fixed once created. To rename, create a model under the new name and delete this one.`,children:e=>L(w,{...e,value:u.id,disabled:n!==null,placeholder:`fast`,onChange:e=>d({...u,id:e.target.value})})}),L(E,{label:`Routing strategy`,children:e=>L(C,{...e,value:u.strategy,onChange:e=>d({...u,strategy:e.target.value}),children:U.map(e=>L(`option`,{value:e.id,children:e.label},e.id))})}),N===void 0?null:L(Me,{children:N.blurb}),R(Fe,{children:[L(y,{checked:u.isAlias,label:`This model is an alias for a provider model name`,onCheckedChange:e=>d({...u,isAlias:e})}),R(r,{$gap:0,children:[L(e,{as:`span`,children:`Alias`}),L(Me,{children:`Mark this when the name mirrors a provider's own model name.`})]})]}),R(r,{$gap:2,children:[R(c,{children:[L(e,{children:`Targets`}),L(o,{}),R(s,{type:`button`,$size:`sm`,onClick:()=>d({...u,targets:[...u.targets,Y(u.targets.at(-1)?.provider??`anthropic`)]}),children:[L(_,{}),`Add target`]})]}),u.targets.map((e,t)=>L(je,{target:e,index:t,removable:u.targets.length>1,endpoints:j,held:A,onChange:t=>d({...u,targets:u.targets.map(n=>n.key===e.key?t:n)}),onRemove:()=>d({...u,targets:u.targets.filter(t=>t.key!==e.key)})},e.key))]}),p===null?null:L(Ne,{role:`alert`,children:p}),h&&p===null?L(Pe,{role:`status`,children:`Saved.`}):null]})}),L(b,{open:v,onOpenChange:x,title:`Delete model`,body:n===null?``:`Deleting "${n.id}" makes it unroutable. Clients asking for it will get a model-unavailable error, and any key allowlisting it keeps a name that no longer resolves.`,confirmLabel:`Delete model`,busy:T.isPending,onConfirm:()=>{n!==null&&T.mutate(n.id,{onSuccess:()=>{x(!1),l()},onError:e=>{x(!1),m(k(e))}})}})]})}var Le=z.div`
103
- display: grid;
104
- grid-template-columns: minmax(230px, 300px) minmax(0, 1fr);
105
- gap: ${({theme:e})=>e.space(4)};
106
- align-items: start;
107
-
108
- @media (max-width: 980px) {
109
- grid-template-columns: minmax(0, 1fr);
110
- }
111
- `,Re=z(r)`
112
- gap: ${({theme:e})=>e.space(4)};
113
- min-width: 0;
114
- `,ze=z.button`
115
- display: flex;
116
- flex-direction: column;
117
- gap: 4px;
118
- width: 100%;
119
- padding: ${({theme:e})=>`${e.space(2)} ${e.space(3)}`};
120
- text-align: left;
121
- background: ${({theme:e,$selected:t})=>t?e.color.accentWash:`transparent`};
122
- border: 0;
123
- border-left: 2px solid
124
- ${({theme:e,$selected:t})=>t?e.color.accent:`transparent`};
125
- border-bottom: 1px solid ${({theme:e})=>e.color.rule};
126
- cursor: pointer;
127
-
128
- &:hover {
129
- background: ${({theme:e,$selected:t})=>t?e.color.accentWash:e.color.panelSunk};
130
- }
131
-
132
- &:last-child {
133
- border-bottom: 0;
134
- }
135
- `,Be=z(l)`
136
- font-family: ${({theme:e})=>e.font.mono};
137
- font-size: 12.5px;
138
- display: block;
139
- max-width: 100%;
140
- `,Ve=z.div`
141
- display: flex;
142
- gap: 2px;
143
- `,He=z.span`
144
- width: 12px;
145
- height: 3px;
146
- border-radius: 1px;
147
- background: ${({$provider:e})=>`var(--p-${e})`};
148
- `,$=`\0new`;function Ue(){let t=n(),[r,a]=F(null),l=t.data??[],u=r===$?null:l.find(e=>e.id===r)??null,d=r===$||r===null&&!t.isLoading&&l.length===0;ne(()=>{r===null&&l.length!==0&&a(l[0]?.id??null)},[l,r]);let f=t.isLoading?`Reading configured models…`:l.length===0?`No virtual models exist yet, so no client request can resolve to an upstream.`:`${l.length} model${l.length===1?``:`s`} routing to ${l.reduce((e,t)=>e+t.targets.length,0)} targets.`;return R(I,{children:[L(g,{legend:`Models`,title:`Virtual models`,summary:f,actions:R(s,{type:`button`,$variant:`primary`,onClick:()=>a($),children:[L(_,{}),`New model`]})}),R(Le,{children:[L(O,{legend:`Configured`,meta:`${l.length}`,flush:!0,children:t.isError?L(A,{error:t.error,onRetry:()=>void t.refetch()}):t.isLoading?L(`div`,{style:{padding:12},children:L(j,{rows:4})}):l.length===0?L(M,{legend:`No models`,message:`Create a model to give clients something to ask for.`,action:L(s,{type:`button`,$size:`sm`,$variant:`primary`,onClick:()=>a($),children:`New model`})}):L(`div`,{children:l.map(t=>{let n=[...new Set(t.targets.map(e=>e.provider))];return R(ze,{type:`button`,$selected:t.id===r,"aria-pressed":t.id===r,onClick:()=>a(t.id),children:[R(c,{$gap:2,style:{width:`100%`},children:[L(Be,{title:t.id,children:t.id}),L(o,{}),t.isAlias?L(S,{children:`alias`}):null]}),R(c,{$gap:2,style:{width:`100%`},children:[L(Ve,{children:n.map(e=>L(He,{$provider:e,title:e},e))}),L(e,{children:t.strategy}),L(o,{}),R(i,{$dim:!0,$size:`11px`,children:[t.targets.length,` target`,t.targets.length===1?``:`s`]})]})]},t.id)})})}),R(Re,{children:[u===null&&!d?L(O,{legend:`Editor`,children:t.isLoading?L(j,{rows:5}):L(M,{legend:`Nothing selected`,message:`Pick a model on the left to change its targets, or create a new one.`})}):L(Ie,{model:u,onSaved:e=>{a(e),t.refetch()},onDeleted:()=>{a(null),t.refetch()}}),L(ge,{modelId:u?.id??null})]})]})]})}var We=Ue;export{We as component};
@@ -1,20 +0,0 @@
1
- import{J as e,X as t,Y as n,Z as r,at as i,k as a}from"./queries-BOAAI06M.js";import{a as o,s}from"./index-B2twwe7y.js";import{t as c}from"./Rack-DhVnjAjC.js";import{a as l,n as u,r as d,t as f}from"./States-6G9NsYha.js";import{Component as p,Suspense as m,createContext as h,lazy as g,useContext as _,useMemo as v}from"react";import{Fragment as y,jsx as b,jsxs as x}from"react/jsx-runtime";import S from"styled-components";var C=/%2e/i;function w(e,t){if(t.length===0)throw TypeError(`plugin api ${e} must not be empty`);if(t.startsWith(`/`))throw TypeError(`plugin api ${e} must be relative to the plugin's own prefix, got ${JSON.stringify(t)}`);if(t.includes(`..`)||C.test(t))throw TypeError(`plugin api ${e} must not escape the plugin's own prefix, got ${JSON.stringify(t)}`)}function T(e,t){if(w(`plugin id`,e),e.includes(`/`))throw TypeError(`plugin api plugin id must be a single path segment, got ${e}`);return w(`path`,t),`/api/plugins/${e}/${t}`}var E=new Map;function D(i){let a=E.get(i);if(a!==void 0)return a;let o={get:(e,t)=>n(T(i,e),t),post:(e,n)=>t(T(i,e),n),put:(e,t)=>r(T(i,e),t),del:t=>e(T(i,t))};return E.set(i,o),o}var O=h(e=>s(()=>import(e),[]));O.Provider;function k(){return _(O)}function A(e,t){let n=e?.default;if(n==null)throw Error(`plugin ${t} has no default export from definePluginUI`);if(typeof n.mount!=`function`)throw Error(`plugin ${t} exported a default without a mount function`);return n}function j(e,t,n){return g(async()=>{let r=A(await n(t),e);return{default:()=>r.mount({pluginId:e,api:D(e)})}})}var M=S.p`
2
- font-size: 13px;
3
- color: ${({theme:e})=>e.color.down};
4
- `,N=S.p`
5
- font-family: ${({theme:e})=>e.font.mono};
6
- font-size: 12px;
7
- color: ${({theme:e})=>e.color.inkDim};
8
- overflow-wrap: anywhere;
9
- `,P=S.p`
10
- font-size: 12px;
11
- color: ${({theme:e})=>e.color.inkDim};
12
- max-width: 68ch;
13
- `;function F(e){return e instanceof Error?e.message:typeof e==`string`?e:`The plugin threw a value that is not an error.`}var I=class extends p{state={message:null};static getDerivedStateFromError(e){return{message:F(e)}}componentDidUpdate(e){e.pluginId!==this.props.pluginId&&this.state.message!==null&&this.setState({message:null})}componentDidCatch(e,t){}render(){let{message:e}=this.state;return e===null?this.props.children:b(l,{legend:`Plugin failed`,meta:this.props.pluginId,children:x(i,{$gap:2,children:[x(M,{children:[this.props.pluginName,` stopped rendering.`]}),b(N,{children:e}),b(P,{children:`The rest of the console is unaffected. Reload the page to try this screen again, and report the message above to whoever maintains the plugin.`})]})})}},L=S.p`
14
- font-size: 13px;
15
- color: ${({theme:e})=>e.color.warn};
16
- `,R=S.p`
17
- font-size: 12px;
18
- color: ${({theme:e})=>e.color.inkDim};
19
- max-width: 68ch;
20
- `;function z({pluginId:e}){let t=a(),n=k(),r=t.data?.find(t=>t.id===e),o=r?.ui??null,s=o?.compatible===!0?o.entry:null,p=v(()=>s===null?null:j(e,s,n),[e,s,n]);if(t.isError)return x(y,{children:[b(c,{legend:`Plugin`,title:`Plugins`,summary:`The installed plugins are unknown.`}),b(u,{legend:`Plugins unavailable`,error:t.error})]});if(r===void 0)return x(y,{children:[b(c,{legend:`Plugin`,title:t.isPending?`Loading…`:e,summary:t.isPending?`Reading the installed plugins.`:`This gateway does not run a plugin with that id.`}),t.isPending?b(d,{}):b(f,{legend:`Not installed`,message:`No plugin with the id ${e} is installed. Install it and restart the gateway.`})]});let h=b(c,{legend:`Plugin`,title:r.nav?.label??r.name,summary:`${r.name} ${r.version}, installed as ${r.id}.`});return o===null?x(y,{children:[h,b(f,{legend:`No interface`,message:`${r.name} runs entirely in the gateway and has no console screen.`})]}):p===null?x(y,{children:[h,b(l,{legend:`Interface unavailable`,meta:r.id,children:x(i,{$gap:2,children:[b(L,{children:o.reason??`This plugin's interface does not match this gateway.`}),b(R,{children:`The plugin's server half is unaffected and keeps running. Update the plugin, or the gateway, so the two agree on a dashboard SDK version.`})]})})]}):x(y,{children:[h,b(I,{pluginId:r.id,pluginName:r.name,children:b(m,{fallback:b(d,{}),children:b(p,{})})})]})}function B(){let{pluginId:e}=o.useParams();return b(z,{pluginId:e})}export{B as component};
@@ -1 +0,0 @@
1
- import*as e from"react";import{jsx as t}from"react/jsx-runtime";import*as n from"react-dom";var r=Object.defineProperty,i=(e,t)=>r(e,`name`,{value:t,configurable:!0});function a(e,t){if(typeof e==`function`)return e(t);e!=null&&(e.current=t)}i(a,`setRef`);function o(...e){return t=>{let n=!1,r=e.map(e=>{let r=a(e,t);return!n&&typeof r==`function`&&(n=!0),r});if(n)return()=>{for(let t=0;t<r.length;t++){let n=r[t];typeof n==`function`?n():a(e[t],null)}}}}i(o,`composeRefs`);function s(...t){return e.useCallback(o(...t),t)}i(s,`useComposedRefs`);var c=Object.defineProperty,l=(e,t)=>c(e,`name`,{value:t,configurable:!0});function u(t){let n=e.forwardRef((n,r)=>{let{children:i,...a}=n,o=null,c=!1,l=[];v(i)&&typeof S==`function`&&(i=S(i._payload)),e.Children.forEach(i,e=>{if(g(e)){c=!0;let t=e,n=`child`in t.props?t.props.child:t.props.children;v(n)&&typeof S==`function`&&(n=S(n._payload)),o=p(t,n),l.push(o?.props?.children)}else l.push(e)}),o?o=e.cloneElement(o,void 0,l):!c&&e.Children.count(i)===1&&e.isValidElement(i)&&(o=i);let u=o?h(o):void 0,d=s(r,u);if(!o){if(i||i===0)throw Error(c?x(t):b(t));return i}let f=m(a,o.props??{});return o.type!==e.Fragment&&(f.ref=r?d:u),e.cloneElement(o,f)});return n.displayName=`${t}.Slot`,n}l(u,`createSlot`);var d=Symbol.for(`radix.slottable`);function f(e){let t=l(e=>`child`in e?e.children(e.child):e.children,`Slottable`);return t.displayName=`${e}.Slottable`,t.__radixId=d,t}l(f,`createSlottable`);var p=l((t,n)=>{if(`child`in t.props){let n=t.props.child;return e.isValidElement(n)?e.cloneElement(n,void 0,t.props.children(n.props.children)):null}return e.isValidElement(n)?n:null},`getSlottableElementFromSlottable`);function m(e,t){let n={...t};for(let r in t){let i=e[r],a=t[r];/^on[A-Z]/.test(r)?i&&a?n[r]=(...e)=>{let t=a(...e);return i(...e),t}:i&&(n[r]=i):r===`style`?n[r]={...i,...a}:r===`className`&&(n[r]=[i,a].filter(Boolean).join(` `))}return{...e,...n}}l(m,`mergeProps`);function h(e){let t=Object.getOwnPropertyDescriptor(e.props,`ref`)?.get,n=t&&`isReactWarning`in t&&t.isReactWarning;return n?e.ref:(t=Object.getOwnPropertyDescriptor(e,`ref`)?.get,n=t&&`isReactWarning`in t&&t.isReactWarning,n?e.props.ref:e.props.ref||e.ref)}l(h,`getElementRef`);function g(t){return e.isValidElement(t)&&typeof t.type==`function`&&`__radixId`in t.type&&t.type.__radixId===d}l(g,`isSlottable`);var _=Symbol.for(`react.lazy`);function v(e){return typeof e==`object`&&!!e&&`$$typeof`in e&&e.$$typeof===_&&`_payload`in e&&y(e._payload)}l(v,`isLazyComponent`);function y(e){return typeof e==`object`&&!!e&&`then`in e}l(y,`isPromiseLike`);var b=l(e=>`${e} failed to slot onto its children. Expected a single React element child or \`Slottable\`.`,`createSlotError`),x=l(e=>`${e} failed to slot onto its \`Slottable\`. Expected \`Slottable\` to receive a single React element child.`,`createSlottableError`),S=e.use,C=Object.defineProperty,w=(e,t)=>C(e,`name`,{value:t,configurable:!0}),T=[`a`,`button`,`div`,`form`,`h2`,`h3`,`img`,`input`,`label`,`li`,`nav`,`ol`,`p`,`select`,`span`,`svg`,`ul`].reduce((n,r)=>{let i=u(`Primitive.${r}`),a=e.forwardRef((e,n)=>{let{asChild:a,...o}=e,s=a?i:r;return typeof window<`u`&&(window[Symbol.for(`radix-ui`)]=!0),t(s,{...o,ref:n})});return a.displayName=`Primitive.${r}`,{...n,[r]:a}},{});function E(e,t){e&&n.flushSync(()=>e.dispatchEvent(t))}w(E,`dispatchDiscreteCustomEvent`);var D=Object.defineProperty,O=(e,t)=>D(e,`name`,{value:t,configurable:!0});function k(n,r){let i=e.createContext(r);i.displayName=n+`Context`;let a=O(n=>{let{children:r,...a}=n,o=e.useMemo(()=>a,Object.values(a));return t(i.Provider,{value:o,children:r})},`Provider`);a.displayName=n+`Provider`;function o(t,a={}){let{optional:o=!1}=a,s=e.useContext(i);if(s)return s;if(r!==void 0)return r;if(!o)throw Error(`\`${t}\` must be used within \`${n}\``)}return O(o,`useContext`),[a,o]}O(k,`createContext`);function A(n,r=[]){let i=[];function a(r,a){let o=e.createContext(a);o.displayName=r+`Context`;let s=i.length;i=[...i,a];let c=O(r=>{let{scope:i,children:a,...c}=r,l=i?.[n]?.[s]||o,u=e.useMemo(()=>c,Object.values(c));return t(l.Provider,{value:u,children:a})},`Provider`);c.displayName=r+`Provider`;function l(t,i,c={}){let{optional:l=!1}=c,u=i?.[n]?.[s]||o,d=e.useContext(u);if(d)return d;if(a!==void 0)return a;if(!l)throw Error(`\`${t}\` must be used within \`${r}\``)}return O(l,`useContext`),[c,l]}O(a,`createContext`);let o=O(()=>{let t=i.map(t=>e.createContext(t));return O(function(r){let i=r?.[n]||t;return e.useMemo(()=>({[`__scope${n}`]:{...r,[n]:i}}),[r,i])},`useScope`)},`createScope`);return o.scopeName=n,[a,j(o,...r)]}O(A,`createContextScope`);function j(...t){let n=t[0];if(t.length===1)return n;let r=O(()=>{let r=t.map(e=>({useScope:e(),scopeName:e.scopeName}));return O(function(t){let i=r.reduce((e,{useScope:n,scopeName:r})=>{let i=n(t)[`__scope${r}`];return{...e,...i}},{});return e.useMemo(()=>({[`__scope${n.scopeName}`]:i}),[i])},`useComposedScopes`)},`createScope`);return r.scopeName=n.scopeName,r}O(j,`composeContextScopes`);var M=Object.defineProperty,N=(e,t)=>M(e,`name`,{value:t,configurable:!0}),P=!!(typeof window<`u`&&window.document&&window.document.createElement);function F(e,t,{checkForDefaultPrevented:n=!0}={}){return N(function(r){if(e?.(r),n===!1||!r||!r.defaultPrevented)return t?.(r)},`handleEvent`)}N(F,`composeEventHandlers`);function I(e){if(!P)throw Error(`Cannot access window outside of the DOM`);return e?.ownerDocument?.defaultView??window}N(I,`getOwnerWindow`);function L(e){if(!P)throw Error(`Cannot access document outside of the DOM`);return e?.ownerDocument??document}N(L,`getOwnerDocument`);function R(e,t=!1){let{activeElement:n}=L(e);if(!n?.nodeName)return null;if(z(n)&&n.contentDocument)return R(n.contentDocument.body,t);if(t){let e=n.getAttribute(`aria-activedescendant`);if(e){let t=L(n).getElementById(e);if(t)return t}}return n}N(R,`getActiveElement`);function z(e){return e.tagName===`IFRAME`}N(z,`isFrame`);var B=globalThis?.document?e.useLayoutEffect:()=>{},V=Object.defineProperty,H=(e,t)=>V(e,`name`,{value:t,configurable:!0}),U=e.useEffectEvent,W=e.useInsertionEffect;function G(t){if(typeof U==`function`)return U(t);let n=e.useRef(()=>{throw Error(`Cannot call an event handler while rendering.`)});return typeof W==`function`?W(()=>{n.current=t}):B(()=>{n.current=t}),e.useMemo(()=>((...e)=>n.current?.(...e)),[])}H(G,`useEffectEvent`);var K=Object.defineProperty,q=(e,t)=>K(e,`name`,{value:t,configurable:!0}),J=e.useInsertionEffect||B;function Y({prop:t,defaultProp:n,onChange:r=q(()=>{},`onChange`),caller:i}){let[a,o,s]=X({defaultProp:n,onChange:r}),c=t!==void 0;return[c?t:a,e.useCallback(e=>{if(c){let n=Z(e)?e(t):e;n!==t&&s.current?.(n)}else o(e)},[c,t,o,s])]}q(Y,`useControllableState`);function X({defaultProp:t,onChange:n}){let[r,i]=e.useState(t),a=e.useRef(r),o=e.useRef(n);return J(()=>{o.current=n},[n]),e.useEffect(()=>{a.current!==r&&(o.current?.(r),a.current=r)},[r,a]),[r,i,o]}q(X,`useUncontrolledState`);function Z(e){return typeof e==`function`}q(Z,`isFunction`);var Q=Symbol(`RADIX:SYNC_STATE`);function $(t,n,r,i){let{prop:a,defaultProp:o,onChange:s,caller:c}=n,l=a!==void 0,u=G(s),d=[{...r,state:o}];i&&d.push(i);let[f,p]=e.useReducer((e,n)=>{if(n.type===Q)return{...e,state:n.state};let r=t(e,n);return l&&!Object.is(r.state,e.state)&&u(r.state),r},...d),m=f.state,h=e.useRef(m);e.useEffect(()=>{h.current!==m&&(h.current=m,l||u(m))},[m,h,l]);let g=e.useMemo(()=>a===void 0?f:{...f,state:a},[f,a]);return e.useEffect(()=>{l&&!Object.is(a,f.state)&&p({type:Q,state:a})},[a,f.state,l]),[g,p]}q($,`useControllableStateReducer`);export{T as a,s as c,A as i,B as n,E as o,F as r,u as s,Y as t};
@@ -1 +0,0 @@
1
- import{c as e}from"./Rack-DhVnjAjC.js";var t=e(`plus`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`M12 5v14`,key:`s699le`}]]);export{t};