omnigateway 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +94 -7
- package/bin/omni.js +4954 -2939
- package/gateway.js +3132 -1164
- package/package.json +1 -1
- package/public/assets/{Chip-BB_5C1Zp.js → Chip-DJwp7gBu.js} +2 -2
- package/public/assets/{Confirm-B6aAiVbT.js → Confirm-CVLz9F7a.js} +1 -1
- package/public/assets/CopyValue-CNZbWS59.js +27 -0
- package/public/assets/{Field-uHZxl4fI.js → Field-BDtp692L.js} +8 -8
- package/public/assets/Lamp-B65uWKbW.js +25 -0
- package/public/assets/{Meter-DI_BRUKt.js → Meter-BREBUFGX.js} +2 -2
- package/public/assets/{Modal-CI6jk2D4.js → Modal-DbydSAlp.js} +8 -8
- package/public/assets/Rack-Bbo4JfEX.js +151 -0
- package/public/assets/{Readout-BocZ2HXP.js → Readout-CEAoN5hu.js} +9 -5
- package/public/assets/{States-Bbiu5cHE.js → States-BEKLros0.js} +10 -10
- package/public/assets/{Table-CdPWxYaz.js → Table-BBypbVWj.js} +1 -1
- package/public/assets/{Toggle-CiLC67Dw.js → Toggle-BUr71O4J.js} +2 -2
- package/public/assets/{TokenBreakdown-B96iPBm9.js → TokenBreakdown-C1ziK9d1.js} +6 -3
- package/public/assets/_app-ByQ1bPbe.js +1 -0
- package/public/assets/_app.accounts-BTug_Xfo.js +64 -0
- package/public/assets/{_app.console-Daz4aKhf.js → _app.console-DKyGL9xx.js} +10 -10
- package/public/assets/_app.index-CSw9gmMf.js +62 -0
- package/public/assets/_app.keys-07Kbw4RS.js +39 -0
- package/public/assets/_app.logs-C9QiV39p.js +32 -0
- package/public/assets/_app.models-CDqVrAeF.js +148 -0
- package/public/assets/{_app.settings-a0FKyQAi.js → _app.settings-DmUEeTaP.js} +10 -10
- package/public/assets/_app.usage-B1WuMGRr.js +83 -0
- package/public/assets/catalog-BBKm8Ih8.js +1 -0
- package/public/assets/{dist-C-IbPRiV.js → dist-Bka7ErcH.js} +1 -1
- package/public/assets/index-DJfb1i4P.js +186 -0
- package/public/assets/{login-CTvH_KAd.js → login-DKZYqRh0.js} +8 -8
- package/public/assets/queries-D8LJNQpL.js +144 -0
- package/public/assets/shared-CIhZ6FCO.js +84 -0
- package/public/assets/{trash-2-BcZb-sCT.js → trash-2-CLYNAAJA.js} +1 -1
- package/public/index.html +2 -2
- package/public/assets/CopyValue-CRQDLo7k.js +0 -27
- package/public/assets/Lamp-B-5SjXbG.js +0 -25
- package/public/assets/Rack-D1WJswv3.js +0 -151
- package/public/assets/_app-BBOF6A0T.js +0 -1
- package/public/assets/_app.accounts-BNkhpvaB.js +0 -54
- package/public/assets/_app.index-LO6d38oe.js +0 -62
- package/public/assets/_app.keys-kBqLqoFf.js +0 -39
- package/public/assets/_app.logs-_wYNS47N.js +0 -32
- package/public/assets/_app.models-Cjng8ohC.js +0 -144
- package/public/assets/_app.usage-D3KtgLrC.js +0 -166
- package/public/assets/catalog-C_OQ0icG.js +0 -1
- package/public/assets/index-PW6EvVh5.js +0 -170
- package/public/assets/queries-D2o-X8Pj.js +0 -144
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{$t as e,Ft as t,Pt as n,q as r}from"./queries-D8LJNQpL.js";import{a as i,c as a,i as o,n as s,r as c,t as l}from"./dist-Bka7ErcH.js";var u=e(t(),1),d=Object.defineProperty,f=(e,t)=>d(e,`name`,{value:t,configurable:!0});function p(e){let[t,n]=u.useState(void 0);return s(()=>{if(e){n({width:e.offsetWidth,height:e.offsetHeight});let t=new ResizeObserver(t=>{if(!Array.isArray(t)||!t.length)return;let r=t[0],i,a;if(`borderBoxSize`in r){let e=r.borderBoxSize,t=Array.isArray(e)?e[0]:e;i=t.inlineSize,a=t.blockSize}else i=e.offsetWidth,a=e.offsetHeight;n({width:i,height:a})});return t.observe(e,{box:`border-box`}),()=>t.unobserve(e)}n(void 0)},[e]),t}f(p,`useSize`);var m=n(),h=Object.defineProperty,g=(e,t)=>h(e,`name`,{value:t,configurable:!0}),_=`Switch`,[v,y]=o(_),[b,x]=v(_);function S(e){let{__scopeSwitch:t,checked:n,children:r,defaultChecked:i,disabled:a,form:o,name:s,onCheckedChange:c,required:d,value:f=`on`,internal_do_not_use_render:p}=e,[h,g]=l({prop:n,defaultProp:i??!1,onChange:c,caller:_}),[v,y]=u.useState(null),[x,S]=u.useState(null),C=u.useRef(!1),[w,T]=u.useReducer(e=>e+1,0),E={checked:h,setChecked:g,disabled:a,control:v,setControl:y,name:s,form:o,value:f,hasConsumerStoppedPropagationRef:C,userInteractionCount:w,onUserInteraction:T,required:d,defaultChecked:i,isFormControl:!v||!!o||!!v.closest(`form`),bubbleInput:x,setBubbleInput:S};return(0,m.jsx)(b,{scope:t,...E,children:A(p)?p(E):r})}g(S,`SwitchProvider`);var C=`SwitchTrigger`,w=u.forwardRef(g(function({__scopeSwitch:e,onClick:t,...n},r){let{control:o,form:s,value:l,disabled:d,checked:f,required:p,setControl:h,setChecked:_,hasConsumerStoppedPropagationRef:v,onUserInteraction:y,isFormControl:b,bubbleInput:S}=x(C,e),w=a(r,h),T=u.useRef(f);return u.useEffect(()=>{let e=s?o?.ownerDocument.getElementById(s):o?.form;if(e instanceof HTMLFormElement){let t=g(()=>_(T.current),`reset`);return e.addEventListener(`reset`,t),()=>e.removeEventListener(`reset`,t)}},[o,s,_]),(0,m.jsx)(i.button,{type:`button`,role:`switch`,"aria-checked":f,"aria-required":p,"data-state":j(f),"data-disabled":d?``:void 0,disabled:d,value:l,...n,ref:w,onClick:c(t,e=>{y(),_(e=>!e),S&&b&&(v.current=e.isPropagationStopped(),v.current||e.stopPropagation())})})},`SwitchTrigger`)),T=u.forwardRef(g(function(e,t){let{__scopeSwitch:n,name:r,checked:i,defaultChecked:a,required:o,disabled:s,value:c,onCheckedChange:l,form:u,...d}=e;return(0,m.jsx)(S,{__scopeSwitch:n,checked:i,defaultChecked:a,disabled:s,required:o,onCheckedChange:l,name:r,form:u,value:c,internal_do_not_use_render:({isFormControl:e})=>(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(w,{...d,ref:t,__scopeSwitch:n}),e&&(0,m.jsx)(k,{__scopeSwitch:n})]})})},`Switch`)),E=`SwitchThumb`,D=u.forwardRef(g(function(e,t){let{__scopeSwitch:n,...r}=e,a=x(E,n);return(0,m.jsx)(i.span,{"data-state":j(a.checked),"data-disabled":a.disabled?``:void 0,...r,ref:t})},`SwitchThumb`)),O=`SwitchBubbleInput`,k=u.forwardRef(g(function({__scopeSwitch:e,onClick:t,...n},r){let{control:o,hasConsumerStoppedPropagationRef:s,userInteractionCount:l,checked:d,defaultChecked:f,required:h,disabled:g,name:_,value:v,form:y,bubbleInput:b,setBubbleInput:S}=x(O,e),C=a(r,S),w=p(o),T=u.useRef(!1),E=u.useRef(d),D=u.useRef(l);u.useEffect(()=>{let e=b;if(!e)return;let t=window.HTMLInputElement.prototype,n=Object.getOwnPropertyDescriptor(t,`checked`).set,r=l!==D.current;D.current=l;let i=E.current!==d;E.current=d;let a=!(r&&s.current);if(i&&n){T.current=!r;let t=new Event(`click`,{bubbles:a});n.call(e,d),e.dispatchEvent(t),T.current=!1}},[b,d,s,l]);let k=u.useRef(d);return(0,m.jsx)(i.input,{type:`checkbox`,"aria-hidden":!0,defaultChecked:f??k.current,required:h,disabled:g,name:_,value:v,form:y,...n,tabIndex:-1,ref:C,onClick:c(t,e=>{T.current&&e.stopPropagation()}),style:{...n.style,...w,position:`absolute`,pointerEvents:`none`,opacity:0,margin:0,transform:`translateX(-100%)`}})},`SwitchBubbleInput`));function A(e){return typeof e==`function`}g(A,`isFunction`);function j(e){return e?`checked`:`unchecked`}g(j,`getState`);var M=r(T)`
|
|
2
2
|
all: unset;
|
|
3
3
|
width: 30px;
|
|
4
4
|
height: 16px;
|
|
@@ -23,7 +23,7 @@ import{G as e,Mt as t,Nt as n,Zt as r}from"./queries-D2o-X8Pj.js";import{a as i,
|
|
|
23
23
|
outline: 2px solid ${({theme:e})=>e.color.accent};
|
|
24
24
|
outline-offset: 2px;
|
|
25
25
|
}
|
|
26
|
-
`,N=
|
|
26
|
+
`,N=r(D)`
|
|
27
27
|
display: block;
|
|
28
28
|
width: 12px;
|
|
29
29
|
height: 12px;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{Pt as e,W as t,q as n}from"./queries-D8LJNQpL.js";import{o as r}from"./Rack-Bbo4JfEX.js";import{b as i}from"./Lamp-B65uWKbW.js";var a=r(`arrow-down`,[[`path`,{d:`M12 5v14`,key:`s699le`}],[`path`,{d:`m19 12-7 7-7-7`,key:`1idqje`}]]),o=r(`arrow-up`,[[`path`,{d:`m5 12 7-7 7 7`,key:`hav0vg`}],[`path`,{d:`M12 19V5`,key:`x0mq9r`}]]),s=r(`database`,[[`ellipse`,{cx:`12`,cy:`5`,rx:`9`,ry:`3`,key:`msslwz`}],[`path`,{d:`M3 5V19A9 3 0 0 0 21 19V5`,key:`1wlel7`}],[`path`,{d:`M3 12A9 3 0 0 0 21 12`,key:`mv7ke4`}]]),c=e(),l=new Intl.NumberFormat(`en-US`);function u(e){return`${l.format(e.inputTokens)} input, ${l.format(e.outputTokens)} output, ${l.format(e.cacheReadTokens)} cache read, ${l.format(e.cacheWriteTokens)} cache write tokens`}var d=n.span`
|
|
2
2
|
display: inline-flex;
|
|
3
3
|
align-items: center;
|
|
4
|
+
flex-wrap: wrap;
|
|
4
5
|
gap: 6px;
|
|
6
|
+
/* Wrapping happens between the four classes, never inside one: a count
|
|
7
|
+
broken across lines from its own arrow reads as a different number. */
|
|
5
8
|
white-space: nowrap;
|
|
6
|
-
`,f=
|
|
9
|
+
`,f=n.span`
|
|
7
10
|
display: inline-flex;
|
|
8
11
|
align-items: center;
|
|
9
12
|
gap: 2px;
|
|
@@ -16,7 +19,7 @@ import{G as e,H as t,Mt as n}from"./queries-D2o-X8Pj.js";import{h as r,s as i}fr
|
|
|
16
19
|
`,p=t`
|
|
17
20
|
from { clip-path: inset(0 2ch 0 0); }
|
|
18
21
|
to { clip-path: inset(0 0 0 0); }
|
|
19
|
-
`,m=
|
|
22
|
+
`,m=n.span`
|
|
20
23
|
display: inline-block;
|
|
21
24
|
width: 3ch;
|
|
22
25
|
vertical-align: bottom;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Pt as e}from"./queries-D8LJNQpL.js";import{o as t}from"./index-DJfb1i4P.js";import{i as n,n as r}from"./Rack-Bbo4JfEX.js";var i=e(),a=()=>(0,i.jsx)(n,{children:(0,i.jsx)(r,{children:(0,i.jsx)(t,{})})});export{a as component};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import{$t as e,Ft as t,H as n,I as r,L as i,N as a,O as o,P as s,Pt as c,T as l,U as u,d,f,l as p,o as m,p as h,q as g,r as _,s as v,x as y,z as b}from"./queries-D8LJNQpL.js";import{a as ee,o as x,t as S}from"./Rack-Bbo4JfEX.js";import{t as te}from"./CopyValue-CNZbWS59.js";import{n as C,t as w}from"./Confirm-CVLz9F7a.js";import{t as T}from"./trash-2-CLYNAAJA.js";import{t as E}from"./Modal-DbydSAlp.js";import{t as D}from"./Toggle-BUr71O4J.js";import{C as O,S as k,T as A,a as j,b as M,g as N,h as P,i as F,m as I,n as L,o as R,p as z,s as ne,t as re,u as ie,v as ae,y as oe}from"./Lamp-B65uWKbW.js";import{t as se}from"./Chip-DJwp7gBu.js";import{i as B,n as V,r as ce,t as H}from"./Field-BDtp692L.js";import{t as le}from"./Meter-BREBUFGX.js";import{a as U,i as W,n as ue,r as de,t as fe}from"./States-BEKLros0.js";import{i as pe,n as G,r as K,t as me}from"./Table-BBypbVWj.js";import{t as he}from"./catalog-BBKm8Ih8.js";import{A as ge,C as _e,E as q,J as ve,T as ye,Y as be,c as xe,dt as Se,t as Ce,w as we}from"./shared-CIhZ6FCO.js";var Te=x(`chevron-down`,[[`path`,{d:`m6 9 6 6 6-6`,key:`qrunsl`}]]),Ee=x(`chevron-right`,[[`path`,{d:`m9 18 6-6-6-6`,key:`mthhwq`}]]),De=x(`external-link`,[[`path`,{d:`M15 3h6v6`,key:`1q9fwt`}],[`path`,{d:`M10 14 21 3`,key:`gplh6r`}],[`path`,{d:`M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6`,key:`a6xqqp`}]]),J=e(t(),1),Y=c(),Oe=Object.keys(he);function X(e){return he[e].authTypes}function ke(e){return X(e).includes(`oauth`)?`oauth`:`apiKey`}var Ae={oauth:`Authorize in the browser`,apiKey:`Paste an API key`},Z={anthropic:`Anthropic`,openai:`OpenAI`,kimi:`Kimi`,kilo:`Kilo`,grok:`Grok`,custom:`OpenAI Compatible`},je={anthropic:`Authorize in the browser, then paste the code Anthropic shows you.`,openai:`Authorize in the browser. When it redirects to localhost, paste the whole URL.`,kimi:`Enter the code on Kimi's device page. This dialog finishes on its own.`,kilo:`Approve the code on Kilo's device page. This dialog finishes on its own.`,grok:`Authorize in the browser. When it redirects to 127.0.0.1, paste the whole URL.`,custom:`Enter endpoint metadata and API key.`},Me={openai:`http://localhost:1455/auth/callback?code=…`,grok:`http://127.0.0.1:56121/callback?code=…`},Ne=g.ol`
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
gap: ${({theme:e})=>e.space(3)};
|
|
5
|
+
`,Pe=g.div`
|
|
6
|
+
font-family: ${({theme:e})=>e.font.mono};
|
|
7
|
+
font-size: 26px;
|
|
8
|
+
letter-spacing: 0.22em;
|
|
9
|
+
text-align: center;
|
|
10
|
+
padding: ${({theme:e})=>e.space(3)};
|
|
11
|
+
background: ${({theme:e})=>e.color.panelSunk};
|
|
12
|
+
border: 1px solid ${({theme:e})=>e.color.ruleStrong};
|
|
13
|
+
border-radius: ${({theme:e})=>e.radius.control};
|
|
14
|
+
`,Fe=g.p`
|
|
15
|
+
font-size: 12px;
|
|
16
|
+
color: ${({theme:e})=>e.color.down};
|
|
17
|
+
`,Ie=g.p`
|
|
18
|
+
font-size: 12px;
|
|
19
|
+
color: ${({theme:e})=>e.color.inkDim};
|
|
20
|
+
`;function Le({open:e,credentials:t,onOpenChange:i,onConnected:o}){let[s,c]=(0,J.useState)(`anthropic`),[l,u]=(0,J.useState)(ke(`anthropic`)),[d,f]=(0,J.useState)(``),[h,g]=(0,J.useState)(null),[y,ee]=(0,J.useState)(``),[x,S]=(0,J.useState)(``),C=(t??[]).filter((e,t,n)=>e.provider===`custom`&&n.findIndex(t=>t.provider===`custom`&&t.providerData.endpointId===e.providerData.endpointId)===t),[w,T]=(0,J.useState)(``),[D,O]=(0,J.useState)(``),[k,A]=(0,J.useState)(`chat_completions`),[j,M]=(0,J.useState)(``),[N,P]=(0,J.useState)(null),F=v(),I=m(),L=p(),R=(0,J.useCallback)(()=>{g(null),ee(``),S(``),T(``),O(``),A(`chat_completions`),M(``),P(null),f(``),F.reset(),I.reset(),L.reset()},[F,I,L]),z=(0,J.useCallback)(e=>{e||R(),i(e)},[i,R]);return(0,J.useEffect)(()=>{if(h===null||h.kind!==`device`)return;let e=!1,t=async()=>{try{let t=await _(h.flowId);if(e)return;if(t.status===`complete`){R(),i(!1),o();return}}catch(t){if(e)return;P(W(t)),g(null);return}e||(n=setTimeout(()=>void t(),h.pollIntervalMs))},n=setTimeout(()=>void t(),h.pollIntervalMs);return()=>{e=!0,clearTimeout(n)}},[h,o,i,R]),(0,Y.jsx)(E,{open:e,onOpenChange:z,title:`Connect an account`,description:`The gateway stores the resulting token encrypted. It is never shown again after this dialog.`,footer:h===null?(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(n,{type:`button`,onClick:()=>z(!1),children:`Cancel`}),(0,Y.jsx)(n,{type:`button`,$variant:`primary`,disabled:F.isPending||L.isPending,onClick:()=>{if(P(null),l===`apiKey`){L.mutate({provider:s,apiKey:j,label:d.trim()||void 0,...s===`custom`?{endpointId:x,endpointLabel:w,origin:D,protocol:k}:{}},{onSuccess:()=>{R(),i(!1),o()},onError:e=>P(W(e))});return}F.mutate({provider:s,label:d.trim().length===0?Z[s]:d.trim()},{onSuccess:e=>g(e),onError:e=>P(W(e))})},children:l===`apiKey`?L.isPending?`Adding…`:`Add API key`:F.isPending?`Starting…`:`Start authorization`})]}):h.kind===`device`?(0,Y.jsx)(n,{type:`button`,onClick:()=>z(!1),children:`Cancel`}):(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(n,{type:`button`,onClick:()=>z(!1),children:`Cancel`}),(0,Y.jsx)(n,{type:`button`,$variant:`primary`,disabled:I.isPending||y.trim().length===0,onClick:()=>{h!==null&&(P(null),I.mutate({flowId:h.flowId,code:y.trim()},{onSuccess:()=>{R(),i(!1),o()},onError:e=>P(W(e))}))},children:I.isPending?`Finishing…`:`Finish connecting`})]}),children:(0,Y.jsxs)(Ne,{children:[h===null?(0,Y.jsxs)(b,{$gap:3,children:[(0,Y.jsx)(H,{label:`Provider`,children:e=>(0,Y.jsx)(B,{...e,value:s,onChange:e=>{let t=e.target.value;c(t),u(ke(t))},children:Oe.map(e=>(0,Y.jsx)(`option`,{value:e,children:Z[e]},e))})}),X(s).length>1?(0,Y.jsx)(H,{label:`How to connect`,children:e=>(0,Y.jsx)(B,{...e,value:l,onChange:e=>u(e.target.value),children:X(s).map(e=>(0,Y.jsx)(`option`,{value:e,children:Ae[e]},e))})}):null,s===`custom`?(0,Y.jsxs)(Y.Fragment,{children:[C.length===0?null:(0,Y.jsx)(H,{label:`Existing endpoint`,children:e=>(0,Y.jsxs)(B,{...e,value:x,onChange:e=>{let t=C.find(t=>t.providerData.endpointId===e.target.value);if(t===void 0){S(``),T(``),O(``),A(`chat_completions`);return}S(String(t.providerData.endpointId)),T(String(t.providerData.endpointLabel)),O(String(t.providerData.origin)),A(t.providerData.protocol===`responses`?`responses`:`chat_completions`)},children:[(0,Y.jsx)(`option`,{value:``,children:`Create new endpoint`}),C.map(e=>(0,Y.jsx)(`option`,{value:String(e.providerData.endpointId),children:String(e.providerData.endpointLabel)},String(e.providerData.endpointId)))]})}),(0,Y.jsx)(H,{label:`Endpoint ID`,children:e=>(0,Y.jsx)(V,{...e,value:x,onChange:e=>S(e.target.value)})}),(0,Y.jsx)(H,{label:`Endpoint label`,children:e=>(0,Y.jsx)(V,{...e,value:w,onChange:e=>T(e.target.value)})}),(0,Y.jsx)(H,{label:`Server origin`,children:e=>(0,Y.jsx)(V,{...e,value:D,placeholder:`https://server.example`,onChange:e=>O(e.target.value)})}),D.trim().toLowerCase().startsWith(`http://`)?(0,Y.jsx)(Fe,{children:`Plaintext transport sends prompts and API keys without TLS.`}):null,(0,Y.jsx)(H,{label:`Protocol`,children:e=>(0,Y.jsxs)(B,{...e,value:k,onChange:e=>A(e.target.value),children:[(0,Y.jsx)(`option`,{value:`chat_completions`,children:`Chat Completions (/v1/chat/completions)`}),(0,Y.jsx)(`option`,{value:`responses`,children:`Responses (/v1/responses)`})]})})]}):null,l===`apiKey`?(0,Y.jsx)(H,{label:`API key`,children:e=>(0,Y.jsx)(V,{...e,type:`password`,value:j,autoComplete:`off`,onChange:e=>M(e.target.value)})}):null,(0,Y.jsx)(H,{label:`Label`,hint:`How this account is named in the rack. Defaults to the provider.`,children:e=>(0,Y.jsx)(V,{...e,value:d,placeholder:Z[s],onChange:e=>f(e.target.value)})})]}):(0,Y.jsxs)(b,{$gap:3,children:[(0,Y.jsxs)(b,{$gap:1,children:[(0,Y.jsx)(a,{children:`Step 1 — authorize`}),(0,Y.jsx)(r,{$gap:2,children:(0,Y.jsxs)(n,{as:`a`,href:h.authorizeUrl,target:`_blank`,rel:`noreferrer noopener`,$variant:`primary`,$size:`sm`,children:[(0,Y.jsx)(De,{}),`Open `,Z[s]]})}),(0,Y.jsx)(te,{value:h.authorizeUrl,label:`Copy authorization link`})]}),h.userCode===null?null:(0,Y.jsxs)(b,{$gap:1,children:[(0,Y.jsx)(a,{children:`Step 2 — enter this code`}),(0,Y.jsx)(Pe,{children:h.userCode})]}),h.kind===`device`?(0,Y.jsxs)(Ie,{children:[je[s],` Waiting for authorization…`]}):(0,Y.jsx)(H,{label:`Authorization code`,hint:je[s],...N===null?{}:{problem:N},children:e=>(0,Y.jsx)(V,{...e,value:y,autoFocus:!0,placeholder:Me[s]??`code#state`,onChange:e=>ee(e.target.value)})})]}),N===null||h?.kind===`pkce`?null:(0,Y.jsx)(Fe,{children:N})]})})}var Re=[`axis`],ze=(0,J.forwardRef)((e,t)=>J.createElement(_e,{chartName:`LineChart`,defaultTooltipEventType:`axis`,validateTooltipEventTypes:Re,tooltipPayloadSearcher:be,categoricalChartProps:e,ref:t})),Be=g(r)`
|
|
21
|
+
gap: ${({theme:e})=>e.space(5)};
|
|
22
|
+
flex-wrap: wrap;
|
|
23
|
+
`,Q=g.div`
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
gap: 2px;
|
|
27
|
+
`,$=g.span`
|
|
28
|
+
font-size: 11.5px;
|
|
29
|
+
color: ${({theme:e})=>e.color.inkDim};
|
|
30
|
+
`,Ve={budget:`1 4`,projection:`6 4`},He=`projected`;function Ue(e){let t=new Map;for(let{key:n,points:r}of e)for(let e of r){let r=t.get(e.at)??{at:e.at};r[n]=e.percent,t.set(e.at,r)}return[...t.values()].sort((e,t)=>e.at-t.at)}function We(e,t,n){return[Math.min(e,...n.map(e=>e.pace.from.at)),Math.max(t,...n.map(e=>e.pace.to.at))]}function Ge(e,t){let n=t?.windowStartsAt??null;return n===null||e.resetsAt===null?null:n-(e.resetsAt-n)}function Ke({credentialId:e,windows:t,burn:n,pollIntervalMs:r,now:i}){let a=t.map(e=>{let t=j(n,e.windowType);return{window:e,estimate:t,since:Ge(e,t)}}),o=a.map(e=>e.since).filter(e=>e!==null),s=o.length===0?0:Math.min(...o),c=y({credentialId:e,since:s},o.length>0),l=c.data?.samples??[],u=c.data?.gatewayRates??[];return(0,Y.jsx)(b,{$gap:4,children:a.map(e=>(0,Y.jsx)(Je,{window:e.window,estimate:e.estimate,since:e.since,samples:l.filter(t=>t.windowType===e.window.windowType&&t.observedAt>=(e.since??0)),gatewayRate:u.find(t=>t.windowType===e.window.windowType),pollIntervalMs:r,now:i},e.window.windowType))})}function qe(e,t,n){let r=ae(e,t);return r===`ok`?`lasts the window`:r!==`empty`||t.exhaustsAt===null?`unknown`:t.exhaustsAt<=n?`empty now`:`empty ~${k(t.exhaustsAt-n)} before it resets`}function Je({window:e,estimate:t,since:n,samples:i,gatewayRate:o,pollIntervalMs:c,now:l}){let u=L[e.windowType],d=e.limit===null?`${M(e.used)} used`:`${M(e.used)} of ${M(e.limit)} used`;if(t===void 0||t.stale||ie(e,l,c))return(0,Y.jsxs)(b,{$gap:2,children:[(0,Y.jsxs)(r,{$gap:2,$wrap:!0,children:[(0,Y.jsxs)(a,{children:[u,` window`]}),(0,Y.jsx)($,{children:d})]}),(0,Y.jsx)($,{children:`reading is stale`})]});let f=P(i),p=f.flatMap(e=>{let t=F(e);return t===null?[]:[{key:`${e.key}-budget`,pace:t}]}),m=z(e,t),h=Ue([...f,...p.map(e=>({key:e.key,points:[e.pace.from,e.pace.to]})),...m===null?[]:[{key:He,points:[m.from,m.to]}]]),g=new Set(f.map(e=>e.key)),_=Math.max(100,...m===null?[]:[m.from.percent,m.to.percent].map(e=>Math.ceil(e)));return(0,Y.jsxs)(b,{$gap:2,children:[(0,Y.jsxs)(r,{$gap:2,$wrap:!0,children:[(0,Y.jsxs)(a,{children:[u,` window`]}),(0,Y.jsx)($,{children:d})]}),(0,Y.jsxs)(Be,{children:[(0,Y.jsxs)(Q,{children:[(0,Y.jsx)(a,{children:`Window average`}),(0,Y.jsx)(s,{children:t.ratePerHour===null?`unknown`:`${M(t.ratePerHour)}/h`})]}),(0,Y.jsxs)(Q,{children:[(0,Y.jsx)(a,{children:`Estimate`}),(0,Y.jsx)(s,{children:qe(e,t,l)})]}),(0,Y.jsxs)(Q,{children:[(0,Y.jsx)(a,{children:`Projected`}),(0,Y.jsx)(s,{children:m===null?`unknown`:`${Math.round(m.to.percent)}% of limit by reset`})]}),(0,Y.jsxs)(Q,{children:[(0,Y.jsx)(a,{children:`This gateway accounts for`}),(0,Y.jsx)(s,{children:o?.gatewayRatePerHour===void 0||o.gatewayRatePerHour===null?`unknown`:`${M(o.gatewayRatePerHour)} tokens/h`})]})]}),e.limit===null?(0,Y.jsx)($,{children:`no ceiling reported`}):e.resetsAt===null||n===null?(0,Y.jsx)($,{children:`no reset reported`}):f.length===0?(0,Y.jsx)($,{children:`not yet observed`}):(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(a,{children:[`Used, this window and the one before`,...p.length===0?[]:[`budget dotted`],...m===null?[]:[`projection dashed`]].join(` · `)}),(0,Y.jsx)(Ce,{$height:160,children:(0,Y.jsx)(Se,{width:`100%`,height:`100%`,children:(0,Y.jsxs)(ze,{data:h,margin:{top:4,right:8,bottom:4,left:4},children:[(0,Y.jsx)(ge,{stroke:`var(--rule)`,vertical:!1}),(0,Y.jsx)(ye,{dataKey:`at`,type:`number`,scale:`time`,domain:We(n,e.resetsAt,p),tickFormatter:e=>oe(e),tick:{fill:`var(--ink-faint)`,fontSize:10},stroke:`var(--rule-strong)`,minTickGap:40}),(0,Y.jsx)(we,{domain:[0,_],allowDataOverflow:!0,tickFormatter:e=>`${Math.round(e)}%`,tick:{fill:`var(--ink-faint)`,fontSize:10},stroke:`var(--rule-strong)`,width:40}),(0,Y.jsx)(ve,{cursor:{stroke:`var(--rule-strong)`},content:({active:e,payload:t})=>{if(e!==!0||t===void 0||t.length===0)return null;let n=t.find(e=>g.has(String(e.dataKey)));if(n===void 0||typeof n.value!=`number`)return null;let r=n.payload.at;return(0,Y.jsxs)(xe,{children:[(0,Y.jsx)(`div`,{children:oe(r)}),(0,Y.jsxs)(`div`,{children:[n.value.toFixed(1),`% used`]})]})}}),f.map(e=>(0,Y.jsx)(q,{type:`monotone`,dataKey:e.key,stroke:`var(--accent)`,strokeWidth:2,dot:!1,connectNulls:!1,isAnimationActive:!1},e.key)),p.map(e=>(0,Y.jsx)(q,{type:`linear`,dataKey:e.key,stroke:`var(--ink-faint)`,strokeWidth:1.5,strokeDasharray:Ve.budget,dot:!1,connectNulls:!0,isAnimationActive:!1},e.key)),m===null?null:(0,Y.jsx)(q,{type:`linear`,dataKey:He,stroke:`var(--ink-dim)`,strokeWidth:1.5,strokeDasharray:Ve.projection,dot:!1,connectNulls:!0,isAnimationActive:!1})]})})})]})]})}var Ye=[`anthropic`,`openai`,`kimi`,`kilo`,`grok`,`custom`],Xe={anthropic:`Anthropic`,openai:`OpenAI`,kimi:`Kimi`,kilo:`Kilo`,grok:`Grok`,custom:`OpenAI Compatible`},Ze=g(U)`
|
|
31
|
+
border-left: 3px solid ${({theme:e,$provider:t})=>e.provider[t]};
|
|
32
|
+
`,Qe=g(V)`
|
|
33
|
+
width: 100%;
|
|
34
|
+
min-width: 140px;
|
|
35
|
+
height: 26px;
|
|
36
|
+
font-family: ${({theme:e})=>e.font.sans};
|
|
37
|
+
font-size: 12.5px;
|
|
38
|
+
background: transparent;
|
|
39
|
+
border-color: transparent;
|
|
40
|
+
|
|
41
|
+
&:hover:not(:disabled),
|
|
42
|
+
&:focus {
|
|
43
|
+
background: ${({theme:e})=>e.color.panelSunk};
|
|
44
|
+
border-color: ${({theme:e})=>e.color.ruleStrong};
|
|
45
|
+
}
|
|
46
|
+
`,$e=g(ce)`
|
|
47
|
+
width: 62px;
|
|
48
|
+
height: 26px;
|
|
49
|
+
`,et=g.span`
|
|
50
|
+
display: block;
|
|
51
|
+
padding-left: 9px;
|
|
52
|
+
font-size: 11px;
|
|
53
|
+
color: ${({theme:e})=>e.color.inkDim};
|
|
54
|
+
`,tt=g.div`
|
|
55
|
+
display: grid;
|
|
56
|
+
grid-template-columns: 96px 1fr;
|
|
57
|
+
align-items: center;
|
|
58
|
+
min-width: 208px;
|
|
59
|
+
gap: 6px;
|
|
60
|
+
`,nt=g.div`
|
|
61
|
+
display: flex;
|
|
62
|
+
flex-direction: column;
|
|
63
|
+
gap: 4px;
|
|
64
|
+
`;function rt(){let e=o();return{pending:e.isPending,commit:(t,n)=>{e.mutate({id:t,patch:n})}}}function it(){let{cadence:e}=ee(),t=f(),o=d(e(1e4)),s=l(),c=h(),{commit:p}=rt(),[m,g]=(0,J.useState)(!1),[_,v]=(0,J.useState)(null),[y,x]=(0,J.useState)(new Set),te=e=>x(t=>{let n=new Set(t);return n.delete(e)||n.add(e),n}),E=Date.now(),k=t.data??[],M=ne(o.data?.health??[],e=>e.credentialId),P=ne(o.data?.quota??[],e=>e.credentialId),F=ne(o.data?.burn??[],e=>e.credentialId),z=s.data?.quotaPollIntervalMs??3e5,ie=k.filter(e=>e.enabled).length,ae=t.isLoading?`Reading connected accounts…`:k.length===0?`No provider credentials are connected, so every request fails at the router.`:`${ie} of ${k.length} accounts are enabled and eligible for routing.`;return(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(S,{legend:`Accounts`,title:`Provider accounts`,summary:ae,actions:(0,Y.jsxs)(n,{type:`button`,$variant:`primary`,onClick:()=>g(!0),children:[(0,Y.jsx)(C,{}),`Connect an account`]})}),t.isError?(0,Y.jsx)(U,{legend:`Accounts`,children:(0,Y.jsx)(ue,{error:t.error,onRetry:()=>void t.refetch()})}):t.isLoading?(0,Y.jsx)(U,{legend:`Accounts`,children:(0,Y.jsx)(de,{rows:5})}):k.length===0?(0,Y.jsx)(U,{legend:`Accounts`,children:(0,Y.jsx)(fe,{legend:`Nothing connected`,message:`Connect a provider account to give the router something to dispatch to. Tokens are encrypted at rest and never shown again.`,action:(0,Y.jsx)(n,{type:`button`,$variant:`primary`,$size:`sm`,onClick:()=>g(!0),children:`Connect an account`})})}):(0,Y.jsx)(b,{$gap:4,children:Ye.filter(e=>k.some(t=>t.provider===e)).map(e=>{let t=k.filter(t=>t.provider===e);return(0,Y.jsx)(Ze,{$provider:e,legend:Xe[e],meta:`${t.length} account${t.length===1?``:`s`}`,flush:!0,children:(0,Y.jsx)(i,{children:(0,Y.jsxs)(me,{children:[(0,Y.jsx)(`thead`,{children:(0,Y.jsxs)(`tr`,{children:[(0,Y.jsx)(K,{$width:`24%`,children:`Account`}),(0,Y.jsx)(K,{$width:`20%`,children:`Sign-in`}),(0,Y.jsx)(K,{$align:`right`,$width:`86px`,children:`Tier`}),(0,Y.jsx)(K,{$align:`right`,$width:`94px`,children:`Weight`}),(0,Y.jsx)(K,{$align:`center`,$width:`86px`,children:`Enabled`}),(0,Y.jsx)(K,{$width:`240px`,children:`Quota`}),(0,Y.jsx)(K,{$align:`right`,$width:`88px`,children:`TTFT`}),(0,Y.jsx)(K,{$align:`right`,$width:`130px`,children:`Token expires`}),(0,Y.jsx)(K,{$width:`76px`})]})}),(0,Y.jsx)(`tbody`,{children:t.map(e=>{let t=R(M.get(e.id)??[],E,e.enabled,e.disabledReason),n=P.get(e.id)??[],i=F.get(e.id)??[],o=N(n),s=y.has(e.id);return(0,Y.jsxs)(J.Fragment,{children:[(0,Y.jsxs)(pe,{children:[(0,Y.jsxs)(G,{children:[(0,Y.jsxs)(r,{$gap:2,children:[(0,Y.jsx)(re,{state:t.state,label:t.note===``?`healthy`:t.note}),(0,Y.jsx)(Qe,{defaultValue:e.label,"aria-label":`Label for ${e.label}`,onBlur:t=>{let n=t.target.value.trim();if(n.length===0||n===e.label){t.target.value=e.label;return}p(e.id,{label:n})}})]}),t.note===``?null:(0,Y.jsx)(et,{children:t.note})]}),(0,Y.jsx)(G,{children:(0,Y.jsxs)(r,{$gap:1,children:[(0,Y.jsx)(se,{children:e.authType===`oauth`?`oauth`:`api key`}),e.accountEmail===null?null:(0,Y.jsx)(a,{children:e.accountEmail})]})}),(0,Y.jsx)(G,{$align:`right`,children:(0,Y.jsx)($e,{min:1,step:1,defaultValue:e.tier,"aria-label":`Tier for ${e.label}`,onBlur:t=>{let n=Number(t.target.value);if(!Number.isInteger(n)||n<1||n===e.tier){t.target.value=String(e.tier);return}p(e.id,{tier:n})}})}),(0,Y.jsx)(G,{$align:`right`,children:(0,Y.jsx)($e,{min:.1,step:.1,defaultValue:e.weight,"aria-label":`Weight for ${e.label}`,onBlur:t=>{let n=Number(t.target.value);if(!Number.isFinite(n)||n<=0||n===e.weight){t.target.value=String(e.weight);return}p(e.id,{weight:n})}})}),(0,Y.jsx)(G,{$align:`center`,children:(0,Y.jsx)(D,{checked:e.enabled,label:`Route to ${e.label}`,onCheckedChange:t=>p(e.id,{enabled:t})})}),(0,Y.jsx)(G,{children:o.length===0?(0,Y.jsx)(a,{children:`unknown`}):(0,Y.jsx)(nt,{children:o.map(({window:e,fraction:t})=>(0,Y.jsxs)(tt,{children:[(0,Y.jsx)(le,{fraction:t,label:`${L[e.windowType]} window, ${Math.round(t*100)}% used`}),(0,Y.jsx)(a,{children:I(e,E,z,A,j(i,e.windowType))})]},e.windowType))})}),(0,Y.jsx)(G,{$align:`right`,$mono:!0,children:O(t.ttftMs)}),(0,Y.jsx)(G,{$align:`right`,$mono:!0,children:e.expiresAt===null?`never`:A(e.expiresAt,E)}),(0,Y.jsx)(G,{$align:`right`,children:(0,Y.jsxs)(r,{$gap:1,$justify:`flex-end`,children:[n.length===0?null:(0,Y.jsx)(u,{type:`button`,$variant:`ghost`,$size:`sm`,"aria-expanded":s,"aria-label":`${s?`Hide`:`Show`} quota history for ${e.label}`,title:`${s?`Hide`:`Show`} quota history for ${e.label}`,onClick:()=>te(e.id),children:s?(0,Y.jsx)(Te,{}):(0,Y.jsx)(Ee,{})}),(0,Y.jsx)(u,{type:`button`,$variant:`ghost`,$size:`sm`,"aria-label":`Remove ${e.label}`,title:`Remove ${e.label}`,onClick:()=>v(e),children:(0,Y.jsx)(T,{})})]})})]}),s?(0,Y.jsx)(pe,{children:(0,Y.jsx)(G,{colSpan:9,children:(0,Y.jsx)(Ke,{credentialId:e.id,windows:n,burn:i,pollIntervalMs:z,now:E})})}):null]},e.id)})})]})})},e)})}),(0,Y.jsx)(Le,{open:m,credentials:t.data??[],onOpenChange:g,onConnected:()=>void t.refetch()}),(0,Y.jsx)(w,{open:_!==null,onOpenChange:e=>{e||v(null)},title:`Remove account`,body:_===null?``:`Removing "${_.label}" deletes its stored token. Any model target pointing at ${Xe[_.provider]} loses this account, and reconnecting means authorizing again.`,confirmLabel:`Remove account`,busy:c.isPending,onConfirm:()=>{_!==null&&c.mutate(_.id,{onSettled:()=>v(null)})}})]})}var at=it;export{at as component};
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{$t as e,F as t,Ft as n,I as r,Pt as i,c as a,q as o,t as s}from"./queries-D8LJNQpL.js";import{a as c,t as l}from"./Rack-Bbo4JfEX.js";import{b as u}from"./Lamp-B65uWKbW.js";import{i as d}from"./Field-BDtp692L.js";import{a as f,n as p,r as m,t as h}from"./States-BEKLros0.js";var g=e(n(),1),_=i(),v=[100,200,500],y=[{value:``,label:`All levels`},{value:`debug`,label:`Debug and above`},{value:`info`,label:`Info and above`},{value:`warn`,label:`Warnings and errors`},{value:`error`,label:`Errors only`}],b=o(r)`
|
|
2
2
|
gap: ${({theme:e})=>e.space(2)};
|
|
3
3
|
flex-wrap: wrap;
|
|
4
|
-
`,x=
|
|
4
|
+
`,x=o(d)`
|
|
5
5
|
width: auto;
|
|
6
|
-
`,S=
|
|
6
|
+
`,S=o.div`
|
|
7
7
|
display: grid;
|
|
8
8
|
grid-template-rows: auto minmax(0, 1fr);
|
|
9
9
|
gap: ${({theme:e})=>e.space(4)};
|
|
10
10
|
min-height: 0;
|
|
11
11
|
flex: 1;
|
|
12
|
-
`,C=
|
|
12
|
+
`,C=o(f)`
|
|
13
13
|
min-height: 0;
|
|
14
14
|
|
|
15
15
|
> div {
|
|
@@ -18,27 +18,27 @@ import{G as e,Mt as t,N as n,Nt as r,P as i,Zt as a,c as o,t as s}from"./queries
|
|
|
18
18
|
flex-direction: column;
|
|
19
19
|
min-height: 0;
|
|
20
20
|
}
|
|
21
|
-
`,w=
|
|
21
|
+
`,w=o.div`
|
|
22
22
|
flex: 1;
|
|
23
23
|
min-height: 0;
|
|
24
24
|
overflow-x: auto;
|
|
25
25
|
overflow-y: auto;
|
|
26
|
-
`,T=
|
|
26
|
+
`,T=o.pre`
|
|
27
27
|
margin: 0;
|
|
28
28
|
padding: ${({theme:e})=>e.space(3)};
|
|
29
29
|
font-family: ${({theme:e})=>e.font.mono};
|
|
30
30
|
font-size: 12px;
|
|
31
31
|
line-height: 1.65;
|
|
32
32
|
white-space: pre;
|
|
33
|
-
`,E=
|
|
33
|
+
`,E=o.div`
|
|
34
34
|
color: ${({theme:e,$level:t})=>t===`error`?e.color.down:t===`warn`?e.color.warn:t===`debug`?e.color.inkFaint:e.color.ink};
|
|
35
|
-
`,D=
|
|
35
|
+
`,D=o.p`
|
|
36
36
|
margin: 0;
|
|
37
37
|
padding: ${({theme:e})=>`${e.space(2)} ${e.space(3)}`};
|
|
38
38
|
border-top: 1px solid ${({theme:e})=>e.color.rule};
|
|
39
39
|
color: ${({theme:e})=>e.color.inkDim};
|
|
40
40
|
font-size: 12px;
|
|
41
|
-
`,O=
|
|
41
|
+
`,O=o.code`
|
|
42
42
|
font-family: ${({theme:e})=>e.font.mono};
|
|
43
43
|
word-break: break-all;
|
|
44
|
-
`;function k({read:e}){return e.source===`file`?(0,_.jsxs)(D,{children:[`Reading `,(0,_.jsx)(O,{children:e.path}),`, named by `,(0,_.jsx)(O,{children:`OMNI_LOG_FILE`}),`. That variable says where the gateway's output is being captured; it does not redirect it.`]}):e.source===`journal`?(0,_.jsxs)(D,{children:[`Reading the systemd journal for `,(0,_.jsx)(O,{children:`omnigateway.service`}),`. To read a file instead, redirect the gateway's output to one and point `,(0,_.jsx)(O,{children:`OMNI_LOG_FILE`}),` at the same path.`]}):null}function A(){let{cadence:e}=c(),[
|
|
44
|
+
`;function k({read:e}){return e.source===`file`?(0,_.jsxs)(D,{children:[`Reading `,(0,_.jsx)(O,{children:e.path}),`, named by `,(0,_.jsx)(O,{children:`OMNI_LOG_FILE`}),`. That variable says where the gateway's output is being captured; it does not redirect it.`]}):e.source===`journal`?(0,_.jsxs)(D,{children:[`Reading the systemd journal for `,(0,_.jsx)(O,{children:`omnigateway.service`}),`. To read a file instead, redirect the gateway's output to one and point `,(0,_.jsx)(O,{children:`OMNI_LOG_FILE`}),` at the same path.`]}):null}function A(){let{cadence:e}=c(),[n,r]=(0,g.useState)(200),[i,o]=(0,g.useState)(``),d=a(n,i,e(s)),f=d.data,D=f?.lines??[],O=(0,g.useRef)(null),A=(0,g.useRef)(!0);return(0,g.useLayoutEffect)(()=>{let e=O.current;e!==null&&A.current&&f!==void 0&&(e.scrollTop=e.scrollHeight)},[f]),(0,_.jsxs)(S,{children:[(0,_.jsx)(l,{legend:`Console`,title:`Gateway output`,summary:d.isLoading?`Reading the gateway's own output…`:`${u(D.length)} lines of what this process is doing. Requests are in Logs; prompt bodies, tokens and keys are never written here.`,actions:(0,_.jsxs)(b,{children:[(0,_.jsx)(x,{value:i,"aria-label":`Which levels to show`,onChange:e=>o(e.target.value),children:y.map(e=>(0,_.jsx)(`option`,{value:e.value,children:e.label},e.value))}),(0,_.jsx)(x,{value:n,"aria-label":`How many lines to fetch`,onChange:e=>r(Number(e.target.value)),children:v.map(e=>(0,_.jsxs)(`option`,{value:e,children:[`last `,e]},e))})]})}),(0,_.jsxs)(C,{legend:`Process output`,meta:f===void 0?void 0:(0,_.jsx)(t,{children:j(f)}),flush:!0,children:[f===void 0?null:(0,_.jsx)(k,{read:f}),(0,_.jsx)(w,{ref:O,"data-testid":`console-terminal`,onScroll:e=>{let t=e.currentTarget;A.current=t.scrollHeight-t.scrollTop-t.clientHeight<=8},children:d.isError?(0,_.jsx)(p,{error:d.error,onRetry:()=>void d.refetch()}):d.isLoading?(0,_.jsx)(`div`,{style:{padding:12},children:(0,_.jsx)(m,{rows:10})}):f!==void 0&&f.source===`none`?(0,_.jsx)(h,{legend:`Nothing is capturing this gateway`,message:"Its output is going to a terminal, so there is nothing to read back. To capture it, run the gateway under systemd with `omni service install`, or start it with `omni start`, which redirects output to a file and points OMNI_LOG_FILE at it."}):D.length===0?(0,_.jsx)(h,{legend:`Nothing to show`,message:i===``?`This log is empty. The gateway writes here when it boots, refreshes a token, or polls a quota.`:`No line in this window is at that level. Widen the filter to see everything.`}):(0,_.jsx)(T,{children:D.map((e,t)=>(0,_.jsx)(E,{$level:e.level,children:e.raw},`${e.at??0}-${t}`))})})]})]})}function j(e){return e.source===`file`?`log file`:e.source===`journal`?`systemd journal`:`not captured`}var M=A;export{M as component};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import{B as e,H as t,I as n,L as r,M as i,N as a,P as o,Pt as s,R as c,T as l,Y as u,b as d,d as f,f as p,k as m,q as h,y as g,z as _}from"./queries-D8LJNQpL.js";import{a as ee,r as v,t as y}from"./Rack-Bbo4JfEX.js";import{n as b,t as x}from"./TokenBreakdown-C1ziK9d1.js";import{C as S,E as C,T as w,_ as te,a as T,b as E,d as D,f as O,g as k,l as A,m as j,n as M,o as N,r as ne,s as P,t as F,w as I,y as L}from"./Lamp-B65uWKbW.js";import{n as R,t as z}from"./Chip-DJwp7gBu.js";import{t as B}from"./Meter-BREBUFGX.js";import{a as V,n as H,t as U}from"./States-BEKLros0.js";import{i as W,n as G,r as K,t as q}from"./Table-BBypbVWj.js";import{t as J}from"./Readout-CEAoN5hu.js";var Y=s(),X=h(e)`
|
|
2
|
+
font-weight: 500;
|
|
3
|
+
display: block;
|
|
4
|
+
max-width: 24ch;
|
|
5
|
+
`,Z=h.span`
|
|
6
|
+
font-size: 11px;
|
|
7
|
+
color: ${({theme:e})=>e.color.inkDim};
|
|
8
|
+
`,re=h.div`
|
|
9
|
+
display: grid;
|
|
10
|
+
grid-template-columns: 72px 1fr;
|
|
11
|
+
align-items: center;
|
|
12
|
+
gap: 6px;
|
|
13
|
+
min-width: 172px;
|
|
14
|
+
`,ie=h.div`
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
gap: 4px;
|
|
18
|
+
`;function ae(e){let t=null;for(let n of e)n.stale||n.survives!==!1||n.exhaustsAt===null||(t===null||n.exhaustsAt<t)&&(t=n.exhaustsAt);return t}function oe(e,t){return e===null?t===null?0:1:t===null?-1:e-t}function se({credentials:e,health:i,quota:o,burn:s,usage:c,quotaPollIntervalMs:l,now:d}){let f=P(i,e=>e.credentialId),p=P(o,e=>e.credentialId),m=P(s,e=>e.credentialId),h=new Map(c.map(e=>[e.key,e])),g={down:0,warn:1,ok:2,idle:3,live:3},_=e.map(e=>{let t=m.get(e.id)??[];return{credential:e,status:N(f.get(e.id)??[],d,e.enabled,e.disabledReason),quota:k(p.get(e.id)??[]),burn:t,exhaustsAt:ae(t),usage:h.get(e.id)}}).sort((e,t)=>g[e.status.state]-g[t.status.state]||oe(e.exhaustsAt,t.exhaustsAt)||e.credential.tier-t.credential.tier);return(0,Y.jsx)(V,{legend:`Accounts`,meta:`${e.length} connected`,flush:!0,actions:(0,Y.jsx)(t,{as:u,to:`/accounts`,$size:`sm`,children:`Manage accounts`}),children:e.length===0?(0,Y.jsx)(U,{legend:`No accounts`,message:`The gateway has no provider credentials, so every request will fail. Connect one to start routing.`,action:(0,Y.jsx)(t,{as:u,to:`/accounts`,$variant:`primary`,$size:`sm`,children:`Connect an account`})}):(0,Y.jsx)(r,{children:(0,Y.jsxs)(q,{children:[(0,Y.jsx)(`thead`,{children:(0,Y.jsxs)(`tr`,{children:[(0,Y.jsx)(K,{children:`Account`}),(0,Y.jsx)(K,{children:`Provider`}),(0,Y.jsx)(K,{$align:`right`,children:`Tier`}),(0,Y.jsx)(K,{children:`Quota`}),(0,Y.jsx)(K,{$align:`right`,children:`TTFT`}),(0,Y.jsx)(K,{$align:`right`,children:`Requests`}),(0,Y.jsx)(K,{$align:`right`,children:`Last used`})]})}),(0,Y.jsx)(`tbody`,{children:_.map(({credential:e,status:t,quota:r,burn:i,usage:o})=>(0,Y.jsxs)(W,{children:[(0,Y.jsx)(G,{children:(0,Y.jsxs)(n,{$gap:2,children:[(0,Y.jsx)(F,{state:t.state,label:t.note===``?`healthy`:t.note}),(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(X,{children:e.label}),t.note===``?null:(0,Y.jsx)(Z,{children:t.note})]})]})}),(0,Y.jsx)(G,{children:(0,Y.jsx)(R,{provider:e.provider})}),(0,Y.jsx)(G,{$align:`right`,$mono:!0,children:e.tier}),(0,Y.jsx)(G,{children:r.length===0?(0,Y.jsx)(Z,{children:`unknown`}):(0,Y.jsx)(ie,{children:r.map(({window:e,fraction:t})=>(0,Y.jsxs)(re,{children:[(0,Y.jsx)(B,{fraction:t,label:`${M[e.windowType]} window, ${Math.round(t*100)}% used`}),(0,Y.jsx)(a,{children:j(e,d,l,w,T(i,e.windowType))})]},e.windowType))})}),(0,Y.jsx)(G,{$align:`right`,$mono:!0,children:S(t.ttftMs)}),(0,Y.jsx)(G,{$align:`right`,$mono:!0,children:o===void 0?`—`:E(o.requests)}),(0,Y.jsx)(G,{$align:`right`,$mono:!0,children:w(t.lastUsedAt,d)})]},e.id))})]})})})}var ce=h.ul`
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
`,le=h.li`
|
|
22
|
+
display: flex;
|
|
23
|
+
align-items: center;
|
|
24
|
+
gap: ${({theme:e})=>e.space(2)};
|
|
25
|
+
padding: 6px ${({theme:e})=>e.space(3)};
|
|
26
|
+
border-bottom: 1px solid ${({theme:e})=>e.color.rule};
|
|
27
|
+
|
|
28
|
+
&:last-child {
|
|
29
|
+
border-bottom: 0;
|
|
30
|
+
}
|
|
31
|
+
`,ue=h(e)`
|
|
32
|
+
font-family: ${({theme:e})=>e.font.mono};
|
|
33
|
+
font-size: 12px;
|
|
34
|
+
max-width: 30ch;
|
|
35
|
+
`,de=h(o)`
|
|
36
|
+
color: ${({theme:e})=>e.color.down};
|
|
37
|
+
font-size: 11px;
|
|
38
|
+
`;function fe({logs:e}){let n=e.slice(0,12);return(0,Y.jsx)(V,{legend:`Activity`,meta:`most recent first`,flush:!0,actions:(0,Y.jsx)(t,{as:u,to:`/logs`,$size:`sm`,children:`Open logs`}),children:n.length===0?(0,Y.jsx)(U,{legend:`No traffic yet`,message:`Point a client at this gateway with an API key and the requests will appear here.`}):(0,Y.jsx)(ce,{children:n.map(e=>(0,Y.jsxs)(le,{children:[(0,Y.jsx)(F,{state:O(e),label:D(e)}),(0,Y.jsx)(o,{$dim:!0,children:L(e.at)}),(0,Y.jsx)(ue,{title:e.requestedModel,children:e.requestedModel||`—`}),e.resolvedProvider===null?null:(0,Y.jsx)(o,{$dim:!0,style:{color:`var(--p-${e.resolvedProvider})`},children:e.resolvedProvider}),(0,Y.jsx)(c,{}),A(e)?(0,Y.jsx)(o,{$dim:!0,"aria-label":`processing`,children:(0,Y.jsx)(x,{})}):(0,Y.jsxs)(Y.Fragment,{children:[e.errorCode===null?null:(0,Y.jsx)(de,{children:e.errorCode}),e.attempts>1?(0,Y.jsxs)(o,{$dim:!0,children:[e.attempts,`×`]}):null,(0,Y.jsx)(o,{$dim:!0,children:(0,Y.jsx)(b,{tokens:e})}),(0,Y.jsx)(o,{$dim:!0,children:S(e.durationMs)}),(0,Y.jsx)(o,{$dim:!0,children:C(e.costUsd)})]})]},e.id))})})}var pe=h.ul`
|
|
39
|
+
display: flex;
|
|
40
|
+
flex-direction: column;
|
|
41
|
+
gap: ${({theme:e})=>e.space(3)};
|
|
42
|
+
`,me=h(e)`
|
|
43
|
+
font-family: ${({theme:e})=>e.font.mono};
|
|
44
|
+
font-size: 12.5px;
|
|
45
|
+
`,Q=h.div`
|
|
46
|
+
display: flex;
|
|
47
|
+
height: 5px;
|
|
48
|
+
border-radius: 2px;
|
|
49
|
+
overflow: hidden;
|
|
50
|
+
background: ${({theme:e})=>e.color.panelSunk};
|
|
51
|
+
border: 1px solid ${({theme:e})=>e.color.rule};
|
|
52
|
+
`,he=h.div`
|
|
53
|
+
flex: ${({$grow:e})=>e} 0 0;
|
|
54
|
+
background: ${({$color:e})=>e};
|
|
55
|
+
opacity: 0.8;
|
|
56
|
+
`,ge=h.div`
|
|
57
|
+
flex: ${({$grow:e})=>e} 0 0;
|
|
58
|
+
`;function _e({models:e,logs:r}){let i=new Map;for(let e of r){let t=i.get(e.requestedModel)??{requests:0,costUsd:0};t.requests+=1,t.costUsd+=e.costUsd,i.set(e.requestedModel,t)}let s=Math.max(1,...[...i.values()].map(e=>e.requests)),l=[...e].map(e=>({model:e,used:i.get(e.id)})).sort((e,t)=>(t.used?.requests??0)-(e.used?.requests??0)).slice(0,8);return(0,Y.jsx)(V,{legend:`Models`,meta:`${e.length} configured`,actions:(0,Y.jsx)(t,{as:u,to:`/models`,$size:`sm`,children:`Edit routing`}),children:e.length===0?(0,Y.jsx)(U,{legend:`No models`,message:`Nothing is routable yet. Create a virtual model and point it at one or more provider targets.`,action:(0,Y.jsx)(t,{as:u,to:`/models`,$variant:`primary`,$size:`sm`,children:`Create a model`})}):(0,Y.jsx)(pe,{children:l.map(({model:e,used:t})=>{let r=(t?.requests??0)/s,i=[...new Set(e.targets.map(e=>e.provider))];return(0,Y.jsxs)(`li`,{children:[(0,Y.jsxs)(n,{$gap:2,children:[(0,Y.jsx)(me,{title:e.id,children:e.id}),e.isAlias?(0,Y.jsx)(z,{children:`alias`}):null,(0,Y.jsx)(z,{$tone:`accent`,children:e.strategy}),(0,Y.jsx)(c,{}),(0,Y.jsx)(o,{$dim:!0,children:E(t?.requests??0)}),(0,Y.jsx)(a,{children:`req`}),(0,Y.jsx)(o,{$dim:!0,children:C(t?.costUsd??0)})]}),(0,Y.jsxs)(Q,{style:{marginTop:6},title:`${Math.round(r*100)}% of the busiest model`,children:[i.map(e=>(0,Y.jsx)(he,{$color:`var(--p-${e})`,$grow:r/i.length},e)),(0,Y.jsx)(ge,{$grow:Math.max(0,1-r)})]})]},e.id)})})})}var ve=h.div`
|
|
59
|
+
display: grid;
|
|
60
|
+
grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
|
|
61
|
+
gap: ${({theme:e})=>e.space(3)};
|
|
62
|
+
`;function ye({logs:e,windowMs:t,now:n}){let r=e.filter(e=>n-e.at<=t),i=te(r,t),a=ne(r,{now:n,spanMs:t,count:32}),o=i.errorRate>=.25?`down`:i.errorRate>=.05?`warn`:`ok`,s=i.inputTokens+i.outputTokens+i.cacheReadTokens+i.cacheWriteTokens;return(0,Y.jsxs)(ve,{children:[(0,Y.jsx)(J,{legend:`Requests`,value:E(i.requests),unit:`${i.ratePerMin.toFixed(1)}/min`,trace:(0,Y.jsx)(v,{values:a.map(e=>e.total),overlay:a.map(e=>e.errors),label:`${i.requests} requests, ${i.errors} of them failed`})}),(0,Y.jsx)(J,{legend:`Error rate`,value:I(i.errorRate),unit:`${E(i.errors)} failed`,tone:i.requests===0?`ink`:o,trace:(0,Y.jsx)(v,{values:a.map(e=>e.errors),scaleTo:Math.max(...a.map(e=>e.total)),color:`var(--down)`,label:`${i.errors} failed requests against ${i.requests} total`})}),(0,Y.jsx)(J,{legend:`Total tokens`,value:E(s),unit:(0,Y.jsx)(b,{tokens:i}),trace:(0,Y.jsx)(v,{values:a.map(e=>e.tokens),label:`token volume over the window, ${s.toLocaleString(`en-US`)} total`})}),(0,Y.jsx)(J,{legend:`Time to first token`,value:S(i.ttftP50),unit:`p95 ${S(i.ttftP95)}`,trace:(0,Y.jsx)(v,{values:a.map(e=>e.ttftMs??0),color:`var(--ok)`,label:`median first-token latency, currently ${S(i.ttftP50)}`})}),(0,Y.jsx)(J,{legend:`Spend`,value:C(i.costUsd),unit:`${E(i.inputTokens+i.outputTokens)} tokens`,trace:(0,Y.jsx)(v,{values:a.map(e=>e.costUsd),color:`var(--warn)`,label:`spend over the window, ${C(i.costUsd)} total`})})]})}var $=36e5;function be(){let{cadence:e}=ee(),t=p(),n=f(e(1e4)),r=d(),a=g(500,e(1e4)),o=l(),s=Date.now(),c=Math.floor((s-$)/6e4)*6e4,u=m({groupBy:`credential`,since:c},e(6e4)),h=t.data??[],v=P(n.data?.health??[],e=>e.credentialId),b=h.filter(e=>N(v.get(e.id)??[],s,e.enabled,e.disabledReason).state===`down`),x=t.isLoading||a.isLoading?`Reading the gateway…`:h.length===0?`No accounts are connected, so every request fails at the router.`:b.length>0?`${b.length} account${b.length===1?` is`:`s are`} out of rotation.`:`All ${h.length} accounts are answering. Nothing needs attention.`;return(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(y,{legend:`Rack`,title:`Gateway`,summary:x}),a.isError?(0,Y.jsx)(V,{legend:`Traffic`,children:(0,Y.jsx)(H,{legend:`The gateway did not answer`,error:a.error,onRetry:()=>void a.refetch()})}):(0,Y.jsxs)(_,{$gap:4,children:[(0,Y.jsx)(ye,{logs:a.data??[],windowMs:$,now:s}),(0,Y.jsx)(se,{credentials:h,health:n.data?.health??[],quota:n.data?.quota??[],burn:n.data?.burn??[],usage:u.data??[],quotaPollIntervalMs:o.data?.quotaPollIntervalMs??3e5,now:s}),(0,Y.jsxs)(i,{$min:`340px`,$gap:4,children:[(0,Y.jsx)(_e,{models:r.data??[],logs:a.data??[]}),(0,Y.jsx)(fe,{logs:a.data??[]})]})]})]})}var xe=be;export{xe as component};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import{$t as e,B as t,Ft as n,H as r,I as i,L as a,N as o,P as s,Pt as c,S as l,b as u,g as d,q as f,u as p,z as m}from"./queries-D8LJNQpL.js";import{t as h}from"./Rack-Bbo4JfEX.js";import{t as g}from"./CopyValue-CNZbWS59.js";import{n as _,t as v}from"./Confirm-CVLz9F7a.js";import{t as y}from"./Modal-DbydSAlp.js";import{t as b}from"./Toggle-BUr71O4J.js";import{x}from"./Lamp-B65uWKbW.js";import{t as S}from"./Chip-DJwp7gBu.js";import{n as C,t as w}from"./Field-BDtp692L.js";import{a as T,i as E,n as D,r as O,t as k}from"./States-BEKLros0.js";import{i as A,n as j,r as M,t as N}from"./Table-BBypbVWj.js";var P=e(n(),1),F=c(),I=f.div`
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
gap: 2px;
|
|
5
|
+
max-height: 190px;
|
|
6
|
+
overflow-y: auto;
|
|
7
|
+
padding: ${({theme:e})=>e.space(1)};
|
|
8
|
+
border: 1px solid ${({theme:e})=>e.color.ruleStrong};
|
|
9
|
+
border-radius: ${({theme:e})=>e.radius.control};
|
|
10
|
+
background: ${({theme:e})=>e.color.panelSunk};
|
|
11
|
+
`,L=f.label`
|
|
12
|
+
display: flex;
|
|
13
|
+
align-items: center;
|
|
14
|
+
gap: ${({theme:e})=>e.space(2)};
|
|
15
|
+
padding: 4px 6px;
|
|
16
|
+
border-radius: 2px;
|
|
17
|
+
cursor: pointer;
|
|
18
|
+
font-family: ${({theme:e})=>e.font.mono};
|
|
19
|
+
font-size: 12px;
|
|
20
|
+
|
|
21
|
+
&:hover {
|
|
22
|
+
background: ${({theme:e})=>e.color.panelRaised};
|
|
23
|
+
}
|
|
24
|
+
`,R=f.p`
|
|
25
|
+
font-size: 12px;
|
|
26
|
+
color: ${({theme:e})=>e.color.warn};
|
|
27
|
+
`,z=f.p`
|
|
28
|
+
font-size: 12px;
|
|
29
|
+
color: ${({theme:e})=>e.color.down};
|
|
30
|
+
`,B=f.p`
|
|
31
|
+
font-size: 12px;
|
|
32
|
+
color: ${({theme:e})=>e.color.inkDim};
|
|
33
|
+
`;function V({open:e,onOpenChange:t}){let n=u(),a=p(),[c,l]=(0,P.useState)(``),[d,f]=(0,P.useState)(!0),[h,_]=(0,P.useState)([]),[v,x]=(0,P.useState)(``),[S,T]=(0,P.useState)(null),[D,O]=(0,P.useState)(null),k=()=>{l(``),f(!0),_([]),x(``),T(null),O(null),a.reset()},A=e=>{e||k(),t(e)};return(0,F.jsx)(y,{open:e,onOpenChange:A,title:S===null?`Create an API key`:`Key created`,description:S===null?`Clients send this key as a bearer token or as x-api-key on every /v1 request.`:void 0,footer:S===null?(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(r,{type:`button`,onClick:()=>A(!1),children:`Cancel`}),(0,F.jsx)(r,{type:`button`,$variant:`primary`,disabled:a.isPending,onClick:()=>{let e=v.trim(),t=e.length===0?null:Number(e);if(t!==null&&(!Number.isInteger(t)||t<1)){O(`The rate limit must be a whole number of requests per minute, or blank for none.`);return}O(null),a.mutate({label:c.trim().length===0?`api key`:c.trim(),modelAllowlist:d?null:h,rateLimitPerMin:t},{onSuccess:e=>T(e),onError:e=>O(E(e))})},children:a.isPending?`Creating…`:`Create key`})]}):(0,F.jsx)(r,{type:`button`,$variant:`primary`,onClick:()=>A(!1),children:`I have copied the key`}),children:S===null?(0,F.jsxs)(m,{$gap:3,children:[(0,F.jsx)(w,{label:`Label`,hint:`Names the client this key belongs to, e.g. laptop or CI.`,children:e=>(0,F.jsx)(C,{...e,value:c,placeholder:`api key`,onChange:e=>l(e.target.value)})}),(0,F.jsxs)(m,{$gap:2,children:[(0,F.jsxs)(i,{$gap:2,children:[(0,F.jsx)(b,{checked:d,label:`Allow every model`,onCheckedChange:f}),(0,F.jsx)(o,{as:`span`,children:`Allow every model`})]}),d?null:(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(I,{children:(n.data??[]).map(e=>(0,F.jsxs)(L,{children:[(0,F.jsx)(`input`,{type:`checkbox`,checked:h.includes(e.id),onChange:t=>_(n=>t.target.checked?[...n,e.id]:n.filter(t=>t!==e.id))}),e.id]},e.id))}),h.length===0?(0,F.jsx)(R,{children:`With no model selected this key is allowed nothing and every request it makes will be refused.`}):null]})]}),(0,F.jsx)(w,{label:`Rate limit`,hint:`Requests per minute for this key. Leave blank for no limit. Counted per process, and reset when the gateway restarts.`,children:e=>(0,F.jsx)(C,{...e,type:`number`,min:1,step:1,value:v,placeholder:`no limit`,onChange:e=>x(e.target.value)})}),D===null?null:(0,F.jsx)(z,{role:`alert`,children:D})]}):(0,F.jsxs)(m,{$gap:3,children:[(0,F.jsx)(B,{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.`}),(0,F.jsx)(g,{value:S.key,label:`Copy API key`}),(0,F.jsxs)(i,{$gap:2,children:[(0,F.jsx)(o,{children:`Label`}),(0,F.jsx)(s,{children:S.label}),(0,F.jsx)(o,{children:`Prefix`}),(0,F.jsx)(s,{children:S.prefix})]})]})})}var H=f(i)`
|
|
34
|
+
gap: 4px;
|
|
35
|
+
flex-wrap: wrap;
|
|
36
|
+
max-width: 34ch;
|
|
37
|
+
`,U=f.span`
|
|
38
|
+
color: ${({theme:e})=>e.color.inkFaint};
|
|
39
|
+
`;function W(){let e=d(),n=l(),[i,s]=(0,P.useState)(!1),[c,u]=(0,P.useState)(null),f=e.data??[],p=f.filter(e=>e.revokedAt===null),m=e.isLoading?`Reading issued keys…`:f.length===0?`No keys exist, so nothing can call this gateway yet.`:`${p.length} active key${p.length===1?``:`s`} of ${f.length} ever issued.`;return(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(h,{legend:`Keys`,title:`Gateway API keys`,summary:m,actions:(0,F.jsxs)(r,{type:`button`,$variant:`primary`,onClick:()=>s(!0),children:[(0,F.jsx)(_,{}),`Create a key`]})}),(0,F.jsx)(T,{legend:`Issued keys`,meta:`${f.length}`,flush:!0,children:e.isError?(0,F.jsx)(D,{error:e.error,onRetry:()=>void e.refetch()}):e.isLoading?(0,F.jsx)(`div`,{style:{padding:12},children:(0,F.jsx)(O,{rows:4})}):f.length===0?(0,F.jsx)(k,{legend:`No keys`,message:`Create a key and give it to a client. The key is shown once, at creation.`,action:(0,F.jsx)(r,{type:`button`,$variant:`primary`,$size:`sm`,onClick:()=>s(!0),children:`Create a key`})}):(0,F.jsx)(a,{children:(0,F.jsxs)(N,{children:[(0,F.jsx)(`thead`,{children:(0,F.jsxs)(`tr`,{children:[(0,F.jsx)(M,{children:`Label`}),(0,F.jsx)(M,{children:`Prefix`}),(0,F.jsx)(M,{children:`Allowed models`}),(0,F.jsx)(M,{$align:`right`,children:`Rate limit`}),(0,F.jsx)(M,{$align:`right`,children:`Created`}),(0,F.jsx)(M,{children:`Status`}),(0,F.jsx)(M,{})]})}),(0,F.jsx)(`tbody`,{children:f.map(e=>(0,F.jsxs)(A,{children:[(0,F.jsx)(j,{children:(0,F.jsx)(t,{style:{maxWidth:`24ch`,display:`block`},children:e.label})}),(0,F.jsxs)(j,{$mono:!0,children:[e.prefix,`…`]}),(0,F.jsx)(j,{children:e.modelAllowlist===null?(0,F.jsx)(o,{children:`every model`}):e.modelAllowlist.length===0?(0,F.jsx)(S,{$tone:`down`,children:`no models`}):(0,F.jsx)(H,{children:e.modelAllowlist.map(e=>(0,F.jsx)(S,{children:e},e))})}),(0,F.jsx)(j,{$align:`right`,$mono:!0,children:e.rateLimitPerMin===null?`—`:`${e.rateLimitPerMin}/min`}),(0,F.jsx)(j,{$align:`right`,$mono:!0,children:x(e.createdAt)}),(0,F.jsx)(j,{children:e.revokedAt===null?(0,F.jsx)(S,{$tone:`ok`,children:`active`}):(0,F.jsx)(U,{title:x(e.revokedAt),children:(0,F.jsx)(S,{children:`revoked`})})}),(0,F.jsx)(j,{$align:`right`,children:e.revokedAt===null?(0,F.jsx)(r,{type:`button`,$variant:`danger`,$size:`sm`,onClick:()=>u(e),children:`Revoke`}):null})]},e.id))})]})})}),(0,F.jsx)(V,{open:i,onOpenChange:s}),(0,F.jsx)(v,{open:c!==null,onOpenChange:e=>{e||u(null)},title:`Revoke key`,body:c===null?``:`Revoking "${c.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:n.isPending,onConfirm:()=>{c!==null&&n.mutate(c.id,{onSettled:()=>u(null)})}})]})}var G=W;export{G as component};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import{$t as e,B as t,Ft as n,H as ee,I as r,L as i,N as a,P as te,Pt as o,f as ne,g as re,n as ie,q as s,y as c,z as l}from"./queries-D8LJNQpL.js";import{a as u,t as d}from"./Rack-Bbo4JfEX.js";import{n as f,r as p,t as m}from"./TokenBreakdown-C1ziK9d1.js";import{t as h}from"./Modal-DbydSAlp.js";import{C as g,D as _,E as v,S as ae,b as y,c as b,d as oe,f as x,l as S,t as C,x as w,y as T}from"./Lamp-B65uWKbW.js";import{n as se,t as E}from"./Chip-DJwp7gBu.js";import{i as D,n as O}from"./Field-BDtp692L.js";import{a as k,n as A,r as j,t as M}from"./States-BEKLros0.js";import{i as N,n as P,r as F,t as I}from"./Table-BBypbVWj.js";var L=e(n(),1),R=o(),z=[50,100,250,500],B=s(r)`
|
|
2
|
+
gap: ${({theme:e})=>e.space(2)};
|
|
3
|
+
flex-wrap: wrap;
|
|
4
|
+
`,V=s(O)`
|
|
5
|
+
width: 220px;
|
|
6
|
+
`,H=s(D)`
|
|
7
|
+
width: auto;
|
|
8
|
+
`,U=s(k)`
|
|
9
|
+
flex: 1;
|
|
10
|
+
min-height: 0;
|
|
11
|
+
|
|
12
|
+
> div {
|
|
13
|
+
display: flex;
|
|
14
|
+
flex: 1;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
min-height: 0;
|
|
17
|
+
}
|
|
18
|
+
`,W=s(i)`
|
|
19
|
+
flex: 1;
|
|
20
|
+
min-height: 0;
|
|
21
|
+
overflow-y: auto;
|
|
22
|
+
`;function G(e){let[t,n]=(0,L.useState)(Date.now);return(0,L.useEffect)(()=>{if(!e)return;n(Date.now());let t=window.setInterval(()=>n(Date.now()),1e3);return()=>window.clearInterval(t)},[e]),t}function ce({log:e}){return(0,R.jsx)(P,{$align:`right`,$mono:!0,...S(e)?{"aria-label":`processing`}:{title:p(e)},children:S(e)?(0,R.jsx)(m,{}):(0,R.jsx)(f,{tokens:e})})}var le=s.dl`
|
|
23
|
+
display: grid;
|
|
24
|
+
grid-template-columns: minmax(120px, auto) minmax(0, 1fr);
|
|
25
|
+
gap: 6px ${({theme:e})=>e.space(3)};
|
|
26
|
+
margin: 0;
|
|
27
|
+
font-size: 12.5px;
|
|
28
|
+
`,K=s.dd`
|
|
29
|
+
margin: 0;
|
|
30
|
+
font-family: ${({theme:e})=>e.font.mono};
|
|
31
|
+
word-break: break-all;
|
|
32
|
+
`;function q(){let{cadence:e,live:n}=u(),[i,o]=(0,L.useState)(100),[s,f]=(0,L.useState)(`all`),[p,m]=(0,L.useState)(``),[D,O]=(0,L.useState)(null),k=c(i,e(ie)),q=ne(),J=re(),ue=(k.data??[]).some(S),de=G(n&&ue),Y=(0,L.useMemo)(()=>{let e=new Map;for(let t of q.data??[])e.set(t.id,t.label);return e},[q.data]),X=(0,L.useMemo)(()=>{let e=new Map;for(let t of J.data??[])e.set(t.id,t.label);return e},[J.data]),Z=p.trim().toLowerCase(),Q=(k.data??[]).filter(e=>s===`failed`&&!b(e)?!1:Z.length===0||e.requestedModel.toLowerCase().includes(Z)||(e.resolvedModel??``).toLowerCase().includes(Z)||(e.errorCode??``).toLowerCase().includes(Z)||(e.credentialId===null?``:Y.get(e.credentialId)??``).toLowerCase().includes(Z)||(e.apiKeyId===null?``:X.get(e.apiKeyId)??e.apiKeyId).toLowerCase().includes(Z)),fe=(k.data??[]).filter(b).length,$=(k.data??[]).filter(S).length;return(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(d,{legend:`Logs`,title:`Recent requests`,summary:k.isLoading?`Reading the request log…`:`${y(k.data?.length??0)} recent requests, ${y(fe)} of them failed${$===0?``:`, ${y($)} still running`}. Prompt and response bodies are never recorded.`,actions:(0,R.jsxs)(B,{children:[(0,R.jsx)(V,{value:p,placeholder:`Filter by model, account, key, or error`,"aria-label":`Filter requests`,onChange:e=>m(e.target.value)}),(0,R.jsxs)(H,{value:s,"aria-label":`Show which requests`,onChange:e=>f(e.target.value),children:[(0,R.jsx)(`option`,{value:`all`,children:`All requests`}),(0,R.jsx)(`option`,{value:`failed`,children:`Failed only`})]}),(0,R.jsx)(H,{value:i,"aria-label":`How many requests to fetch`,onChange:e=>o(Number(e.target.value)),children:z.map(e=>(0,R.jsxs)(`option`,{value:e,children:[`last `,e]},e))})]})}),(0,R.jsx)(U,{legend:`Request log`,meta:`${Q.length} shown`,flush:!0,children:k.isError?(0,R.jsx)(A,{error:k.error,onRetry:()=>void k.refetch()}):k.isLoading?(0,R.jsx)(`div`,{style:{padding:12},children:(0,R.jsx)(j,{rows:8})}):Q.length===0?(0,R.jsx)(M,{legend:`Nothing to show`,message:(k.data?.length??0)===0?`No requests have reached the gateway yet.`:`No request in this window matches the filter. Clear it to see everything.`}):(0,R.jsx)(W,{"data-testid":`request-log-scroller`,children:(0,R.jsxs)(I,{children:[(0,R.jsx)(`thead`,{children:(0,R.jsxs)(`tr`,{children:[(0,R.jsx)(F,{}),(0,R.jsx)(F,{$align:`right`,children:`Time`}),(0,R.jsx)(F,{children:`Requested`}),(0,R.jsx)(F,{children:`Routed to`}),(0,R.jsx)(F,{children:`Account`}),(0,R.jsx)(F,{children:`Key`}),(0,R.jsx)(F,{$align:`right`,children:`Try`}),(0,R.jsx)(F,{$align:`right`,children:`TTFT`}),(0,R.jsx)(F,{$align:`right`,children:`Total`}),(0,R.jsx)(F,{$align:`right`,children:`Tokens`}),(0,R.jsx)(F,{$align:`right`,children:`Cost`}),(0,R.jsx)(F,{children:`Outcome`})]})}),(0,R.jsx)(`tbody`,{children:Q.map(e=>(0,R.jsxs)(N,{$selectable:!0,onClick:()=>O(e),children:[(0,R.jsx)(P,{children:(0,R.jsx)(C,{state:x(e),label:oe(e)})}),(0,R.jsx)(P,{$align:`right`,$mono:!0,title:w(e.at),children:T(e.at)}),(0,R.jsx)(P,{$mono:!0,children:(0,R.jsx)(t,{style:{display:`block`,maxWidth:`20ch`},children:e.requestedModel||`—`})}),(0,R.jsx)(P,{children:e.resolvedProvider===null?(0,R.jsx)(a,{children:S(e)?`routing…`:`not routed`}):(0,R.jsxs)(r,{$gap:1,children:[(0,R.jsx)(se,{provider:e.resolvedProvider}),(0,R.jsx)(te,{$dim:!0,children:e.resolvedModel??`—`})]})}),(0,R.jsx)(P,{children:(0,R.jsx)(t,{style:{display:`block`,maxWidth:`18ch`},children:e.credentialId===null?`—`:Y.get(e.credentialId)??_(e.credentialId)})}),(0,R.jsx)(P,{children:(0,R.jsx)(t,{style:{display:`block`,maxWidth:`16ch`},title:e.apiKeyId??void 0,children:e.apiKeyId===null?`—`:X.get(e.apiKeyId)??_(e.apiKeyId)})}),(0,R.jsx)(P,{$align:`right`,$mono:!0,children:S(e)?`—`:e.attempts}),(0,R.jsx)(P,{$align:`right`,$mono:!0,children:S(e)?`—`:g(e.ttftMs)}),(0,R.jsx)(P,{$align:`right`,$mono:!0,children:S(e)?ae(Math.max(0,de-e.at)):g(e.durationMs)}),(0,R.jsx)(ce,{log:e}),(0,R.jsx)(P,{$align:`right`,$mono:!0,children:S(e)?`—`:v(e.costUsd)}),(0,R.jsx)(P,{children:S(e)?(0,R.jsx)(E,{$tone:`accent`,children:`live`}):e.errorCode===null?(0,R.jsx)(E,{$tone:`ok`,children:e.status}):(0,R.jsx)(E,{$tone:`down`,children:e.errorCode})})]},e.id))})]})})}),(0,R.jsx)(h,{open:D!==null,onOpenChange:e=>{e||O(null)},title:`Request detail`,width:`600px`,footer:(0,R.jsx)(ee,{type:`button`,onClick:()=>O(null),children:`Close`}),children:D===null?null:(0,R.jsxs)(l,{$gap:3,children:[(0,R.jsxs)(le,{children:[(0,R.jsx)(a,{as:`dt`,children:`Request id`}),(0,R.jsx)(K,{children:D.id}),(0,R.jsx)(a,{as:`dt`,children:`At`}),(0,R.jsx)(K,{children:w(D.at)}),(0,R.jsx)(a,{as:`dt`,children:`Requested model`}),(0,R.jsx)(K,{children:D.requestedModel||`—`}),(0,R.jsx)(a,{as:`dt`,children:`Routed to`}),(0,R.jsx)(K,{children:S(D)?`—`:D.resolvedProvider===null?`not routed`:`${D.resolvedProvider} · ${D.resolvedModel??`—`}`}),(0,R.jsx)(a,{as:`dt`,children:`Account`}),(0,R.jsx)(K,{children:D.credentialId===null?`—`:Y.get(D.credentialId)??D.credentialId}),(0,R.jsx)(a,{as:`dt`,children:`Key`}),(0,R.jsx)(K,{children:D.apiKeyId===null?`—`:X.get(D.apiKeyId)??D.apiKeyId}),(0,R.jsx)(a,{as:`dt`,children:`Attempts`}),(0,R.jsx)(K,{children:S(D)?`—`:D.attempts}),(0,R.jsx)(a,{as:`dt`,children:`Status`}),(0,R.jsx)(K,{children:S(D)?`in flight`:D.errorCode===null?D.status:`${D.status} ${D.errorCode}`}),(0,R.jsx)(a,{as:`dt`,children:`Timing`}),(0,R.jsx)(K,{children:S(D)?`—`:`first token ${g(D.ttftMs)} · total ${g(D.durationMs)}`}),(0,R.jsx)(a,{as:`dt`,children:`Tokens`}),(0,R.jsx)(K,{children:S(D)?`—`:(0,R.jsxs)(R.Fragment,{children:[y(D.inputTokens),` in · `,y(D.outputTokens),` out ·`,` `,y(D.cacheReadTokens),` cache read ·`,` `,y(D.cacheWriteTokens),` cache write`]})}),(0,R.jsx)(a,{as:`dt`,children:`Cost`}),(0,R.jsx)(K,{children:S(D)?`—`:v(D.costUsd)}),(0,R.jsx)(a,{as:`dt`,children:`RTK compression`}),(0,R.jsx)(K,{children:S(D)?`—`:D.rtkApplied?`${y(D.rtkFilterHits)} hits · ${y(D.rtkOriginalCodeUnits)} → ${y(D.rtkCompressedCodeUnits)} code units · ~${y(D.rtkEstimatedTokensSaved)} tokens saved`:`not applied`}),(0,R.jsx)(a,{as:`dt`,children:`RTK filters`}),(0,R.jsx)(K,{children:D.rtkFilters.length===0?`—`:D.rtkFilters.join(`, `)})]}),D.degradations.length===0?null:(0,R.jsxs)(l,{$gap:1,children:[(0,R.jsx)(a,{children:`Capabilities dropped to fit the target`}),(0,R.jsx)(r,{$gap:1,$wrap:!0,children:D.degradations.map(e=>(0,R.jsx)(E,{$tone:`warn`,children:e},e))})]})]})})]})}var J=q;export{J as component};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import{$t as e,B as t,C as n,Ft as r,H as i,I as a,N as o,P as s,Pt as c,R as l,T as u,U as d,b as f,f as p,h as m,m as h,q as g,z as _}from"./queries-D8LJNQpL.js";import{r as v}from"./index-DJfb1i4P.js";import{o as y,t as b}from"./Rack-Bbo4JfEX.js";import{n as x,t as ee}from"./Confirm-CVLz9F7a.js";import{t as S}from"./trash-2-CLYNAAJA.js";import{t as C}from"./Toggle-BUr71O4J.js";import{n as w,t as T}from"./Chip-DJwp7gBu.js";import{i as E,n as te,r as D,t as O}from"./Field-BDtp692L.js";import{t as k}from"./Meter-BREBUFGX.js";import{a as A,i as j,n as ne,r as M,t as N}from"./States-BEKLros0.js";import{i as re,n as ie,r as P,t as F}from"./catalog-BBKm8Ih8.js";var ae=y(`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`}]]),oe=y(`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`}]]),I=e(r(),1),L=c(),se=[`tier`,`health`,`quota`,`cost`,`latency`,`load`],ce={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`},le=g.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
|
+
`,ue=g(s)`
|
|
9
|
+
width: 22px;
|
|
10
|
+
color: ${({theme:e})=>e.color.inkFaint};
|
|
11
|
+
flex: none;
|
|
12
|
+
`,de=g(T)`
|
|
13
|
+
border-color: ${({theme:e})=>e.color.ok};
|
|
14
|
+
color: ${({theme:e})=>e.color.ok};
|
|
15
|
+
background: ${({theme:e})=>e.color.okWash};
|
|
16
|
+
`,fe=g.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
|
+
`,pe=g.div`
|
|
23
|
+
display: flex;
|
|
24
|
+
flex-direction: column;
|
|
25
|
+
gap: 3px;
|
|
26
|
+
min-width: 0;
|
|
27
|
+
`,me=g.div`
|
|
28
|
+
display: flex;
|
|
29
|
+
align-items: baseline;
|
|
30
|
+
justify-content: space-between;
|
|
31
|
+
gap: 6px;
|
|
32
|
+
`,he=g.li`
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
gap: ${({theme:e})=>e.space(2)};
|
|
36
|
+
padding: 5px 0;
|
|
37
|
+
`,ge=g(a)`
|
|
38
|
+
gap: ${({theme:e})=>e.space(3)};
|
|
39
|
+
flex-wrap: wrap;
|
|
40
|
+
`,R=g.label`
|
|
41
|
+
display: flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
gap: 6px;
|
|
44
|
+
cursor: pointer;
|
|
45
|
+
font-size: 12.5px;
|
|
46
|
+
`,_e=g.p`
|
|
47
|
+
font-size: 12px;
|
|
48
|
+
color: ${({theme:e})=>e.color.down};
|
|
49
|
+
`;function z(e,t,n){return(e[t]??0)*n[t]}function ve({modelId:e}){let[n,r]=(0,I.useState)({tools:!1,images:!1,reasoning:!1}),[c,d]=(0,I.useState)(null),[f,p]=(0,I.useState)(null),h=u(),g=m(),v=h.data?.weights,y=()=>{e!==null&&(p(null),g.mutate({modelId:e,need:n},{onSuccess:e=>d(e),onError:e=>{d(null),p(j(e))}}))},b=new Map(se.map(e=>[e,Math.max(1e-4,...(c?.candidates??[]).map(t=>v===void 0?0:Math.abs(z(t.reasons,e,v))))]));return(0,L.jsx)(A,{legend:`Explain`,meta:e??`no model selected`,actions:(0,L.jsxs)(i,{type:`button`,$size:`sm`,$variant:`primary`,disabled:e===null||g.isPending,onClick:y,children:[(0,L.jsx)(ae,{}),g.isPending?`Ranking…`:`Rank candidates`]}),children:(0,L.jsxs)(_,{$gap:3,children:[(0,L.jsxs)(_,{$gap:1,children:[(0,L.jsx)(o,{children:`Pretend the request needs`}),(0,L.jsxs)(ge,{children:[(0,L.jsxs)(R,{children:[(0,L.jsx)(C,{checked:n.tools,label:`Probe request uses tools`,onCheckedChange:e=>r({...n,tools:e})}),`Tools`]}),(0,L.jsxs)(R,{children:[(0,L.jsx)(C,{checked:n.images,label:`Probe request includes an image`,onCheckedChange:e=>r({...n,images:e})}),`Images`]}),(0,L.jsxs)(R,{children:[(0,L.jsx)(C,{checked:n.reasoning,label:`Probe request asks for reasoning`,onCheckedChange:e=>r({...n,reasoning:e})}),`Reasoning`]})]})]}),f===null?null:(0,L.jsx)(_e,{children:f}),c===null?(0,L.jsx)(N,{legend:`Not ranked yet`,message:e===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.`}):(0,L.jsxs)(_,{$gap:3,children:[(0,L.jsxs)(a,{$gap:2,$wrap:!0,children:[(0,L.jsx)(T,{$tone:`accent`,children:c.strategy}),c.deterministic?null:(0,L.jsx)(T,{$tone:`warn`,children:`order varies per request`}),(0,L.jsx)(l,{}),(0,L.jsxs)(o,{children:[c.candidates.length,` eligible · `,c.excluded.length,` filtered out`]})]}),c.candidates.length===0?(0,L.jsx)(N,{legend:`Nothing eligible`,message:`Every target was filtered out. The reasons below say which rule removed each one.`}):(0,L.jsx)(`ul`,{children:c.candidates.map((e,n)=>(0,L.jsxs)(le,{children:[(0,L.jsxs)(a,{$gap:2,children:[(0,L.jsx)(ue,{children:n+1}),(0,L.jsx)(w,{provider:e.provider}),(0,L.jsx)(t,{style:{maxWidth:`22ch`},children:e.credentialLabel}),(0,L.jsx)(s,{$dim:!0,children:e.model}),(0,L.jsxs)(T,{children:[`tier `,e.tier]}),(0,L.jsx)(l,{}),n===0?(0,L.jsx)(de,{children:`would be used`}):null,(0,L.jsx)(s,{children:e.score.toFixed(2)})]}),v===void 0?null:(0,L.jsx)(fe,{children:se.map(t=>{let n=z(e.reasons,t,v),r=b.get(t)??1;return(0,L.jsxs)(pe,{title:ce[t],children:[(0,L.jsxs)(me,{children:[(0,L.jsx)(o,{children:t}),(0,L.jsx)(s,{$dim:!0,$size:`10.5px`,children:n.toFixed(2)})]}),(0,L.jsx)(k,{fraction:Math.abs(n)/r,height:4,tone:`var(--accent)`,label:`${t} contributes ${n.toFixed(2)} of ${e.score.toFixed(2)}`})]},t)})})]},`${e.credentialId}:${e.model}`))}),c.excluded.length===0?null:(0,L.jsxs)(_,{$gap:1,children:[(0,L.jsx)(o,{children:`Filtered out`}),(0,L.jsx)(`ul`,{children:c.excluded.map(e=>(0,L.jsxs)(he,{children:[(0,L.jsx)(s,{$dim:!0,children:e.model}),(0,L.jsx)(l,{}),(0,L.jsx)(T,{$tone:e.reason.startsWith(`capability`)?`warn`:`down`,children:e.reason})]},`${e.credentialId}:${e.model}:${e.reason}`))})]})]})]})})}var B=[{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.`}],V=0;function H(){return V+=1,`target-${V}`}function U(e,t){let n=re(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 ye(e,t){let n=ie(e,t);return n===null?null:{contextWindow:String(n.contextWindow),maxOutputTokens:String(n.maxOutputTokens)}}var be={oauth:`OAuth`,apiKey:`an API key`};function W(e){return e.map(e=>be[e]).join(` or `)}function xe(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 G(e,t,n){let r=n[e];return r===void 0||r.length===0||P(e,t).some(e=>r.includes(e))}function Se(e,t){return F[e].models.filter(n=>G(e,n.id,t))}function Ce(e,t,n){if(t.trim().length===0||G(e,t,n))return null;let r=n[e]??[];return`${e} serves this model to ${W(P(e,t))} only, and every ${e} account here is ${W(r)}. Requests routed here will fail.`}function we(e,t){return{...e,...t,...U(t.provider,t.model)??{},contextWindow:``,maxOutputTokens:``}}function K(e=`anthropic`){let t=F[e].defaultModel,n=U(e,t);return{key:H(),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 q(){return{id:``,strategy:`score`,isAlias:!1,targets:[K()]}}function J(e){return{id:e.id,strategy:e.strategy,isAlias:e.isAlias,targets:e.targets.map(e=>({key:H(),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 Te(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 Ee=Object.keys(F),De=g.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
|
+
`,Oe=g.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
|
+
`,Y=g.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
|
+
`,X=g.div`
|
|
75
|
+
display: flex;
|
|
76
|
+
flex-direction: column;
|
|
77
|
+
gap: 4px;
|
|
78
|
+
min-width: 0;
|
|
79
|
+
`,ke=g(a)`
|
|
80
|
+
gap: ${({theme:e})=>e.space(3)};
|
|
81
|
+
flex-wrap: wrap;
|
|
82
|
+
`,Ae=g.p`
|
|
83
|
+
font-size: 11.5px;
|
|
84
|
+
color: ${({theme:e})=>e.color.down};
|
|
85
|
+
margin: 0;
|
|
86
|
+
`,Z=g.label`
|
|
87
|
+
display: flex;
|
|
88
|
+
align-items: center;
|
|
89
|
+
gap: 6px;
|
|
90
|
+
cursor: pointer;
|
|
91
|
+
`;function je({target:e,index:t,onChange:n,onRemove:r,removable:s,endpoints:c,held:u}){let f=(0,I.useId)(),p=F[e.provider],m=Se(e.provider,u),h=Ce(e.provider,e.model,u),g=(t,r)=>{n({...e,[t]:r})},y=U(e.provider,e.model),b=ye(e.provider,e.model),x=t=>{n(we(e,t))};return(0,L.jsxs)(De,{$provider:e.provider,children:[(0,L.jsxs)(a,{$gap:2,children:[(0,L.jsxs)(o,{as:`legend`,children:[`Target `,t+1]}),(0,L.jsx)(l,{}),(0,L.jsx)(d,{type:`button`,$variant:`ghost`,$size:`sm`,disabled:!s,"aria-label":`Remove target ${t+1}`,title:s?`Remove target ${t+1}`:`A model needs at least one target`,onClick:r,children:(0,L.jsx)(S,{})})]}),(0,L.jsxs)(Oe,{children:[(0,L.jsxs)(X,{children:[(0,L.jsx)(o,{as:`label`,htmlFor:`${f}-provider`,children:`Provider`}),(0,L.jsx)(E,{id:`${f}-provider`,value:e.provider,onChange:t=>{let n=t.target.value,r=F[n].models.some(t=>t.id===e.model);x({provider:n,model:r?e.model:F[n].defaultModel})},children:Ee.map(e=>(0,L.jsx)(`option`,{value:e,children:v[e]},e))})]}),e.provider===`custom`?(0,L.jsxs)(X,{children:[(0,L.jsx)(o,{as:`label`,htmlFor:`${f}-endpoint`,children:`Endpoint`}),(0,L.jsxs)(E,{id:`${f}-endpoint`,value:e.endpointId,onChange:e=>g(`endpointId`,e.target.value),children:[(0,L.jsx)(`option`,{value:``,children:`Choose endpoint`}),c.map(e=>(0,L.jsx)(`option`,{value:e.id,children:e.label},e.id))]})]}):null,(0,L.jsxs)(X,{children:[(0,L.jsx)(o,{as:`label`,htmlFor:`${f}-model`,children:`Provider model`}),(0,L.jsx)(te,{id:`${f}-model`,list:`${f}-catalog`,value:e.model,placeholder:p.defaultModel,onChange:t=>x({provider:e.provider,model:t.target.value})}),(0,L.jsx)(`datalist`,{id:`${f}-catalog`,children:m.map(e=>(0,L.jsx)(`option`,{value:e.id,children:e.label},e.id))}),h===null?null:(0,L.jsx)(Ae,{role:`note`,children:h})]}),(0,L.jsxs)(X,{children:[(0,L.jsx)(o,{as:`label`,htmlFor:`${f}-tier`,children:`Tier`}),(0,L.jsx)(D,{id:`${f}-tier`,min:1,step:1,value:e.tier,onChange:e=>g(`tier`,e.target.value)})]}),(0,L.jsxs)(X,{children:[(0,L.jsx)(o,{as:`label`,htmlFor:`${f}-weight`,children:`Weight`}),(0,L.jsx)(D,{id:`${f}-weight`,min:0,step:.1,value:e.weight,onChange:e=>g(`weight`,e.target.value)})]})]}),(0,L.jsxs)(_,{$gap:1,children:[(0,L.jsxs)(a,{$gap:2,children:[(0,L.jsx)(o,{children:`Price per million tokens`}),(0,L.jsx)(l,{}),y===null?(0,L.jsx)(o,{as:`span`,children:`not in the catalog — price it yourself`}):(0,L.jsxs)(i,{type:`button`,$size:`sm`,$variant:`ghost`,disabled:e.costInput===y.costInput&&e.costOutput===y.costOutput&&e.costCacheRead===y.costCacheRead&&e.costCacheWrite5m===y.costCacheWrite5m&&e.costCacheWrite1h===y.costCacheWrite1h,onClick:()=>n({...e,...y}),children:[(0,L.jsx)(oe,{}),`Use list price`]})]}),(0,L.jsxs)(Y,{children:[(0,L.jsxs)(X,{children:[(0,L.jsx)(o,{as:`label`,htmlFor:`${f}-in`,children:`Input`}),(0,L.jsx)(D,{id:`${f}-in`,min:0,step:.01,value:e.costInput,onChange:e=>g(`costInput`,e.target.value)})]}),(0,L.jsxs)(X,{children:[(0,L.jsx)(o,{as:`label`,htmlFor:`${f}-out`,children:`Output`}),(0,L.jsx)(D,{id:`${f}-out`,min:0,step:.01,value:e.costOutput,onChange:e=>g(`costOutput`,e.target.value)})]}),(0,L.jsxs)(X,{children:[(0,L.jsx)(o,{as:`label`,htmlFor:`${f}-cache`,children:`Cache read`}),(0,L.jsx)(D,{id:`${f}-cache`,min:0,step:.01,placeholder:`same as input`,value:e.costCacheRead,onChange:e=>g(`costCacheRead`,e.target.value)})]}),(0,L.jsxs)(X,{children:[(0,L.jsx)(o,{as:`label`,htmlFor:`${f}-write5m`,children:`Cache write 5m`}),(0,L.jsx)(D,{id:`${f}-write5m`,min:0,step:.01,placeholder:`1.25x input`,value:e.costCacheWrite5m,onChange:e=>g(`costCacheWrite5m`,e.target.value)})]}),(0,L.jsxs)(X,{children:[(0,L.jsx)(o,{as:`label`,htmlFor:`${f}-write1h`,children:`Cache write 1h`}),(0,L.jsx)(D,{id:`${f}-write1h`,min:0,step:.01,placeholder:`2x input`,value:e.costCacheWrite1h,onChange:e=>g(`costCacheWrite1h`,e.target.value)})]})]})]}),(0,L.jsxs)(_,{$gap:1,children:[(0,L.jsxs)(a,{$gap:2,children:[(0,L.jsx)(o,{children:`Token limits`}),(0,L.jsx)(l,{}),b===null?(0,L.jsx)(o,{as:`span`,children:`not in the catalog — state them yourself`}):(0,L.jsx)(o,{as:`span`,children:`left empty, the published figures are used — and for an OpenAI target, the narrower ones its OAuth backend allows`})]}),(0,L.jsxs)(Y,{children:[(0,L.jsxs)(X,{children:[(0,L.jsx)(o,{as:`label`,htmlFor:`${f}-context`,children:`Context window`}),(0,L.jsx)(D,{id:`${f}-context`,min:1,step:1024,placeholder:b?.contextWindow??`published`,value:e.contextWindow,onChange:e=>g(`contextWindow`,e.target.value)})]}),(0,L.jsxs)(X,{children:[(0,L.jsx)(o,{as:`label`,htmlFor:`${f}-maxout`,children:`Max output`}),(0,L.jsx)(D,{id:`${f}-maxout`,min:1,step:1024,placeholder:b?.maxOutputTokens??`published`,value:e.maxOutputTokens,onChange:e=>g(`maxOutputTokens`,e.target.value)})]})]})]}),(0,L.jsxs)(_,{$gap:1,children:[(0,L.jsx)(o,{children:`Capabilities`}),(0,L.jsxs)(ke,{children:[(0,L.jsxs)(Z,{children:[(0,L.jsx)(C,{checked:e.tools,label:`Target ${t+1} supports tools`,onCheckedChange:e=>g(`tools`,e)}),`Tools`]}),(0,L.jsxs)(Z,{children:[(0,L.jsx)(C,{checked:e.images,label:`Target ${t+1} supports images`,onCheckedChange:e=>g(`images`,e)}),`Images`]}),(0,L.jsxs)(Z,{children:[(0,L.jsx)(C,{checked:e.reasoning,label:`Target ${t+1} supports reasoning`,onCheckedChange:e=>g(`reasoning`,e)}),`Reasoning`]})]})]})]})}var Q=g.p`
|
|
92
|
+
font-size: 11.5px;
|
|
93
|
+
color: ${({theme:e})=>e.color.inkDim};
|
|
94
|
+
`,Me=g.p`
|
|
95
|
+
font-size: 12px;
|
|
96
|
+
color: ${({theme:e})=>e.color.down};
|
|
97
|
+
`,Ne=g.p`
|
|
98
|
+
font-size: 12px;
|
|
99
|
+
color: ${({theme:e})=>e.color.ok};
|
|
100
|
+
`,Pe=g(a)`
|
|
101
|
+
gap: 8px;
|
|
102
|
+
`;function Fe({model:e,onSaved:t,onDeleted:r}){let[s,c]=(0,I.useState)(()=>e===null?q():J(e)),[u,d]=(0,I.useState)(null),[f,m]=(0,I.useState)(!1),[g,v]=(0,I.useState)(!1),y=n(),b=h(),S=p(),w=xe(S.data??[]),T=(S.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),D=e?.id??null;(0,I.useEffect)(()=>{c(e===null?q():J(e)),d(null),m(!1)},[D]);let k=B.find(e=>e.id===s.strategy);return(0,L.jsxs)(L.Fragment,{children:[(0,L.jsx)(A,{legend:e===null?`New model`:`Edit model`,meta:e===null?void 0:e.id,actions:(0,L.jsxs)(L.Fragment,{children:[e===null?null:(0,L.jsx)(i,{type:`button`,$variant:`danger`,$size:`sm`,onClick:()=>v(!0),children:`Delete`}),(0,L.jsx)(i,{type:`button`,$variant:`primary`,$size:`sm`,disabled:y.isPending,onClick:()=>{m(!1);let e=Te(s);if(!e.ok){d(e.problem);return}d(null),y.mutate(e.model,{onSuccess:()=>{m(!0),t(e.model.id)},onError:e=>d(j(e))})},children:y.isPending?`Saving…`:e===null?`Create model`:`Save changes`})]}),children:(0,L.jsxs)(_,{$gap:3,children:[(0,L.jsx)(O,{label:`Model name`,hint:e===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:t=>(0,L.jsx)(te,{...t,value:s.id,disabled:e!==null,placeholder:`fast`,onChange:e=>c({...s,id:e.target.value})})}),(0,L.jsx)(O,{label:`Routing strategy`,children:e=>(0,L.jsx)(E,{...e,value:s.strategy,onChange:e=>c({...s,strategy:e.target.value}),children:B.map(e=>(0,L.jsx)(`option`,{value:e.id,children:e.label},e.id))})}),k===void 0?null:(0,L.jsx)(Q,{children:k.blurb}),(0,L.jsxs)(Pe,{children:[(0,L.jsx)(C,{checked:s.isAlias,label:`This model is an alias for a provider model name`,onCheckedChange:e=>c({...s,isAlias:e})}),(0,L.jsxs)(_,{$gap:0,children:[(0,L.jsx)(o,{as:`span`,children:`Alias`}),(0,L.jsx)(Q,{children:`Mark this when the name mirrors a provider's own model name.`})]})]}),(0,L.jsxs)(_,{$gap:2,children:[(0,L.jsxs)(a,{children:[(0,L.jsx)(o,{children:`Targets`}),(0,L.jsx)(l,{}),(0,L.jsxs)(i,{type:`button`,$size:`sm`,onClick:()=>c({...s,targets:[...s.targets,K(s.targets.at(-1)?.provider??`anthropic`)]}),children:[(0,L.jsx)(x,{}),`Add target`]})]}),s.targets.map((e,t)=>(0,L.jsx)(je,{target:e,index:t,removable:s.targets.length>1,endpoints:T,held:w,onChange:t=>c({...s,targets:s.targets.map(n=>n.key===e.key?t:n)}),onRemove:()=>c({...s,targets:s.targets.filter(t=>t.key!==e.key)})},e.key))]}),u===null?null:(0,L.jsx)(Me,{role:`alert`,children:u}),f&&u===null?(0,L.jsx)(Ne,{role:`status`,children:`Saved.`}):null]})}),(0,L.jsx)(ee,{open:g,onOpenChange:v,title:`Delete model`,body:e===null?``:`Deleting "${e.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:b.isPending,onConfirm:()=>{e!==null&&b.mutate(e.id,{onSuccess:()=>{v(!1),r()},onError:e=>{v(!1),d(j(e))}})}})]})}var Ie=g.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
|
+
`,Le=g(_)`
|
|
112
|
+
gap: ${({theme:e})=>e.space(4)};
|
|
113
|
+
min-width: 0;
|
|
114
|
+
`,Re=g.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
|
+
`,ze=g(t)`
|
|
136
|
+
font-family: ${({theme:e})=>e.font.mono};
|
|
137
|
+
font-size: 12.5px;
|
|
138
|
+
display: block;
|
|
139
|
+
max-width: 100%;
|
|
140
|
+
`,Be=g.div`
|
|
141
|
+
display: flex;
|
|
142
|
+
gap: 2px;
|
|
143
|
+
`,Ve=g.span`
|
|
144
|
+
width: 12px;
|
|
145
|
+
height: 3px;
|
|
146
|
+
border-radius: 1px;
|
|
147
|
+
background: ${({$provider:e})=>`var(--p-${e})`};
|
|
148
|
+
`,$=`\0new`;function He(){let e=f(),[t,n]=(0,I.useState)(null),r=e.data??[],c=t===$?null:r.find(e=>e.id===t)??null,u=t===$||t===null&&!e.isLoading&&r.length===0;(0,I.useEffect)(()=>{t===null&&r.length!==0&&n(r[0]?.id??null)},[r,t]);let d=e.isLoading?`Reading configured models…`:r.length===0?`No virtual models exist yet, so no client request can resolve to an upstream.`:`${r.length} model${r.length===1?``:`s`} routing to ${r.reduce((e,t)=>e+t.targets.length,0)} targets.`;return(0,L.jsxs)(L.Fragment,{children:[(0,L.jsx)(b,{legend:`Models`,title:`Virtual models`,summary:d,actions:(0,L.jsxs)(i,{type:`button`,$variant:`primary`,onClick:()=>n($),children:[(0,L.jsx)(x,{}),`New model`]})}),(0,L.jsxs)(Ie,{children:[(0,L.jsx)(A,{legend:`Configured`,meta:`${r.length}`,flush:!0,children:e.isError?(0,L.jsx)(ne,{error:e.error,onRetry:()=>void e.refetch()}):e.isLoading?(0,L.jsx)(`div`,{style:{padding:12},children:(0,L.jsx)(M,{rows:4})}):r.length===0?(0,L.jsx)(N,{legend:`No models`,message:`Create a model to give clients something to ask for.`,action:(0,L.jsx)(i,{type:`button`,$size:`sm`,$variant:`primary`,onClick:()=>n($),children:`New model`})}):(0,L.jsx)(`div`,{children:r.map(e=>{let r=[...new Set(e.targets.map(e=>e.provider))];return(0,L.jsxs)(Re,{type:`button`,$selected:e.id===t,"aria-pressed":e.id===t,onClick:()=>n(e.id),children:[(0,L.jsxs)(a,{$gap:2,style:{width:`100%`},children:[(0,L.jsx)(ze,{title:e.id,children:e.id}),(0,L.jsx)(l,{}),e.isAlias?(0,L.jsx)(T,{children:`alias`}):null]}),(0,L.jsxs)(a,{$gap:2,style:{width:`100%`},children:[(0,L.jsx)(Be,{children:r.map(e=>(0,L.jsx)(Ve,{$provider:e,title:e},e))}),(0,L.jsx)(o,{children:e.strategy}),(0,L.jsx)(l,{}),(0,L.jsxs)(s,{$dim:!0,$size:`11px`,children:[e.targets.length,` target`,e.targets.length===1?``:`s`]})]})]},e.id)})})}),(0,L.jsxs)(Le,{children:[c===null&&!u?(0,L.jsx)(A,{legend:`Editor`,children:e.isLoading?(0,L.jsx)(M,{rows:5}):(0,L.jsx)(N,{legend:`Nothing selected`,message:`Pick a model on the left to change its targets, or create a new one.`})}):(0,L.jsx)(Fe,{model:c,onSaved:t=>{n(t),e.refetch()},onDeleted:()=>{n(null),e.refetch()}}),(0,L.jsx)(ve,{modelId:c?.id??null})]})]})]})}var Ue=He;export{Ue as component};
|