aigetwey 1.4.1 → 1.4.3
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/CHANGELOG.md +32 -0
- package/README.md +8 -1
- package/dashboard/.next/BUILD_ID +1 -1
- package/dashboard/.next/build-manifest.json +3 -3
- package/dashboard/.next/diagnostics/route-bundle-stats.json +28 -28
- package/dashboard/.next/fallback-build-manifest.json +3 -3
- package/dashboard/.next/server/app/(console)/combos/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/(console)/config/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/(console)/console/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/(console)/endpoint/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/(console)/keys/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/(console)/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/(console)/providers/[id]/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/(console)/providers/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/(console)/quota/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/(console)/tools/[id]/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/(console)/tools/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/(console)/usage/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/_global-error.html +1 -1
- package/dashboard/.next/server/app/_global-error.rsc +1 -1
- package/dashboard/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/_not-found.html +1 -1
- package/dashboard/.next/server/app/_not-found.rsc +2 -2
- package/dashboard/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/dashboard/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/dashboard/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dashboard/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/server/app/combos.html +1 -1
- package/dashboard/.next/server/app/combos.rsc +5 -5
- package/dashboard/.next/server/app/combos.segments/!KGNvbnNvbGUp/combos/__PAGE__.segment.rsc +2 -2
- package/dashboard/.next/server/app/combos.segments/!KGNvbnNvbGUp/combos.segment.rsc +1 -1
- package/dashboard/.next/server/app/combos.segments/!KGNvbnNvbGUp.segment.rsc +3 -3
- package/dashboard/.next/server/app/combos.segments/_full.segment.rsc +5 -5
- package/dashboard/.next/server/app/combos.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/server/app/combos.segments/_index.segment.rsc +2 -2
- package/dashboard/.next/server/app/combos.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/server/app/config.html +1 -1
- package/dashboard/.next/server/app/config.rsc +5 -5
- package/dashboard/.next/server/app/config.segments/!KGNvbnNvbGUp/config/__PAGE__.segment.rsc +2 -2
- package/dashboard/.next/server/app/config.segments/!KGNvbnNvbGUp/config.segment.rsc +1 -1
- package/dashboard/.next/server/app/config.segments/!KGNvbnNvbGUp.segment.rsc +3 -3
- package/dashboard/.next/server/app/config.segments/_full.segment.rsc +5 -5
- package/dashboard/.next/server/app/config.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/server/app/config.segments/_index.segment.rsc +2 -2
- package/dashboard/.next/server/app/config.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/server/app/console.html +1 -1
- package/dashboard/.next/server/app/console.rsc +5 -5
- package/dashboard/.next/server/app/console.segments/!KGNvbnNvbGUp/console/__PAGE__.segment.rsc +2 -2
- package/dashboard/.next/server/app/console.segments/!KGNvbnNvbGUp/console.segment.rsc +1 -1
- package/dashboard/.next/server/app/console.segments/!KGNvbnNvbGUp.segment.rsc +3 -3
- package/dashboard/.next/server/app/console.segments/_full.segment.rsc +5 -5
- package/dashboard/.next/server/app/console.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/server/app/console.segments/_index.segment.rsc +2 -2
- package/dashboard/.next/server/app/console.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/server/app/endpoint.html +1 -1
- package/dashboard/.next/server/app/endpoint.rsc +5 -5
- package/dashboard/.next/server/app/endpoint.segments/!KGNvbnNvbGUp/endpoint/__PAGE__.segment.rsc +2 -2
- package/dashboard/.next/server/app/endpoint.segments/!KGNvbnNvbGUp/endpoint.segment.rsc +1 -1
- package/dashboard/.next/server/app/endpoint.segments/!KGNvbnNvbGUp.segment.rsc +3 -3
- package/dashboard/.next/server/app/endpoint.segments/_full.segment.rsc +5 -5
- package/dashboard/.next/server/app/endpoint.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/server/app/endpoint.segments/_index.segment.rsc +2 -2
- package/dashboard/.next/server/app/endpoint.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/server/app/index.html +1 -1
- package/dashboard/.next/server/app/index.rsc +5 -5
- package/dashboard/.next/server/app/index.segments/!KGNvbnNvbGUp/__PAGE__.segment.rsc +2 -2
- package/dashboard/.next/server/app/index.segments/!KGNvbnNvbGUp.segment.rsc +3 -3
- package/dashboard/.next/server/app/index.segments/_full.segment.rsc +5 -5
- package/dashboard/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/dashboard/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/server/app/keys.html +1 -1
- package/dashboard/.next/server/app/keys.rsc +5 -5
- package/dashboard/.next/server/app/keys.segments/!KGNvbnNvbGUp/keys/__PAGE__.segment.rsc +2 -2
- package/dashboard/.next/server/app/keys.segments/!KGNvbnNvbGUp/keys.segment.rsc +1 -1
- package/dashboard/.next/server/app/keys.segments/!KGNvbnNvbGUp.segment.rsc +3 -3
- package/dashboard/.next/server/app/keys.segments/_full.segment.rsc +5 -5
- package/dashboard/.next/server/app/keys.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/server/app/keys.segments/_index.segment.rsc +2 -2
- package/dashboard/.next/server/app/keys.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/login.html +1 -1
- package/dashboard/.next/server/app/login.rsc +2 -2
- package/dashboard/.next/server/app/login.segments/_full.segment.rsc +2 -2
- package/dashboard/.next/server/app/login.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/server/app/login.segments/_index.segment.rsc +2 -2
- package/dashboard/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/server/app/login.segments/login/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/server/app/login.segments/login.segment.rsc +1 -1
- package/dashboard/.next/server/app/providers.html +1 -1
- package/dashboard/.next/server/app/providers.rsc +5 -5
- package/dashboard/.next/server/app/providers.segments/!KGNvbnNvbGUp/providers/__PAGE__.segment.rsc +2 -2
- package/dashboard/.next/server/app/providers.segments/!KGNvbnNvbGUp/providers.segment.rsc +1 -1
- package/dashboard/.next/server/app/providers.segments/!KGNvbnNvbGUp.segment.rsc +3 -3
- package/dashboard/.next/server/app/providers.segments/_full.segment.rsc +5 -5
- package/dashboard/.next/server/app/providers.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/server/app/providers.segments/_index.segment.rsc +2 -2
- package/dashboard/.next/server/app/providers.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/server/app/quota.html +1 -1
- package/dashboard/.next/server/app/quota.rsc +5 -5
- package/dashboard/.next/server/app/quota.segments/!KGNvbnNvbGUp/quota/__PAGE__.segment.rsc +2 -2
- package/dashboard/.next/server/app/quota.segments/!KGNvbnNvbGUp/quota.segment.rsc +1 -1
- package/dashboard/.next/server/app/quota.segments/!KGNvbnNvbGUp.segment.rsc +3 -3
- package/dashboard/.next/server/app/quota.segments/_full.segment.rsc +5 -5
- package/dashboard/.next/server/app/quota.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/server/app/quota.segments/_index.segment.rsc +2 -2
- package/dashboard/.next/server/app/quota.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/server/app/tools.html +1 -1
- package/dashboard/.next/server/app/tools.rsc +5 -5
- package/dashboard/.next/server/app/tools.segments/!KGNvbnNvbGUp/tools/__PAGE__.segment.rsc +2 -2
- package/dashboard/.next/server/app/tools.segments/!KGNvbnNvbGUp/tools.segment.rsc +1 -1
- package/dashboard/.next/server/app/tools.segments/!KGNvbnNvbGUp.segment.rsc +3 -3
- package/dashboard/.next/server/app/tools.segments/_full.segment.rsc +5 -5
- package/dashboard/.next/server/app/tools.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/server/app/tools.segments/_index.segment.rsc +2 -2
- package/dashboard/.next/server/app/tools.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/server/chunks/[root-of-the-server]__07euc03._.js.map +1 -1
- package/dashboard/.next/server/chunks/[root-of-the-server]__0uqpr_c._.js.map +1 -1
- package/dashboard/.next/server/chunks/ssr/[root-of-the-server]__0zf4yft._.js +1 -1
- package/dashboard/.next/server/chunks/ssr/[root-of-the-server]__0zf4yft._.js.map +1 -1
- package/dashboard/.next/server/chunks/ssr/_0p90gyy._.js +1 -1
- package/dashboard/.next/server/chunks/ssr/_0p90gyy._.js.map +1 -1
- package/dashboard/.next/server/chunks/ssr/_1mumvwn._.js.map +1 -1
- package/dashboard/.next/server/chunks/ssr/src_components_10h9ide._.js +1 -1
- package/dashboard/.next/server/chunks/ssr/src_components_10h9ide._.js.map +1 -1
- package/dashboard/.next/server/chunks/ssr/src_components_ProviderDetail_tsx_06sxu0r._.js +1 -1
- package/dashboard/.next/server/chunks/ssr/src_components_ProviderDetail_tsx_06sxu0r._.js.map +1 -1
- package/dashboard/.next/server/chunks/ssr/src_components_ProviderManager_tsx_09d2dzw._.js +1 -1
- package/dashboard/.next/server/chunks/ssr/src_components_ProviderManager_tsx_09d2dzw._.js.map +1 -1
- package/dashboard/.next/server/middleware-build-manifest.js +3 -3
- package/dashboard/.next/server/pages/404.html +1 -1
- package/dashboard/.next/server/pages/500.html +1 -1
- package/dashboard/.next/static/chunks/{0pf-u__m67vld.js → 03xhjt1ta90pp.js} +1 -1
- package/dashboard/.next/static/chunks/{40pm83c1_d0jz.js → 0lcp6ibeqkbpk.js} +19 -19
- package/dashboard/.next/static/chunks/{0-qqj0_fg6ef0.js → 0wb0jg5y8b49o.js} +1 -1
- package/dashboard/.next/static/chunks/{3y0b8yet0vgwr.js → 15d148buj9byd.js} +1 -1
- package/dashboard/.next/static/chunks/2ltht8xwlssac.js +1 -0
- package/dashboard/.next/static/chunks/2mpe3tpzx0wtj.css +3 -0
- package/dashboard/.next/trace +1 -1
- package/dashboard/.next/trace-build +1 -1
- package/dashboard/src/components/AreaChart.tsx +88 -19
- package/dashboard/src/components/AutostartToggle.tsx +63 -0
- package/dashboard/src/components/ConfigEditor.tsx +3 -0
- package/dashboard/src/components/ProviderDetail.tsx +10 -5
- package/dashboard/src/components/ProviderManager.tsx +7 -3
- package/dashboard/src/components/TopBar.tsx +1 -1
- package/dashboard/src/lib/client.ts +1 -0
- package/dashboard/src/lib/gateway.ts +2 -1
- package/dist/cli/tray/autostart.js +3 -3
- package/dist/cli/tray/autostart.js.map +1 -1
- package/dist/cli.js +5 -3
- package/dist/cli.js.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/core/handler.js +23 -3
- package/dist/core/handler.js.map +1 -1
- package/dist/headroom/process.js +22 -6
- package/dist/headroom/process.js.map +1 -1
- package/dist/routes/admin.js +29 -0
- package/dist/routes/admin.js.map +1 -1
- package/dist/routes/v1.js +4 -2
- package/dist/routes/v1.js.map +1 -1
- package/dist/server.js +32 -5
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/tray/autostart.ts +3 -3
- package/src/cli.ts +5 -3
- package/src/config.ts +2 -0
- package/src/core/handler.ts +22 -3
- package/src/headroom/process.ts +19 -5
- package/src/routes/admin.ts +29 -0
- package/src/routes/v1.ts +4 -2
- package/src/server.ts +33 -5
- package/dashboard/.next/static/chunks/0347y27liw05t.js +0 -1
- package/dashboard/.next/static/chunks/0iv69e64f1ywa.css +0 -3
- /package/dashboard/.next/static/{DzOHVl0QeJ1RnKMho8Q0_ → 3ctBU8K8tClTVQCiGy65u}/_buildManifest.js +0 -0
- /package/dashboard/.next/static/{DzOHVl0QeJ1RnKMho8Q0_ → 3ctBU8K8tClTVQCiGy65u}/_clientMiddlewareManifest.js +0 -0
- /package/dashboard/.next/static/{DzOHVl0QeJ1RnKMho8Q0_ → 3ctBU8K8tClTVQCiGy65u}/_ssgManifest.js +0 -0
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
module.exports=[42532,a=>{"use strict";var b=a.i(87924),c=a.i(72131);let d=[{key:"tokens",label:"Tokens"},{key:"cost",label:"Cost"},{key:"requests",label:"Requests"}];function e(a,b){return"cost"===b?a<.01?`$${a.toFixed(4)}`:`$${a.toFixed(2)}`:a>=1e6?`${(a/1e6).toFixed(1)}M`:a>=1e3?`${(a/1e3).toFixed(1)}K`:String(Math.round(a))}function f(a){return new Date(a).toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit",hour12:!1})}function g({series:a}){let[h,i]=(0,c.useState)("tokens"),j=a.map(a=>"tokens"===h?a.tokens_in+a.tokens_out:"cost"===h?a.cost:a.requests),k=Math.max(1,...j),l=a.length,m=a=>l<=1?8:8+a/(l-1)*984,n=a=>224-a/k*208,o=j.map((a,b)=>`${0===b?"M":"L"}${m(b).toFixed(1)},${n(a).toFixed(1)}`).join(" "),p=`${o} L${m(l-1).toFixed(1)},224 L${m(0).toFixed(1)},224 Z`,q=j.length?j.indexOf(Math.max(...j)):-1,r=j.reduce((a,b)=>a+b,0);return(0,b.jsxs)("div",{className:"overflow-hidden rounded-brand-lg border border-border bg-surface shadow-soft",children:[(0,b.jsxs)("header",{className:"flex items-center justify-between gap-3 border-b border-border-subtle px-4 py-3",children:[(0,b.jsxs)("div",{className:"flex items-center gap-2.5",children:[(0,b.jsx)("span",{className:"text-[13px] font-semibold text-text",children:"Over time"}),(0,b.jsxs)("span",{className:"tnum text-[12px] text-text-muted",children:[e(r,h)," total"]})]}),(0,b.jsx)("div",{className:"flex items-center gap-1",children:d.map(a=>(0,b.jsx)("button",{onClick:()=>i(a.key),className:`rounded-full px-3 py-1 text-[12px] font-medium transition-colors ${h===a.key?"bg-surface-2 text-text":"text-text-muted hover:text-text"}`,children:a.label},a.key))})]}),(0,b.jsx)("div",{className:"px-2 py-3",children:0===l||0===r?(0,b.jsx)("div",{className:"flex h-[200px] items-center justify-center text-[13px] text-text-muted",children:"No activity in this range."}):(0,b.jsxs)("svg",{viewBox:"0 0 1000 240",className:"h-[200px] w-full",preserveAspectRatio:"none",children:[(0,b.jsx)("defs",{children:(0,b.jsxs)("linearGradient",{id:"areaFill",x1:"0",y1:"0",x2:"0",y2:"1",children:[(0,b.jsx)("stop",{offset:"0%",stopColor:"var(--color-accent)",stopOpacity:"0.28"}),(0,b.jsx)("stop",{offset:"100%",stopColor:"var(--color-accent)",stopOpacity:"0"})]})}),(0,b.jsx)("path",{d:p,fill:"url(#areaFill)"}),(0,b.jsx)("path",{d:o,fill:"none",stroke:"var(--color-accent)",strokeWidth:"2",vectorEffect:"non-scaling-stroke"}),q>=0&&(0,b.jsx)("circle",{cx:m(q),cy:n(j[q]),r:"3",fill:"var(--color-accent)",vectorEffect:"non-scaling-stroke"})]})}),l>0&&r>0&&q>=0&&(0,b.jsxs)("div",{className:"flex justify-between border-t border-border-subtle px-4 py-2 tnum text-[10px] text-text-subtle",children:[(0,b.jsx)("span",{children:f(a[0].ts)}),(0,b.jsxs)("span",{children:["peak ",e(j[q],h)," @ ",f(a[q].ts)]}),(0,b.jsx)("span",{children:f(a[l-1].ts)})]})]})}var h=a.i(58918),i=a.i(85732);let j=[{label:"Today",key:"today",bucketMs:36e5},{label:"24h",key:"24h",bucketMs:36e5},{label:"7D",key:"7d",bucketMs:216e5},{label:"30D",key:"30d",bucketMs:864e5},{label:"60D",key:"60d",bucketMs:1728e5}];function k({rows:a,loading:c}){return(0,b.jsx)("div",{className:`table-wrap ${c?"opacity-50":""}`,children:(0,b.jsxs)("table",{className:"w-full border-collapse",children:[(0,b.jsx)("thead",{children:(0,b.jsx)("tr",{className:"text-text-subtle",children:["","Reqs","In","Out","Cost"].map((a,c)=>(0,b.jsx)("th",{className:`pb-2 text-[10px] font-medium uppercase tracking-wider ${0===c?"text-left":"text-right"}`,children:a},a+c))})}),(0,b.jsx)("tbody",{children:a.map(a=>(0,b.jsxs)("tr",{className:"border-t border-border-subtle",children:[(0,b.jsx)("td",{className:"py-2 text-[12.5px] text-text",children:a.label}),(0,b.jsx)("td",{className:"py-2 text-right tnum text-[12.5px] text-text-muted",children:h.fmt.int(a.requests)}),(0,b.jsx)("td",{className:"py-2 text-right tnum text-[12.5px] text-text-muted",children:h.fmt.compact(a.tokens_in)}),(0,b.jsx)("td",{className:"py-2 text-right tnum text-[12.5px] text-text-muted",children:h.fmt.compact(a.tokens_out)}),(0,b.jsx)("td",{className:"py-2 text-right tnum text-[12.5px] text-text",children:h.fmt.cost(a.cost)})]},a.label))})]})})}a.s(["UsageView",0,function(){let[a,d]=(0,c.useState)(j[0]),[e,f]=(0,c.useState)(null),[l,m]=(0,c.useState)([]),[n,o]=(0,c.useState)(""),[p,q]=(0,c.useState)(!0),r=(0,c.useCallback)(async a=>{q(!0),o("");let b=function(a){let b=Date.now();switch(a){case"today":{let a=new Date;return a.setHours(0,0,0,0),a.getTime()}case"24h":return b-864e5;case"7d":return b-6048e5;case"30d":return b-2592e6;case"60d":return b-5184e6}}(a.key),[c,d]=await Promise.all([fetch(`/api/gw/admin/usage?since=${b}`),fetch(`/api/gw/admin/usage/series?since=${b}&bucket=${a.bucketMs}`)]);if(!c.ok){o("could not load usage"),q(!1);return}f(await c.json()),m((d.ok?await d.json():{series:[]}).series),q(!1)},[]);(0,c.useEffect)(()=>{r(a)},[a,r]);let s=e?.total;return(0,b.jsxs)("div",{children:[(0,b.jsxs)("div",{className:"mb-6 flex items-center justify-between gap-3",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("h1",{className:"text-[22px] font-semibold tracking-tight text-text",children:"Usage"}),(0,b.jsx)("p",{className:"mt-1 text-[13px] text-text-muted",children:"Tokens and cost across providers and models."})]}),(0,b.jsx)("div",{className:"flex items-center gap-1 rounded-full border border-border bg-surface p-1",children:j.map(c=>(0,b.jsx)("button",{onClick:()=>d(c),className:`rounded-full px-3 py-1 text-[12px] font-medium transition-colors ${a.label===c.label?"bg-surface-2 text-text":"text-text-muted hover:text-text"}`,children:c.label},c.label))})]}),n?(0,b.jsx)(h.Empty,{children:n}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("div",{className:"mb-5 grid grid-cols-2 gap-3 sm:grid-cols-4",children:[(0,b.jsx)(h.Stat,{label:"Requests",value:h.fmt.int(s?.requests??0)}),(0,b.jsx)(h.Stat,{label:"Tokens in",value:h.fmt.compact(s?.tokens_in??0)}),(0,b.jsx)(h.Stat,{label:"Tokens out",value:h.fmt.compact(s?.tokens_out??0)}),(0,b.jsx)(h.Stat,{label:"Cost",value:h.fmt.cost(s?.cost??0)})]}),(0,b.jsx)("div",{className:"mb-5",children:(0,b.jsx)(g,{series:l})}),(0,b.jsxs)("div",{className:"grid gap-4 lg:grid-cols-2",children:[(0,b.jsx)(i.RichCard,{header:(0,b.jsx)("span",{className:"text-[13px] font-semibold text-text",children:"By provider"}),children:e?.by_provider.length?(0,b.jsx)(k,{rows:e.by_provider.map(a=>({label:a.provider,...a})),loading:p}):(0,b.jsx)(h.Empty,{children:"No usage in this window."})}),(0,b.jsx)(i.RichCard,{header:(0,b.jsx)("span",{className:"text-[13px] font-semibold text-text",children:"By model"}),children:e?.by_model.length?(0,b.jsx)(k,{rows:e.by_model.map(a=>({label:`${a.alias} → ${a.model}`,...a})),loading:p}):(0,b.jsx)(h.Empty,{children:"No usage in this window."})})]})]})]})}],42532)},61574,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(47153),e=a.i(2693),f=a.i(93026),g=a.i(58918);let h=[{key:"all",label:"All"},{key:"ok",label:"Success"},{key:"error",label:"Errors"}],i=[{label:"1h",ms:36e5},{label:"6h",ms:216e5},{label:"24h",ms:864e5},{label:"7d",ms:6048e5},{label:"All",ms:null}];function j({label:a,children:c}){return(0,b.jsxs)("label",{className:"flex flex-col gap-1",children:[(0,b.jsx)("span",{className:"text-[10px] font-medium uppercase tracking-wider text-text-subtle",children:a}),c]})}function k({children:a,muted:c,right:d,title:e,className:f,suppressHydrationWarning:g}){return(0,b.jsx)("td",{title:e,suppressHydrationWarning:g,className:`whitespace-nowrap px-4 py-2.5 tnum text-[12.5px] ${d?"text-right":"text-left"} ${c?"text-text-muted":"text-text"}${f?` ${f}`:""}`,children:a})}function l({log:a,onClose:c}){let d=a.status>=200&&a.status<300,e=a.tokens_in+a.tokens_out;return(0,b.jsxs)("div",{className:"border-t border-border-subtle bg-surface-2/40 px-5 py-4",children:[(0,b.jsxs)("div",{className:"mb-3 flex items-center justify-between",children:[(0,b.jsx)("span",{className:"text-[12px] font-semibold text-text",children:"Request Details"}),(0,b.jsx)("button",{onClick:c,className:"text-text-subtle hover:text-text",children:(0,b.jsx)(f.Icon,{name:"close",size:16})})]}),(0,b.jsxs)("div",{className:"grid grid-cols-2 gap-x-8 gap-y-2 text-[12px] sm:grid-cols-4",children:[(0,b.jsx)(m,{label:"Status",value:`${a.status} ${d?"OK":"Error"}`}),(0,b.jsx)(m,{label:"Timestamp",value:new Date(a.ts).toLocaleString()}),(0,b.jsx)(m,{label:"Alias",value:a.alias}),(0,b.jsx)(m,{label:"Provider",value:a.provider}),(0,b.jsx)(m,{label:"Model",value:a.model}),(0,b.jsx)(m,{label:"Mode",value:a.stream?"Streaming":"Unary"}),(0,b.jsx)(m,{label:"Latency",value:`${a.latency_ms}ms`}),(0,b.jsx)(m,{label:"Cost",value:g.fmt.cost(a.cost)}),(0,b.jsx)(m,{label:"Input tokens",value:g.fmt.int(a.tokens_in)}),(0,b.jsx)(m,{label:"Output tokens",value:g.fmt.int(a.tokens_out)}),(0,b.jsx)(m,{label:"Cached tokens",value:g.fmt.int(a.cached_tokens)}),(0,b.jsx)(m,{label:"Total tokens",value:g.fmt.int(e)})]})]})}function m({label:a,value:c}){return(0,b.jsxs)("div",{children:[(0,b.jsx)("span",{className:"text-[10px] uppercase tracking-wider text-text-subtle",children:a}),(0,b.jsx)("div",{className:"tnum text-text",children:c})]})}a.s(["LogTable",0,function({logs:a}){let[m,n]=(0,c.useState)(a),[o,p]=(0,c.useState)("all"),[q,r]=(0,c.useState)("all"),[s,t]=(0,c.useState)(null),[u,v]=(0,c.useState)(!0),[w,x]=(0,c.useState)(!1),[y,z]=(0,c.useState)(null),A=(0,c.useRef)(null),B=(0,c.useCallback)(async()=>{try{let a=await fetch("/api/gw/admin/logs?limit=200");if(a.ok){let b=await a.json();n(b.logs)}}catch{}},[]);(0,c.useEffect)(()=>{if(u)return A.current=setInterval(B,5e3),()=>{A.current&&clearInterval(A.current)};A.current&&clearInterval(A.current)},[u,B]);let C=[...new Set(m.map(a=>a.provider))].sort(),D=m.filter(a=>a.status>=200&&a.status<300).length,E=m.length-D,F=null!==s?Date.now()-s:null,G=m.filter(a=>("ok"!==o||!!(a.status>=200&&a.status<300))&&("error"!==o||!(a.status>=200)||!(a.status<300))&&("all"===q||a.provider===q)&&(null===F||!(a.ts<F))),H="all"!==o||"all"!==q||null!==s;return(0,b.jsxs)("div",{className:"overflow-hidden rounded-brand-lg border border-border bg-surface shadow-soft",children:[(0,b.jsxs)("header",{className:"flex flex-col gap-3 border-b border-border-subtle px-4 py-3",children:[(0,b.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,b.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,b.jsx)("button",{onClick:()=>x(a=>!a),className:"flex-none rounded p-0.5 text-text-subtle transition-colors hover:text-text","aria-label":w?"Expand requests":"Collapse requests",title:w?"Expand":"Collapse",children:(0,b.jsx)(f.Icon,{name:w?"chevron_right":"expand_more",size:18})}),(0,b.jsx)("div",{className:"flex items-center gap-1",children:h.map(a=>{let c;return(0,b.jsxs)("button",{onClick:()=>p(a.key),className:`flex items-center gap-1.5 rounded-full px-3 py-1.5 text-[12px] font-medium transition-colors ${o===a.key?"bg-surface-2 text-text":"text-text-muted hover:text-text"}`,children:[a.label,(0,b.jsx)("span",{className:"tnum text-text-subtle",children:"all"===(c=a.key)?m.length:"ok"===c?D:E})]},a.key)})})]}),(0,b.jsxs)("button",{onClick:()=>v(a=>!a),className:`flex items-center gap-1 rounded-full px-2.5 py-1 text-[11px] font-medium transition-colors ${u?"bg-success/15 text-success":"text-text-muted hover:text-text"}`,title:u?"Auto-refresh ON (5s)":"Auto-refresh OFF",children:[(0,b.jsx)(f.Icon,{name:u?"radio_button_checked":"radio_button_unchecked",size:12}),"Live"]})]}),!w&&(0,b.jsxs)("div",{className:"flex flex-wrap items-end gap-2.5",children:[(0,b.jsx)(j,{label:"Provider",children:(0,b.jsxs)("select",{value:q,onChange:a=>r(a.target.value),className:"h-9 rounded-brand border border-border bg-surface-2 px-2.5 text-[12.5px] text-text focus:border-accent focus:outline-none w-40",children:[(0,b.jsx)("option",{value:"all",children:"All providers"}),C.map(a=>(0,b.jsx)("option",{value:a,children:a},a))]})}),(0,b.jsx)(j,{label:"Since",children:(0,b.jsx)("div",{className:"flex h-9 items-center gap-0.5 rounded-brand border border-border bg-surface-2 px-1",children:i.map(a=>{let c;return(0,b.jsx)("button",{type:"button",onClick:()=>t(a.ms),className:(c=s===a.ms,`rounded-full px-2.5 py-1 text-[12px] font-medium transition-colors ${c?"bg-accent/15 text-accent":"text-text-muted hover:text-text"}`),children:a.label},a.label)})})}),(0,b.jsxs)("button",{onClick:()=>{p("all"),r("all"),t(null)},disabled:!H,className:"flex h-9 items-center gap-1.5 rounded-brand border border-border bg-surface-2 px-3 text-[12.5px] font-medium text-text-muted transition-colors hover:border-text-subtle hover:text-text disabled:opacity-40 disabled:hover:border-border disabled:hover:text-text-muted",title:H?"Reset all filters":"No filters applied",children:[(0,b.jsx)(f.Icon,{name:"filter_alt_off",size:15}),"Clear"]})]})]}),w?null:0===G.length?(0,b.jsx)("div",{className:"px-4 py-8 text-center text-[13px] text-text-muted",children:0===m.length?"No requests recorded yet.":"No requests match this filter."}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)("div",{className:"table-wrap",children:(0,b.jsxs)("table",{className:"w-full min-w-[720px] border-collapse",children:[(0,b.jsx)("thead",{children:(0,b.jsx)("tr",{className:"text-text-subtle",children:["Status","Time","Alias","Provider","Model","In","Out","ms","Mode"].map((a,c)=>(0,b.jsx)("th",{className:`whitespace-nowrap px-4 pb-2.5 pt-3 text-[10px] font-medium uppercase tracking-wider ${c>=5&&c<=7?"text-right":"text-left"}`,children:a},a+c))})}),(0,b.jsx)("tbody",{children:G.map((a,c)=>{let f=a.status>=200&&a.status<300,h=y===c;return(0,b.jsxs)("tr",{onClick:()=>z(h?null:c),className:`border-t border-border-subtle cursor-pointer transition-colors ${h?"bg-surface-2/60":"hover:bg-surface-2/70"}`,children:[(0,b.jsx)(k,{children:(0,b.jsxs)(e.Badge,{tone:f?"live":"down",children:[(0,b.jsx)(d.Lamp,{state:f?"live":"down"}),a.status]})}),(0,b.jsxs)(k,{muted:!0,title:g.fmt.time(a.ts),suppressHydrationWarning:!0,children:[g.fmt.ago(a.ts)," ago"]}),(0,b.jsx)(k,{className:"text-text",children:a.alias}),(0,b.jsx)(k,{muted:!0,children:a.provider}),(0,b.jsx)(k,{muted:!0,children:a.model}),(0,b.jsx)(k,{right:!0,children:g.fmt.int(a.tokens_in)}),(0,b.jsx)(k,{right:!0,children:g.fmt.int(a.tokens_out)}),(0,b.jsx)(k,{right:!0,children:g.fmt.int(a.latency_ms)}),(0,b.jsx)(k,{muted:!0,children:a.stream?"stream":"unary"})]},c)})})]})}),null!==y&&G[y]&&(0,b.jsx)(l,{log:G[y],onClose:()=>z(null)})]})]})}])}];
|
|
1
|
+
module.exports=[42532,a=>{"use strict";var b=a.i(87924),c=a.i(72131);let d=[{key:"tokens",label:"Tokens"},{key:"cost",label:"Cost"},{key:"requests",label:"Requests"}];function e(a,b){return"tokens"===b?a.tokens_in+a.tokens_out:"cost"===b?a.cost:a.requests}function f(a,b){return"cost"===b?a<.01?`$${a.toFixed(4)}`:`$${a.toFixed(2)}`:a>=1e6?`${(a/1e6).toFixed(1)}M`:a>=1e3?`${(a/1e3).toFixed(1)}K`:String(Math.round(a))}function g(a){return new Date(a).toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit",hour12:!1})}function h({series:a}){let[i,j]=(0,c.useState)("tokens"),[k,l]=(0,c.useState)(null),m=(0,c.useRef)(null),n=a.map(a=>e(a,i)),o=Math.max(1,...n),p=a.length,q=a=>p<=1?8:8+a/(p-1)*984,r=a=>224-a/o*208,s=n.map((a,b)=>`${0===b?"M":"L"}${q(b).toFixed(1)},${r(a).toFixed(1)}`).join(" "),t=`${s} L${q(p-1).toFixed(1)},224 L${q(0).toFixed(1)},224 Z`,u=n.length?n.indexOf(Math.max(...n)):-1,v=n.reduce((a,b)=>a+b,0),w=(0,c.useCallback)(a=>{if(p<=1||!m.current)return;let b=m.current.getBoundingClientRect(),c=Math.round((a.clientX-b.left)/b.width*(p-1));l(Math.max(0,Math.min(p-1,c)))},[p]),x=(0,c.useCallback)(()=>l(null),[]),y=null!==k?a[k]:null;return(0,b.jsxs)("div",{className:"overflow-hidden rounded-brand-lg border border-border bg-surface shadow-soft",children:[(0,b.jsxs)("header",{className:"flex items-center justify-between gap-3 border-b border-border-subtle px-4 py-3",children:[(0,b.jsxs)("div",{className:"flex items-center gap-2.5",children:[(0,b.jsx)("span",{className:"text-[13px] font-semibold text-text",children:"Over time"}),(0,b.jsxs)("span",{className:"tnum text-[12px] text-text-muted",children:[f(v,i)," total"]})]}),(0,b.jsx)("div",{className:"flex items-center gap-1",children:d.map(a=>(0,b.jsx)("button",{onClick:()=>j(a.key),className:`rounded-full px-3 py-1 text-[12px] font-medium transition-colors ${i===a.key?"bg-surface-2 text-text":"text-text-muted hover:text-text"}`,children:a.label},a.key))})]}),(0,b.jsx)("div",{className:"relative px-2 py-3",children:0===p||0===v?(0,b.jsx)("div",{className:"flex h-[200px] items-center justify-center text-[13px] text-text-muted",children:"No activity in this range."}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("svg",{ref:m,viewBox:"0 0 1000 240",className:"h-[200px] w-full cursor-crosshair",preserveAspectRatio:"none",onMouseMove:w,onMouseLeave:x,children:[(0,b.jsx)("defs",{children:(0,b.jsxs)("linearGradient",{id:"areaFill",x1:"0",y1:"0",x2:"0",y2:"1",children:[(0,b.jsx)("stop",{offset:"0%",stopColor:"var(--color-accent)",stopOpacity:"0.28"}),(0,b.jsx)("stop",{offset:"100%",stopColor:"var(--color-accent)",stopOpacity:"0"})]})}),(0,b.jsx)("path",{d:t,fill:"url(#areaFill)"}),(0,b.jsx)("path",{d:s,fill:"none",stroke:"var(--color-accent)",strokeWidth:"2",vectorEffect:"non-scaling-stroke"}),u>=0&&null===k&&(0,b.jsx)("circle",{cx:q(u),cy:r(n[u]),r:"3",fill:"var(--color-accent)",vectorEffect:"non-scaling-stroke"}),null!==k&&(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)("line",{x1:q(k),y1:16,x2:q(k),y2:224,stroke:"var(--color-accent)",strokeWidth:"1",strokeDasharray:"4 3",vectorEffect:"non-scaling-stroke",opacity:"0.5"}),(0,b.jsx)("circle",{cx:q(k),cy:r(n[k]),r:"4",fill:"var(--color-accent)",stroke:"var(--color-bg)",strokeWidth:"2",vectorEffect:"non-scaling-stroke"})]})]}),null!==k&&y&&(0,b.jsxs)("div",{className:"pointer-events-none absolute top-2 z-10 rounded-lg border border-border bg-surface-2 px-3 py-2 shadow-lg",style:{left:`${Math.min(85,Math.max(5,k/(p-1)*100))}%`,transform:"translateX(-50%)"},children:[(0,b.jsx)("div",{className:"text-[11px] text-text-muted",children:new Date(y.ts).toLocaleDateString("en-US",{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1})}),(0,b.jsxs)("div",{className:"mt-1 flex flex-col gap-0.5 tnum text-[12px]",children:[(0,b.jsxs)("span",{className:"text-text",children:[f(e(y,i),i)," ",(0,b.jsx)("span",{className:"text-text-muted",children:i})]}),"tokens"===i&&(0,b.jsxs)("span",{className:"text-text-subtle text-[10px]",children:["in: ",f(y.tokens_in,"tokens")," · out: ",f(y.tokens_out,"tokens")]}),(0,b.jsxs)("span",{className:"text-text-subtle text-[10px]",children:[y.requests," req · $",y.cost.toFixed(4)]})]})]})]})}),p>0&&v>0&&u>=0&&(0,b.jsxs)("div",{className:"flex justify-between border-t border-border-subtle px-4 py-2 tnum text-[10px] text-text-subtle",children:[(0,b.jsx)("span",{children:g(a[0].ts)}),(0,b.jsxs)("span",{children:["peak ",f(n[u],i)," @ ",g(a[u].ts)]}),(0,b.jsx)("span",{children:g(a[p-1].ts)})]})]})}var i=a.i(58918),j=a.i(85732);let k=[{label:"Today",key:"today",bucketMs:36e5},{label:"24h",key:"24h",bucketMs:36e5},{label:"7D",key:"7d",bucketMs:216e5},{label:"30D",key:"30d",bucketMs:864e5},{label:"60D",key:"60d",bucketMs:1728e5}];function l({rows:a,loading:c}){return(0,b.jsx)("div",{className:`table-wrap ${c?"opacity-50":""}`,children:(0,b.jsxs)("table",{className:"w-full border-collapse",children:[(0,b.jsx)("thead",{children:(0,b.jsx)("tr",{className:"text-text-subtle",children:["","Reqs","In","Out","Cost"].map((a,c)=>(0,b.jsx)("th",{className:`pb-2 text-[10px] font-medium uppercase tracking-wider ${0===c?"text-left":"text-right"}`,children:a},a+c))})}),(0,b.jsx)("tbody",{children:a.map(a=>(0,b.jsxs)("tr",{className:"border-t border-border-subtle",children:[(0,b.jsx)("td",{className:"py-2 text-[12.5px] text-text",children:a.label}),(0,b.jsx)("td",{className:"py-2 text-right tnum text-[12.5px] text-text-muted",children:i.fmt.int(a.requests)}),(0,b.jsx)("td",{className:"py-2 text-right tnum text-[12.5px] text-text-muted",children:i.fmt.compact(a.tokens_in)}),(0,b.jsx)("td",{className:"py-2 text-right tnum text-[12.5px] text-text-muted",children:i.fmt.compact(a.tokens_out)}),(0,b.jsx)("td",{className:"py-2 text-right tnum text-[12.5px] text-text",children:i.fmt.cost(a.cost)})]},a.label))})]})})}a.s(["UsageView",0,function(){let[a,d]=(0,c.useState)(k[0]),[e,f]=(0,c.useState)(null),[g,m]=(0,c.useState)([]),[n,o]=(0,c.useState)(""),[p,q]=(0,c.useState)(!0),r=(0,c.useCallback)(async a=>{q(!0),o("");let b=function(a){let b=Date.now();switch(a){case"today":{let a=new Date;return a.setHours(0,0,0,0),a.getTime()}case"24h":return b-864e5;case"7d":return b-6048e5;case"30d":return b-2592e6;case"60d":return b-5184e6}}(a.key),[c,d]=await Promise.all([fetch(`/api/gw/admin/usage?since=${b}`),fetch(`/api/gw/admin/usage/series?since=${b}&bucket=${a.bucketMs}`)]);if(!c.ok){o("could not load usage"),q(!1);return}f(await c.json()),m((d.ok?await d.json():{series:[]}).series),q(!1)},[]);(0,c.useEffect)(()=>{r(a)},[a,r]);let s=e?.total;return(0,b.jsxs)("div",{children:[(0,b.jsxs)("div",{className:"mb-6 flex items-center justify-between gap-3",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("h1",{className:"text-[22px] font-semibold tracking-tight text-text",children:"Usage"}),(0,b.jsx)("p",{className:"mt-1 text-[13px] text-text-muted",children:"Tokens and cost across providers and models."})]}),(0,b.jsx)("div",{className:"flex items-center gap-1 rounded-full border border-border bg-surface p-1",children:k.map(c=>(0,b.jsx)("button",{onClick:()=>d(c),className:`rounded-full px-3 py-1 text-[12px] font-medium transition-colors ${a.label===c.label?"bg-surface-2 text-text":"text-text-muted hover:text-text"}`,children:c.label},c.label))})]}),n?(0,b.jsx)(i.Empty,{children:n}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("div",{className:"mb-5 grid grid-cols-2 gap-3 sm:grid-cols-4",children:[(0,b.jsx)(i.Stat,{label:"Requests",value:i.fmt.int(s?.requests??0)}),(0,b.jsx)(i.Stat,{label:"Tokens in",value:i.fmt.compact(s?.tokens_in??0)}),(0,b.jsx)(i.Stat,{label:"Tokens out",value:i.fmt.compact(s?.tokens_out??0)}),(0,b.jsx)(i.Stat,{label:"Cost",value:i.fmt.cost(s?.cost??0)})]}),(0,b.jsx)("div",{className:"mb-5",children:(0,b.jsx)(h,{series:g})}),(0,b.jsxs)("div",{className:"grid gap-4 lg:grid-cols-2",children:[(0,b.jsx)(j.RichCard,{header:(0,b.jsx)("span",{className:"text-[13px] font-semibold text-text",children:"By provider"}),children:e?.by_provider.length?(0,b.jsx)(l,{rows:e.by_provider.map(a=>({label:a.provider,...a})),loading:p}):(0,b.jsx)(i.Empty,{children:"No usage in this window."})}),(0,b.jsx)(j.RichCard,{header:(0,b.jsx)("span",{className:"text-[13px] font-semibold text-text",children:"By model"}),children:e?.by_model.length?(0,b.jsx)(l,{rows:e.by_model.map(a=>({label:`${a.alias} → ${a.model}`,...a})),loading:p}):(0,b.jsx)(i.Empty,{children:"No usage in this window."})})]})]})]})}],42532)},61574,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(47153),e=a.i(2693),f=a.i(93026),g=a.i(58918);let h=[{key:"all",label:"All"},{key:"ok",label:"Success"},{key:"error",label:"Errors"}],i=[{label:"1h",ms:36e5},{label:"6h",ms:216e5},{label:"24h",ms:864e5},{label:"7d",ms:6048e5},{label:"All",ms:null}];function j({label:a,children:c}){return(0,b.jsxs)("label",{className:"flex flex-col gap-1",children:[(0,b.jsx)("span",{className:"text-[10px] font-medium uppercase tracking-wider text-text-subtle",children:a}),c]})}function k({children:a,muted:c,right:d,title:e,className:f,suppressHydrationWarning:g}){return(0,b.jsx)("td",{title:e,suppressHydrationWarning:g,className:`whitespace-nowrap px-4 py-2.5 tnum text-[12.5px] ${d?"text-right":"text-left"} ${c?"text-text-muted":"text-text"}${f?` ${f}`:""}`,children:a})}function l({log:a,onClose:c}){let d=a.status>=200&&a.status<300,e=a.tokens_in+a.tokens_out;return(0,b.jsxs)("div",{className:"border-t border-border-subtle bg-surface-2/40 px-5 py-4",children:[(0,b.jsxs)("div",{className:"mb-3 flex items-center justify-between",children:[(0,b.jsx)("span",{className:"text-[12px] font-semibold text-text",children:"Request Details"}),(0,b.jsx)("button",{onClick:c,className:"text-text-subtle hover:text-text",children:(0,b.jsx)(f.Icon,{name:"close",size:16})})]}),(0,b.jsxs)("div",{className:"grid grid-cols-2 gap-x-8 gap-y-2 text-[12px] sm:grid-cols-4",children:[(0,b.jsx)(m,{label:"Status",value:`${a.status} ${d?"OK":"Error"}`}),(0,b.jsx)(m,{label:"Timestamp",value:new Date(a.ts).toLocaleString()}),(0,b.jsx)(m,{label:"Alias",value:a.alias}),(0,b.jsx)(m,{label:"Provider",value:a.provider}),(0,b.jsx)(m,{label:"Model",value:a.model}),(0,b.jsx)(m,{label:"Mode",value:a.stream?"Streaming":"Unary"}),(0,b.jsx)(m,{label:"Latency",value:`${a.latency_ms}ms`}),(0,b.jsx)(m,{label:"Cost",value:g.fmt.cost(a.cost)}),(0,b.jsx)(m,{label:"Input tokens",value:g.fmt.int(a.tokens_in)}),(0,b.jsx)(m,{label:"Output tokens",value:g.fmt.int(a.tokens_out)}),(0,b.jsx)(m,{label:"Cached tokens",value:g.fmt.int(a.cached_tokens)}),(0,b.jsx)(m,{label:"Total tokens",value:g.fmt.int(e)})]})]})}function m({label:a,value:c}){return(0,b.jsxs)("div",{children:[(0,b.jsx)("span",{className:"text-[10px] uppercase tracking-wider text-text-subtle",children:a}),(0,b.jsx)("div",{className:"tnum text-text",children:c})]})}a.s(["LogTable",0,function({logs:a}){let[m,n]=(0,c.useState)(a),[o,p]=(0,c.useState)("all"),[q,r]=(0,c.useState)("all"),[s,t]=(0,c.useState)(null),[u,v]=(0,c.useState)(!0),[w,x]=(0,c.useState)(!1),[y,z]=(0,c.useState)(null),A=(0,c.useRef)(null),B=(0,c.useCallback)(async()=>{try{let a=await fetch("/api/gw/admin/logs?limit=200");if(a.ok){let b=await a.json();n(b.logs)}}catch{}},[]);(0,c.useEffect)(()=>{if(u)return A.current=setInterval(B,5e3),()=>{A.current&&clearInterval(A.current)};A.current&&clearInterval(A.current)},[u,B]);let C=[...new Set(m.map(a=>a.provider))].sort(),D=m.filter(a=>a.status>=200&&a.status<300).length,E=m.length-D,F=null!==s?Date.now()-s:null,G=m.filter(a=>("ok"!==o||!!(a.status>=200&&a.status<300))&&("error"!==o||!(a.status>=200)||!(a.status<300))&&("all"===q||a.provider===q)&&(null===F||!(a.ts<F))),H="all"!==o||"all"!==q||null!==s;return(0,b.jsxs)("div",{className:"overflow-hidden rounded-brand-lg border border-border bg-surface shadow-soft",children:[(0,b.jsxs)("header",{className:"flex flex-col gap-3 border-b border-border-subtle px-4 py-3",children:[(0,b.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,b.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,b.jsx)("button",{onClick:()=>x(a=>!a),className:"flex-none rounded p-0.5 text-text-subtle transition-colors hover:text-text","aria-label":w?"Expand requests":"Collapse requests",title:w?"Expand":"Collapse",children:(0,b.jsx)(f.Icon,{name:w?"chevron_right":"expand_more",size:18})}),(0,b.jsx)("div",{className:"flex items-center gap-1",children:h.map(a=>{let c;return(0,b.jsxs)("button",{onClick:()=>p(a.key),className:`flex items-center gap-1.5 rounded-full px-3 py-1.5 text-[12px] font-medium transition-colors ${o===a.key?"bg-surface-2 text-text":"text-text-muted hover:text-text"}`,children:[a.label,(0,b.jsx)("span",{className:"tnum text-text-subtle",children:"all"===(c=a.key)?m.length:"ok"===c?D:E})]},a.key)})})]}),(0,b.jsxs)("button",{onClick:()=>v(a=>!a),className:`flex items-center gap-1 rounded-full px-2.5 py-1 text-[11px] font-medium transition-colors ${u?"bg-success/15 text-success":"text-text-muted hover:text-text"}`,title:u?"Auto-refresh ON (5s)":"Auto-refresh OFF",children:[(0,b.jsx)(f.Icon,{name:u?"radio_button_checked":"radio_button_unchecked",size:12}),"Live"]})]}),!w&&(0,b.jsxs)("div",{className:"flex flex-wrap items-end gap-2.5",children:[(0,b.jsx)(j,{label:"Provider",children:(0,b.jsxs)("select",{value:q,onChange:a=>r(a.target.value),className:"h-9 rounded-brand border border-border bg-surface-2 px-2.5 text-[12.5px] text-text focus:border-accent focus:outline-none w-40",children:[(0,b.jsx)("option",{value:"all",children:"All providers"}),C.map(a=>(0,b.jsx)("option",{value:a,children:a},a))]})}),(0,b.jsx)(j,{label:"Since",children:(0,b.jsx)("div",{className:"flex h-9 items-center gap-0.5 rounded-brand border border-border bg-surface-2 px-1",children:i.map(a=>{let c;return(0,b.jsx)("button",{type:"button",onClick:()=>t(a.ms),className:(c=s===a.ms,`rounded-full px-2.5 py-1 text-[12px] font-medium transition-colors ${c?"bg-accent/15 text-accent":"text-text-muted hover:text-text"}`),children:a.label},a.label)})})}),(0,b.jsxs)("button",{onClick:()=>{p("all"),r("all"),t(null)},disabled:!H,className:"flex h-9 items-center gap-1.5 rounded-brand border border-border bg-surface-2 px-3 text-[12.5px] font-medium text-text-muted transition-colors hover:border-text-subtle hover:text-text disabled:opacity-40 disabled:hover:border-border disabled:hover:text-text-muted",title:H?"Reset all filters":"No filters applied",children:[(0,b.jsx)(f.Icon,{name:"filter_alt_off",size:15}),"Clear"]})]})]}),w?null:0===G.length?(0,b.jsx)("div",{className:"px-4 py-8 text-center text-[13px] text-text-muted",children:0===m.length?"No requests recorded yet.":"No requests match this filter."}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)("div",{className:"table-wrap",children:(0,b.jsxs)("table",{className:"w-full min-w-[720px] border-collapse",children:[(0,b.jsx)("thead",{children:(0,b.jsx)("tr",{className:"text-text-subtle",children:["Status","Time","Alias","Provider","Model","In","Out","ms","Mode"].map((a,c)=>(0,b.jsx)("th",{className:`whitespace-nowrap px-4 pb-2.5 pt-3 text-[10px] font-medium uppercase tracking-wider ${c>=5&&c<=7?"text-right":"text-left"}`,children:a},a+c))})}),(0,b.jsx)("tbody",{children:G.map((a,c)=>{let f=a.status>=200&&a.status<300,h=y===c;return(0,b.jsxs)("tr",{onClick:()=>z(h?null:c),className:`border-t border-border-subtle cursor-pointer transition-colors ${h?"bg-surface-2/60":"hover:bg-surface-2/70"}`,children:[(0,b.jsx)(k,{children:(0,b.jsxs)(e.Badge,{tone:f?"live":"down",children:[(0,b.jsx)(d.Lamp,{state:f?"live":"down"}),a.status]})}),(0,b.jsxs)(k,{muted:!0,title:g.fmt.time(a.ts),suppressHydrationWarning:!0,children:[g.fmt.ago(a.ts)," ago"]}),(0,b.jsx)(k,{className:"text-text",children:a.alias}),(0,b.jsx)(k,{muted:!0,children:a.provider}),(0,b.jsx)(k,{muted:!0,children:a.model}),(0,b.jsx)(k,{right:!0,children:g.fmt.int(a.tokens_in)}),(0,b.jsx)(k,{right:!0,children:g.fmt.int(a.tokens_out)}),(0,b.jsx)(k,{right:!0,children:g.fmt.int(a.latency_ms)}),(0,b.jsx)(k,{muted:!0,children:a.stream?"stream":"unary"})]},c)})})]})}),null!==y&&G[y]&&(0,b.jsx)(l,{log:G[y],onClose:()=>z(null)})]})]})}])}];
|
|
2
2
|
|
|
3
3
|
//# sourceMappingURL=src_components_10h9ide._.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/UsageView.tsx","../../../../src/components/AreaChart.tsx","../../../../src/components/LogTable.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState, useCallback } from \"react\";\nimport { AreaChart, type SeriesPoint } from \"@/components/AreaChart\";\nimport { Stat, fmt, Empty } from \"@/components/ui\";\nimport { RichCard } from \"@/components/RichCard\";\nimport type { UsageSummary } from \"@/lib/gateway\";\n\ntype Window = { label: string; key: \"today\" | \"24h\" | \"7d\" | \"30d\" | \"60d\"; bucketMs: number };\n\n// window -> chart bucket size. Buckets keep ~24-60 points per range.\nconst WINDOWS: Window[] = [\n { label: \"Today\", key: \"today\", bucketMs: 3600_000 },\n { label: \"24h\", key: \"24h\", bucketMs: 3600_000 },\n { label: \"7D\", key: \"7d\", bucketMs: 6 * 3600_000 },\n { label: \"30D\", key: \"30d\", bucketMs: 86400_000 },\n { label: \"60D\", key: \"60d\", bucketMs: 2 * 86400_000 },\n];\n\n/** Lookback start (ms epoch) for a window. \"Today\" is since local midnight; the\n * rest are rolling lookbacks from now. */\nfunction sinceFor(key: Window[\"key\"]): number {\n const now = Date.now();\n switch (key) {\n case \"today\": {\n const d = new Date();\n d.setHours(0, 0, 0, 0);\n return d.getTime();\n }\n case \"24h\": return now - 24 * 3600_000;\n case \"7d\": return now - 7 * 86400_000;\n case \"30d\": return now - 30 * 86400_000;\n case \"60d\": return now - 60 * 86400_000;\n }\n}\n\nexport function UsageView() {\n const [win, setWin] = useState<Window>(WINDOWS[0]!);\n const [summary, setSummary] = useState<UsageSummary | null>(null);\n const [series, setSeries] = useState<SeriesPoint[]>([]);\n const [error, setError] = useState(\"\");\n const [loading, setLoading] = useState(true);\n\n const load = useCallback(async (w: Window) => {\n setLoading(true);\n setError(\"\");\n const since = sinceFor(w.key);\n const [sumRes, serRes] = await Promise.all([\n fetch(`/api/gw/admin/usage?since=${since}`),\n fetch(`/api/gw/admin/usage/series?since=${since}&bucket=${w.bucketMs}`),\n ]);\n if (!sumRes.ok) {\n setError(\"could not load usage\");\n setLoading(false);\n return;\n }\n setSummary((await sumRes.json()) as UsageSummary);\n const ser = serRes.ok ? ((await serRes.json()) as { series: SeriesPoint[] }) : { series: [] };\n setSeries(ser.series);\n setLoading(false);\n }, []);\n\n useEffect(() => {\n void load(win);\n }, [win, load]);\n\n const total = summary?.total;\n\n return (\n <div>\n <div className=\"mb-6 flex items-center justify-between gap-3\">\n <div>\n <h1 className=\"text-[22px] font-semibold tracking-tight text-text\">Usage</h1>\n <p className=\"mt-1 text-[13px] text-text-muted\">Tokens and cost across providers and models.</p>\n </div>\n <div className=\"flex items-center gap-1 rounded-full border border-border bg-surface p-1\">\n {WINDOWS.map((w) => (\n <button\n key={w.label}\n onClick={() => setWin(w)}\n className={`rounded-full px-3 py-1 text-[12px] font-medium transition-colors ${\n win.label === w.label ? \"bg-surface-2 text-text\" : \"text-text-muted hover:text-text\"\n }`}\n >\n {w.label}\n </button>\n ))}\n </div>\n </div>\n\n {error ? (\n <Empty>{error}</Empty>\n ) : (\n <>\n <div className=\"mb-5 grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <Stat label=\"Requests\" value={fmt.int(total?.requests ?? 0)} />\n <Stat label=\"Tokens in\" value={fmt.compact(total?.tokens_in ?? 0)} />\n <Stat label=\"Tokens out\" value={fmt.compact(total?.tokens_out ?? 0)} />\n <Stat label=\"Cost\" value={fmt.cost(total?.cost ?? 0)} />\n </div>\n\n <div className=\"mb-5\">\n <AreaChart series={series} />\n </div>\n\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <RichCard header={<span className=\"text-[13px] font-semibold text-text\">By provider</span>}>\n {summary?.by_provider.length ? (\n <BreakdownTable\n rows={summary.by_provider.map((p) => ({ label: p.provider, ...p }))}\n loading={loading}\n />\n ) : (\n <Empty>No usage in this window.</Empty>\n )}\n </RichCard>\n <RichCard header={<span className=\"text-[13px] font-semibold text-text\">By model</span>}>\n {summary?.by_model.length ? (\n <BreakdownTable\n rows={summary.by_model.map((m) => ({ label: `${m.alias} → ${m.model}`, ...m }))}\n loading={loading}\n />\n ) : (\n <Empty>No usage in this window.</Empty>\n )}\n </RichCard>\n </div>\n </>\n )}\n </div>\n );\n}\n\nfunction BreakdownTable({\n rows,\n loading,\n}: {\n rows: Array<{ label: string; requests: number; tokens_in: number; tokens_out: number; cost: number }>;\n loading: boolean;\n}) {\n return (\n <div className={`table-wrap ${loading ? \"opacity-50\" : \"\"}`}>\n <table className=\"w-full border-collapse\">\n <thead>\n <tr className=\"text-text-subtle\">\n {[\"\", \"Reqs\", \"In\", \"Out\", \"Cost\"].map((h, i) => (\n <th\n key={h + i}\n className={`pb-2 text-[10px] font-medium uppercase tracking-wider ${i === 0 ? \"text-left\" : \"text-right\"}`}\n >\n {h}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((r) => (\n <tr key={r.label} className=\"border-t border-border-subtle\">\n <td className=\"py-2 text-[12.5px] text-text\">{r.label}</td>\n <td className=\"py-2 text-right tnum text-[12.5px] text-text-muted\">{fmt.int(r.requests)}</td>\n <td className=\"py-2 text-right tnum text-[12.5px] text-text-muted\">{fmt.compact(r.tokens_in)}</td>\n <td className=\"py-2 text-right tnum text-[12.5px] text-text-muted\">{fmt.compact(r.tokens_out)}</td>\n <td className=\"py-2 text-right tnum text-[12.5px] text-text\">{fmt.cost(r.cost)}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n","\"use client\";\n\nimport { useState } from \"react\";\n\nexport interface SeriesPoint {\n ts: number;\n requests: number;\n tokens_in: number;\n tokens_out: number;\n cost: number;\n}\n\ntype Metric = \"tokens\" | \"cost\" | \"requests\";\n\nconst METRICS: { key: Metric; label: string }[] = [\n { key: \"tokens\", label: \"Tokens\" },\n { key: \"cost\", label: \"Cost\" },\n { key: \"requests\", label: \"Requests\" },\n];\n\nfunction valueOf(p: SeriesPoint, m: Metric): number {\n if (m === \"tokens\") return p.tokens_in + p.tokens_out;\n if (m === \"cost\") return p.cost;\n return p.requests;\n}\n\nfunction fmtVal(v: number, m: Metric): string {\n if (m === \"cost\") return v < 0.01 ? `$${v.toFixed(4)}` : `$${v.toFixed(2)}`;\n if (v >= 1_000_000) return `${(v / 1_000_000).toFixed(1)}M`;\n if (v >= 1_000) return `${(v / 1_000).toFixed(1)}K`;\n return String(Math.round(v));\n}\n\nfunction fmtTime(ts: number): string {\n return new Date(ts).toLocaleTimeString(\"en-US\", { hour: \"2-digit\", minute: \"2-digit\", hour12: false });\n}\n\n/** Inline-SVG area chart with a metric toggle. No charting dependency. */\nexport function AreaChart({ series }: { series: SeriesPoint[] }) {\n const [metric, setMetric] = useState<Metric>(\"tokens\");\n\n const W = 1000;\n const H = 240;\n const padX = 8;\n const padY = 16;\n\n const vals = series.map((p) => valueOf(p, metric));\n const max = Math.max(1, ...vals);\n const n = series.length;\n\n const x = (i: number) => (n <= 1 ? padX : padX + (i / (n - 1)) * (W - padX * 2));\n const y = (v: number) => H - padY - (v / max) * (H - padY * 2);\n\n const line = vals.map((v, i) => `${i === 0 ? \"M\" : \"L\"}${x(i).toFixed(1)},${y(v).toFixed(1)}`).join(\" \");\n const area = `${line} L${x(n - 1).toFixed(1)},${H - padY} L${x(0).toFixed(1)},${H - padY} Z`;\n\n const peak = vals.length ? vals.indexOf(Math.max(...vals)) : -1;\n const total = vals.reduce((a, b) => a + b, 0);\n\n return (\n <div className=\"overflow-hidden rounded-brand-lg border border-border bg-surface shadow-soft\">\n <header className=\"flex items-center justify-between gap-3 border-b border-border-subtle px-4 py-3\">\n <div className=\"flex items-center gap-2.5\">\n <span className=\"text-[13px] font-semibold text-text\">Over time</span>\n <span className=\"tnum text-[12px] text-text-muted\">{fmtVal(total, metric)} total</span>\n </div>\n <div className=\"flex items-center gap-1\">\n {METRICS.map((m) => (\n <button\n key={m.key}\n onClick={() => setMetric(m.key)}\n className={`rounded-full px-3 py-1 text-[12px] font-medium transition-colors ${\n metric === m.key ? \"bg-surface-2 text-text\" : \"text-text-muted hover:text-text\"\n }`}\n >\n {m.label}\n </button>\n ))}\n </div>\n </header>\n\n <div className=\"px-2 py-3\">\n {n === 0 || total === 0 ? (\n <div className=\"flex h-[200px] items-center justify-center text-[13px] text-text-muted\">\n No activity in this range.\n </div>\n ) : (\n <svg viewBox={`0 0 ${W} ${H}`} className=\"h-[200px] w-full\" preserveAspectRatio=\"none\">\n <defs>\n <linearGradient id=\"areaFill\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor=\"var(--color-accent)\" stopOpacity=\"0.28\" />\n <stop offset=\"100%\" stopColor=\"var(--color-accent)\" stopOpacity=\"0\" />\n </linearGradient>\n </defs>\n <path d={area} fill=\"url(#areaFill)\" />\n <path d={line} fill=\"none\" stroke=\"var(--color-accent)\" strokeWidth=\"2\" vectorEffect=\"non-scaling-stroke\" />\n {peak >= 0 && (\n <circle cx={x(peak)} cy={y(vals[peak]!)} r=\"3\" fill=\"var(--color-accent)\" vectorEffect=\"non-scaling-stroke\" />\n )}\n </svg>\n )}\n </div>\n\n {n > 0 && total > 0 && peak >= 0 && (\n <div className=\"flex justify-between border-t border-border-subtle px-4 py-2 tnum text-[10px] text-text-subtle\">\n <span>{fmtTime(series[0]!.ts)}</span>\n <span>\n peak {fmtVal(vals[peak]!, metric)} @ {fmtTime(series[peak]!.ts)}\n </span>\n <span>{fmtTime(series[n - 1]!.ts)}</span>\n </div>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport { useState, useEffect, useRef, useCallback } from \"react\";\nimport { Lamp } from \"@/components/Lamp\";\nimport { Badge } from \"@/components/Badge\";\nimport { Icon } from \"@/components/Icon\";\nimport { fmt } from \"@/components/ui\";\nimport type { UsageLog } from \"@/lib/gateway\";\n\ntype StatusFilter = \"all\" | \"ok\" | \"error\";\n\nconst FILTERS: { key: StatusFilter; label: string }[] = [\n { key: \"all\", label: \"All\" },\n { key: \"ok\", label: \"Success\" },\n { key: \"error\", label: \"Errors\" },\n];\n\n// shared control style for the filter row — bordered surface chip, accent on focus.\nconst ctrl = \"h-9 rounded-brand border border-border bg-surface-2 px-2.5 text-[12.5px] text-text focus:border-accent focus:outline-none\";\n\n// recency presets for the request log (a live 200-row buffer, so relative\n// windows fit better than absolute dates). null = no time filter.\nconst SINCE_PRESETS: { label: string; ms: number | null }[] = [\n { label: \"1h\", ms: 3600_000 },\n { label: \"6h\", ms: 6 * 3600_000 },\n { label: \"24h\", ms: 24 * 3600_000 },\n { label: \"7d\", ms: 7 * 86400_000 },\n { label: \"All\", ms: null },\n];\nconst sincePill = (active: boolean): string =>\n `rounded-full px-2.5 py-1 text-[12px] font-medium transition-colors ${\n active ? \"bg-accent/15 text-accent\" : \"text-text-muted hover:text-text\"\n }`;\n\nexport function LogTable({ logs: initial }: { logs: UsageLog[] }) {\n const [logs, setLogs] = useState(initial);\n const [filter, setFilter] = useState<StatusFilter>(\"all\");\n const [provFilter, setProvFilter] = useState<string>(\"all\");\n const [sinceMs, setSinceMs] = useState<number | null>(null);\n const [live, setLive] = useState(true);\n const [collapsed, setCollapsed] = useState(false);\n const [expandedIdx, setExpandedIdx] = useState<number | null>(null);\n const timer = useRef<ReturnType<typeof setInterval> | null>(null);\n\n const refresh = useCallback(async () => {\n try {\n const res = await fetch(\"/api/gw/admin/logs?limit=200\");\n if (res.ok) {\n const data = (await res.json()) as { logs: UsageLog[] };\n setLogs(data.logs);\n }\n } catch { /* ignore */ }\n }, []);\n\n useEffect(() => {\n if (live) {\n timer.current = setInterval(refresh, 5000);\n return () => { if (timer.current) clearInterval(timer.current); };\n }\n if (timer.current) clearInterval(timer.current);\n }, [live, refresh]);\n\n const providers = [...new Set(logs.map((l) => l.provider))].sort();\n\n const okCount = logs.filter((l) => l.status >= 200 && l.status < 300).length;\n const errCount = logs.length - okCount;\n\n const sinceFloor = sinceMs !== null ? Date.now() - sinceMs : null;\n\n const shown = logs.filter((l) => {\n if (filter === \"ok\" && !(l.status >= 200 && l.status < 300)) return false;\n if (filter === \"error\" && l.status >= 200 && l.status < 300) return false;\n if (provFilter !== \"all\" && l.provider !== provFilter) return false;\n if (sinceFloor !== null && l.ts < sinceFloor) return false;\n return true;\n });\n\n const hasFilters = filter !== \"all\" || provFilter !== \"all\" || sinceMs !== null;\n const clearFilters = () => { setFilter(\"all\"); setProvFilter(\"all\"); setSinceMs(null); };\n\n const count = (k: StatusFilter) => (k === \"all\" ? logs.length : k === \"ok\" ? okCount : errCount);\n\n return (\n <div className=\"overflow-hidden rounded-brand-lg border border-border bg-surface shadow-soft\">\n <header className=\"flex flex-col gap-3 border-b border-border-subtle px-4 py-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"flex items-center gap-1.5\">\n <button\n onClick={() => setCollapsed((v) => !v)}\n className=\"flex-none rounded p-0.5 text-text-subtle transition-colors hover:text-text\"\n aria-label={collapsed ? \"Expand requests\" : \"Collapse requests\"}\n title={collapsed ? \"Expand\" : \"Collapse\"}\n >\n <Icon name={collapsed ? \"chevron_right\" : \"expand_more\"} size={18} />\n </button>\n <div className=\"flex items-center gap-1\">\n {FILTERS.map((f) => (\n <button\n key={f.key}\n onClick={() => setFilter(f.key)}\n className={`flex items-center gap-1.5 rounded-full px-3 py-1.5 text-[12px] font-medium transition-colors ${\n filter === f.key ? \"bg-surface-2 text-text\" : \"text-text-muted hover:text-text\"\n }`}\n >\n {f.label}\n <span className=\"tnum text-text-subtle\">{count(f.key)}</span>\n </button>\n ))}\n </div>\n </div>\n <button\n onClick={() => setLive((v) => !v)}\n className={`flex items-center gap-1 rounded-full px-2.5 py-1 text-[11px] font-medium transition-colors ${\n live ? \"bg-success/15 text-success\" : \"text-text-muted hover:text-text\"\n }`}\n title={live ? \"Auto-refresh ON (5s)\" : \"Auto-refresh OFF\"}\n >\n <Icon name={live ? \"radio_button_checked\" : \"radio_button_unchecked\"} size={12} />\n Live\n </button>\n </div>\n\n {!collapsed && (\n <div className=\"flex flex-wrap items-end gap-2.5\">\n <FilterField label=\"Provider\">\n <select\n value={provFilter}\n onChange={(e) => setProvFilter(e.target.value)}\n className={ctrl + \" w-40\"}\n >\n <option value=\"all\">All providers</option>\n {providers.map((p) => (\n <option key={p} value={p}>{p}</option>\n ))}\n </select>\n </FilterField>\n <FilterField label=\"Since\">\n <div className=\"flex h-9 items-center gap-0.5 rounded-brand border border-border bg-surface-2 px-1\">\n {SINCE_PRESETS.map((p) => (\n <button\n key={p.label}\n type=\"button\"\n onClick={() => setSinceMs(p.ms)}\n className={sincePill(sinceMs === p.ms)}\n >\n {p.label}\n </button>\n ))}\n </div>\n </FilterField>\n <button\n onClick={clearFilters}\n disabled={!hasFilters}\n className=\"flex h-9 items-center gap-1.5 rounded-brand border border-border bg-surface-2 px-3 text-[12.5px] font-medium text-text-muted transition-colors hover:border-text-subtle hover:text-text disabled:opacity-40 disabled:hover:border-border disabled:hover:text-text-muted\"\n title={hasFilters ? \"Reset all filters\" : \"No filters applied\"}\n >\n <Icon name=\"filter_alt_off\" size={15} />\n Clear\n </button>\n </div>\n )}\n </header>\n\n {collapsed ? null : shown.length === 0 ? (\n <div className=\"px-4 py-8 text-center text-[13px] text-text-muted\">\n {logs.length === 0 ? \"No requests recorded yet.\" : \"No requests match this filter.\"}\n </div>\n ) : (\n <>\n <div className=\"table-wrap\">\n <table className=\"w-full min-w-[720px] border-collapse\">\n <thead>\n <tr className=\"text-text-subtle\">\n {[\"Status\", \"Time\", \"Alias\", \"Provider\", \"Model\", \"In\", \"Out\", \"ms\", \"Mode\"].map((h, i) => (\n <th\n key={h + i}\n className={`whitespace-nowrap px-4 pb-2.5 pt-3 text-[10px] font-medium uppercase tracking-wider ${\n i >= 5 && i <= 7 ? \"text-right\" : \"text-left\"\n }`}\n >\n {h}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {shown.map((l, i) => {\n const ok = l.status >= 200 && l.status < 300;\n const isExpanded = expandedIdx === i;\n return (\n <tr key={i} onClick={() => setExpandedIdx(isExpanded ? null : i)} className={`border-t border-border-subtle cursor-pointer transition-colors ${isExpanded ? \"bg-surface-2/60\" : \"hover:bg-surface-2/70\"}`}>\n <Td>\n <Badge tone={ok ? \"live\" : \"down\"}>\n <Lamp state={ok ? \"live\" : \"down\"} />\n {l.status}\n </Badge>\n </Td>\n <Td muted title={fmt.time(l.ts)} suppressHydrationWarning>\n {fmt.ago(l.ts)} ago\n </Td>\n <Td className=\"text-text\">{l.alias}</Td>\n <Td muted>{l.provider}</Td>\n <Td muted>{l.model}</Td>\n <Td right>{fmt.int(l.tokens_in)}</Td>\n <Td right>{fmt.int(l.tokens_out)}</Td>\n <Td right>{fmt.int(l.latency_ms)}</Td>\n <Td muted>{l.stream ? \"stream\" : \"unary\"}</Td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n\n {expandedIdx !== null && shown[expandedIdx] && (\n <RequestDetail log={shown[expandedIdx]} onClose={() => setExpandedIdx(null)} />\n )}\n </>\n )}\n </div>\n );\n}\n\nfunction FilterField({ label, children }: { label: string; children: React.ReactNode }) {\n return (\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-[10px] font-medium uppercase tracking-wider text-text-subtle\">{label}</span>\n {children}\n </label>\n );\n}\n\nfunction Td({\n children,\n muted,\n right,\n title,\n className,\n suppressHydrationWarning,\n}: {\n children: React.ReactNode;\n muted?: boolean;\n right?: boolean;\n title?: string;\n className?: string;\n suppressHydrationWarning?: boolean;\n}) {\n return (\n <td\n title={title}\n suppressHydrationWarning={suppressHydrationWarning}\n className={`whitespace-nowrap px-4 py-2.5 tnum text-[12.5px] ${right ? \"text-right\" : \"text-left\"} ${\n muted ? \"text-text-muted\" : \"text-text\"\n }${className ? ` ${className}` : \"\"}`}\n >\n {children}\n </td>\n );\n}\n\nfunction RequestDetail({ log, onClose }: { log: UsageLog; onClose: () => void }) {\n const ok = log.status >= 200 && log.status < 300;\n const totalTokens = log.tokens_in + log.tokens_out;\n\n return (\n <div className=\"border-t border-border-subtle bg-surface-2/40 px-5 py-4\">\n <div className=\"mb-3 flex items-center justify-between\">\n <span className=\"text-[12px] font-semibold text-text\">Request Details</span>\n <button onClick={onClose} className=\"text-text-subtle hover:text-text\">\n <Icon name=\"close\" size={16} />\n </button>\n </div>\n <div className=\"grid grid-cols-2 gap-x-8 gap-y-2 text-[12px] sm:grid-cols-4\">\n <DetailCell label=\"Status\" value={`${log.status} ${ok ? \"OK\" : \"Error\"}`} />\n <DetailCell label=\"Timestamp\" value={new Date(log.ts).toLocaleString()} />\n <DetailCell label=\"Alias\" value={log.alias} />\n <DetailCell label=\"Provider\" value={log.provider} />\n <DetailCell label=\"Model\" value={log.model} />\n <DetailCell label=\"Mode\" value={log.stream ? \"Streaming\" : \"Unary\"} />\n <DetailCell label=\"Latency\" value={`${log.latency_ms}ms`} />\n <DetailCell label=\"Cost\" value={fmt.cost(log.cost)} />\n <DetailCell label=\"Input tokens\" value={fmt.int(log.tokens_in)} />\n <DetailCell label=\"Output tokens\" value={fmt.int(log.tokens_out)} />\n <DetailCell label=\"Cached tokens\" value={fmt.int(log.cached_tokens)} />\n <DetailCell label=\"Total tokens\" value={fmt.int(totalTokens)} />\n </div>\n </div>\n );\n}\n\nfunction DetailCell({ label, value }: { label: string; value: string }) {\n return (\n <div>\n <span className=\"text-[10px] uppercase tracking-wider text-text-subtle\">{label}</span>\n <div className=\"tnum text-text\">{value}</div>\n </div>\n );\n}\n"],"names":["METRICS","key","label","valueOf","p","m","tokens_in","tokens_out","cost","requests","fmtVal","v","toFixed","String","Math","round","fmtTime","ts","Date","toLocaleTimeString","hour","minute","hour12","AreaChart","series","metric","setMetric","W","H","padX","padY","vals","map","max","n","length","x","i","y","line","join","area","peak","indexOf","total","reduce","a","b","className","onClick","viewBox","preserveAspectRatio","id","x1","y1","x2","y2","offset","stopColor","stopOpacity","d","fill","stroke","strokeWidth","vectorEffect","cx","cy","r","FILTERS","ctrl","SINCE_PRESETS","ms","sincePill","active","LogTable","logs","initial","setLogs","filter","setFilter","provFilter","setProvFilter","sinceMs","setSinceMs","live","setLive","collapsed","setCollapsed","expandedIdx","setExpandedIdx","timer","refresh","res","fetch","ok","data","json","current","setInterval","clearInterval","providers","Set","l","provider","sort","okCount","status","errCount","sinceFloor","now","shown","hasFilters","clearFilters","count","k","title","name","size","f","FilterField","value","onChange","e","target","type","disabled","h","isExpanded","Td","tone","state","muted","time","suppressHydrationWarning","ago","alias","model","right","int","latency_ms","stream","RequestDetail","log","onClose","children","totalTokens","DetailCell","toLocaleString","cached_tokens"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/UsageView.tsx","../../../../src/components/AreaChart.tsx","../../../../src/components/LogTable.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState, useCallback } from \"react\";\nimport { AreaChart, type SeriesPoint } from \"@/components/AreaChart\";\nimport { Stat, fmt, Empty } from \"@/components/ui\";\nimport { RichCard } from \"@/components/RichCard\";\nimport type { UsageSummary } from \"@/lib/gateway\";\n\ntype Window = { label: string; key: \"today\" | \"24h\" | \"7d\" | \"30d\" | \"60d\"; bucketMs: number };\n\n// window -> chart bucket size. Buckets keep ~24-60 points per range.\nconst WINDOWS: Window[] = [\n { label: \"Today\", key: \"today\", bucketMs: 3600_000 },\n { label: \"24h\", key: \"24h\", bucketMs: 3600_000 },\n { label: \"7D\", key: \"7d\", bucketMs: 6 * 3600_000 },\n { label: \"30D\", key: \"30d\", bucketMs: 86400_000 },\n { label: \"60D\", key: \"60d\", bucketMs: 2 * 86400_000 },\n];\n\n/** Lookback start (ms epoch) for a window. \"Today\" is since local midnight; the\n * rest are rolling lookbacks from now. */\nfunction sinceFor(key: Window[\"key\"]): number {\n const now = Date.now();\n switch (key) {\n case \"today\": {\n const d = new Date();\n d.setHours(0, 0, 0, 0);\n return d.getTime();\n }\n case \"24h\": return now - 24 * 3600_000;\n case \"7d\": return now - 7 * 86400_000;\n case \"30d\": return now - 30 * 86400_000;\n case \"60d\": return now - 60 * 86400_000;\n }\n}\n\nexport function UsageView() {\n const [win, setWin] = useState<Window>(WINDOWS[0]!);\n const [summary, setSummary] = useState<UsageSummary | null>(null);\n const [series, setSeries] = useState<SeriesPoint[]>([]);\n const [error, setError] = useState(\"\");\n const [loading, setLoading] = useState(true);\n\n const load = useCallback(async (w: Window) => {\n setLoading(true);\n setError(\"\");\n const since = sinceFor(w.key);\n const [sumRes, serRes] = await Promise.all([\n fetch(`/api/gw/admin/usage?since=${since}`),\n fetch(`/api/gw/admin/usage/series?since=${since}&bucket=${w.bucketMs}`),\n ]);\n if (!sumRes.ok) {\n setError(\"could not load usage\");\n setLoading(false);\n return;\n }\n setSummary((await sumRes.json()) as UsageSummary);\n const ser = serRes.ok ? ((await serRes.json()) as { series: SeriesPoint[] }) : { series: [] };\n setSeries(ser.series);\n setLoading(false);\n }, []);\n\n useEffect(() => {\n void load(win);\n }, [win, load]);\n\n const total = summary?.total;\n\n return (\n <div>\n <div className=\"mb-6 flex items-center justify-between gap-3\">\n <div>\n <h1 className=\"text-[22px] font-semibold tracking-tight text-text\">Usage</h1>\n <p className=\"mt-1 text-[13px] text-text-muted\">Tokens and cost across providers and models.</p>\n </div>\n <div className=\"flex items-center gap-1 rounded-full border border-border bg-surface p-1\">\n {WINDOWS.map((w) => (\n <button\n key={w.label}\n onClick={() => setWin(w)}\n className={`rounded-full px-3 py-1 text-[12px] font-medium transition-colors ${\n win.label === w.label ? \"bg-surface-2 text-text\" : \"text-text-muted hover:text-text\"\n }`}\n >\n {w.label}\n </button>\n ))}\n </div>\n </div>\n\n {error ? (\n <Empty>{error}</Empty>\n ) : (\n <>\n <div className=\"mb-5 grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <Stat label=\"Requests\" value={fmt.int(total?.requests ?? 0)} />\n <Stat label=\"Tokens in\" value={fmt.compact(total?.tokens_in ?? 0)} />\n <Stat label=\"Tokens out\" value={fmt.compact(total?.tokens_out ?? 0)} />\n <Stat label=\"Cost\" value={fmt.cost(total?.cost ?? 0)} />\n </div>\n\n <div className=\"mb-5\">\n <AreaChart series={series} />\n </div>\n\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <RichCard header={<span className=\"text-[13px] font-semibold text-text\">By provider</span>}>\n {summary?.by_provider.length ? (\n <BreakdownTable\n rows={summary.by_provider.map((p) => ({ label: p.provider, ...p }))}\n loading={loading}\n />\n ) : (\n <Empty>No usage in this window.</Empty>\n )}\n </RichCard>\n <RichCard header={<span className=\"text-[13px] font-semibold text-text\">By model</span>}>\n {summary?.by_model.length ? (\n <BreakdownTable\n rows={summary.by_model.map((m) => ({ label: `${m.alias} → ${m.model}`, ...m }))}\n loading={loading}\n />\n ) : (\n <Empty>No usage in this window.</Empty>\n )}\n </RichCard>\n </div>\n </>\n )}\n </div>\n );\n}\n\nfunction BreakdownTable({\n rows,\n loading,\n}: {\n rows: Array<{ label: string; requests: number; tokens_in: number; tokens_out: number; cost: number }>;\n loading: boolean;\n}) {\n return (\n <div className={`table-wrap ${loading ? \"opacity-50\" : \"\"}`}>\n <table className=\"w-full border-collapse\">\n <thead>\n <tr className=\"text-text-subtle\">\n {[\"\", \"Reqs\", \"In\", \"Out\", \"Cost\"].map((h, i) => (\n <th\n key={h + i}\n className={`pb-2 text-[10px] font-medium uppercase tracking-wider ${i === 0 ? \"text-left\" : \"text-right\"}`}\n >\n {h}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((r) => (\n <tr key={r.label} className=\"border-t border-border-subtle\">\n <td className=\"py-2 text-[12.5px] text-text\">{r.label}</td>\n <td className=\"py-2 text-right tnum text-[12.5px] text-text-muted\">{fmt.int(r.requests)}</td>\n <td className=\"py-2 text-right tnum text-[12.5px] text-text-muted\">{fmt.compact(r.tokens_in)}</td>\n <td className=\"py-2 text-right tnum text-[12.5px] text-text-muted\">{fmt.compact(r.tokens_out)}</td>\n <td className=\"py-2 text-right tnum text-[12.5px] text-text\">{fmt.cost(r.cost)}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n","\"use client\";\n\nimport { useState, useRef, useCallback } from \"react\";\n\nexport interface SeriesPoint {\n ts: number;\n requests: number;\n tokens_in: number;\n tokens_out: number;\n cost: number;\n}\n\ntype Metric = \"tokens\" | \"cost\" | \"requests\";\n\nconst METRICS: { key: Metric; label: string }[] = [\n { key: \"tokens\", label: \"Tokens\" },\n { key: \"cost\", label: \"Cost\" },\n { key: \"requests\", label: \"Requests\" },\n];\n\nfunction valueOf(p: SeriesPoint, m: Metric): number {\n if (m === \"tokens\") return p.tokens_in + p.tokens_out;\n if (m === \"cost\") return p.cost;\n return p.requests;\n}\n\nfunction fmtVal(v: number, m: Metric): string {\n if (m === \"cost\") return v < 0.01 ? `$${v.toFixed(4)}` : `$${v.toFixed(2)}`;\n if (v >= 1_000_000) return `${(v / 1_000_000).toFixed(1)}M`;\n if (v >= 1_000) return `${(v / 1_000).toFixed(1)}K`;\n return String(Math.round(v));\n}\n\nfunction fmtTime(ts: number): string {\n return new Date(ts).toLocaleTimeString(\"en-US\", { hour: \"2-digit\", minute: \"2-digit\", hour12: false });\n}\n\nfunction fmtDate(ts: number): string {\n return new Date(ts).toLocaleDateString(\"en-US\", { month: \"short\", day: \"numeric\", hour: \"2-digit\", minute: \"2-digit\", hour12: false });\n}\n\n/** Inline-SVG area chart with metric toggle and hover tooltip. No charting dependency. */\nexport function AreaChart({ series }: { series: SeriesPoint[] }) {\n const [metric, setMetric] = useState<Metric>(\"tokens\");\n const [hoverIdx, setHoverIdx] = useState<number | null>(null);\n const svgRef = useRef<SVGSVGElement>(null);\n\n const W = 1000;\n const H = 240;\n const padX = 8;\n const padY = 16;\n\n const vals = series.map((p) => valueOf(p, metric));\n const max = Math.max(1, ...vals);\n const n = series.length;\n\n const xPos = (i: number) => (n <= 1 ? padX : padX + (i / (n - 1)) * (W - padX * 2));\n const yPos = (v: number) => H - padY - (v / max) * (H - padY * 2);\n\n const line = vals.map((v, i) => `${i === 0 ? \"M\" : \"L\"}${xPos(i).toFixed(1)},${yPos(v).toFixed(1)}`).join(\" \");\n const area = `${line} L${xPos(n - 1).toFixed(1)},${H - padY} L${xPos(0).toFixed(1)},${H - padY} Z`;\n\n const peak = vals.length ? vals.indexOf(Math.max(...vals)) : -1;\n const total = vals.reduce((a, b) => a + b, 0);\n\n const handleMouseMove = useCallback(\n (e: React.MouseEvent<SVGSVGElement>) => {\n if (n <= 1 || !svgRef.current) return;\n const rect = svgRef.current.getBoundingClientRect();\n const relX = (e.clientX - rect.left) / rect.width;\n const idx = Math.round(relX * (n - 1));\n setHoverIdx(Math.max(0, Math.min(n - 1, idx)));\n },\n [n],\n );\n\n const handleMouseLeave = useCallback(() => setHoverIdx(null), []);\n\n const hp = hoverIdx !== null ? series[hoverIdx] : null;\n\n return (\n <div className=\"overflow-hidden rounded-brand-lg border border-border bg-surface shadow-soft\">\n <header className=\"flex items-center justify-between gap-3 border-b border-border-subtle px-4 py-3\">\n <div className=\"flex items-center gap-2.5\">\n <span className=\"text-[13px] font-semibold text-text\">Over time</span>\n <span className=\"tnum text-[12px] text-text-muted\">{fmtVal(total, metric)} total</span>\n </div>\n <div className=\"flex items-center gap-1\">\n {METRICS.map((m) => (\n <button\n key={m.key}\n onClick={() => setMetric(m.key)}\n className={`rounded-full px-3 py-1 text-[12px] font-medium transition-colors ${\n metric === m.key ? \"bg-surface-2 text-text\" : \"text-text-muted hover:text-text\"\n }`}\n >\n {m.label}\n </button>\n ))}\n </div>\n </header>\n\n <div className=\"relative px-2 py-3\">\n {n === 0 || total === 0 ? (\n <div className=\"flex h-[200px] items-center justify-center text-[13px] text-text-muted\">\n No activity in this range.\n </div>\n ) : (\n <>\n <svg\n ref={svgRef}\n viewBox={`0 0 ${W} ${H}`}\n className=\"h-[200px] w-full cursor-crosshair\"\n preserveAspectRatio=\"none\"\n onMouseMove={handleMouseMove}\n onMouseLeave={handleMouseLeave}\n >\n <defs>\n <linearGradient id=\"areaFill\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor=\"var(--color-accent)\" stopOpacity=\"0.28\" />\n <stop offset=\"100%\" stopColor=\"var(--color-accent)\" stopOpacity=\"0\" />\n </linearGradient>\n </defs>\n <path d={area} fill=\"url(#areaFill)\" />\n <path d={line} fill=\"none\" stroke=\"var(--color-accent)\" strokeWidth=\"2\" vectorEffect=\"non-scaling-stroke\" />\n {peak >= 0 && hoverIdx === null && (\n <circle cx={xPos(peak)} cy={yPos(vals[peak]!)} r=\"3\" fill=\"var(--color-accent)\" vectorEffect=\"non-scaling-stroke\" />\n )}\n {hoverIdx !== null && (\n <>\n <line\n x1={xPos(hoverIdx)}\n y1={padY}\n x2={xPos(hoverIdx)}\n y2={H - padY}\n stroke=\"var(--color-accent)\"\n strokeWidth=\"1\"\n strokeDasharray=\"4 3\"\n vectorEffect=\"non-scaling-stroke\"\n opacity=\"0.5\"\n />\n <circle\n cx={xPos(hoverIdx)}\n cy={yPos(vals[hoverIdx]!)}\n r=\"4\"\n fill=\"var(--color-accent)\"\n stroke=\"var(--color-bg)\"\n strokeWidth=\"2\"\n vectorEffect=\"non-scaling-stroke\"\n />\n </>\n )}\n </svg>\n {hoverIdx !== null && hp && (\n <div\n className=\"pointer-events-none absolute top-2 z-10 rounded-lg border border-border bg-surface-2 px-3 py-2 shadow-lg\"\n style={{ left: `${Math.min(85, Math.max(5, (hoverIdx / (n - 1)) * 100))}%`, transform: \"translateX(-50%)\" }}\n >\n <div className=\"text-[11px] text-text-muted\">{fmtDate(hp.ts)}</div>\n <div className=\"mt-1 flex flex-col gap-0.5 tnum text-[12px]\">\n <span className=\"text-text\">{fmtVal(valueOf(hp, metric), metric)} <span className=\"text-text-muted\">{metric}</span></span>\n {metric === \"tokens\" && (\n <span className=\"text-text-subtle text-[10px]\">in: {fmtVal(hp.tokens_in, \"tokens\")} · out: {fmtVal(hp.tokens_out, \"tokens\")}</span>\n )}\n <span className=\"text-text-subtle text-[10px]\">{hp.requests} req · ${hp.cost.toFixed(4)}</span>\n </div>\n </div>\n )}\n </>\n )}\n </div>\n\n {n > 0 && total > 0 && peak >= 0 && (\n <div className=\"flex justify-between border-t border-border-subtle px-4 py-2 tnum text-[10px] text-text-subtle\">\n <span>{fmtTime(series[0]!.ts)}</span>\n <span>\n peak {fmtVal(vals[peak]!, metric)} @ {fmtTime(series[peak]!.ts)}\n </span>\n <span>{fmtTime(series[n - 1]!.ts)}</span>\n </div>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport { useState, useEffect, useRef, useCallback } from \"react\";\nimport { Lamp } from \"@/components/Lamp\";\nimport { Badge } from \"@/components/Badge\";\nimport { Icon } from \"@/components/Icon\";\nimport { fmt } from \"@/components/ui\";\nimport type { UsageLog } from \"@/lib/gateway\";\n\ntype StatusFilter = \"all\" | \"ok\" | \"error\";\n\nconst FILTERS: { key: StatusFilter; label: string }[] = [\n { key: \"all\", label: \"All\" },\n { key: \"ok\", label: \"Success\" },\n { key: \"error\", label: \"Errors\" },\n];\n\n// shared control style for the filter row — bordered surface chip, accent on focus.\nconst ctrl = \"h-9 rounded-brand border border-border bg-surface-2 px-2.5 text-[12.5px] text-text focus:border-accent focus:outline-none\";\n\n// recency presets for the request log (a live 200-row buffer, so relative\n// windows fit better than absolute dates). null = no time filter.\nconst SINCE_PRESETS: { label: string; ms: number | null }[] = [\n { label: \"1h\", ms: 3600_000 },\n { label: \"6h\", ms: 6 * 3600_000 },\n { label: \"24h\", ms: 24 * 3600_000 },\n { label: \"7d\", ms: 7 * 86400_000 },\n { label: \"All\", ms: null },\n];\nconst sincePill = (active: boolean): string =>\n `rounded-full px-2.5 py-1 text-[12px] font-medium transition-colors ${\n active ? \"bg-accent/15 text-accent\" : \"text-text-muted hover:text-text\"\n }`;\n\nexport function LogTable({ logs: initial }: { logs: UsageLog[] }) {\n const [logs, setLogs] = useState(initial);\n const [filter, setFilter] = useState<StatusFilter>(\"all\");\n const [provFilter, setProvFilter] = useState<string>(\"all\");\n const [sinceMs, setSinceMs] = useState<number | null>(null);\n const [live, setLive] = useState(true);\n const [collapsed, setCollapsed] = useState(false);\n const [expandedIdx, setExpandedIdx] = useState<number | null>(null);\n const timer = useRef<ReturnType<typeof setInterval> | null>(null);\n\n const refresh = useCallback(async () => {\n try {\n const res = await fetch(\"/api/gw/admin/logs?limit=200\");\n if (res.ok) {\n const data = (await res.json()) as { logs: UsageLog[] };\n setLogs(data.logs);\n }\n } catch { /* ignore */ }\n }, []);\n\n useEffect(() => {\n if (live) {\n timer.current = setInterval(refresh, 5000);\n return () => { if (timer.current) clearInterval(timer.current); };\n }\n if (timer.current) clearInterval(timer.current);\n }, [live, refresh]);\n\n const providers = [...new Set(logs.map((l) => l.provider))].sort();\n\n const okCount = logs.filter((l) => l.status >= 200 && l.status < 300).length;\n const errCount = logs.length - okCount;\n\n const sinceFloor = sinceMs !== null ? Date.now() - sinceMs : null;\n\n const shown = logs.filter((l) => {\n if (filter === \"ok\" && !(l.status >= 200 && l.status < 300)) return false;\n if (filter === \"error\" && l.status >= 200 && l.status < 300) return false;\n if (provFilter !== \"all\" && l.provider !== provFilter) return false;\n if (sinceFloor !== null && l.ts < sinceFloor) return false;\n return true;\n });\n\n const hasFilters = filter !== \"all\" || provFilter !== \"all\" || sinceMs !== null;\n const clearFilters = () => { setFilter(\"all\"); setProvFilter(\"all\"); setSinceMs(null); };\n\n const count = (k: StatusFilter) => (k === \"all\" ? logs.length : k === \"ok\" ? okCount : errCount);\n\n return (\n <div className=\"overflow-hidden rounded-brand-lg border border-border bg-surface shadow-soft\">\n <header className=\"flex flex-col gap-3 border-b border-border-subtle px-4 py-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"flex items-center gap-1.5\">\n <button\n onClick={() => setCollapsed((v) => !v)}\n className=\"flex-none rounded p-0.5 text-text-subtle transition-colors hover:text-text\"\n aria-label={collapsed ? \"Expand requests\" : \"Collapse requests\"}\n title={collapsed ? \"Expand\" : \"Collapse\"}\n >\n <Icon name={collapsed ? \"chevron_right\" : \"expand_more\"} size={18} />\n </button>\n <div className=\"flex items-center gap-1\">\n {FILTERS.map((f) => (\n <button\n key={f.key}\n onClick={() => setFilter(f.key)}\n className={`flex items-center gap-1.5 rounded-full px-3 py-1.5 text-[12px] font-medium transition-colors ${\n filter === f.key ? \"bg-surface-2 text-text\" : \"text-text-muted hover:text-text\"\n }`}\n >\n {f.label}\n <span className=\"tnum text-text-subtle\">{count(f.key)}</span>\n </button>\n ))}\n </div>\n </div>\n <button\n onClick={() => setLive((v) => !v)}\n className={`flex items-center gap-1 rounded-full px-2.5 py-1 text-[11px] font-medium transition-colors ${\n live ? \"bg-success/15 text-success\" : \"text-text-muted hover:text-text\"\n }`}\n title={live ? \"Auto-refresh ON (5s)\" : \"Auto-refresh OFF\"}\n >\n <Icon name={live ? \"radio_button_checked\" : \"radio_button_unchecked\"} size={12} />\n Live\n </button>\n </div>\n\n {!collapsed && (\n <div className=\"flex flex-wrap items-end gap-2.5\">\n <FilterField label=\"Provider\">\n <select\n value={provFilter}\n onChange={(e) => setProvFilter(e.target.value)}\n className={ctrl + \" w-40\"}\n >\n <option value=\"all\">All providers</option>\n {providers.map((p) => (\n <option key={p} value={p}>{p}</option>\n ))}\n </select>\n </FilterField>\n <FilterField label=\"Since\">\n <div className=\"flex h-9 items-center gap-0.5 rounded-brand border border-border bg-surface-2 px-1\">\n {SINCE_PRESETS.map((p) => (\n <button\n key={p.label}\n type=\"button\"\n onClick={() => setSinceMs(p.ms)}\n className={sincePill(sinceMs === p.ms)}\n >\n {p.label}\n </button>\n ))}\n </div>\n </FilterField>\n <button\n onClick={clearFilters}\n disabled={!hasFilters}\n className=\"flex h-9 items-center gap-1.5 rounded-brand border border-border bg-surface-2 px-3 text-[12.5px] font-medium text-text-muted transition-colors hover:border-text-subtle hover:text-text disabled:opacity-40 disabled:hover:border-border disabled:hover:text-text-muted\"\n title={hasFilters ? \"Reset all filters\" : \"No filters applied\"}\n >\n <Icon name=\"filter_alt_off\" size={15} />\n Clear\n </button>\n </div>\n )}\n </header>\n\n {collapsed ? null : shown.length === 0 ? (\n <div className=\"px-4 py-8 text-center text-[13px] text-text-muted\">\n {logs.length === 0 ? \"No requests recorded yet.\" : \"No requests match this filter.\"}\n </div>\n ) : (\n <>\n <div className=\"table-wrap\">\n <table className=\"w-full min-w-[720px] border-collapse\">\n <thead>\n <tr className=\"text-text-subtle\">\n {[\"Status\", \"Time\", \"Alias\", \"Provider\", \"Model\", \"In\", \"Out\", \"ms\", \"Mode\"].map((h, i) => (\n <th\n key={h + i}\n className={`whitespace-nowrap px-4 pb-2.5 pt-3 text-[10px] font-medium uppercase tracking-wider ${\n i >= 5 && i <= 7 ? \"text-right\" : \"text-left\"\n }`}\n >\n {h}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {shown.map((l, i) => {\n const ok = l.status >= 200 && l.status < 300;\n const isExpanded = expandedIdx === i;\n return (\n <tr key={i} onClick={() => setExpandedIdx(isExpanded ? null : i)} className={`border-t border-border-subtle cursor-pointer transition-colors ${isExpanded ? \"bg-surface-2/60\" : \"hover:bg-surface-2/70\"}`}>\n <Td>\n <Badge tone={ok ? \"live\" : \"down\"}>\n <Lamp state={ok ? \"live\" : \"down\"} />\n {l.status}\n </Badge>\n </Td>\n <Td muted title={fmt.time(l.ts)} suppressHydrationWarning>\n {fmt.ago(l.ts)} ago\n </Td>\n <Td className=\"text-text\">{l.alias}</Td>\n <Td muted>{l.provider}</Td>\n <Td muted>{l.model}</Td>\n <Td right>{fmt.int(l.tokens_in)}</Td>\n <Td right>{fmt.int(l.tokens_out)}</Td>\n <Td right>{fmt.int(l.latency_ms)}</Td>\n <Td muted>{l.stream ? \"stream\" : \"unary\"}</Td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n\n {expandedIdx !== null && shown[expandedIdx] && (\n <RequestDetail log={shown[expandedIdx]} onClose={() => setExpandedIdx(null)} />\n )}\n </>\n )}\n </div>\n );\n}\n\nfunction FilterField({ label, children }: { label: string; children: React.ReactNode }) {\n return (\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-[10px] font-medium uppercase tracking-wider text-text-subtle\">{label}</span>\n {children}\n </label>\n );\n}\n\nfunction Td({\n children,\n muted,\n right,\n title,\n className,\n suppressHydrationWarning,\n}: {\n children: React.ReactNode;\n muted?: boolean;\n right?: boolean;\n title?: string;\n className?: string;\n suppressHydrationWarning?: boolean;\n}) {\n return (\n <td\n title={title}\n suppressHydrationWarning={suppressHydrationWarning}\n className={`whitespace-nowrap px-4 py-2.5 tnum text-[12.5px] ${right ? \"text-right\" : \"text-left\"} ${\n muted ? \"text-text-muted\" : \"text-text\"\n }${className ? ` ${className}` : \"\"}`}\n >\n {children}\n </td>\n );\n}\n\nfunction RequestDetail({ log, onClose }: { log: UsageLog; onClose: () => void }) {\n const ok = log.status >= 200 && log.status < 300;\n const totalTokens = log.tokens_in + log.tokens_out;\n\n return (\n <div className=\"border-t border-border-subtle bg-surface-2/40 px-5 py-4\">\n <div className=\"mb-3 flex items-center justify-between\">\n <span className=\"text-[12px] font-semibold text-text\">Request Details</span>\n <button onClick={onClose} className=\"text-text-subtle hover:text-text\">\n <Icon name=\"close\" size={16} />\n </button>\n </div>\n <div className=\"grid grid-cols-2 gap-x-8 gap-y-2 text-[12px] sm:grid-cols-4\">\n <DetailCell label=\"Status\" value={`${log.status} ${ok ? \"OK\" : \"Error\"}`} />\n <DetailCell label=\"Timestamp\" value={new Date(log.ts).toLocaleString()} />\n <DetailCell label=\"Alias\" value={log.alias} />\n <DetailCell label=\"Provider\" value={log.provider} />\n <DetailCell label=\"Model\" value={log.model} />\n <DetailCell label=\"Mode\" value={log.stream ? \"Streaming\" : \"Unary\"} />\n <DetailCell label=\"Latency\" value={`${log.latency_ms}ms`} />\n <DetailCell label=\"Cost\" value={fmt.cost(log.cost)} />\n <DetailCell label=\"Input tokens\" value={fmt.int(log.tokens_in)} />\n <DetailCell label=\"Output tokens\" value={fmt.int(log.tokens_out)} />\n <DetailCell label=\"Cached tokens\" value={fmt.int(log.cached_tokens)} />\n <DetailCell label=\"Total tokens\" value={fmt.int(totalTokens)} />\n </div>\n </div>\n );\n}\n\nfunction DetailCell({ label, value }: { label: string; value: string }) {\n return (\n <div>\n <span className=\"text-[10px] uppercase tracking-wider text-text-subtle\">{label}</span>\n <div className=\"tnum text-text\">{value}</div>\n </div>\n );\n}\n"],"names":["METRICS","key","label","valueOf","p","m","tokens_in","tokens_out","cost","requests","fmtVal","v","toFixed","String","Math","round","fmtTime","ts","Date","toLocaleTimeString","hour","minute","hour12","fmtDate","toLocaleDateString","month","day","AreaChart","series","metric","setMetric","hoverIdx","setHoverIdx","svgRef","W","H","padX","padY","vals","map","max","n","length","xPos","i","yPos","line","join","area","peak","indexOf","total","reduce","a","b","handleMouseMove","e","current","rect","getBoundingClientRect","relX","clientX","left","width","idx","min","handleMouseLeave","hp","className","onClick","ref","viewBox","preserveAspectRatio","onMouseMove","onMouseLeave","id","x1","y1","x2","y2","offset","stopColor","stopOpacity","d","fill","stroke","strokeWidth","vectorEffect","cx","cy","r","strokeDasharray","opacity","style","transform","FILTERS","ctrl","SINCE_PRESETS","ms","sincePill","active","LogTable","logs","initial","setLogs","filter","setFilter","provFilter","setProvFilter","sinceMs","setSinceMs","live","setLive","collapsed","setCollapsed","expandedIdx","setExpandedIdx","timer","refresh","res","fetch","ok","data","json","setInterval","clearInterval","providers","Set","l","provider","sort","okCount","status","errCount","sinceFloor","now","shown","hasFilters","clearFilters","count","k","title","name","size","f","FilterField","value","onChange","target","type","disabled","h","isExpanded","Td","tone","state","muted","time","suppressHydrationWarning","ago","alias","model","right","int","latency_ms","stream","RequestDetail","log","onClose","children","totalTokens","DetailCell","toLocaleString","cached_tokens"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
module.exports=[33410,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(50944),e=a.i(56173),f=a.i(47153),g=a.i(2693),h=a.i(2799),i=a.i(85732),j=a.i(7078),k=a.i(93026),l=a.i(58918);function m({checked:a,indeterminate:c,onChange:d,className:e,ariaLabel:f}){let g=a||c;return(0,b.jsx)("button",{type:"button",role:"checkbox","aria-checked":c?"mixed":a,"aria-label":f,onClick:a=>{a.stopPropagation(),d()},className:`flex h-[18px] w-[18px] flex-none items-center justify-center rounded-[5px] border transition-colors ${g?"border-accent bg-accent text-accent-ink":"border-border bg-bg text-transparent hover:border-text-subtle"}${e?` ${e}`:""}`,children:(0,b.jsx)(k.Icon,{name:c?"remove":"check",size:13})})}function n({models:a,busy:d,onAdd:e,onClose:f}){let[g,h]=(0,c.useState)(""),[i,l]=(0,c.useState)(()=>new Set(a.filter(a=>!a.added).map(a=>a.id))),o=(0,c.useMemo)(()=>{let b=g.trim().toLowerCase();return b?a.filter(a=>a.id.toLowerCase().includes(b)):a},[a,g]);function p(a){l(b=>{let c=new Set(b);return c.has(a)?c.delete(a):c.add(a),c})}let q=o.filter(a=>i.has(a.id)).length,r=o.length>0&&q===o.length;function s(){l(a=>{let b=new Set(a);return r?o.forEach(a=>b.delete(a.id)):o.forEach(a=>b.add(a.id)),b})}return(0,b.jsx)("div",{className:"fixed inset-0 z-50 grid place-items-center bg-black/50 p-6",onClick:f,children:(0,b.jsxs)("div",{className:"flex max-h-[80vh] w-full max-w-[480px] flex-col overflow-hidden rounded-brand-lg border border-border bg-surface shadow-elevated",onClick:a=>a.stopPropagation(),children:[(0,b.jsxs)("header",{className:"flex items-center justify-between border-b border-border-subtle px-4 py-3",children:[(0,b.jsxs)("span",{className:"text-[14px] font-semibold text-text",children:[a.length," models found"]}),(0,b.jsx)("button",{onClick:f,className:"text-text-subtle hover:text-text","aria-label":"Close",children:(0,b.jsx)(k.Icon,{name:"close",size:18})})]}),(0,b.jsx)("div",{className:"border-b border-border-subtle px-4 py-2.5",children:(0,b.jsx)(j.Input,{value:g,onChange:a=>h(a.target.value),placeholder:"filter…",autoFocus:!0})}),o.length>0&&(0,b.jsxs)("button",{onClick:s,className:"flex items-center gap-2.5 border-b border-border-subtle px-4 py-2 text-left hover:bg-surface-2",children:[(0,b.jsx)(m,{checked:r,indeterminate:q>0&&!r,onChange:s,ariaLabel:"Select all"}),(0,b.jsxs)("span",{className:"text-[12.5px] font-medium text-text",children:["Select all",g?" (filtered)":""]}),(0,b.jsxs)("span",{className:"ml-auto tnum text-[11px] text-text-subtle",children:[q,"/",o.length]})]}),(0,b.jsx)("div",{className:"flex-1 overflow-y-auto px-2 py-2",children:0===o.length?(0,b.jsx)("div",{className:"px-2 py-6 text-center text-[13px] text-text-muted",children:"No matches."}):o.map(a=>{let c=i.has(a.id);return(0,b.jsxs)("button",{onClick:()=>p(a.id),className:`flex w-full items-center gap-2.5 rounded-brand border px-2.5 py-2 text-left transition-colors ${c?"border-accent/40 bg-accent-soft":"border-transparent hover:bg-surface-2"}`,children:[(0,b.jsx)(m,{checked:c,onChange:()=>p(a.id),ariaLabel:a.id}),(0,b.jsx)("span",{className:"flex-1 truncate text-[12.5px] text-text",children:a.id}),a.added&&(0,b.jsx)("span",{className:"text-[11px] text-text-subtle",children:"in catalog"})]},a.id)})}),(0,b.jsxs)("footer",{className:"flex items-center justify-between gap-3 border-t border-border-subtle bg-bg-alt px-4 py-2.5",children:[(0,b.jsxs)("span",{className:"tnum text-[12px] text-text-muted",children:[i.size," selected"]}),(0,b.jsxs)("div",{className:"flex gap-2",children:[(0,b.jsx)(j.Button,{variant:"ghost",onClick:f,children:"Cancel"}),(0,b.jsx)(j.Button,{disabled:0===i.size||d,onClick:()=>e([...i]),children:d?"Adding…":`Add ${i.size}`})]})]})]})})}var o=a.i(52065),p=a.i(73858);function q({k:a,v:c}){return(0,b.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,b.jsx)("span",{className:"text-text-subtle",children:a}),(0,b.jsx)("span",{className:"truncate text-text",children:c})]})}a.s(["ProviderDetail",0,function({id:a}){let m=(0,d.useRouter)(),[r,s]=(0,c.useState)(null),[t,u]=(0,c.useState)(null),[v,w]=(0,c.useState)(""),[x,y]=(0,c.useState)(null),[z,A]=(0,c.useState)(""),[B,C]=(0,c.useState)(""),[D,E]=(0,c.useState)(""),[F,G]=(0,c.useState)(null),[H,I]=(0,c.useState)(""),[J,K]=(0,c.useState)(""),[L,M]=(0,c.useState)(""),[N,O]=(0,c.useState)(""),[P,Q]=(0,c.useState)(null),[R,S]=(0,c.useState)({}),[T,U]=(0,c.useState)({}),[V,W]=(0,c.useState)(!1),[X,Y]=(0,c.useState)(null),Z=(0,c.useRef)(!1),[$,_]=(0,c.useState)(!1),[aa,ab]=(0,c.useState)(""),[ac,ad]=(0,c.useState)(""),[ae,af]=(0,c.useState)({}),[ag,ah]=(0,c.useState)(!1);async function ai(b){S(a=>({...a,[b]:"testing"}));let c=await e.adminApi.testModel(a,b);S(a=>({...a,[b]:c.ok&&c.data?.ok?"ok":"fail"}))}async function aj(b){U(a=>({...a,[b]:"testing"}));let c=await e.adminApi.testKey(a,b);U(a=>({...a,[b]:c.data??{ok:!1,reachable:!1,status:0,error:c.error}}))}async function ak(b){Z.current=!1,W(!0),Y(null),U({});let c=0,d=0;for(let f=0;f<b&&!Z.current;f++){U(a=>({...a,[f]:"testing"}));let g=await e.adminApi.testKey(a,f),h=g.data??{ok:!1,reachable:!1,status:0,error:g.error};U(a=>({...a,[f]:h})),h.ok?c++:d++,f<b-1&&!Z.current&&await new Promise(a=>setTimeout(a,500))}W(!1),Y({total:b,passed:c,failed:d})}let al=(0,c.useCallback)(async()=>{let[b,c]=await Promise.all([fetch("/api/gw/admin/config"),e.adminApi.providers()]);if(!b.ok)return void w("could not reach the gateway");let d=(await b.json()).providers.find(b=>b.id===a)??null;d?(w(""),s(d),u(c.data?.providers.find(b=>b.id===a)??null)):w(`provider "${a}" not found`)},[a]);if((0,c.useEffect)(()=>{al()},[al]),v)return(0,b.jsx)(l.Empty,{children:v});if(!r)return(0,b.jsx)(l.Empty,{children:"Loading…"});let am=r.api_keys??(r.api_key?[r.api_key]:[]),an=N.trim().toLowerCase(),ao=an?r.models.filter(a=>a.id.toLowerCase().includes(an)):r.models;async function ap(a,b){A(a);let c=await b();A(""),c.ok?(w(""),await al()):w(c.error??"action failed")}return(0,b.jsxs)("div",{children:[(0,b.jsxs)("button",{onClick:()=>m.push("/providers"),className:"mb-4 inline-flex items-center gap-1 text-[12px] text-text-muted hover:text-text",children:[(0,b.jsx)(k.Icon,{name:"arrow_back",size:15})," Providers"]}),(0,b.jsxs)("div",{className:"mb-6 flex items-center gap-3",children:[(0,b.jsx)(f.Lamp,{state:r.disabled?"idle":t?.keys.some(a=>a.healthy)??!0?"live":"down"}),(0,b.jsxs)("div",{children:[(0,b.jsx)("h1",{className:"text-[22px] font-semibold tracking-tight text-text",children:r.name||r.id}),r.name&&(0,b.jsxs)("span",{className:"text-[12px] text-text-subtle",children:[r.id,"/"]})]}),(0,b.jsx)(g.FormatBadge,{format:r.format}),r.free&&(0,b.jsx)(g.Badge,{tone:"info",children:"free"}),r.service_account&&(0,b.jsx)(g.Badge,{tone:"info",children:"service-account"}),r.disabled&&(0,b.jsx)(g.Badge,{tone:"down",children:"disabled"})]}),(0,b.jsxs)("div",{className:`grid gap-4 lg:grid-cols-2 transition-opacity ${r.disabled?"opacity-50":""}`,children:[(0,b.jsx)(i.RichCard,{header:(0,b.jsx)(i.CardTitle,{title:"Connection"}),children:$?(0,b.jsxs)("div",{className:"space-y-3",children:[(0,b.jsx)(j.Field,{label:"Name",hint:"the id — also the call prefix (name/model) & combos",children:(0,b.jsx)(j.Input,{value:ac,onChange:a=>ad(a.target.value),placeholder:"e.g. openai",className:"font-mono text-[12.5px]"})}),ac.trim()&&ac.trim()!==a&&(0,b.jsxs)("p",{className:"flex items-start gap-1.5 rounded-brand border border-warning/40 bg-warning/8 px-2.5 py-2 text-[11.5px] text-warning",children:[(0,b.jsx)(k.Icon,{name:"warning",size:14,className:"mt-0.5 flex-none"}),(0,b.jsxs)("span",{children:["Renaming rewrites the call string. CLI tools pointing at"," ",(0,b.jsxs)("code",{className:"tnum",children:[a,"/…"]})," will break until repointed; combos that target it are updated automatically."]})]}),(0,b.jsx)(j.Field,{label:"Base URL",children:(0,b.jsx)(j.Input,{value:aa,onChange:a=>ab(a.target.value),placeholder:"https://...",className:"font-mono text-[12.5px]"})}),(0,b.jsxs)("div",{className:"flex justify-end gap-2",children:[(0,b.jsx)(j.Button,{variant:"ghost",onClick:()=>_(!1),children:"Cancel"}),(0,b.jsx)(j.Button,{disabled:"editconn"===z,onClick:()=>ap("editconn",async()=>{let b=ac.trim(),c=a;if(b&&b!==a){let d=await e.adminApi.renameProvider(a,b);if(!d.ok)return d;c=b}let d=await e.adminApi.editProvider(c,{base_url:aa.trim()||void 0});return d.ok&&(_(!1),c!==a&&m.push(`/providers/${encodeURIComponent(c)}`)),d}),children:"Save"})]})]}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("div",{className:"space-y-2 text-[13px]",children:[(0,b.jsx)(q,{k:"Base URL",v:r.base_url}),(0,b.jsx)(q,{k:"Format",v:r.format}),(0,b.jsx)(q,{k:"Cooldown base",v:`${r.cooldown_base_ms}ms`}),(0,b.jsx)(q,{k:"Max retries",v:String(r.max_retries)})]}),(0,b.jsxs)("div",{className:"mt-4 flex items-center gap-2",children:[(0,b.jsxs)(j.Button,{variant:"ghost",onClick:()=>{_(!0),ab(r.base_url),ad(r.id)},children:[(0,b.jsx)(k.Icon,{name:"edit",size:15})," Edit"]}),(0,b.jsxs)(j.Button,{variant:"ghost",disabled:"test"===z,onClick:()=>ap("test",async()=>{let b=await e.adminApi.testProvider(a);return b.ok&&y(b.data),b}),children:[(0,b.jsx)(k.Icon,{name:"wifi_tethering",size:16})," ","test"===z?"Testing…":"Test connection"]}),(0,b.jsxs)(j.Button,{variant:"ghost",disabled:"discover"===z,onClick:()=>ap("discover",async()=>{let b=await e.adminApi.discoverModels(a);return b.ok&&Q(b.data?.models??[]),b}),children:[(0,b.jsx)(k.Icon,{name:"sync",size:16})," ","discover"===z?"Fetching…":"Fetch models"]})]}),x&&(0,b.jsxs)("div",{className:"mt-3 text-[12px]",children:[(0,b.jsx)(g.Badge,{tone:x.ok?"live":x.reachable?"warn":"down",children:x.ok?`ok (${x.status})`:x.reachable?`reachable (${x.status})`:"unreachable"}),x.error&&(0,b.jsx)("span",{className:"ml-2 text-text-subtle",children:x.error})]})]})}),(0,b.jsxs)(i.RichCard,{header:(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(i.CardTitle,{title:"Keys",sub:`${am.length} configured`}),(0,b.jsxs)("div",{className:"flex flex-wrap items-center gap-3",children:[am.length>1&&(0,b.jsxs)(j.Button,{variant:"ghost",disabled:V,onClick:()=>ak(am.length),children:[(0,b.jsx)(k.Icon,{name:V?"progress_activity":"sync",size:15}),V?"Testing…":"Test All"]}),V&&(0,b.jsxs)(j.Button,{variant:"ghost",onClick:()=>{Z.current=!0},children:[(0,b.jsx)(k.Icon,{name:"stop",size:15})," Stop"]}),(0,b.jsx)("span",{className:"text-[11px] text-text-subtle",children:"Round Robin"}),(0,b.jsx)("button",{onClick:()=>{let b="round-robin"===r.strategy?null:"round-robin";e.adminApi.setProviderStrategy(a,b,r.sticky??1).then(()=>al())},className:`relative h-5 w-9 rounded-full transition-colors ${"round-robin"===r.strategy?"bg-accent":"bg-border-subtle"}`,"aria-label":"Toggle round-robin",children:(0,b.jsx)("span",{className:`absolute left-0.5 top-0.5 h-4 w-4 rounded-full bg-white transition-transform ${"round-robin"===r.strategy?"translate-x-[18px]":"translate-x-0"}`})}),"round-robin"===r.strategy&&(0,b.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,b.jsx)("span",{className:"text-[11px] text-text-subtle",children:"Sticky:"}),(0,b.jsxs)("div",{className:"flex items-center rounded-brand border border-border-subtle",children:[(0,b.jsx)("button",{type:"button",disabled:(r.sticky??1)<=1,onClick:()=>void e.adminApi.setProviderStrategy(a,"round-robin",Math.max(1,(r.sticky??1)-1)).then(()=>al()),className:"px-1.5 py-0.5 text-text-subtle transition-colors hover:text-text disabled:opacity-30","aria-label":"Decrease sticky",children:(0,b.jsx)(k.Icon,{name:"remove",size:13})}),(0,b.jsx)("span",{className:"tnum w-6 text-center text-[11px] text-text",children:r.sticky??1}),(0,b.jsx)("button",{type:"button",onClick:()=>void e.adminApi.setProviderStrategy(a,"round-robin",(r.sticky??1)+1).then(()=>al()),className:"px-1.5 py-0.5 text-text-subtle transition-colors hover:text-text","aria-label":"Increase sticky",children:(0,b.jsx)(k.Icon,{name:"add",size:13})})]})]})]})]}),children:[X&&(0,b.jsx)("div",{className:"mb-3 flex items-center gap-2 text-[11.5px]",children:(0,b.jsxs)(g.Badge,{tone:0===X.failed?"live":"warn",children:[X.total," tested: ",X.passed," valid, ",X.failed," failed"]})}),0===am.length?(0,b.jsx)(l.Empty,{children:"No keys (free / service-account provider)."}):(0,b.jsx)("div",{className:"space-y-1.5",children:am.map((c,d)=>{let i=t?.keys[d],l=T[d],m=l&&"testing"!==l?l:null,n=m?m.ok?"live":m.reachable?"idle":"down":i?i.healthy?"live":"down":"idle",o=r.key_names?.[c],p=r.disabled_keys?.includes(d)??!1;return F===d?(0,b.jsxs)("div",{className:"space-y-2 rounded-brand border border-accent bg-accent-soft/40 px-3 py-2.5",children:[(0,b.jsx)(j.Input,{value:H,onChange:a=>I(a.target.value),placeholder:"key name (optional)"}),(0,b.jsx)(j.Input,{value:J,onChange:a=>K(a.target.value),placeholder:"new key value (leave blank to keep)",className:"font-mono text-[12.5px]"}),(0,b.jsxs)("div",{className:"flex justify-end gap-2",children:[(0,b.jsx)(j.Button,{variant:"ghost",onClick:()=>G(null),children:"Cancel"}),(0,b.jsx)(j.Button,{disabled:z===`editkey${d}`,onClick:()=>ap(`editkey${d}`,async()=>{let b=await e.adminApi.editKey(a,d,{name:H,key:J.trim()||void 0});return b.ok&&G(null),b}),children:"Save"})]})]},d):(0,b.jsxs)("div",{className:`rounded-brand border border-border-subtle px-3 py-2${p?" opacity-60":""}`,children:[(0,b.jsxs)("div",{className:"flex items-center gap-2",children:[(0,b.jsxs)("div",{className:"flex flex-col",children:[(0,b.jsx)("button",{onClick:()=>ap(`reorder${d}up`,()=>e.adminApi.reorderKey(a,d,d-1)),disabled:0===d,className:"p-0.5 text-text-subtle hover:text-text disabled:opacity-30","aria-label":"Move up",children:(0,b.jsx)(k.Icon,{name:"keyboard_arrow_up",size:14})}),(0,b.jsx)("button",{onClick:()=>ap(`reorder${d}dn`,()=>e.adminApi.reorderKey(a,d,d+1)),disabled:d===am.length-1,className:"p-0.5 text-text-subtle hover:text-text disabled:opacity-30","aria-label":"Move down",children:(0,b.jsx)(k.Icon,{name:"keyboard_arrow_down",size:14})})]}),(0,b.jsx)(f.Lamp,{state:n}),(0,b.jsxs)("div",{className:"min-w-0 flex-1",children:[o&&(0,b.jsx)("div",{className:"text-[12px] font-semibold text-text-muted",children:o}),(0,b.jsx)("span",{className:"block truncate font-mono text-[12.5px] text-text",children:ae[d]??c})]}),ae[d]&&(0,b.jsx)("button",{onClick:()=>{navigator.clipboard.writeText(ae[d])},className:"flex-none rounded p-1 text-text-subtle transition-colors hover:text-text","aria-label":"Copy key",title:"Copy to clipboard",children:(0,b.jsx)(k.Icon,{name:"content_copy",size:14})}),i&&i.cooldown_ms>0&&(0,b.jsx)(h.CooldownTimer,{ms:i.cooldown_ms}),(0,b.jsx)("button",{onClick:async()=>{if(ae[d])return void af(a=>{let b={...a};return delete b[d],b});let b=await e.adminApi.revealKey(a,d);b.ok&&b.data?.key&&af(a=>({...a,[d]:b.data.key}))},className:"flex-none rounded p-1 text-text-subtle transition-colors hover:text-text","aria-label":ae[d]?"Hide key":"Show key",title:ae[d]?"Hide key":"Show key",children:(0,b.jsx)(k.Icon,{name:ae[d]?"visibility_off":"visibility",size:15})}),(0,b.jsx)("button",{onClick:()=>ap(`toggle${d}`,()=>e.adminApi.toggleKey(a,d,p)),className:"flex-none rounded p-1 text-text-subtle transition-colors hover:text-text","aria-label":p?"Enable key":"Disable key",title:p?"Enable this key":"Disable this key",children:(0,b.jsx)(k.Icon,{name:p?"toggle_off":"toggle_on",size:20,className:p?"text-text-subtle":"text-success"})}),(0,b.jsx)("button",{onClick:()=>aj(d),disabled:"testing"===l,className:"flex-none rounded p-1 text-text-subtle transition-colors hover:text-text disabled:opacity-60","aria-label":`Check key ${d+1}`,title:"Check this key against the base URL",children:(0,b.jsx)(k.Icon,{name:"testing"===l?"progress_activity":"wifi_tethering",size:15})}),(0,b.jsx)("button",{onClick:()=>{G(d),I(o??""),K("")},className:"flex-none rounded p-1 text-text-subtle transition-colors hover:text-text","aria-label":`Edit key ${d+1}`,title:"Rename or replace this key",children:(0,b.jsx)(k.Icon,{name:"edit",size:15})}),(0,b.jsx)("button",{onClick:()=>ap(`rmkey${d}`,()=>e.adminApi.removeKey(a,d)),className:"flex-none rounded p-1 text-text-subtle transition-colors hover:text-danger","aria-label":"Remove key",children:(0,b.jsx)(k.Icon,{name:"delete",size:15})})]}),m&&(0,b.jsxs)("div",{className:"mt-1.5 flex items-center gap-2 pl-8 text-[11.5px]",children:[(0,b.jsx)(g.Badge,{tone:m.ok?"live":m.reachable?"warn":"down",children:m.ok?"valid":m.reachable?`reachable (${m.status})`:"invalid"}),m.error&&(0,b.jsx)("span",{className:"truncate text-danger",children:m.error})]}),!m&&i?.last_error&&(0,b.jsxs)("div",{className:"mt-1.5 flex items-center gap-2 pl-8 text-[11.5px]",children:[(0,b.jsxs)("span",{className:"text-danger",children:[i.last_error.status?`${i.last_error.status}: `:"",i.last_error.message]}),(0,b.jsx)("span",{className:"text-text-subtle",children:new Date(i.last_error.at).toLocaleTimeString()})]})]},d)})}),(0,b.jsxs)("div",{className:"mt-3 space-y-2",children:[(0,b.jsx)(j.Input,{value:D,onChange:a=>E(a.target.value),placeholder:"key name (optional, e.g. primary)"}),(0,b.jsxs)("div",{className:"flex gap-2",children:[(0,b.jsx)(j.Input,{value:B,onChange:a=>C(a.target.value),placeholder:"add a key…",className:"font-mono text-[12.5px]"}),(0,b.jsx)(j.Button,{disabled:!B||"addkey"===z,onClick:()=>ap("addkey",async()=>{let b=await e.adminApi.addKey(a,B,D.trim()||void 0);return b.ok&&(C(""),E("")),b}),children:"Add"})]})]})]}),(0,b.jsxs)(i.RichCard,{className:"lg:col-span-2",header:(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(i.CardTitle,{title:"Models served",sub:`${r.models.length} in catalog`}),r.models.length>0&&(0,b.jsx)("button",{onClick:()=>ap("clear",()=>e.adminApi.clearModels(a)),disabled:"clear"===z,className:"text-[12px] text-text-subtle hover:text-danger",children:"Clear all"})]}),children:[0===r.models.length?(0,b.jsx)(l.Empty,{children:"No models. Add one below, or fetch them for a free/auto provider."}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("p",{className:"mb-2.5 text-[12px] text-text-subtle",children:["Call any of these as ",(0,b.jsxs)("span",{className:"tnum text-text-muted",children:[r.id,"/<model>"]}),", as a combo alias, or by the bare id."]}),r.models.length>8&&(0,b.jsxs)("div",{className:"mb-2.5 flex items-center gap-2",children:[(0,b.jsxs)("div",{className:"relative flex-1",children:[(0,b.jsx)(k.Icon,{name:"search",size:15,className:"pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-text-subtle"}),(0,b.jsx)(j.Input,{value:N,onChange:a=>O(a.target.value),placeholder:"filter models…",className:"pl-8"})]}),(0,b.jsx)("span",{className:"tnum whitespace-nowrap text-[12px] text-text-subtle",children:an?`${ao.length} of ${r.models.length}`:`${r.models.length}`})]}),0===ao.length?(0,b.jsxs)(l.Empty,{children:["No model matches “",N,"”."]}):(0,b.jsx)("div",{className:"max-h-[360px] divide-y divide-border-subtle overflow-y-auto rounded-brand border border-border-subtle",children:ao.map(c=>{let d=R[c.id];return(0,b.jsxs)("div",{className:"group flex items-center justify-between gap-3 px-3 py-2 hover:bg-bg",children:[(0,b.jsxs)("div",{className:"flex min-w-0 items-center gap-2",children:[(0,b.jsx)(k.Icon,{name:"ok"===d?"check_circle":"fail"===d?"cancel":"smart_toy",size:15,className:`flex-none ${"ok"===d?"text-success":"fail"===d?"text-danger":"text-text-subtle"}`}),(0,b.jsxs)("span",{className:"tnum truncate text-[12.5px]",children:[(0,b.jsxs)("span",{className:"text-text-subtle",children:[r.id,"/"]}),(0,b.jsx)("span",{className:"text-text",children:c.id})]}),(0,b.jsx)(o.CapacityBadges,{model:c.id,provider:r.id}),(void 0!==c.price_in||void 0!==c.price_out)&&(0,b.jsxs)("span",{className:"tnum whitespace-nowrap text-[11px] text-text-subtle",children:[l.fmt.cost(c.price_in??0),"/",l.fmt.cost(c.price_out??0)," per 1M"]})]}),(0,b.jsxs)("div",{className:"flex flex-none items-center gap-0.5",children:[(0,b.jsx)("button",{onClick:()=>ai(c.id),disabled:"testing"===d,className:"rounded p-1 text-text-subtle transition-colors hover:bg-surface hover:text-accent disabled:opacity-60","aria-label":`Test ${c.id}`,title:"fail"===d?"Test failed — click to retry":"Test this model",children:(0,b.jsx)(k.Icon,{name:"testing"===d?"progress_activity":"science",size:15})}),(0,b.jsx)("button",{onClick:()=>ap(`rmmodel${c.id}`,()=>e.adminApi.removeModel(a,c.id)),disabled:z===`rmmodel${c.id}`,className:"rounded p-1 text-text-subtle transition-colors hover:bg-surface hover:text-danger disabled:opacity-40","aria-label":`Remove ${c.id}`,children:(0,b.jsx)(k.Icon,{name:"delete",size:16})})]})]},c.id)})})]}),(0,b.jsxs)("div",{className:"mt-3 flex gap-2",children:[(0,b.jsx)(j.Input,{value:L,onChange:a=>M(a.target.value),placeholder:"add a model id…"}),(0,b.jsx)(j.Button,{disabled:!L||"addmodel"===z,onClick:()=>ap("addmodel",async()=>{let b=await e.adminApi.addModel(a,L);return b.ok&&M(""),b}),children:"Add"})]})]})]}),P&&(0,b.jsx)(n,{models:P,busy:"addmodels"===z,onClose:()=>Q(null),onAdd:b=>ap("addmodels",async()=>{let c=await e.adminApi.addModels(a,b);return c.ok&&Q(null),c})}),(0,b.jsx)("div",{className:"mt-6",children:(0,b.jsxs)(j.Button,{variant:"danger",onClick:()=>ah(!0),children:[(0,b.jsx)(k.Icon,{name:"delete",size:16})," Remove provider"]})}),ag&&(0,b.jsx)(p.ConfirmModal,{title:"Remove provider",message:`Delete "${r.name??a}"? All keys and model associations will be lost.`,confirmLabel:"Remove",busy:"rmprov"===z,onCancel:()=>ah(!1),onConfirm:()=>ap("rmprov",async()=>{let b=await e.adminApi.removeProvider(a);return b.ok?m.push("/providers"):ah(!1),b})})]})}],33410)}];
|
|
1
|
+
module.exports=[33410,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(50944),e=a.i(56173),f=a.i(47153),g=a.i(2693),h=a.i(2799),i=a.i(85732),j=a.i(7078),k=a.i(93026),l=a.i(58918);function m({checked:a,indeterminate:c,onChange:d,className:e,ariaLabel:f}){let g=a||c;return(0,b.jsx)("button",{type:"button",role:"checkbox","aria-checked":c?"mixed":a,"aria-label":f,onClick:a=>{a.stopPropagation(),d()},className:`flex h-[18px] w-[18px] flex-none items-center justify-center rounded-[5px] border transition-colors ${g?"border-accent bg-accent text-accent-ink":"border-border bg-bg text-transparent hover:border-text-subtle"}${e?` ${e}`:""}`,children:(0,b.jsx)(k.Icon,{name:c?"remove":"check",size:13})})}function n({models:a,busy:d,onAdd:e,onClose:f}){let[g,h]=(0,c.useState)(""),[i,l]=(0,c.useState)(()=>new Set(a.filter(a=>!a.added).map(a=>a.id))),o=(0,c.useMemo)(()=>{let b=g.trim().toLowerCase();return b?a.filter(a=>a.id.toLowerCase().includes(b)):a},[a,g]);function p(a){l(b=>{let c=new Set(b);return c.has(a)?c.delete(a):c.add(a),c})}let q=o.filter(a=>i.has(a.id)).length,r=o.length>0&&q===o.length;function s(){l(a=>{let b=new Set(a);return r?o.forEach(a=>b.delete(a.id)):o.forEach(a=>b.add(a.id)),b})}return(0,b.jsx)("div",{className:"fixed inset-0 z-50 grid place-items-center bg-black/50 p-6",onClick:f,children:(0,b.jsxs)("div",{className:"flex max-h-[80vh] w-full max-w-[480px] flex-col overflow-hidden rounded-brand-lg border border-border bg-surface shadow-elevated",onClick:a=>a.stopPropagation(),children:[(0,b.jsxs)("header",{className:"flex items-center justify-between border-b border-border-subtle px-4 py-3",children:[(0,b.jsxs)("span",{className:"text-[14px] font-semibold text-text",children:[a.length," models found"]}),(0,b.jsx)("button",{onClick:f,className:"text-text-subtle hover:text-text","aria-label":"Close",children:(0,b.jsx)(k.Icon,{name:"close",size:18})})]}),(0,b.jsx)("div",{className:"border-b border-border-subtle px-4 py-2.5",children:(0,b.jsx)(j.Input,{value:g,onChange:a=>h(a.target.value),placeholder:"filter…",autoFocus:!0})}),o.length>0&&(0,b.jsxs)("button",{onClick:s,className:"flex items-center gap-2.5 border-b border-border-subtle px-4 py-2 text-left hover:bg-surface-2",children:[(0,b.jsx)(m,{checked:r,indeterminate:q>0&&!r,onChange:s,ariaLabel:"Select all"}),(0,b.jsxs)("span",{className:"text-[12.5px] font-medium text-text",children:["Select all",g?" (filtered)":""]}),(0,b.jsxs)("span",{className:"ml-auto tnum text-[11px] text-text-subtle",children:[q,"/",o.length]})]}),(0,b.jsx)("div",{className:"flex-1 overflow-y-auto px-2 py-2",children:0===o.length?(0,b.jsx)("div",{className:"px-2 py-6 text-center text-[13px] text-text-muted",children:"No matches."}):o.map(a=>{let c=i.has(a.id);return(0,b.jsxs)("button",{onClick:()=>p(a.id),className:`flex w-full items-center gap-2.5 rounded-brand border px-2.5 py-2 text-left transition-colors ${c?"border-accent/40 bg-accent-soft":"border-transparent hover:bg-surface-2"}`,children:[(0,b.jsx)(m,{checked:c,onChange:()=>p(a.id),ariaLabel:a.id}),(0,b.jsx)("span",{className:"flex-1 truncate text-[12.5px] text-text",children:a.id}),a.added&&(0,b.jsx)("span",{className:"text-[11px] text-text-subtle",children:"in catalog"})]},a.id)})}),(0,b.jsxs)("footer",{className:"flex items-center justify-between gap-3 border-t border-border-subtle bg-bg-alt px-4 py-2.5",children:[(0,b.jsxs)("span",{className:"tnum text-[12px] text-text-muted",children:[i.size," selected"]}),(0,b.jsxs)("div",{className:"flex gap-2",children:[(0,b.jsx)(j.Button,{variant:"ghost",onClick:f,children:"Cancel"}),(0,b.jsx)(j.Button,{disabled:0===i.size||d,onClick:()=>e([...i]),children:d?"Adding…":`Add ${i.size}`})]})]})]})})}var o=a.i(52065),p=a.i(73858);function q({k:a,v:c}){return(0,b.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,b.jsx)("span",{className:"text-text-subtle",children:a}),(0,b.jsx)("span",{className:"truncate text-text",children:c})]})}a.s(["ProviderDetail",0,function({id:a}){let m=(0,d.useRouter)(),[r,s]=(0,c.useState)(null),[t,u]=(0,c.useState)(null),[v,w]=(0,c.useState)(""),[x,y]=(0,c.useState)(null),[z,A]=(0,c.useState)(""),[B,C]=(0,c.useState)(""),[D,E]=(0,c.useState)(""),[F,G]=(0,c.useState)(null),[H,I]=(0,c.useState)(""),[J,K]=(0,c.useState)(""),[L,M]=(0,c.useState)(""),[N,O]=(0,c.useState)(""),[P,Q]=(0,c.useState)(null),[R,S]=(0,c.useState)({}),[T,U]=(0,c.useState)({}),[V,W]=(0,c.useState)(!1),[X,Y]=(0,c.useState)(null),Z=(0,c.useRef)(!1),[$,_]=(0,c.useState)(!1),[aa,ab]=(0,c.useState)(""),[ac,ad]=(0,c.useState)(""),[ae,af]=(0,c.useState)(""),[ag,ah]=(0,c.useState)({}),[ai,aj]=(0,c.useState)(!1);async function ak(b){S(a=>({...a,[b]:"testing"}));let c=await e.adminApi.testModel(a,b);S(a=>({...a,[b]:c.ok&&c.data?.ok?"ok":"fail"}))}async function al(b){U(a=>({...a,[b]:"testing"}));let c=await e.adminApi.testKey(a,b);U(a=>({...a,[b]:c.data??{ok:!1,reachable:!1,status:0,error:c.error}}))}async function am(b){Z.current=!1,W(!0),Y(null),U({});let c=0,d=0;for(let f=0;f<b&&!Z.current;f++){U(a=>({...a,[f]:"testing"}));let g=await e.adminApi.testKey(a,f),h=g.data??{ok:!1,reachable:!1,status:0,error:g.error};U(a=>({...a,[f]:h})),h.ok?c++:d++,f<b-1&&!Z.current&&await new Promise(a=>setTimeout(a,500))}W(!1),Y({total:b,passed:c,failed:d})}let an=(0,c.useCallback)(async()=>{let[b,c]=await Promise.all([fetch("/api/gw/admin/config"),e.adminApi.providers()]);if(!b.ok)return void w("could not reach the gateway");let d=(await b.json()).providers.find(b=>b.id===a)??null;d?(w(""),s(d),u(c.data?.providers.find(b=>b.id===a)??null)):w(`provider "${a}" not found`)},[a]);if((0,c.useEffect)(()=>{an()},[an]),v)return(0,b.jsx)(l.Empty,{children:v});if(!r)return(0,b.jsx)(l.Empty,{children:"Loading…"});let ao=r.api_keys??(r.api_key?[r.api_key]:[]),ap=N.trim().toLowerCase(),aq=ap?r.models.filter(a=>a.id.toLowerCase().includes(ap)):r.models;async function ar(a,b){A(a);let c=await b();A(""),c.ok?(w(""),await an()):w(c.error??"action failed")}return(0,b.jsxs)("div",{children:[(0,b.jsxs)("button",{onClick:()=>m.push("/providers"),className:"mb-4 inline-flex items-center gap-1 text-[12px] text-text-muted hover:text-text",children:[(0,b.jsx)(k.Icon,{name:"arrow_back",size:15})," Providers"]}),(0,b.jsxs)("div",{className:"mb-6 flex items-center gap-3",children:[(0,b.jsx)(f.Lamp,{state:r.disabled?"idle":t?.keys.some(a=>a.healthy)??!0?"live":"down"}),(0,b.jsxs)("div",{children:[(0,b.jsx)("h1",{className:"text-[22px] font-semibold tracking-tight text-text",children:r.name||r.id}),r.name&&(0,b.jsxs)("span",{className:"text-[12px] text-text-subtle",children:[r.id,"/"]})]}),(0,b.jsx)(g.FormatBadge,{format:r.format}),r.free&&(0,b.jsx)(g.Badge,{tone:"info",children:"free"}),r.service_account&&(0,b.jsx)(g.Badge,{tone:"info",children:"service-account"}),r.disabled&&(0,b.jsx)(g.Badge,{tone:"down",children:"disabled"})]}),(0,b.jsxs)("div",{className:`grid gap-4 lg:grid-cols-2 transition-opacity ${r.disabled?"opacity-50":""}`,children:[(0,b.jsx)(i.RichCard,{header:(0,b.jsx)(i.CardTitle,{title:"Connection"}),children:$?(0,b.jsxs)("div",{className:"space-y-3",children:[(0,b.jsx)(j.Field,{label:"Label",hint:"display name in dashboard (optional, does not affect routing)",children:(0,b.jsx)(j.Input,{value:ae,onChange:a=>af(a.target.value),placeholder:ac||"e.g. My Provider",className:"text-[12.5px]"})}),(0,b.jsx)(j.Field,{label:"ID / Prefix",hint:"the call prefix (id/model) — changing this breaks CLI tools",children:(0,b.jsx)(j.Input,{value:ac,onChange:a=>ad(a.target.value),placeholder:"e.g. openai",className:"font-mono text-[12.5px]"})}),ac.trim()&&ac.trim()!==a&&(0,b.jsxs)("p",{className:"flex items-start gap-1.5 rounded-brand border border-warning/40 bg-warning/8 px-2.5 py-2 text-[11.5px] text-warning",children:[(0,b.jsx)(k.Icon,{name:"warning",size:14,className:"mt-0.5 flex-none"}),(0,b.jsxs)("span",{children:["Renaming rewrites the call string. CLI tools pointing at"," ",(0,b.jsxs)("code",{className:"tnum",children:[a,"/…"]})," will break until repointed; combos that target it are updated automatically."]})]}),(0,b.jsx)(j.Field,{label:"Base URL",children:(0,b.jsx)(j.Input,{value:aa,onChange:a=>ab(a.target.value),placeholder:"https://...",className:"font-mono text-[12.5px]"})}),(0,b.jsxs)("div",{className:"flex justify-end gap-2",children:[(0,b.jsx)(j.Button,{variant:"ghost",onClick:()=>_(!1),children:"Cancel"}),(0,b.jsx)(j.Button,{disabled:"editconn"===z,onClick:()=>ar("editconn",async()=>{let b=ac.trim(),c=a;if(b&&b!==a){let d=await e.adminApi.renameProvider(a,b);if(!d.ok)return d;c=b}let d=ae.trim()||void 0,f=await e.adminApi.editProvider(c,{base_url:aa.trim()||void 0,name:d});return f.ok&&(_(!1),c!==a&&m.push(`/providers/${encodeURIComponent(c)}`)),f}),children:"Save"})]})]}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("div",{className:"space-y-2 text-[13px]",children:[r.name&&(0,b.jsx)(q,{k:"Label",v:r.name}),(0,b.jsx)(q,{k:"ID / Prefix",v:r.id}),(0,b.jsx)(q,{k:"Base URL",v:r.base_url}),(0,b.jsx)(q,{k:"Format",v:r.format}),(0,b.jsx)(q,{k:"Cooldown base",v:`${r.cooldown_base_ms}ms`}),(0,b.jsx)(q,{k:"Max retries",v:String(r.max_retries)})]}),(0,b.jsxs)("div",{className:"mt-4 flex items-center gap-2",children:[(0,b.jsxs)(j.Button,{variant:"ghost",onClick:()=>{_(!0),ab(r.base_url),ad(r.id),af(r.name??"")},children:[(0,b.jsx)(k.Icon,{name:"edit",size:15})," Edit"]}),(0,b.jsxs)(j.Button,{variant:"ghost",disabled:"test"===z,onClick:()=>ar("test",async()=>{let b=await e.adminApi.testProvider(a);return b.ok&&y(b.data),b}),children:[(0,b.jsx)(k.Icon,{name:"wifi_tethering",size:16})," ","test"===z?"Testing…":"Test connection"]}),(0,b.jsxs)(j.Button,{variant:"ghost",disabled:"discover"===z,onClick:()=>ar("discover",async()=>{let b=await e.adminApi.discoverModels(a);return b.ok&&Q(b.data?.models??[]),b}),children:[(0,b.jsx)(k.Icon,{name:"sync",size:16})," ","discover"===z?"Fetching…":"Fetch models"]})]}),x&&(0,b.jsxs)("div",{className:"mt-3 text-[12px]",children:[(0,b.jsx)(g.Badge,{tone:x.ok?"live":x.reachable?"warn":"down",children:x.ok?`ok (${x.status})`:x.reachable?`reachable (${x.status})`:"unreachable"}),x.error&&(0,b.jsx)("span",{className:"ml-2 text-text-subtle",children:x.error})]})]})}),(0,b.jsxs)(i.RichCard,{header:(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(i.CardTitle,{title:"Keys",sub:`${ao.length} configured`}),(0,b.jsxs)("div",{className:"flex flex-wrap items-center gap-3",children:[ao.length>1&&(0,b.jsxs)(j.Button,{variant:"ghost",disabled:V,onClick:()=>am(ao.length),children:[(0,b.jsx)(k.Icon,{name:V?"progress_activity":"sync",size:15}),V?"Testing…":"Test All"]}),V&&(0,b.jsxs)(j.Button,{variant:"ghost",onClick:()=>{Z.current=!0},children:[(0,b.jsx)(k.Icon,{name:"stop",size:15})," Stop"]}),(0,b.jsx)("span",{className:"text-[11px] text-text-subtle",children:"Round Robin"}),(0,b.jsx)("button",{onClick:()=>{let b="round-robin"===r.strategy?null:"round-robin";e.adminApi.setProviderStrategy(a,b,r.sticky??1).then(()=>an())},className:`relative h-5 w-9 rounded-full transition-colors ${"round-robin"===r.strategy?"bg-accent":"bg-border-subtle"}`,"aria-label":"Toggle round-robin",children:(0,b.jsx)("span",{className:`absolute left-0.5 top-0.5 h-4 w-4 rounded-full bg-white transition-transform ${"round-robin"===r.strategy?"translate-x-[18px]":"translate-x-0"}`})}),"round-robin"===r.strategy&&(0,b.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,b.jsx)("span",{className:"text-[11px] text-text-subtle",children:"Sticky:"}),(0,b.jsxs)("div",{className:"flex items-center rounded-brand border border-border-subtle",children:[(0,b.jsx)("button",{type:"button",disabled:(r.sticky??1)<=1,onClick:()=>void e.adminApi.setProviderStrategy(a,"round-robin",Math.max(1,(r.sticky??1)-1)).then(()=>an()),className:"px-1.5 py-0.5 text-text-subtle transition-colors hover:text-text disabled:opacity-30","aria-label":"Decrease sticky",children:(0,b.jsx)(k.Icon,{name:"remove",size:13})}),(0,b.jsx)("span",{className:"tnum w-6 text-center text-[11px] text-text",children:r.sticky??1}),(0,b.jsx)("button",{type:"button",onClick:()=>void e.adminApi.setProviderStrategy(a,"round-robin",(r.sticky??1)+1).then(()=>an()),className:"px-1.5 py-0.5 text-text-subtle transition-colors hover:text-text","aria-label":"Increase sticky",children:(0,b.jsx)(k.Icon,{name:"add",size:13})})]})]})]})]}),children:[X&&(0,b.jsx)("div",{className:"mb-3 flex items-center gap-2 text-[11.5px]",children:(0,b.jsxs)(g.Badge,{tone:0===X.failed?"live":"warn",children:[X.total," tested: ",X.passed," valid, ",X.failed," failed"]})}),0===ao.length?(0,b.jsx)(l.Empty,{children:"No keys (free / service-account provider)."}):(0,b.jsx)("div",{className:"space-y-1.5",children:ao.map((c,d)=>{let i=t?.keys[d],l=T[d],m=l&&"testing"!==l?l:null,n=m?m.ok?"live":m.reachable?"idle":"down":i?i.healthy?"live":"down":"idle",o=r.key_names?.[c],p=r.disabled_keys?.includes(d)??!1;return F===d?(0,b.jsxs)("div",{className:"space-y-2 rounded-brand border border-accent bg-accent-soft/40 px-3 py-2.5",children:[(0,b.jsx)(j.Input,{value:H,onChange:a=>I(a.target.value),placeholder:"key name (optional)"}),(0,b.jsx)(j.Input,{value:J,onChange:a=>K(a.target.value),placeholder:"new key value (leave blank to keep)",className:"font-mono text-[12.5px]"}),(0,b.jsxs)("div",{className:"flex justify-end gap-2",children:[(0,b.jsx)(j.Button,{variant:"ghost",onClick:()=>G(null),children:"Cancel"}),(0,b.jsx)(j.Button,{disabled:z===`editkey${d}`,onClick:()=>ar(`editkey${d}`,async()=>{let b=await e.adminApi.editKey(a,d,{name:H,key:J.trim()||void 0});return b.ok&&G(null),b}),children:"Save"})]})]},d):(0,b.jsxs)("div",{className:`rounded-brand border border-border-subtle px-3 py-2${p?" opacity-60":""}`,children:[(0,b.jsxs)("div",{className:"flex items-center gap-2",children:[(0,b.jsxs)("div",{className:"flex flex-col",children:[(0,b.jsx)("button",{onClick:()=>ar(`reorder${d}up`,()=>e.adminApi.reorderKey(a,d,d-1)),disabled:0===d,className:"p-0.5 text-text-subtle hover:text-text disabled:opacity-30","aria-label":"Move up",children:(0,b.jsx)(k.Icon,{name:"keyboard_arrow_up",size:14})}),(0,b.jsx)("button",{onClick:()=>ar(`reorder${d}dn`,()=>e.adminApi.reorderKey(a,d,d+1)),disabled:d===ao.length-1,className:"p-0.5 text-text-subtle hover:text-text disabled:opacity-30","aria-label":"Move down",children:(0,b.jsx)(k.Icon,{name:"keyboard_arrow_down",size:14})})]}),(0,b.jsx)(f.Lamp,{state:n}),(0,b.jsxs)("div",{className:"min-w-0 flex-1",children:[o&&(0,b.jsx)("div",{className:"text-[12px] font-semibold text-text-muted",children:o}),(0,b.jsx)("span",{className:"block truncate font-mono text-[12.5px] text-text",children:ag[d]??c})]}),ag[d]&&(0,b.jsx)("button",{onClick:()=>{navigator.clipboard.writeText(ag[d])},className:"flex-none rounded p-1 text-text-subtle transition-colors hover:text-text","aria-label":"Copy key",title:"Copy to clipboard",children:(0,b.jsx)(k.Icon,{name:"content_copy",size:14})}),i&&i.cooldown_ms>0&&(0,b.jsx)(h.CooldownTimer,{ms:i.cooldown_ms}),(0,b.jsx)("button",{onClick:async()=>{if(ag[d])return void ah(a=>{let b={...a};return delete b[d],b});let b=await e.adminApi.revealKey(a,d);b.ok&&b.data?.key&&ah(a=>({...a,[d]:b.data.key}))},className:"flex-none rounded p-1 text-text-subtle transition-colors hover:text-text","aria-label":ag[d]?"Hide key":"Show key",title:ag[d]?"Hide key":"Show key",children:(0,b.jsx)(k.Icon,{name:ag[d]?"visibility_off":"visibility",size:15})}),(0,b.jsx)("button",{onClick:()=>ar(`toggle${d}`,()=>e.adminApi.toggleKey(a,d,p)),className:"flex-none rounded p-1 text-text-subtle transition-colors hover:text-text","aria-label":p?"Enable key":"Disable key",title:p?"Enable this key":"Disable this key",children:(0,b.jsx)(k.Icon,{name:p?"toggle_off":"toggle_on",size:20,className:p?"text-text-subtle":"text-success"})}),(0,b.jsx)("button",{onClick:()=>al(d),disabled:"testing"===l,className:"flex-none rounded p-1 text-text-subtle transition-colors hover:text-text disabled:opacity-60","aria-label":`Check key ${d+1}`,title:"Check this key against the base URL",children:(0,b.jsx)(k.Icon,{name:"testing"===l?"progress_activity":"wifi_tethering",size:15})}),(0,b.jsx)("button",{onClick:()=>{G(d),I(o??""),K("")},className:"flex-none rounded p-1 text-text-subtle transition-colors hover:text-text","aria-label":`Edit key ${d+1}`,title:"Rename or replace this key",children:(0,b.jsx)(k.Icon,{name:"edit",size:15})}),(0,b.jsx)("button",{onClick:()=>ar(`rmkey${d}`,()=>e.adminApi.removeKey(a,d)),className:"flex-none rounded p-1 text-text-subtle transition-colors hover:text-danger","aria-label":"Remove key",children:(0,b.jsx)(k.Icon,{name:"delete",size:15})})]}),m&&(0,b.jsxs)("div",{className:"mt-1.5 flex items-center gap-2 pl-8 text-[11.5px]",children:[(0,b.jsx)(g.Badge,{tone:m.ok?"live":m.reachable?"warn":"down",children:m.ok?"valid":m.reachable?`reachable (${m.status})`:"invalid"}),m.error&&(0,b.jsx)("span",{className:"truncate text-danger",children:m.error})]}),!m&&i?.last_error&&(0,b.jsxs)("div",{className:"mt-1.5 flex items-center gap-2 pl-8 text-[11.5px]",children:[(0,b.jsxs)("span",{className:"text-danger",children:[i.last_error.status?`${i.last_error.status}: `:"",i.last_error.message]}),(0,b.jsx)("span",{className:"text-text-subtle",children:new Date(i.last_error.at).toLocaleTimeString()})]})]},d)})}),(0,b.jsxs)("div",{className:"mt-3 space-y-2",children:[(0,b.jsx)(j.Input,{value:D,onChange:a=>E(a.target.value),placeholder:"key name (optional, e.g. primary)"}),(0,b.jsxs)("div",{className:"flex gap-2",children:[(0,b.jsx)(j.Input,{value:B,onChange:a=>C(a.target.value),placeholder:"add a key…",className:"font-mono text-[12.5px]"}),(0,b.jsx)(j.Button,{disabled:!B||"addkey"===z,onClick:()=>ar("addkey",async()=>{let b=await e.adminApi.addKey(a,B,D.trim()||void 0);return b.ok&&(C(""),E("")),b}),children:"Add"})]})]})]}),(0,b.jsxs)(i.RichCard,{className:"lg:col-span-2",header:(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(i.CardTitle,{title:"Models served",sub:`${r.models.length} in catalog`}),r.models.length>0&&(0,b.jsx)("button",{onClick:()=>ar("clear",()=>e.adminApi.clearModels(a)),disabled:"clear"===z,className:"text-[12px] text-text-subtle hover:text-danger",children:"Clear all"})]}),children:[0===r.models.length?(0,b.jsx)(l.Empty,{children:"No models. Add one below, or fetch them for a free/auto provider."}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("p",{className:"mb-2.5 text-[12px] text-text-subtle",children:["Call any of these as ",(0,b.jsxs)("span",{className:"tnum text-text-muted",children:[r.id,"/<model>"]}),", as a combo alias, or by the bare id."]}),r.models.length>8&&(0,b.jsxs)("div",{className:"mb-2.5 flex items-center gap-2",children:[(0,b.jsxs)("div",{className:"relative flex-1",children:[(0,b.jsx)(k.Icon,{name:"search",size:15,className:"pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-text-subtle"}),(0,b.jsx)(j.Input,{value:N,onChange:a=>O(a.target.value),placeholder:"filter models…",className:"pl-8"})]}),(0,b.jsx)("span",{className:"tnum whitespace-nowrap text-[12px] text-text-subtle",children:ap?`${aq.length} of ${r.models.length}`:`${r.models.length}`})]}),0===aq.length?(0,b.jsxs)(l.Empty,{children:["No model matches “",N,"”."]}):(0,b.jsx)("div",{className:"max-h-[360px] divide-y divide-border-subtle overflow-y-auto rounded-brand border border-border-subtle",children:aq.map(c=>{let d=R[c.id];return(0,b.jsxs)("div",{className:"group flex items-center justify-between gap-3 px-3 py-2 hover:bg-bg",children:[(0,b.jsxs)("div",{className:"flex min-w-0 items-center gap-2",children:[(0,b.jsx)(k.Icon,{name:"ok"===d?"check_circle":"fail"===d?"cancel":"smart_toy",size:15,className:`flex-none ${"ok"===d?"text-success":"fail"===d?"text-danger":"text-text-subtle"}`}),(0,b.jsxs)("span",{className:"tnum truncate text-[12.5px]",children:[(0,b.jsxs)("span",{className:"text-text-subtle",children:[r.id,"/"]}),(0,b.jsx)("span",{className:"text-text",children:c.id})]}),(0,b.jsx)(o.CapacityBadges,{model:c.id,provider:r.id}),(void 0!==c.price_in||void 0!==c.price_out)&&(0,b.jsxs)("span",{className:"tnum whitespace-nowrap text-[11px] text-text-subtle",children:[l.fmt.cost(c.price_in??0),"/",l.fmt.cost(c.price_out??0)," per 1M"]})]}),(0,b.jsxs)("div",{className:"flex flex-none items-center gap-0.5",children:[(0,b.jsx)("button",{onClick:()=>ak(c.id),disabled:"testing"===d,className:"rounded p-1 text-text-subtle transition-colors hover:bg-surface hover:text-accent disabled:opacity-60","aria-label":`Test ${c.id}`,title:"fail"===d?"Test failed — click to retry":"Test this model",children:(0,b.jsx)(k.Icon,{name:"testing"===d?"progress_activity":"science",size:15})}),(0,b.jsx)("button",{onClick:()=>ar(`rmmodel${c.id}`,()=>e.adminApi.removeModel(a,c.id)),disabled:z===`rmmodel${c.id}`,className:"rounded p-1 text-text-subtle transition-colors hover:bg-surface hover:text-danger disabled:opacity-40","aria-label":`Remove ${c.id}`,children:(0,b.jsx)(k.Icon,{name:"delete",size:16})})]})]},c.id)})})]}),(0,b.jsxs)("div",{className:"mt-3 flex gap-2",children:[(0,b.jsx)(j.Input,{value:L,onChange:a=>M(a.target.value),placeholder:"add a model id…"}),(0,b.jsx)(j.Button,{disabled:!L||"addmodel"===z,onClick:()=>ar("addmodel",async()=>{let b=await e.adminApi.addModel(a,L);return b.ok&&M(""),b}),children:"Add"})]})]})]}),P&&(0,b.jsx)(n,{models:P,busy:"addmodels"===z,onClose:()=>Q(null),onAdd:b=>ar("addmodels",async()=>{let c=await e.adminApi.addModels(a,b);return c.ok&&Q(null),c})}),(0,b.jsx)("div",{className:"mt-6",children:(0,b.jsxs)(j.Button,{variant:"danger",onClick:()=>aj(!0),children:[(0,b.jsx)(k.Icon,{name:"delete",size:16})," Remove provider"]})}),ai&&(0,b.jsx)(p.ConfirmModal,{title:"Remove provider",message:`Delete "${r.name??a}"? All keys and model associations will be lost.`,confirmLabel:"Remove",busy:"rmprov"===z,onCancel:()=>aj(!1),onConfirm:()=>ar("rmprov",async()=>{let b=await e.adminApi.removeProvider(a);return b.ok?m.push("/providers"):aj(!1),b})})]})}],33410)}];
|
|
2
2
|
|
|
3
3
|
//# sourceMappingURL=src_components_ProviderDetail_tsx_06sxu0r._.js.map
|