omnigateway 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +334 -8
  2. package/bin/omni.js +1929 -147
  3. package/gateway.js +3129 -555
  4. package/package.json +1 -1
  5. package/public/assets/{Chip-DJwp7gBu.js → Chip-DbKk1ExR.js} +1 -1
  6. package/public/assets/Confirm-C5DYoI93.js +4 -0
  7. package/public/assets/CopyValue-CXjietiZ.js +27 -0
  8. package/public/assets/{Field-BDtp692L.js → Field-B7GOsJf8.js} +1 -1
  9. package/public/assets/Lamp-QRSv-SqM.js +25 -0
  10. package/public/assets/{Meter-BREBUFGX.js → Meter-Dngwbpjo.js} +1 -1
  11. package/public/assets/Modal-DfltaSCz.js +82 -0
  12. package/public/assets/Rack-D1zBw9SW.js +151 -0
  13. package/public/assets/{Readout-CEAoN5hu.js → Readout--CQnPjoO.js} +2 -2
  14. package/public/assets/{States-BEKLros0.js → States-CQFkw1UZ.js} +3 -3
  15. package/public/assets/{Table-BBypbVWj.js → Table-Ba58Wg4-.js} +1 -1
  16. package/public/assets/Toggle-DWrWc9-9.js +39 -0
  17. package/public/assets/TokenBreakdown-CyHJv0O5.js +31 -0
  18. package/public/assets/_app-CTDgfstQ.js +1 -0
  19. package/public/assets/_app.accounts-DP6T8z7I.js +64 -0
  20. package/public/assets/{_app.console-DKyGL9xx.js → _app.console-DYr7TCAl.js} +10 -10
  21. package/public/assets/_app.database-BzO1S_VR.js +39 -0
  22. package/public/assets/_app.index-CBt6b-lA.js +62 -0
  23. package/public/assets/_app.keys-B8HGsPPS.js +76 -0
  24. package/public/assets/_app.logs-DKsxa2Su.js +68 -0
  25. package/public/assets/{_app.models-CDqVrAeF.js → _app.models-CZD2UpM-.js} +28 -28
  26. package/public/assets/_app.settings-B2C1LQIF.js +46 -0
  27. package/public/assets/_app.usage-CDWUXtZy.js +83 -0
  28. package/public/assets/dist-IkJ0qg-4.js +1 -0
  29. package/public/assets/index-ClU3Xqui.js +186 -0
  30. package/public/assets/login-E3gh2_Cl.js +36 -0
  31. package/public/assets/plus-DkO4vG-T.js +1 -0
  32. package/public/assets/queries-BJHk_wso.js +144 -0
  33. package/public/assets/reasons-Cb8yF4Oy.js +1 -0
  34. package/public/assets/{shared-CIhZ6FCO.js → shared-Bp35cgFf.js} +7 -7
  35. package/public/assets/{trash-2-CLYNAAJA.js → trash-2-DTWWI3vA.js} +1 -1
  36. package/public/index.html +2 -2
  37. package/public/assets/Confirm-CVLz9F7a.js +0 -4
  38. package/public/assets/CopyValue-CNZbWS59.js +0 -27
  39. package/public/assets/Lamp-B65uWKbW.js +0 -25
  40. package/public/assets/Modal-DbydSAlp.js +0 -82
  41. package/public/assets/Rack-Bbo4JfEX.js +0 -151
  42. package/public/assets/Toggle-BUr71O4J.js +0 -39
  43. package/public/assets/TokenBreakdown-C1ziK9d1.js +0 -31
  44. package/public/assets/_app-ByQ1bPbe.js +0 -1
  45. package/public/assets/_app.accounts-BTug_Xfo.js +0 -64
  46. package/public/assets/_app.index-CSw9gmMf.js +0 -62
  47. package/public/assets/_app.keys-07Kbw4RS.js +0 -39
  48. package/public/assets/_app.logs-C9QiV39p.js +0 -32
  49. package/public/assets/_app.settings-DmUEeTaP.js +0 -38
  50. package/public/assets/_app.usage-B1WuMGRr.js +0 -83
  51. package/public/assets/dist-Bka7ErcH.js +0 -1
  52. package/public/assets/index-DJfb1i4P.js +0 -186
  53. package/public/assets/login-DKZYqRh0.js +0 -33
  54. package/public/assets/queries-D8LJNQpL.js +0 -144
@@ -0,0 +1,64 @@
1
+ import{$ as e,$t as t,Q as n,Qt as r,R as i,U as a,X as o,Y as s,_n as c,at as l,f as u,g as d,h as f,k as p,l as m,ot as h,r as g,tt as _,u as v,ut as y,v as b}from"./queries-BJHk_wso.js";import{a as x,c as S,t as C}from"./Rack-D1zBw9SW.js";import{n as w,r as ee,t as te}from"./CopyValue-CXjietiZ.js";import{t as T}from"./plus-DkO4vG-T.js";import{t as E}from"./trash-2-DTWWI3vA.js";import{t as D}from"./Modal-DfltaSCz.js";import{t as O}from"./Toggle-DWrWc9-9.js";import{t as ne}from"./Confirm-C5DYoI93.js";import{D as k,S as A,T as j,a as M,g as N,h as P,i as F,m as I,n as L,o as R,p as re,s as z,t as ie,u as B,v as ae,w as oe,x as se,y as ce}from"./Lamp-QRSv-SqM.js";import{t as le}from"./Chip-DbKk1ExR.js";import{i as V,n as H,r as ue,t as U}from"./Field-B7GOsJf8.js";import{t as de}from"./Meter-Dngwbpjo.js";import{a as W,i as G,n as fe,r as pe,t as me}from"./States-CQFkw1UZ.js";import{i as he,n as K,r as q,t as ge}from"./Table-Ba58Wg4-.js";import{t as _e}from"./catalog-BBKm8Ih8.js";import{A as ve,C as ye,E as J,J as be,T as xe,Y as Se,c as Ce,dt as we,t as Te,w as Ee}from"./shared-Bp35cgFf.js";var De=S(`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`}]]),Y=c(t(),1),X=r(),Oe=Object.keys(_e);function ke(e){return _e[e].authTypes}function Ae(e){return ke(e).includes(`oauth`)?`oauth`:`apiKey`}var je={oauth:`Authorize in the browser`,apiKey:`Paste an API key`},Z={anthropic:`Anthropic`,openai:`OpenAI`,kimi:`Kimi`,kilo:`Kilo`,grok:`Grok`,custom:`OpenAI Compatible`},Me={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.`},Ne={openai:`http://localhost:1455/auth/callback?code=…`,grok:`http://127.0.0.1:56121/callback?code=…`},Pe=y.ol`
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: ${({theme:e})=>e.space(3)};
5
+ `,Fe=y.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
+ `,Ie=y.p`
15
+ font-size: 12px;
16
+ color: ${({theme:e})=>e.color.down};
17
+ `,Le=y.p`
18
+ font-size: 12px;
19
+ color: ${({theme:e})=>e.color.inkDim};
20
+ `;function Re({open:e,credentials:t,onOpenChange:r,onConnected:i}){let[a,o]=(0,Y.useState)(`anthropic`),[c,d]=(0,Y.useState)(Ae(`anthropic`)),[f,p]=(0,Y.useState)(``),[h,y]=(0,Y.useState)(null),[b,x]=(0,Y.useState)(``),[S,C]=(0,Y.useState)(``),w=(t??[]).filter((e,t,n)=>e.provider===`custom`&&n.findIndex(t=>t.provider===`custom`&&t.providerData.endpointId===e.providerData.endpointId)===t),[ee,T]=(0,Y.useState)(``),[E,O]=(0,Y.useState)(``),[ne,k]=(0,Y.useState)(`chat_completions`),[A,j]=(0,Y.useState)(``),[M,N]=(0,Y.useState)(null),P=v(),F=m(),I=u(),L=(0,Y.useCallback)(()=>{y(null),x(``),C(``),T(``),O(``),k(`chat_completions`),j(``),N(null),p(``),P.reset(),F.reset(),I.reset()},[P,F,I]),R=(0,Y.useCallback)(e=>{e||L(),r(e)},[r,L]);return(0,Y.useEffect)(()=>{if(h===null||h.kind!==`device`)return;let e=!1,t=async()=>{try{let t=await g(h.flowId);if(e)return;if(t.status===`complete`){L(),r(!1),i();return}}catch(t){if(e)return;N(G(t)),y(null);return}e||(n=setTimeout(()=>void t(),h.pollIntervalMs))},n=setTimeout(()=>void t(),h.pollIntervalMs);return()=>{e=!0,clearTimeout(n)}},[h,i,r,L]),(0,X.jsx)(D,{open:e,onOpenChange:R,title:`Connect an account`,description:`The gateway stores the resulting token encrypted. It is never shown again after this dialog.`,footer:h===null?(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(l,{type:`button`,onClick:()=>R(!1),children:`Cancel`}),(0,X.jsx)(l,{type:`button`,$variant:`primary`,disabled:P.isPending||I.isPending,onClick:()=>{if(N(null),c===`apiKey`){I.mutate({provider:a,apiKey:A,label:f.trim()||void 0,...a===`custom`?{endpointId:S,endpointLabel:ee,origin:E,protocol:ne}:{}},{onSuccess:()=>{L(),r(!1),i()},onError:e=>N(G(e))});return}P.mutate({provider:a,label:f.trim().length===0?Z[a]:f.trim()},{onSuccess:e=>y(e),onError:e=>N(G(e))})},children:c===`apiKey`?I.isPending?`Adding…`:`Add API key`:P.isPending?`Starting…`:`Start authorization`})]}):h.kind===`device`?(0,X.jsx)(l,{type:`button`,onClick:()=>R(!1),children:`Cancel`}):(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(l,{type:`button`,onClick:()=>R(!1),children:`Cancel`}),(0,X.jsx)(l,{type:`button`,$variant:`primary`,disabled:F.isPending||b.trim().length===0,onClick:()=>{h!==null&&(N(null),F.mutate({flowId:h.flowId,code:b.trim()},{onSuccess:()=>{L(),r(!1),i()},onError:e=>N(G(e))}))},children:F.isPending?`Finishing…`:`Finish connecting`})]}),children:(0,X.jsxs)(Pe,{children:[h===null?(0,X.jsxs)(_,{$gap:3,children:[(0,X.jsx)(U,{label:`Provider`,children:e=>(0,X.jsx)(V,{...e,value:a,onChange:e=>{let t=e.target.value;o(t),d(Ae(t))},children:Oe.map(e=>(0,X.jsx)(`option`,{value:e,children:Z[e]},e))})}),ke(a).length>1?(0,X.jsx)(U,{label:`How to connect`,children:e=>(0,X.jsx)(V,{...e,value:c,onChange:e=>d(e.target.value),children:ke(a).map(e=>(0,X.jsx)(`option`,{value:e,children:je[e]},e))})}):null,a===`custom`?(0,X.jsxs)(X.Fragment,{children:[w.length===0?null:(0,X.jsx)(U,{label:`Existing endpoint`,children:e=>(0,X.jsxs)(V,{...e,value:S,onChange:e=>{let t=w.find(t=>t.providerData.endpointId===e.target.value);if(t===void 0){C(``),T(``),O(``),k(`chat_completions`);return}C(String(t.providerData.endpointId)),T(String(t.providerData.endpointLabel)),O(String(t.providerData.origin)),k(t.providerData.protocol===`responses`?`responses`:`chat_completions`)},children:[(0,X.jsx)(`option`,{value:``,children:`Create new endpoint`}),w.map(e=>(0,X.jsx)(`option`,{value:String(e.providerData.endpointId),children:String(e.providerData.endpointLabel)},String(e.providerData.endpointId)))]})}),(0,X.jsx)(U,{label:`Endpoint ID`,children:e=>(0,X.jsx)(H,{...e,value:S,onChange:e=>C(e.target.value)})}),(0,X.jsx)(U,{label:`Endpoint label`,children:e=>(0,X.jsx)(H,{...e,value:ee,onChange:e=>T(e.target.value)})}),(0,X.jsx)(U,{label:`Server origin`,children:e=>(0,X.jsx)(H,{...e,value:E,placeholder:`https://server.example`,onChange:e=>O(e.target.value)})}),E.trim().toLowerCase().startsWith(`http://`)?(0,X.jsx)(Ie,{children:`Plaintext transport sends prompts and API keys without TLS.`}):null,(0,X.jsx)(U,{label:`Protocol`,children:e=>(0,X.jsxs)(V,{...e,value:ne,onChange:e=>k(e.target.value),children:[(0,X.jsx)(`option`,{value:`chat_completions`,children:`Chat Completions (/v1/chat/completions)`}),(0,X.jsx)(`option`,{value:`responses`,children:`Responses (/v1/responses)`})]})})]}):null,c===`apiKey`?(0,X.jsx)(U,{label:`API key`,children:e=>(0,X.jsx)(H,{...e,type:`password`,value:A,autoComplete:`off`,onChange:e=>j(e.target.value)})}):null,(0,X.jsx)(U,{label:`Label`,hint:`How this account is named in the rack. Defaults to the provider.`,children:e=>(0,X.jsx)(H,{...e,value:f,placeholder:Z[a],onChange:e=>p(e.target.value)})})]}):(0,X.jsxs)(_,{$gap:3,children:[(0,X.jsxs)(_,{$gap:1,children:[(0,X.jsx)(s,{children:`Step 1 — authorize`}),(0,X.jsx)(n,{$gap:2,children:(0,X.jsxs)(l,{as:`a`,href:h.authorizeUrl,target:`_blank`,rel:`noreferrer noopener`,$variant:`primary`,$size:`sm`,children:[(0,X.jsx)(De,{}),`Open `,Z[a]]})}),(0,X.jsx)(te,{value:h.authorizeUrl,label:`Copy authorization link`})]}),h.userCode===null?null:(0,X.jsxs)(_,{$gap:1,children:[(0,X.jsx)(s,{children:`Step 2 — enter this code`}),(0,X.jsx)(Fe,{children:h.userCode})]}),h.kind===`device`?(0,X.jsxs)(Le,{children:[Me[a],` Waiting for authorization…`]}):(0,X.jsx)(U,{label:`Authorization code`,hint:Me[a],...M===null?{}:{problem:M},children:e=>(0,X.jsx)(H,{...e,value:b,autoFocus:!0,placeholder:Ne[a]??`code#state`,onChange:e=>x(e.target.value)})})]}),M===null||h?.kind===`pkce`?null:(0,X.jsx)(Ie,{children:M})]})})}var ze=[`axis`],Be=(0,Y.forwardRef)((e,t)=>Y.createElement(ye,{chartName:`LineChart`,defaultTooltipEventType:`axis`,validateTooltipEventTypes:ze,tooltipPayloadSearcher:Se,categoricalChartProps:e,ref:t})),Ve=y(n)`
21
+ gap: ${({theme:e})=>e.space(5)};
22
+ flex-wrap: wrap;
23
+ `,Q=y.div`
24
+ display: flex;
25
+ flex-direction: column;
26
+ gap: 2px;
27
+ `,$=y.span`
28
+ font-size: 11.5px;
29
+ color: ${({theme:e})=>e.color.inkDim};
30
+ `,He={budget:`1 4`,projection:`6 4`},Ue=`projected`;function We(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 Ge(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 Ke(e,t){let n=t?.windowStartsAt??null;return n===null||e.resetsAt===null?null:n-(e.resetsAt-n)}function qe({credentialId:e,windows:t,burn:n,pollIntervalMs:r,now:i}){let a=t.map(e=>{let t=M(n,e.windowType);return{window:e,estimate:t,since:Ke(e,t)}}),o=a.map(e=>e.since).filter(e=>e!==null),s=o.length===0?0:Math.min(...o),c=p({credentialId:e,since:s},o.length>0),l=c.data?.samples??[],u=c.data?.gatewayRates??[];return(0,X.jsx)(_,{$gap:4,children:a.map(e=>(0,X.jsx)(Ye,{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 Je(e,t,n){let r=ce(e,t);return r===`ok`?`lasts the window`:r!==`empty`||t.exhaustsAt===null?`unknown`:t.exhaustsAt<=n?`empty now`:`empty ~${oe(t.exhaustsAt-n)} before it resets`}function Ye({window:e,estimate:t,since:r,samples:i,gatewayRate:a,pollIntervalMs:c,now:l}){let u=L[e.windowType],d=e.limit===null?`${A(e.used)} used`:`${A(e.used)} of ${A(e.limit)} used`;if(t===void 0||t.stale||B(e,l,c))return(0,X.jsxs)(_,{$gap:2,children:[(0,X.jsxs)(n,{$gap:2,$wrap:!0,children:[(0,X.jsxs)(s,{children:[u,` window`]}),(0,X.jsx)($,{children:d})]}),(0,X.jsx)($,{children:`reading is stale`})]});let f=ae(P(i),e),p=f.flatMap(e=>{let t=F(e);return t===null?[]:[{key:`${e.key}-budget`,pace:t}]}),m=re(e,t),h=We([...f,...p.map(e=>({key:e.key,points:[e.pace.from,e.pace.to]})),...m===null?[]:[{key:Ue,points:[m.from,m.to]}]]),g=new Set(f.map(e=>e.key)),v=Math.max(100,...m===null?[]:[m.from.percent,m.to.percent].map(e=>Math.ceil(e)));return(0,X.jsxs)(_,{$gap:2,children:[(0,X.jsxs)(n,{$gap:2,$wrap:!0,children:[(0,X.jsxs)(s,{children:[u,` window`]}),(0,X.jsx)($,{children:d})]}),(0,X.jsxs)(Ve,{children:[(0,X.jsxs)(Q,{children:[(0,X.jsx)(s,{children:`Window average`}),(0,X.jsx)(o,{children:t.ratePerHour===null?`unknown`:`${A(t.ratePerHour)}/h`})]}),(0,X.jsxs)(Q,{children:[(0,X.jsx)(s,{children:`Estimate`}),(0,X.jsx)(o,{children:Je(e,t,l)})]}),(0,X.jsxs)(Q,{children:[(0,X.jsx)(s,{children:`Projected`}),(0,X.jsx)(o,{children:m===null?`unknown`:`${Math.round(m.to.percent)}% of limit by reset`})]}),(0,X.jsxs)(Q,{children:[(0,X.jsx)(s,{children:`This gateway accounts for`}),(0,X.jsx)(o,{children:a?.gatewayRatePerHour===void 0||a.gatewayRatePerHour===null?`unknown`:`${A(a.gatewayRatePerHour)} tokens/h`})]})]}),e.limit===null?(0,X.jsx)($,{children:`no ceiling reported`}):e.resetsAt===null||r===null?(0,X.jsx)($,{children:`no reset reported`}):f.length===0?(0,X.jsx)($,{children:`not yet observed`}):(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(s,{children:[`Used, this window and the one before`,...p.length===0?[]:[`budget dotted`],...m===null?[]:[`projection dashed`]].join(` · `)}),(0,X.jsx)(Te,{$height:160,children:(0,X.jsx)(we,{width:`100%`,height:`100%`,children:(0,X.jsxs)(Be,{data:h,margin:{top:4,right:8,bottom:4,left:4},children:[(0,X.jsx)(ve,{stroke:`var(--rule)`,vertical:!1}),(0,X.jsx)(xe,{dataKey:`at`,type:`number`,scale:`time`,domain:Ge(r,e.resetsAt,p),tickFormatter:e=>se(e),tick:{fill:`var(--ink-faint)`,fontSize:10},stroke:`var(--rule-strong)`,minTickGap:40}),(0,X.jsx)(Ee,{domain:[0,v],allowDataOverflow:!0,tickFormatter:e=>`${Math.round(e)}%`,tick:{fill:`var(--ink-faint)`,fontSize:10},stroke:`var(--rule-strong)`,width:40}),(0,X.jsx)(be,{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,X.jsxs)(Ce,{children:[(0,X.jsx)(`div`,{children:se(r)}),(0,X.jsxs)(`div`,{children:[n.value.toFixed(1),`% used`]})]})}}),f.map(e=>(0,X.jsx)(J,{type:`monotone`,dataKey:e.key,stroke:`var(--accent)`,strokeWidth:2,dot:e.points.length===1&&{r:2.5,fill:`var(--accent)`,stroke:`var(--accent)`},connectNulls:!0,isAnimationActive:!1},e.key)),p.map(e=>(0,X.jsx)(J,{type:`linear`,dataKey:e.key,stroke:`var(--ink-faint)`,strokeWidth:1.5,strokeDasharray:He.budget,dot:!1,connectNulls:!0,isAnimationActive:!1},e.key)),m===null?null:(0,X.jsx)(J,{type:`linear`,dataKey:Ue,stroke:`var(--ink-dim)`,strokeWidth:1.5,strokeDasharray:He.projection,dot:!1,connectNulls:!0,isAnimationActive:!1})]})})})]})]})}var Xe=[`anthropic`,`openai`,`kimi`,`kilo`,`grok`,`custom`],Ze={anthropic:`Anthropic`,openai:`OpenAI`,kimi:`Kimi`,kilo:`Kilo`,grok:`Grok`,custom:`OpenAI Compatible`},Qe=y(W)`
31
+ border-left: 3px solid ${({theme:e,$provider:t})=>e.provider[t]};
32
+ `,$e=y(H)`
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
+ `,et=y(ue)`
47
+ width: 62px;
48
+ height: 26px;
49
+ `,tt=y.span`
50
+ display: block;
51
+ padding-left: 9px;
52
+ font-size: 11px;
53
+ color: ${({theme:e})=>e.color.inkDim};
54
+ `,nt=y.div`
55
+ display: grid;
56
+ grid-template-columns: 96px 1fr;
57
+ align-items: center;
58
+ min-width: 208px;
59
+ gap: 6px;
60
+ `,rt=y.div`
61
+ display: flex;
62
+ flex-direction: column;
63
+ gap: 4px;
64
+ `;function it(){let e=a();return{pending:e.isPending,commit:(t,n)=>{e.mutate({id:t,patch:n})}}}function at(){let{cadence:t}=x(),r=d(),a=f(t(1e4)),o=i(),c=b(),{commit:u}=it(),[p,m]=(0,Y.useState)(!1),[g,v]=(0,Y.useState)(null),[y,S]=(0,Y.useState)(new Set),te=e=>S(t=>{let n=new Set(t);return n.delete(e)||n.add(e),n}),D=Date.now(),A=r.data??[],P=z(a.data?.health??[],e=>e.credentialId),F=z(a.data?.quota??[],e=>e.credentialId),re=z(a.data?.burn??[],e=>e.credentialId),B=o.data?.quotaPollIntervalMs??3e5,ae=A.filter(e=>e.enabled).length,oe=r.isLoading?`Reading connected accounts…`:A.length===0?`No provider credentials are connected, so every request fails at the router.`:`${ae} of ${A.length} accounts are enabled and eligible for routing.`;return(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(C,{legend:`Accounts`,title:`Provider accounts`,summary:oe,actions:(0,X.jsxs)(l,{type:`button`,$variant:`primary`,onClick:()=>m(!0),children:[(0,X.jsx)(T,{}),`Connect an account`]})}),r.isError?(0,X.jsx)(W,{legend:`Accounts`,children:(0,X.jsx)(fe,{error:r.error,onRetry:()=>void r.refetch()})}):r.isLoading?(0,X.jsx)(W,{legend:`Accounts`,children:(0,X.jsx)(pe,{rows:5})}):A.length===0?(0,X.jsx)(W,{legend:`Accounts`,children:(0,X.jsx)(me,{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,X.jsx)(l,{type:`button`,$variant:`primary`,$size:`sm`,onClick:()=>m(!0),children:`Connect an account`})})}):(0,X.jsx)(_,{$gap:4,children:Xe.filter(e=>A.some(t=>t.provider===e)).map(t=>{let r=A.filter(e=>e.provider===t);return(0,X.jsx)(Qe,{$provider:t,legend:Ze[t],meta:`${r.length} account${r.length===1?``:`s`}`,flush:!0,children:(0,X.jsx)(e,{children:(0,X.jsxs)(ge,{children:[(0,X.jsx)(`thead`,{children:(0,X.jsxs)(`tr`,{children:[(0,X.jsx)(q,{$width:`24%`,children:`Account`}),(0,X.jsx)(q,{$width:`20%`,children:`Sign-in`}),(0,X.jsx)(q,{$align:`right`,$width:`86px`,children:`Tier`}),(0,X.jsx)(q,{$align:`right`,$width:`94px`,children:`Weight`}),(0,X.jsx)(q,{$align:`center`,$width:`86px`,children:`Enabled`}),(0,X.jsx)(q,{$width:`240px`,children:`Quota`}),(0,X.jsx)(q,{$align:`right`,$width:`88px`,children:`TTFT`}),(0,X.jsx)(q,{$align:`right`,$width:`130px`,children:`Token expires`}),(0,X.jsx)(q,{$width:`76px`})]})}),(0,X.jsx)(`tbody`,{children:r.map(e=>{let t=R(P.get(e.id)??[],D,e.enabled,e.disabledReason),r=F.get(e.id)??[],i=re.get(e.id)??[],a=N(r),o=y.has(e.id);return(0,X.jsxs)(Y.Fragment,{children:[(0,X.jsxs)(he,{children:[(0,X.jsxs)(K,{children:[(0,X.jsxs)(n,{$gap:2,children:[(0,X.jsx)(ie,{state:t.state,label:t.note===``?`healthy`:t.note}),(0,X.jsx)($e,{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}u(e.id,{label:n})}})]}),t.note===``?null:(0,X.jsx)(tt,{children:t.note})]}),(0,X.jsx)(K,{children:(0,X.jsxs)(n,{$gap:1,children:[(0,X.jsx)(le,{children:e.authType===`oauth`?`oauth`:`api key`}),e.accountEmail===null?null:(0,X.jsx)(s,{children:e.accountEmail})]})}),(0,X.jsx)(K,{$align:`right`,children:(0,X.jsx)(et,{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}u(e.id,{tier:n})}})}),(0,X.jsx)(K,{$align:`right`,children:(0,X.jsx)(et,{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}u(e.id,{weight:n})}})}),(0,X.jsx)(K,{$align:`center`,children:(0,X.jsx)(O,{checked:e.enabled,label:`Route to ${e.label}`,onCheckedChange:t=>u(e.id,{enabled:t})})}),(0,X.jsx)(K,{children:a.length===0?(0,X.jsx)(s,{children:`unknown`}):(0,X.jsx)(rt,{children:a.map(({window:e,fraction:t})=>(0,X.jsxs)(nt,{children:[(0,X.jsx)(de,{fraction:t,label:`${L[e.windowType]} window, ${Math.round(t*100)}% used`}),(0,X.jsx)(s,{children:I(e,D,B,k,M(i,e.windowType))})]},e.windowType))})}),(0,X.jsx)(K,{$align:`right`,$mono:!0,children:j(t.ttftMs)}),(0,X.jsx)(K,{$align:`right`,$mono:!0,children:e.expiresAt===null?`never`:k(e.expiresAt,D)}),(0,X.jsx)(K,{$align:`right`,children:(0,X.jsxs)(n,{$gap:1,$justify:`flex-end`,children:[r.length===0?null:(0,X.jsx)(h,{type:`button`,$variant:`ghost`,$size:`sm`,"aria-expanded":o,"aria-label":`${o?`Hide`:`Show`} quota history for ${e.label}`,title:`${o?`Hide`:`Show`} quota history for ${e.label}`,onClick:()=>te(e.id),children:o?(0,X.jsx)(ee,{}):(0,X.jsx)(w,{})}),(0,X.jsx)(h,{type:`button`,$variant:`ghost`,$size:`sm`,"aria-label":`Remove ${e.label}`,title:`Remove ${e.label}`,onClick:()=>v(e),children:(0,X.jsx)(E,{})})]})})]}),o?(0,X.jsx)(he,{children:(0,X.jsx)(K,{colSpan:9,children:(0,X.jsx)(qe,{credentialId:e.id,windows:r,burn:i,pollIntervalMs:B,now:D})})}):null]},e.id)})})]})})},t)})}),(0,X.jsx)(Re,{open:p,credentials:r.data??[],onOpenChange:m,onConnected:()=>void r.refetch()}),(0,X.jsx)(ne,{open:g!==null,onOpenChange:e=>{e||v(null)},title:`Remove account`,body:g===null?``:`Removing "${g.label}" deletes its stored token. Any model target pointing at ${Ze[g.provider]} loses this account, and reconnecting means authorizing again.`,confirmLabel:`Remove account`,busy:c.isPending,onConfirm:()=>{g!==null&&c.mutate(g.id,{onSettled:()=>v(null)})}})]})}var ot=at;export{ot as component};
@@ -1,15 +1,15 @@
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)`
1
+ import{$t as e,Q as t,Qt as n,Z as r,_n as i,d as a,t as o,ut as s}from"./queries-BJHk_wso.js";import{a as c,t as l}from"./Rack-D1zBw9SW.js";import{S as u}from"./Lamp-QRSv-SqM.js";import{i as d}from"./Field-B7GOsJf8.js";import{a as f,n as p,r as m,t as h}from"./States-CQFkw1UZ.js";var g=i(e(),1),_=n(),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=s(t)`
2
2
  gap: ${({theme:e})=>e.space(2)};
3
3
  flex-wrap: wrap;
4
- `,x=o(d)`
4
+ `,x=s(d)`
5
5
  width: auto;
6
- `,S=o.div`
6
+ `,S=s.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=o(f)`
12
+ `,C=s(f)`
13
13
  min-height: 0;
14
14
 
15
15
  > div {
@@ -18,27 +18,27 @@ 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
18
18
  flex-direction: column;
19
19
  min-height: 0;
20
20
  }
21
- `,w=o.div`
21
+ `,w=s.div`
22
22
  flex: 1;
23
23
  min-height: 0;
24
24
  overflow-x: auto;
25
25
  overflow-y: auto;
26
- `,T=o.pre`
26
+ `,T=s.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=o.div`
33
+ `,E=s.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=o.p`
35
+ `,D=s.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=o.code`
41
+ `,O=s.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(),[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};
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(),[t,n]=(0,g.useState)(200),[i,s]=(0,g.useState)(``),d=a(t,i,e(o)),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=>s(e.target.value),children:y.map(e=>(0,_.jsx)(`option`,{value:e.value,children:e.label},e.value))}),(0,_.jsx)(x,{value:t,"aria-label":`How many lines to fetch`,onChange:e=>n(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)(r,{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,39 @@
1
+ import{$ as e,$t as t,B as n,F as r,G as i,J as a,M as o,Q as s,Qt as c,S as l,V as u,Y as d,Zt as f,_ as p,_n as m,a as h,at as g,b as _,j as v,m as y,nt as b,rt as x,tt as S,ut as C,w}from"./queries-BJHk_wso.js";import{c as T,t as E}from"./Rack-D1zBw9SW.js";import{t as D}from"./Confirm-C5DYoI93.js";import{C as ee,E as O,T as k,b as A}from"./Lamp-QRSv-SqM.js";import{r as j,t as M}from"./Field-B7GOsJf8.js";import{t as te}from"./Meter-Dngwbpjo.js";import{a as N,i as P,n as F,r as I,t as ne}from"./States-CQFkw1UZ.js";import{i as re,n as L,r as R,t as ie}from"./Table-Ba58Wg4-.js";import{t as z}from"./Readout--CQnPjoO.js";import{n as B}from"./reasons-Cb8yF4Oy.js";var V=T(`camera`,[[`path`,{d:`M13.997 4a2 2 0 0 1 1.76 1.05l.486.9A2 2 0 0 0 18.003 7H20a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h1.997a2 2 0 0 0 1.759-1.048l.489-.904A2 2 0 0 1 10.004 4z`,key:`18u6gg`}],[`circle`,{cx:`12`,cy:`13`,r:`3`,key:`1vg3eu`}]]),H=T(`minimize-2`,[[`path`,{d:`m14 10 7-7`,key:`oa77jy`}],[`path`,{d:`M20 10h-6V4`,key:`mjg0md`}],[`path`,{d:`m3 21 7-7`,key:`tjx5ai`}],[`path`,{d:`M4 14h6v6`,key:`rmj7iw`}]]),U=T(`power`,[[`path`,{d:`M12 2v10`,key:`mnfbl`}],[`path`,{d:`M18.4 6.6a9 9 0 1 1-12.77.04`,key:`obofu9`}]]),W=T(`rotate-cw`,[[`path`,{d:`M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8`,key:`1p45f6`}],[`path`,{d:`M21 3v5h-5`,key:`1q7to0`}]]),G=m(t(),1),K=c(),q={systemd:`systemd is capturing this process, so a restart asks the manager to bring the unit back rather than signalling the gateway itself.`,container:`This gateway is running in a container, so a restart is an exit and the container's restart policy decides what happens next.`,none:`Nothing is supervising this process. It was started directly, and whatever stops it leaves it stopped.`},J=C.p`
2
+ font-size: 12px;
3
+ color: ${({theme:e})=>e.color.inkDim};
4
+ max-width: 72ch;
5
+ `,ae=C.p`
6
+ font-size: 12px;
7
+ color: ${({theme:e})=>e.color.warn};
8
+ max-width: 72ch;
9
+ `,Y=C.p`
10
+ font-size: 12px;
11
+ color: ${({theme:e})=>e.color.down};
12
+ `,X=C.p`
13
+ font-size: 12px;
14
+ color: ${({theme:e})=>e.color.inkDim};
15
+ ${x}
16
+ `,oe=9e4;async function se(){try{return(await fetch(`/health`,{cache:`no-store`})).ok}catch{return!1}}function ce({pollMs:e=750}){let t=w(),r=v(),i=n(),[a,o]=(0,G.useState)(null),[c,l]=(0,G.useState)(!1),[u,f]=(0,G.useState)(!1),[p,m]=(0,G.useState)(`idle`),h=t.data;(0,G.useEffect)(()=>{if(!c)return;let t=!1,n,r=!1,i=0,a=Math.max(1,Math.ceil(oe/e)),o=async()=>{let s=await se();if(!t){if(!r&&!s)r=!0,m(`returning`);else if(r&&s){window.location.reload();return}if(i+=1,i>=a){m(`lost`),l(!1);return}n=setTimeout(()=>void o(),e)}};return n=setTimeout(()=>void o(),e),()=>{t=!0,n!==void 0&&clearTimeout(n)}},[c,e]);let _=()=>{m(`leaving`),r.mutate(void 0,{onSuccess:()=>l(!0),onError:()=>m(`idle`)})};return u?(0,K.jsx)(N,{legend:`Lifecycle`,meta:`stopped`,children:(0,K.jsxs)(S,{$gap:2,children:[(0,K.jsx)(d,{children:`Gateway stopped`}),(0,K.jsxs)(J,{children:[`The gateway accepted the shutdown and is no longer serving. Nothing on this page will update again, and nothing here can start it: that needs`,` `,h?.supervisor===`container`?`the host that runs this container`:`a shell on the machine it runs on`,`.`]})]})}):(0,K.jsxs)(N,{legend:`Lifecycle`,meta:h?.supervisor,children:[t.isError?(0,K.jsx)(F,{error:t.error,onRetry:()=>void t.refetch()}):h===void 0?(0,K.jsx)(I,{rows:2}):(0,K.jsxs)(S,{$gap:3,children:[(0,K.jsx)(J,{children:q[h.supervisor]}),h.note===void 0?null:(0,K.jsx)(ae,{children:h.note}),(0,K.jsxs)(s,{$gap:2,children:[(0,K.jsxs)(g,{type:`button`,disabled:!h.canRestart||r.isPending||c,onClick:()=>o(`restart`),children:[(0,K.jsx)(W,{}),`Restart gateway`]}),(0,K.jsxs)(g,{type:`button`,$variant:`danger`,disabled:!h.canShutdown||i.isPending||c,onClick:()=>o(`shutdown`),children:[(0,K.jsx)(U,{}),`Shut down gateway`]})]}),p===`leaving`?(0,K.jsx)(X,{role:`status`,children:`Asked the gateway to restart. Waiting for it to stop answering.`}):p===`returning`?(0,K.jsx)(X,{role:`status`,children:`The gateway has stopped answering. Waiting for it to come back, then this page reloads.`}):p===`lost`?(0,K.jsx)(Y,{role:`alert`,children:`The gateway has not come back. Reload this page once it is running again, or check the machine it runs on.`}):null,r.isError?(0,K.jsx)(Y,{role:`alert`,children:P(r.error)}):null,i.isError?(0,K.jsx)(Y,{role:`alert`,children:P(i.error)}):null]}),(0,K.jsx)(D,{open:a===`restart`,onOpenChange:e=>{e||o(null)},title:`Restart gateway`,body:`Requests in flight are dropped when the process goes. This console waits for the gateway to stop answering and to answer again, then reloads itself.`,confirmLabel:`Restart now`,busy:r.isPending,onConfirm:()=>{o(null),_()}}),(0,K.jsx)(D,{open:a===`shutdown`,onOpenChange:e=>{e||o(null)},title:`Shut down gateway`,body:h?.supervisor===`container`?`Stopping the only process in this container takes this dashboard with it, and the dashboard is what would have restarted the gateway. Unless the container's restart policy brings it back, getting it running again needs access to the host.`:`The gateway stops serving and stays stopped. This console goes with it, so starting the gateway again needs a shell on the machine it runs on.`,confirmLabel:`Shut down now`,busy:i.isPending,onConfirm:()=>{o(null),i.mutate(void 0,{onSuccess:()=>f(!0)})}})]})}var Z=[{id:`keepLatest`,label:`Snapshots kept`,hint:`How many survive regardless of age. The newest is always kept, whatever both numbers say.`,unit:`files`,max:100},{id:`maxAgeDays`,label:`Maximum age`,hint:`Older snapshots are pruned after every new one and on the hourly maintenance sweep.`,unit:`days`,max:3650}],le=C.p`
17
+ font-size: 12px;
18
+ color: ${({theme:e})=>e.color.down};
19
+ `,ue=C.p`
20
+ font-size: 12px;
21
+ color: ${({theme:e})=>e.color.ok};
22
+ `,de=C.div`
23
+ display: grid;
24
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
25
+ gap: ${({theme:e})=>e.space(3)};
26
+ `;function fe(e){let t={};for(let n of Z){let r=e[n.id].trim(),i=Number(r);if(r.length===0||!Number.isInteger(i)||i<1)return{ok:!1,problem:`${n.label} must be a whole number of 1 or more.`};if(i>n.max)return{ok:!1,problem:`${n.label} cannot exceed ${n.max}.`};t[n.id]=i}return{ok:!0,policy:t}}function pe({retention:e}){let t=r(),[n,i]=(0,G.useState)({}),[a,o]=(0,G.useState)(null),[c,l]=(0,G.useState)(!1),u={keepLatest:n.keepLatest??(e===void 0?``:String(e.keepLatest)),maxAgeDays:n.maxAgeDays??(e===void 0?``:String(e.maxAgeDays))};return(0,K.jsx)(N,{legend:`Retention`,actions:(0,K.jsx)(g,{type:`button`,$size:`sm`,disabled:t.isPending||e===void 0,onClick:()=>{l(!1);let e=fe(u);if(!e.ok){o(e.problem);return}o(null),t.mutate(e.policy,{onSuccess:()=>{l(!0),i({})},onError:e=>o(P(e))})},children:t.isPending?`Saving…`:`Save retention`}),children:(0,K.jsxs)(S,{$gap:3,children:[(0,K.jsx)(de,{children:Z.map(e=>(0,K.jsx)(M,{label:e.label,hint:e.hint,children:t=>(0,K.jsxs)(s,{$gap:2,children:[(0,K.jsx)(j,{...t,min:1,max:e.max,step:1,value:u[e.id],onChange:t=>i({...n,[e.id]:t.target.value})}),(0,K.jsx)(d,{children:e.unit})]})},e.id))}),a===null?null:(0,K.jsx)(le,{role:`alert`,children:a}),c&&a===null?(0,K.jsx)(ue,{role:`status`,children:`Retention saved.`}):null]})})}function me(){let e=f();return(0,G.useCallback)(t=>{if(t.adminPasswordChanged){B(`admin-password-changed`);return}e.invalidateQueries()},[e])}var Q=C.p`
27
+ font-size: 12px;
28
+ color: ${({theme:e})=>e.color.down};
29
+ `,he=C.input`
30
+ font-size: 12px;
31
+ color: ${({theme:e})=>e.color.inkDim};
32
+ max-width: 40ch;
33
+ `;function ge(){let t=u(),n=y(),r=o(),i=me(),a=_(),c=l(),[d,f]=(0,G.useState)(null),[p,m]=(0,G.useState)(null),[v,x]=(0,G.useState)(null),[C,w]=(0,G.useState)(!1),T=t.data??[],E=(0,K.jsxs)(g,{type:`button`,$variant:`primary`,$size:`sm`,disabled:n.isPending,onClick:()=>n.mutate(),children:[(0,K.jsx)(V,{}),n.isPending?`Copying…`:`Take a snapshot`]}),O=(0,K.jsxs)(S,{$gap:2,children:[(0,K.jsxs)(s,{$gap:2,$wrap:!0,children:[(0,K.jsx)(M,{label:`Database file to import`,hint:`A snapshot taken from this or another OmniGateway. It is checked for integrity and rejected if it is not one of ours.`,children:e=>(0,K.jsx)(he,{...e,type:`file`,accept:`.sqlite,.db,application/octet-stream`,onChange:e=>x(e.target.files?.[0]??null)})}),(0,K.jsx)(g,{type:`button`,$variant:`danger`,$size:`sm`,disabled:v===null||c.isPending,onClick:()=>w(!0),children:c.isPending?`Replacing…`:`Import`})]}),c.isError?(0,K.jsx)(Q,{role:`alert`,children:P(c.error)}):null,r.isError?(0,K.jsx)(Q,{role:`alert`,children:P(r.error)}):null,n.isError?(0,K.jsx)(Q,{role:`alert`,children:P(n.error)}):null]});return(0,K.jsxs)(N,{legend:`Snapshots`,meta:`${T.length}`,actions:E,footer:O,flush:!0,children:[t.isError?(0,K.jsx)(F,{error:t.error,onRetry:()=>void t.refetch()}):t.isLoading?(0,K.jsx)(`div`,{style:{padding:12},children:(0,K.jsx)(I,{rows:3})}):T.length===0?(0,K.jsx)(ne,{legend:`No snapshots`,message:`Nothing has been copied yet, so there is nothing to go back to. Take one before a migration or a settings change you are unsure of.`,action:(0,K.jsx)(g,{type:`button`,$variant:`primary`,$size:`sm`,disabled:n.isPending,onClick:()=>n.mutate(),children:`Take the first snapshot`})}):(0,K.jsx)(e,{children:(0,K.jsxs)(ie,{children:[(0,K.jsx)(`thead`,{children:(0,K.jsxs)(`tr`,{children:[(0,K.jsx)(R,{children:`File`}),(0,K.jsx)(R,{children:`Reason`}),(0,K.jsx)(R,{$align:`right`,children:`Size`}),(0,K.jsx)(R,{$align:`right`,children:`Taken`}),(0,K.jsx)(R,{})]})}),(0,K.jsx)(`tbody`,{children:T.map(e=>(0,K.jsxs)(re,{children:[(0,K.jsx)(L,{$mono:!0,children:(0,K.jsx)(b,{style:{maxWidth:`38ch`,display:`block`},children:e.filename})}),(0,K.jsx)(L,{children:e.reason}),(0,K.jsx)(L,{$align:`right`,$mono:!0,children:A(e.sizeBytes)}),(0,K.jsx)(L,{$align:`right`,$mono:!0,children:ee(e.createdAt)}),(0,K.jsx)(L,{$align:`right`,children:(0,K.jsxs)(s,{$gap:1,$justify:`flex-end`,children:[(0,K.jsx)(g,{as:`a`,$size:`sm`,href:h(e.id),download:e.filename,children:`Download`}),(0,K.jsx)(g,{type:`button`,$variant:`danger`,$size:`sm`,onClick:()=>f(e),children:`Restore`}),(0,K.jsx)(g,{type:`button`,$variant:`danger`,$size:`sm`,onClick:()=>m(e),children:`Delete`})]})})]},e.id))})]})}),(0,K.jsx)(D,{open:d!==null,onOpenChange:e=>{e||f(null)},title:`Restore database`,body:d===null?``:`Replacing the live database with ${d.filename}. Client requests are refused while the file is swapped, and a copy of the current database is taken first so this can be undone. Captured request bodies are not part of a snapshot and are left where they are.`,confirmLabel:`Restore database`,busy:r.isPending,onConfirm:()=>{d!==null&&r.mutate(d.id,{onSuccess:i,onSettled:()=>f(null)})}}),(0,K.jsx)(D,{open:p!==null,onOpenChange:e=>{e||m(null)},title:`Delete snapshot`,body:p===null?``:`Deleting ${p.filename} from disk. Download it first if it is the copy you would go back to; there is no other one of it.`,confirmLabel:`Delete snapshot`,busy:a.isPending,onConfirm:()=>{p!==null&&a.mutate(p.id,{onSettled:()=>m(null)})}}),(0,K.jsx)(D,{open:C,onOpenChange:w,title:`Import database`,body:v===null?``:`Replacing the live database with ${v.name}. It is validated before anything is touched, and a copy of the current database is taken first. If the file carries a different admin password, every session ends and you will be asked to sign in again.`,confirmLabel:`Replace database`,busy:c.isPending,onConfirm:()=>{v!==null&&c.mutate(v,{onSuccess:i,onSettled:()=>w(!1)})}})]})}var $=C.p`
34
+ font-size: 12px;
35
+ color: ${({theme:e})=>e.color.ok};
36
+ `,_e=C.p`
37
+ font-size: 12px;
38
+ color: ${({theme:e})=>e.color.down};
39
+ `;function ve(){let e=p(),t=i(),[n,r]=(0,G.useState)(!1),o=e.data,s=o===void 0||o.logicalBytes===0?0:o.freePageBytes/o.logicalBytes;return(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(E,{legend:`Database`,title:`Storage, snapshots, and lifecycle`,summary:e.isLoading?`Measuring the database…`:`The one SQLite file this gateway runs from, the copies taken of it, and the controls that stop and start the process.`}),(0,K.jsx)(N,{legend:`Size`,meta:o===void 0?void 0:`schema v${o.stats.schemaVersion}`,actions:(0,K.jsxs)(g,{type:`button`,$size:`sm`,disabled:t.isPending||o===void 0,onClick:()=>r(!0),children:[(0,K.jsx)(H,{}),t.isPending?`Compacting…`:`Compact`]}),footer:t.isError?(0,K.jsx)(_e,{role:`alert`,children:P(t.error)}):t.data===void 0?void 0:(0,K.jsx)($,{role:`status`,children:`Compacted, reclaiming ${A(t.data.reclaimedBytes)} in ${k(t.data.durationMs)}.`}),children:e.isError?(0,K.jsx)(F,{error:e.error,onRetry:()=>void e.refetch()}):o===void 0?(0,K.jsx)(I,{rows:3}):(0,K.jsxs)(a,{$min:`180px`,children:[(0,K.jsx)(z,{legend:`Database file`,value:A(o.fileBytes),unit:`${o.stats.pageCount} pages of ${A(o.stats.pageSize)}`,trace:(0,K.jsx)(te,{fraction:s,label:`${O(s,0)} of the file is reclaimable`})}),(0,K.jsx)(z,{legend:`Reclaimable`,value:A(o.freePageBytes),unit:`${o.stats.freelistCount} free pages`}),(0,K.jsx)(z,{legend:`Write-ahead log`,value:A(o.walBytes),unit:`folded into every snapshot`}),(0,K.jsx)(z,{legend:`Captured bodies`,value:A(o.bodiesBytes),unit:`never in a snapshot`}),(0,K.jsx)(z,{legend:`Snapshots`,value:A(o.snapshots.totalBytes),unit:`${o.snapshots.count} kept`}),(0,K.jsx)(z,{legend:`Free disk`,value:A(o.freeDiskBytes),unit:o.freeDiskBytes===null?`not readable here`:`on this filesystem`})]})}),(0,K.jsx)(ge,{}),(0,K.jsx)(pe,{retention:o?.retention}),(0,K.jsx)(ce,{}),(0,K.jsx)(D,{open:n,onOpenChange:r,title:`Compact database`,body:`Running VACUUM rewrites the database to give back its free pages. It holds the write lock for as long as it takes, so requests in flight will wait, and it needs room on disk for a second copy while it runs.`,confirmLabel:`Compact database`,busy:t.isPending,onConfirm:()=>t.mutate(void 0,{onSettled:()=>r(!1)})})]})}var ye=ve;export{ye as component};
@@ -0,0 +1,62 @@
1
+ import{$ as e,D as t,J as n,O as r,Q as i,Qt as a,R as o,W as s,X as c,Y as l,at as u,et as d,ft as f,g as p,h as m,nt as h,tt as g,ut as _}from"./queries-BJHk_wso.js";import{a as v,r as y,t as ee}from"./Rack-D1zBw9SW.js";import{n as b,t as x}from"./TokenBreakdown-CyHJv0O5.js";import{D as S,E as C,O as w,S as T,T as E,_ as D,a as O,d as k,f as A,g as j,l as M,m as N,n as te,o as P,r as ne,s as F,t as I,x as L}from"./Lamp-QRSv-SqM.js";import{n as R,t as z}from"./Chip-DbKk1ExR.js";import{t as B}from"./Meter-Dngwbpjo.js";import{a as V,n as H,t as U}from"./States-CQFkw1UZ.js";import{i as W,n as G,r as K,t as q}from"./Table-Ba58Wg4-.js";import{t as J}from"./Readout--CQnPjoO.js";var Y=a(),X=_(h)`
2
+ font-weight: 500;
3
+ display: block;
4
+ max-width: 24ch;
5
+ `,Z=_.span`
6
+ font-size: 11px;
7
+ color: ${({theme:e})=>e.color.inkDim};
8
+ `,re=_.div`
9
+ display: grid;
10
+ grid-template-columns: 72px 1fr;
11
+ align-items: center;
12
+ gap: 6px;
13
+ min-width: 172px;
14
+ `,ie=_.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:t,health:n,quota:r,burn:a,usage:o,quotaPollIntervalMs:s,now:c}){let d=F(n,e=>e.credentialId),p=F(r,e=>e.credentialId),m=F(a,e=>e.credentialId),h=new Map(o.map(e=>[e.key,e])),g={down:0,warn:1,ok:2,idle:3,live:3},_=t.map(e=>{let t=m.get(e.id)??[];return{credential:e,status:P(d.get(e.id)??[],c,e.enabled,e.disabledReason),quota:j(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:`${t.length} connected`,flush:!0,actions:(0,Y.jsx)(u,{as:f,to:`/accounts`,$size:`sm`,children:`Manage accounts`}),children:t.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)(u,{as:f,to:`/accounts`,$variant:`primary`,$size:`sm`,children:`Connect an account`})}):(0,Y.jsx)(e,{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:n,burn:r,usage:a})=>(0,Y.jsxs)(W,{children:[(0,Y.jsx)(G,{children:(0,Y.jsxs)(i,{$gap:2,children:[(0,Y.jsx)(I,{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:n.length===0?(0,Y.jsx)(Z,{children:`unknown`}):(0,Y.jsx)(ie,{children:n.map(({window:e,fraction:t})=>(0,Y.jsxs)(re,{children:[(0,Y.jsx)(B,{fraction:t,label:`${te[e.windowType]} window, ${Math.round(t*100)}% used`}),(0,Y.jsx)(l,{children:N(e,c,s,S,O(r,e.windowType))})]},e.windowType))})}),(0,Y.jsx)(G,{$align:`right`,$mono:!0,children:E(t.ttftMs)}),(0,Y.jsx)(G,{$align:`right`,$mono:!0,children:a===void 0?`—`:T(a.requests)}),(0,Y.jsx)(G,{$align:`right`,$mono:!0,children:S(t.lastUsedAt,c)})]},e.id))})]})})})}var ce=_.ul`
19
+ display: flex;
20
+ flex-direction: column;
21
+ `,le=_.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)`
32
+ font-family: ${({theme:e})=>e.font.mono};
33
+ font-size: 12px;
34
+ max-width: 30ch;
35
+ `,de=_(c)`
36
+ color: ${({theme:e})=>e.color.down};
37
+ font-size: 11px;
38
+ `;function fe({logs:e}){let t=e.slice(0,12);return(0,Y.jsx)(V,{legend:`Activity`,meta:`most recent first`,flush:!0,actions:(0,Y.jsx)(u,{as:f,to:`/logs`,$size:`sm`,children:`Open logs`}),children:t.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:t.map(e=>(0,Y.jsxs)(le,{children:[(0,Y.jsx)(I,{state:A(e),label:k(e)}),(0,Y.jsx)(c,{$dim:!0,children:L(e.at)}),(0,Y.jsx)(ue,{title:e.requestedModel,children:e.requestedModel||`—`}),e.resolvedProvider===null?null:(0,Y.jsx)(c,{$dim:!0,style:{color:`var(--p-${e.resolvedProvider})`},children:e.resolvedProvider}),(0,Y.jsx)(d,{}),M(e)?(0,Y.jsx)(c,{$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)(c,{$dim:!0,children:[e.attempts,`×`]}):null,(0,Y.jsx)(c,{$dim:!0,children:(0,Y.jsx)(b,{tokens:e})}),(0,Y.jsx)(c,{$dim:!0,children:E(e.durationMs)}),(0,Y.jsx)(c,{$dim:!0,children:w(e.costUsd)})]})]},e.id))})})}var pe=_.ul`
39
+ display: flex;
40
+ flex-direction: column;
41
+ gap: ${({theme:e})=>e.space(3)};
42
+ `,me=_(h)`
43
+ font-family: ${({theme:e})=>e.font.mono};
44
+ font-size: 12.5px;
45
+ `,Q=_.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=_.div`
53
+ flex: ${({$grow:e})=>e} 0 0;
54
+ background: ${({$color:e})=>e};
55
+ opacity: 0.8;
56
+ `,ge=_.div`
57
+ flex: ${({$grow:e})=>e} 0 0;
58
+ `;function _e({models:e,logs:t}){let n=new Map;for(let e of t){let t=n.get(e.requestedModel)??{requests:0,costUsd:0};t.requests+=1,t.costUsd+=e.costUsd,n.set(e.requestedModel,t)}let r=Math.max(1,...[...n.values()].map(e=>e.requests)),a=[...e].map(e=>({model:e,used:n.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)(u,{as:f,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)(u,{as:f,to:`/models`,$variant:`primary`,$size:`sm`,children:`Create a model`})}):(0,Y.jsx)(pe,{children:a.map(({model:e,used:t})=>{let n=(t?.requests??0)/r,a=[...new Set(e.targets.map(e=>e.provider))];return(0,Y.jsxs)(`li`,{children:[(0,Y.jsxs)(i,{$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)(d,{}),(0,Y.jsx)(c,{$dim:!0,children:T(t?.requests??0)}),(0,Y.jsx)(l,{children:`req`}),(0,Y.jsx)(c,{$dim:!0,children:w(t?.costUsd??0)})]}),(0,Y.jsxs)(Q,{style:{marginTop:6},title:`${Math.round(n*100)}% of the busiest model`,children:[a.map(e=>(0,Y.jsx)(he,{$color:`var(--p-${e})`,$grow:n/a.length},e)),(0,Y.jsx)(ge,{$grow:Math.max(0,1-n)})]})]},e.id)})})})}var ve=_.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=D(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:T(i.requests),unit:`${i.ratePerMin.toFixed(1)}/min`,trace:(0,Y.jsx)(y,{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:C(i.errorRate),unit:`${T(i.errors)} failed`,tone:i.requests===0?`ink`:o,trace:(0,Y.jsx)(y,{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:T(s),unit:(0,Y.jsx)(b,{tokens:i}),trace:(0,Y.jsx)(y,{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:E(i.ttftP50),unit:`p95 ${E(i.ttftP95)}`,trace:(0,Y.jsx)(y,{values:a.map(e=>e.ttftMs??0),color:`var(--ok)`,label:`median first-token latency, currently ${E(i.ttftP50)}`})}),(0,Y.jsx)(J,{legend:`Spend`,value:w(i.costUsd),unit:`${T(i.inputTokens+i.outputTokens)} tokens`,trace:(0,Y.jsx)(y,{values:a.map(e=>e.costUsd),color:`var(--warn)`,label:`spend over the window, ${w(i.costUsd)} total`})})]})}var $=36e5;function be(){let{cadence:e}=v(),i=p(),a=m(e(1e4)),c=r(),l=t(500,e(1e4)),u=o(),d=Date.now(),f=Math.floor((d-$)/6e4)*6e4,h=s({groupBy:`credential`,since:f},e(6e4)),_=i.data??[],y=F(a.data?.health??[],e=>e.credentialId),b=_.filter(e=>P(y.get(e.id)??[],d,e.enabled,e.disabledReason).state===`down`),x=i.isLoading||l.isLoading?`Reading the gateway…`:_.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 ${_.length} accounts are answering. Nothing needs attention.`;return(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(ee,{legend:`Rack`,title:`Gateway`,summary:x}),l.isError?(0,Y.jsx)(V,{legend:`Traffic`,children:(0,Y.jsx)(H,{legend:`The gateway did not answer`,error:l.error,onRetry:()=>void l.refetch()})}):(0,Y.jsxs)(g,{$gap:4,children:[(0,Y.jsx)(ye,{logs:l.data??[],windowMs:$,now:d}),(0,Y.jsx)(se,{credentials:_,health:a.data?.health??[],quota:a.data?.quota??[],burn:a.data?.burn??[],usage:h.data??[],quotaPollIntervalMs:u.data?.quotaPollIntervalMs??3e5,now:d}),(0,Y.jsxs)(n,{$min:`340px`,$gap:4,children:[(0,Y.jsx)(_e,{models:c.data??[],logs:l.data??[]}),(0,Y.jsx)(fe,{logs:l.data??[]})]})]})]})}var xe=be;export{xe as component};
@@ -0,0 +1,76 @@
1
+ import{$ as e,$t as t,C as n,L as r,N as i,O as a,Q as o,Qt as s,X as c,Y as l,_n as u,at as d,nt as f,ot as p,p as m,tt as h,ut as g}from"./queries-BJHk_wso.js";import{o as _,t as v}from"./Rack-D1zBw9SW.js";import{n as y,r as b,t as x}from"./CopyValue-CXjietiZ.js";import{t as S}from"./plus-DkO4vG-T.js";import{t as C}from"./Modal-DfltaSCz.js";import{t as w}from"./Toggle-DWrWc9-9.js";import{t as T}from"./Confirm-C5DYoI93.js";import{C as E}from"./Lamp-QRSv-SqM.js";import{t as D}from"./Chip-DbKk1ExR.js";import{n as O,r as k,t as A}from"./Field-B7GOsJf8.js";import{t as j}from"./Meter-Dngwbpjo.js";import{a as M,i as N,n as P,r as F,t as I}from"./States-CQFkw1UZ.js";import{i as L,n as R,r as z,t as B}from"./Table-Ba58Wg4-.js";var V=u(t(),1),H=[{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 U(e){return e.window===null?e.dimension:`${e.dimension}:${e.window}`}var ee={requests:`Requests`,tokens:`Tokens`,spend:`Spend`,concurrency:`Concurrent`},W={"1m":`per minute`,"5h":`per 5 hours`,"1w":`per week`};function G(e){let t=ee[e.dimension];return e.window===null?t:`${t} ${W[e.window]}`}function K(e,t){return e===`spend`?`$${t<1?t.toFixed(4):t.toFixed(2)}`:t.toLocaleString(`en-US`)}function q(e){return e.used===null||e.limit<=0?null:Math.max(0,e.used/e.limit)}function te(e){let t=null,n=-1;for(let r of e){let e=q(r);e!==null&&e>n&&(t=r,n=e)}return t}function J(e){let t={};for(let e of H)t[U(e)]=``;if(e===null)return t;for(let n of H){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[U(n)]=String(r))}return t}function Y(e){let t={},n={},r={},i;for(let a of H){let o=(e[U(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?`${G(a)} must be an amount above zero, or blank for no limit.`:`${G(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 X=s(),Z=g.div`
2
+ display: grid;
3
+ grid-template-columns: repeat(3, minmax(0, 1fr));
4
+ gap: ${({theme:e})=>e.space(2)};
5
+ `,ne=g.p`
6
+ font-size: 11px;
7
+ color: ${({theme:e})=>e.color.inkDim};
8
+ `;function Q({draft:e,onChange:t,disabled:n=!1}){return(0,X.jsxs)(h,{$gap:2,children:[(0,X.jsx)(Z,{children:H.map(r=>{let i=U(r);return(0,X.jsx)(A,{label:G(r),children:a=>(0,X.jsx)(k,{...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)})}),(0,X.jsx)(ne,{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 re=g.p`
9
+ font-size: 12px;
10
+ color: ${({theme:e})=>e.color.down};
11
+ `,ie=g.p`
12
+ font-size: 12px;
13
+ color: ${({theme:e})=>e.color.warn};
14
+ `;function ae({apiKey:e,onOpenChange:t}){let n=r(),[i,a]=(0,V.useState)(()=>J(e?.limits??{})),[o,s]=(0,V.useState)(null);return(0,X.jsx)(C,{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:(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(d,{type:`button`,onClick:()=>t(!1),children:`Cancel`}),(0,X.jsx)(d,{type:`button`,$variant:`primary`,disabled:n.isPending,onClick:()=>{if(e===null)return;let r=Y(i);if(`problem`in r){s(r.problem);return}s(null),n.mutate({id:e.id,limits:r.limits},{onSuccess:()=>t(!1),onError:e=>s(N(e))})},children:n.isPending?`Saving…`:`Save limits`})]}),children:(0,X.jsxs)(h,{$gap:3,children:[e?.limits===null?(0,X.jsx)(ie,{role:`status`,children:`The stored limits for this key cannot be read, so the gateway refuses it. Saving here replaces them.`}):null,(0,X.jsx)(Q,{draft:i,onChange:a,disabled:n.isPending}),o===null?null:(0,X.jsx)(re,{role:`alert`,children:o})]})})}var oe=g.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
+ `,se=g.span`
20
+ font-size: 11.5px;
21
+ color: ${({theme:e})=>e.color.inkDim};
22
+ `,ce=g.p`
23
+ font-size: 11px;
24
+ color: ${({theme:e})=>e.color.inkDim};
25
+ `;function le({label:e,readings:t}){return(0,X.jsxs)(h,{$gap:3,children:[(0,X.jsx)(oe,{children:t.map(t=>{let n=G({dimension:t.dimension,window:t.window}),r=q(t),i=K(t.dimension,t.limit);return(0,X.jsxs)(V.Fragment,{children:[(0,X.jsx)(l,{as:`span`,children:n}),(0,X.jsx)(c,{children:t.used===null?i:`${K(t.dimension,t.used)} of ${i}`}),r===null?(0,X.jsx)(se,{children:`in flight now, counted in the gateway process`}):(0,X.jsx)(j,{fraction:Math.min(1,r),label:`${e}, ${n}, ${Math.round(r*100)}% used`}),(0,X.jsx)(c,{children:r===null?`—`:`${Math.round(r*100)}%`})]},n)})}),(0,X.jsx)(ce,{children:`Usage counts completed requests still inside each window. Requests in flight are added by the gateway itself and are not shown here.`})]})}var ue=g.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
+ `,de=g.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
+ `,fe=g.p`
49
+ font-size: 12px;
50
+ color: ${({theme:e})=>e.color.warn};
51
+ `,pe=g.p`
52
+ font-size: 12px;
53
+ color: ${({theme:e})=>e.color.down};
54
+ `,me=g.p`
55
+ font-size: 12px;
56
+ color: ${({theme:e})=>e.color.inkDim};
57
+ `,he=g(d)`
58
+ gap: 4px;
59
+ `,ge=g.p`
60
+ font-size: 11px;
61
+ color: ${({theme:e})=>e.color.inkDim};
62
+ `;function $({open:e,onOpenChange:t}){let n=a(),r=m(),[i,s]=(0,V.useState)(``),[u,f]=(0,V.useState)(!0),[p,g]=(0,V.useState)([]),[_,v]=(0,V.useState)(()=>J({})),[S,T]=(0,V.useState)(!1),[E,D]=(0,V.useState)(!1),[k,j]=(0,V.useState)(null),[M,P]=(0,V.useState)(null),F=()=>{s(``),f(!0),g([]),v(J({})),T(!1),D(!1),j(null),P(null),r.reset()},I=e=>{e||F(),t(e)},L=Object.values(_).filter(e=>e.trim().length>0).length;return(0,X.jsx)(C,{open:e,onOpenChange:I,title:k===null?`Create an API key`:`Key created`,description:k===null?`Clients send this key as a bearer token or as x-api-key on every /v1 request.`:void 0,footer:k===null?(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(d,{type:`button`,onClick:()=>I(!1),children:`Cancel`}),(0,X.jsx)(d,{type:`button`,$variant:`primary`,disabled:r.isPending,onClick:()=>{let e=Y(_);if(`problem`in e){T(!0),P(e.problem);return}P(null),r.mutate({label:i.trim().length===0?`api key`:i.trim(),modelAllowlist:u?null:p,limits:e.limits,bodyLoggingOptOut:E},{onSuccess:e=>j(e),onError:e=>P(N(e))})},children:r.isPending?`Creating…`:`Create key`})]}):(0,X.jsx)(d,{type:`button`,$variant:`primary`,onClick:()=>I(!1),children:`I have copied the key`}),children:k===null?(0,X.jsxs)(h,{$gap:3,children:[(0,X.jsx)(A,{label:`Label`,hint:`Names the client this key belongs to, e.g. laptop or CI.`,children:e=>(0,X.jsx)(O,{...e,value:i,placeholder:`api key`,onChange:e=>s(e.target.value)})}),(0,X.jsxs)(h,{$gap:2,children:[(0,X.jsxs)(o,{$gap:2,children:[(0,X.jsx)(w,{checked:u,label:`Allow every model`,onCheckedChange:f}),(0,X.jsx)(l,{as:`span`,children:`Allow every model`})]}),u?null:(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(ue,{children:(n.data??[]).map(e=>(0,X.jsxs)(de,{children:[(0,X.jsx)(`input`,{type:`checkbox`,checked:p.includes(e.id),onChange:t=>g(n=>t.target.checked?[...n,e.id]:n.filter(t=>t!==e.id))}),e.id]},e.id))}),p.length===0?(0,X.jsx)(fe,{children:`With no model selected this key is allowed nothing and every request it makes will be refused.`}):null]})]}),(0,X.jsxs)(h,{$gap:2,children:[(0,X.jsxs)(o,{$gap:2,children:[(0,X.jsxs)(he,{type:`button`,$size:`sm`,"aria-expanded":S,onClick:()=>T(e=>!e),children:[S?(0,X.jsx)(b,{}):(0,X.jsx)(y,{}),`Limits`]}),(0,X.jsx)(l,{as:`span`,children:L===0?`no limits; this key is unbounded`:`${L} limit${L===1?``:`s`} set`})]}),S?(0,X.jsx)(Q,{draft:_,onChange:v}):null]}),(0,X.jsxs)(h,{$gap:2,children:[(0,X.jsxs)(o,{$gap:2,children:[(0,X.jsx)(w,{checked:E,label:`Never record this key's bodies`,onCheckedChange:D}),(0,X.jsx)(l,{as:`span`,children:`Never record this key's bodies`})]}),(0,X.jsx)(ge,{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.`})]}),M===null?null:(0,X.jsx)(pe,{role:`alert`,children:M})]}):(0,X.jsxs)(h,{$gap:3,children:[(0,X.jsx)(me,{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,X.jsx)(x,{value:k.key,label:`Copy API key`}),(0,X.jsxs)(o,{$gap:2,children:[(0,X.jsx)(l,{children:`Label`}),(0,X.jsx)(c,{children:k.label}),(0,X.jsx)(l,{children:`Prefix`}),(0,X.jsx)(c,{children:k.prefix})]})]})})}var _e=g(o)`
63
+ gap: 4px;
64
+ flex-wrap: wrap;
65
+ max-width: 34ch;
66
+ `,ve=g.span`
67
+ color: ${({theme:e})=>e.color.inkFaint};
68
+ `,ye=g.span`
69
+ font-size: 11px;
70
+ color: ${({theme:e})=>e.color.inkDim};
71
+ `,be=g.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=q(e);return`${G({dimension:e.dimension,window:e.window})} ${K(e.dimension,e.limit)}, ${t===null?`—`:Math.round(t*100)}% used`}function Se(){let t=n(),r=i(),[a,s]=(0,V.useState)(!1),[c,u]=(0,V.useState)(null),[m,h]=(0,V.useState)(null),[g,x]=(0,V.useState)(null),C=t.data??[],w=C.filter(e=>e.revokedAt===null),O=t.isLoading?`Reading issued keys…`:C.length===0?`No keys exist, so nothing can call this gateway yet.`:`${w.length} active key${w.length===1?``:`s`} of ${C.length} ever issued.`;return(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(v,{legend:`Keys`,title:`Gateway API keys`,summary:O,actions:(0,X.jsxs)(d,{type:`button`,$variant:`primary`,onClick:()=>s(!0),children:[(0,X.jsx)(S,{}),`Create a key`]})}),(0,X.jsx)(M,{legend:`Issued keys`,meta:`${C.length}`,flush:!0,children:t.isError?(0,X.jsx)(P,{error:t.error,onRetry:()=>void t.refetch()}):t.isLoading?(0,X.jsx)(`div`,{style:{padding:12},children:(0,X.jsx)(F,{rows:4})}):C.length===0?(0,X.jsx)(I,{legend:`No keys`,message:`Create a key and give it to a client. The key is shown once, at creation.`,action:(0,X.jsx)(d,{type:`button`,$variant:`primary`,$size:`sm`,onClick:()=>s(!0),children:`Create a key`})}):(0,X.jsx)(e,{children:(0,X.jsxs)(B,{children:[(0,X.jsx)(`thead`,{children:(0,X.jsxs)(`tr`,{children:[(0,X.jsx)(z,{children:`Label`}),(0,X.jsx)(z,{children:`Prefix`}),(0,X.jsx)(z,{children:`Allowed models`}),(0,X.jsx)(z,{$align:`right`,children:`Limits`}),(0,X.jsx)(z,{$align:`right`,children:`Created`}),(0,X.jsx)(z,{children:`Body capture`}),(0,X.jsx)(z,{children:`Status`}),(0,X.jsx)(z,{})]})}),(0,X.jsx)(`tbody`,{children:C.map(e=>{let t=m===e.id,n=te(e.limitUsage);return(0,X.jsxs)(V.Fragment,{children:[(0,X.jsxs)(L,{children:[(0,X.jsx)(R,{children:(0,X.jsx)(f,{style:{maxWidth:`24ch`,display:`block`},children:e.label})}),(0,X.jsxs)(R,{$mono:!0,children:[e.prefix,`…`]}),(0,X.jsx)(R,{children:e.modelAllowlist===null?(0,X.jsx)(l,{children:`every model`}):e.modelAllowlist.length===0?(0,X.jsx)(D,{$tone:`down`,children:`no models`}):(0,X.jsx)(_e,{children:e.modelAllowlist.map(e=>(0,X.jsx)(D,{children:e},e))})}),(0,X.jsx)(R,{$align:`right`,children:e.limits===null?(0,X.jsx)(D,{$tone:`down`,children:`unreadable`}):e.limitUsage.length===0?(0,X.jsx)(l,{children:`no limits`}):(0,X.jsxs)(be,{children:[(0,X.jsxs)(`span`,{children:[e.limitUsage.length,` limit`,e.limitUsage.length===1?``:`s`]}),(0,X.jsx)(ye,{children:xe(n)})]})}),(0,X.jsx)(R,{$align:`right`,$mono:!0,children:E(e.createdAt)}),(0,X.jsx)(R,{children:e.bodyLoggingOptOut?(0,X.jsx)(D,{children:`no bodies`}):(0,X.jsx)(l,{children:`—`})}),(0,X.jsx)(R,{children:e.revokedAt===null?(0,X.jsx)(D,{$tone:`ok`,children:`active`}):(0,X.jsx)(ve,{title:E(e.revokedAt),children:(0,X.jsx)(D,{children:`revoked`})})}),(0,X.jsx)(R,{$align:`right`,children:(0,X.jsxs)(o,{$gap:1,$justify:`flex-end`,children:[e.limitUsage.length===0?null:(0,X.jsx)(p,{type:`button`,$variant:`ghost`,$size:`sm`,"aria-expanded":t,"aria-label":`${t?`Hide`:`Show`} limits for ${e.label}`,title:`${t?`Hide`:`Show`} limits for ${e.label}`,onClick:()=>h(t?null:e.id),children:t?(0,X.jsx)(b,{}):(0,X.jsx)(y,{})}),e.revokedAt===null?(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(p,{type:`button`,$variant:`ghost`,$size:`sm`,"aria-label":`Edit limits for ${e.label}`,title:`Edit limits for ${e.label}`,onClick:()=>u(e),children:(0,X.jsx)(_,{})}),(0,X.jsx)(d,{type:`button`,$variant:`danger`,$size:`sm`,onClick:()=>x(e),children:`Revoke`})]}):null]})})]}),t?(0,X.jsx)(L,{children:(0,X.jsx)(R,{colSpan:8,children:(0,X.jsx)(le,{label:e.label,readings:e.limitUsage})})}):null]},e.id)})})]})})}),(0,X.jsx)($,{open:a,onOpenChange:s}),(0,X.jsx)(ae,{apiKey:c,onOpenChange:e=>{e||u(null)}},c?.id??`none`),(0,X.jsx)(T,{open:g!==null,onOpenChange:e=>{e||x(null)},title:`Revoke key`,body:g===null?``:`Revoking "${g.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:r.isPending,onConfirm:()=>{g!==null&&r.mutate(g.id,{onSettled:()=>x(null)})}})]})}var Ce=Se;export{Ce as component};
@@ -0,0 +1,68 @@
1
+ import{$ as e,$t as t,A as n,C as r,D as ee,Q as i,Qt as a,X as te,Y as o,_n as s,at as ne,g as c,n as l,nt as u,s as re,tt as d,ut as f}from"./queries-BJHk_wso.js";import{a as ie,t as p}from"./Rack-D1zBw9SW.js";import{n as m,r as h,t as g}from"./TokenBreakdown-CyHJv0O5.js";import{t as ae}from"./Modal-DfltaSCz.js";import{C as _,O as v,S as y,T as b,c as x,d as S,f as C,k as w,l as T,t as E,w as D,x as O}from"./Lamp-QRSv-SqM.js";import{n as k,t as A}from"./Chip-DbKk1ExR.js";import{i as j,n as M}from"./Field-B7GOsJf8.js";import{a as N,n as P,r as F,t as oe}from"./States-CQFkw1UZ.js";import{i as se,n as I,r as L,t as R}from"./Table-Ba58Wg4-.js";var z=s(t(),1),B=a(),V={none:{legend:`Not captured`,message:`Body capture was not running for this request. It needs OMNI_BODY_LOGGING_ALLOWED in the environment and the body logging setting turned on, and the calling key must not have opted out.`},missing:{legend:`Captured, then lost`,message:`This request was captured, but its artifact is no longer on disk. Retention or the row cap has since pruned it, or something removed the file underneath the gateway.`},corrupt:{legend:`Captured, but unreadable`,message:`This request was captured and the artifact is still on disk, but it failed its checksum or would not decrypt. Changing OMNI_ENCRYPTION_KEY invalidates every artifact written under the old one.`}},H=new Intl.NumberFormat(`en-US`),U=f.p`
2
+ font-size: 12px;
3
+ color: ${({theme:e})=>e.color.inkDim};
4
+ max-width: 62ch;
5
+ `,W=f(U)`
6
+ border-left: 2px solid ${({theme:e})=>e.color.ruleStrong};
7
+ padding-left: ${({theme:e})=>e.space(2)};
8
+ `,G=f.h4`
9
+ font-size: 11px;
10
+ font-weight: 600;
11
+ letter-spacing: 0.12em;
12
+ text-transform: uppercase;
13
+ color: ${({theme:e})=>e.color.inkDim};
14
+ margin: 0;
15
+ `,K=f.figcaption`
16
+ display: flex;
17
+ align-items: center;
18
+ gap: ${({theme:e})=>e.space(2)};
19
+ flex-wrap: wrap;
20
+ margin-bottom: 4px;
21
+ `,q=f.figure`
22
+ margin: 0;
23
+ min-width: 0;
24
+ `,J=f.pre`
25
+ margin: 0;
26
+ padding: ${({theme:e})=>e.space(2)};
27
+ max-height: 260px;
28
+ overflow: auto;
29
+ border: 1px solid ${({theme:e})=>e.color.rule};
30
+ border-radius: ${({theme:e})=>e.radius.control};
31
+ background: ${({theme:e})=>e.color.panelSunk};
32
+ font-family: ${({theme:e})=>e.font.mono};
33
+ font-size: 11.5px;
34
+ line-height: 1.5;
35
+ white-space: pre-wrap;
36
+ word-break: break-word;
37
+ `;function Y(e){if(typeof e!=`object`||!e||Array.isArray(e))return null;let t=e;if(t.omitted!==!0||typeof t.reason!=`string`)return null;let n=t.serializedBytes;return{omitted:!0,reason:t.reason,serializedBytes:typeof n==`number`?n:0}}function X({title:e,stage:t,value:n}){let r=Y(n);return(0,B.jsxs)(q,{children:[(0,B.jsxs)(K,{children:[(0,B.jsx)(G,{children:e}),t===void 0?null:(0,B.jsx)(A,{children:t})]}),r===null?n==null?(0,B.jsx)(U,{children:`Nothing was recorded for this half — it never happened, or never completed.`}):(0,B.jsx)(J,{children:JSON.stringify(n,null,2)}):(0,B.jsxs)(U,{children:[`Too large to keep: `,r.reason,`. The payload was`,` `,H.format(r.serializedBytes),` bytes after structural bounding, so it was replaced by this marker rather than written oversized or dropped without a trace.`]})]})}function ce({attempt:e}){return(0,B.jsxs)(d,{$gap:2,children:[(0,B.jsxs)(i,{$gap:2,$wrap:!0,children:[(0,B.jsxs)(o,{as:`h3`,children:[`Attempt `,e.attempt,` · `,e.provider]}),e.truncated?(0,B.jsx)(A,{$tone:`warn`,children:`truncated`}):null]}),(0,B.jsx)(X,{title:`Request sent to the provider`,stage:`post-RTK`,value:e.request}),(0,B.jsx)(X,{title:`Response from the provider`,value:e.response}),e.streamChunks===null?null:(0,B.jsx)(X,{title:`Raw stream frames (${y(e.streamChunks.length)})`,value:e.streamChunks})]})}function le({body:e}){let t=e.artifact;if(t===null){let t=V[e.detailState===`ready`?`corrupt`:e.detailState];return(0,B.jsxs)(d,{$gap:1,children:[(0,B.jsx)(o,{children:t.legend}),(0,B.jsx)(U,{children:t.message})]})}return(0,B.jsxs)(d,{$gap:3,children:[t.attempts.length===0?null:(0,B.jsx)(W,{children:`The client request below is what arrived at the gateway. Each attempt request is what went upstream after RTK filters ran, so the two are not the same payload — compare them to see what compression actually removed.`}),(0,B.jsxs)(d,{$gap:2,children:[(0,B.jsxs)(i,{$gap:2,$wrap:!0,children:[(0,B.jsx)(o,{as:`h3`,children:`Client`}),t.client.truncated?(0,B.jsx)(A,{$tone:`warn`,children:`truncated`}):null]}),(0,B.jsx)(X,{title:`Request from the client`,stage:`pre-RTK`,value:t.client.request}),(0,B.jsx)(X,{title:`Response returned to the client`,value:t.client.response})]}),t.attempts.map(e=>(0,B.jsx)(ce,{attempt:e},`${e.attempt}-${e.provider}`)),t.error===null||t.error===void 0?null:(0,B.jsx)(X,{title:`Error`,value:t.error})]})}function ue({requestId:e}){let t=n(e),r=t.data===void 0||t.data.detailState!==`ready`?void 0:`${H.format(t.data.sizeBytes)} bytes on disk`;return(0,B.jsx)(N,{legend:`Captured bodies`,...r===void 0?{}:{meta:r},...t.data?.truncated===!0?{actions:(0,B.jsx)(A,{$tone:`warn`,children:`truncated`})}:{},children:t.isError?(0,B.jsx)(P,{error:t.error,onRetry:()=>void t.refetch()}):t.isPending?(0,B.jsx)(F,{rows:3}):(0,B.jsx)(le,{body:t.data})})}var de=[50,100,250,500],fe=f(i)`
38
+ gap: ${({theme:e})=>e.space(2)};
39
+ flex-wrap: wrap;
40
+ `,pe=f(M)`
41
+ width: 220px;
42
+ `,Z=f(j)`
43
+ width: auto;
44
+ `,me=f(N)`
45
+ flex: 1;
46
+ min-height: 0;
47
+
48
+ > div {
49
+ display: flex;
50
+ flex: 1;
51
+ flex-direction: column;
52
+ min-height: 0;
53
+ }
54
+ `,Q=f(e)`
55
+ flex: 1;
56
+ min-height: 0;
57
+ overflow-y: auto;
58
+ `;function he(e){let[t,n]=(0,z.useState)(Date.now);return(0,z.useEffect)(()=>{if(!e)return;n(Date.now());let t=window.setInterval(()=>n(Date.now()),1e3);return()=>window.clearInterval(t)},[e]),t}function ge({log:e}){return(0,B.jsx)(I,{$align:`right`,$mono:!0,...T(e)?{"aria-label":`processing`}:{title:h(e)},children:T(e)?(0,B.jsx)(g,{}):(0,B.jsx)(m,{tokens:e})})}var _e=f.dl`
59
+ display: grid;
60
+ grid-template-columns: minmax(120px, auto) minmax(0, 1fr);
61
+ gap: 6px ${({theme:e})=>e.space(3)};
62
+ margin: 0;
63
+ font-size: 12.5px;
64
+ `,$=f.dd`
65
+ margin: 0;
66
+ font-family: ${({theme:e})=>e.font.mono};
67
+ word-break: break-all;
68
+ `;function ve(){let{cadence:e,live:t}=ie(),[n,a]=(0,z.useState)(100),[s,f]=(0,z.useState)(`all`),[m,h]=(0,z.useState)(``),[g,j]=(0,z.useState)(null),M=ee(n,e(l)),N=c(),V=r(),H=re(),U=(M.data??[]).some(T),W=he(t&&U),G=(0,z.useMemo)(()=>{let e=new Map;for(let t of N.data??[])e.set(t.id,t.label);return e},[N.data]),K=(0,z.useMemo)(()=>{let e=new Map;for(let t of V.data??[])e.set(t.id,t.label);return e},[V.data]),q=m.trim().toLowerCase(),J=(M.data??[]).filter(e=>s===`failed`&&!x(e)?!1:q.length===0||e.requestedModel.toLowerCase().includes(q)||(e.resolvedModel??``).toLowerCase().includes(q)||(e.errorCode??``).toLowerCase().includes(q)||(e.credentialId===null?``:G.get(e.credentialId)??``).toLowerCase().includes(q)||(e.apiKeyId===null?``:K.get(e.apiKeyId)??e.apiKeyId).toLowerCase().includes(q)),Y=(M.data??[]).filter(x).length,X=(M.data??[]).filter(T).length;return(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(p,{legend:`Logs`,title:`Recent requests`,summary:M.isLoading?`Reading the request log…`:`${y(M.data?.length??0)} recent requests, ${y(Y)} of them failed${X===0?``:`, ${y(X)} still running`}. ${H.data===!0?`Body capture is on: open a request to read what it sent and received.`:`Prompt and response bodies are not being recorded.`}`,actions:(0,B.jsxs)(fe,{children:[(0,B.jsx)(pe,{value:m,placeholder:`Filter by model, account, key, or error`,"aria-label":`Filter requests`,onChange:e=>h(e.target.value)}),(0,B.jsxs)(Z,{value:s,"aria-label":`Show which requests`,onChange:e=>f(e.target.value),children:[(0,B.jsx)(`option`,{value:`all`,children:`All requests`}),(0,B.jsx)(`option`,{value:`failed`,children:`Failed only`})]}),(0,B.jsx)(Z,{value:n,"aria-label":`How many requests to fetch`,onChange:e=>a(Number(e.target.value)),children:de.map(e=>(0,B.jsxs)(`option`,{value:e,children:[`last `,e]},e))})]})}),(0,B.jsx)(me,{legend:`Request log`,meta:`${J.length} shown`,flush:!0,children:M.isError?(0,B.jsx)(P,{error:M.error,onRetry:()=>void M.refetch()}):M.isLoading?(0,B.jsx)(`div`,{style:{padding:12},children:(0,B.jsx)(F,{rows:8})}):J.length===0?(0,B.jsx)(oe,{legend:`Nothing to show`,message:(M.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,B.jsx)(Q,{"data-testid":`request-log-scroller`,children:(0,B.jsxs)(R,{children:[(0,B.jsx)(`thead`,{children:(0,B.jsxs)(`tr`,{children:[(0,B.jsx)(L,{}),(0,B.jsx)(L,{$align:`right`,children:`Time`}),(0,B.jsx)(L,{children:`Requested`}),(0,B.jsx)(L,{children:`Routed to`}),(0,B.jsx)(L,{children:`Account`}),(0,B.jsx)(L,{children:`Key`}),(0,B.jsx)(L,{$align:`right`,children:`Try`}),(0,B.jsx)(L,{$align:`right`,children:`TTFT`}),(0,B.jsx)(L,{$align:`right`,children:`Total`}),(0,B.jsx)(L,{$align:`right`,children:`Tokens`}),(0,B.jsx)(L,{$align:`right`,children:`Cost`}),(0,B.jsx)(L,{children:`Outcome`})]})}),(0,B.jsx)(`tbody`,{children:J.map(e=>(0,B.jsxs)(se,{$selectable:!0,onClick:()=>j(e),children:[(0,B.jsx)(I,{children:(0,B.jsx)(E,{state:C(e),label:S(e)})}),(0,B.jsx)(I,{$align:`right`,$mono:!0,title:_(e.at),children:O(e.at)}),(0,B.jsx)(I,{$mono:!0,children:(0,B.jsx)(u,{style:{display:`block`,maxWidth:`20ch`},children:e.requestedModel||`—`})}),(0,B.jsx)(I,{children:e.resolvedProvider===null?(0,B.jsx)(o,{children:T(e)?`routing…`:`not routed`}):(0,B.jsxs)(i,{$gap:1,children:[(0,B.jsx)(k,{provider:e.resolvedProvider}),(0,B.jsx)(te,{$dim:!0,children:e.resolvedModel??`—`})]})}),(0,B.jsx)(I,{children:(0,B.jsx)(u,{style:{display:`block`,maxWidth:`18ch`},children:e.credentialId===null?`—`:G.get(e.credentialId)??w(e.credentialId)})}),(0,B.jsx)(I,{children:(0,B.jsx)(u,{style:{display:`block`,maxWidth:`16ch`},title:e.apiKeyId??void 0,children:e.apiKeyId===null?`—`:K.get(e.apiKeyId)??w(e.apiKeyId)})}),(0,B.jsx)(I,{$align:`right`,$mono:!0,children:T(e)?`—`:e.attempts}),(0,B.jsx)(I,{$align:`right`,$mono:!0,children:T(e)?`—`:b(e.ttftMs)}),(0,B.jsx)(I,{$align:`right`,$mono:!0,children:T(e)?D(Math.max(0,W-e.at)):b(e.durationMs)}),(0,B.jsx)(ge,{log:e}),(0,B.jsx)(I,{$align:`right`,$mono:!0,children:T(e)?`—`:v(e.costUsd)}),(0,B.jsx)(I,{children:T(e)?(0,B.jsx)(A,{$tone:`accent`,children:`live`}):e.errorCode===null?(0,B.jsx)(A,{$tone:`ok`,children:e.status}):(0,B.jsx)(A,{$tone:`down`,children:e.errorCode})})]},e.id))})]})})}),(0,B.jsx)(ae,{open:g!==null,onOpenChange:e=>{e||j(null)},title:`Request detail`,width:`760px`,footer:(0,B.jsx)(ne,{type:`button`,onClick:()=>j(null),children:`Close`}),children:g===null?null:(0,B.jsxs)(d,{$gap:3,children:[(0,B.jsxs)(_e,{children:[(0,B.jsx)(o,{as:`dt`,children:`Request id`}),(0,B.jsx)($,{children:g.id}),(0,B.jsx)(o,{as:`dt`,children:`At`}),(0,B.jsx)($,{children:_(g.at)}),(0,B.jsx)(o,{as:`dt`,children:`Requested model`}),(0,B.jsx)($,{children:g.requestedModel||`—`}),(0,B.jsx)(o,{as:`dt`,children:`Routed to`}),(0,B.jsx)($,{children:T(g)?`—`:g.resolvedProvider===null?`not routed`:`${g.resolvedProvider} · ${g.resolvedModel??`—`}`}),(0,B.jsx)(o,{as:`dt`,children:`Account`}),(0,B.jsx)($,{children:g.credentialId===null?`—`:G.get(g.credentialId)??g.credentialId}),(0,B.jsx)(o,{as:`dt`,children:`Key`}),(0,B.jsx)($,{children:g.apiKeyId===null?`—`:K.get(g.apiKeyId)??g.apiKeyId}),(0,B.jsx)(o,{as:`dt`,children:`Attempts`}),(0,B.jsx)($,{children:T(g)?`—`:g.attempts}),(0,B.jsx)(o,{as:`dt`,children:`Status`}),(0,B.jsx)($,{children:T(g)?`in flight`:g.errorCode===null?g.status:`${g.status} ${g.errorCode}`}),(0,B.jsx)(o,{as:`dt`,children:`Timing`}),(0,B.jsx)($,{children:T(g)?`—`:`first token ${b(g.ttftMs)} · total ${b(g.durationMs)}`}),(0,B.jsx)(o,{as:`dt`,children:`Tokens`}),(0,B.jsx)($,{children:T(g)?`—`:(0,B.jsxs)(B.Fragment,{children:[y(g.inputTokens),` in · `,y(g.outputTokens),` out ·`,` `,y(g.cacheReadTokens),` cache read ·`,` `,y(g.cacheWriteTokens),` cache write`]})}),(0,B.jsx)(o,{as:`dt`,children:`Cost`}),(0,B.jsx)($,{children:T(g)?`—`:v(g.costUsd)}),(0,B.jsx)(o,{as:`dt`,children:`RTK compression`}),(0,B.jsx)($,{children:T(g)?`—`:g.rtkApplied?`${y(g.rtkFilterHits)} hits · ${y(g.rtkOriginalCodeUnits)} → ${y(g.rtkCompressedCodeUnits)} code units · ~${y(g.rtkEstimatedTokensSaved)} tokens saved`:`not applied`}),(0,B.jsx)(o,{as:`dt`,children:`RTK filters`}),(0,B.jsx)($,{children:g.rtkFilters.length===0?`—`:g.rtkFilters.join(`, `)})]}),g.degradations.length===0?null:(0,B.jsxs)(d,{$gap:1,children:[(0,B.jsx)(o,{children:`Capabilities dropped to fit the target`}),(0,B.jsx)(i,{$gap:1,$wrap:!0,children:g.degradations.map(e=>(0,B.jsx)(A,{$tone:`warn`,children:e},e))})]}),(0,B.jsx)(ue,{requestId:g.id})]})})]})}var ye=ve;export{ye as component};