@cartanova/qgrid-cli 2.3.5 → 2.3.7
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/bundle/dist/application/qgrid/oauth.js +15 -12
- package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +2 -1
- package/bundle/dist/application/qgrid/qgrid.dispatcher.js +2 -1
- package/bundle/dist/application/qgrid/qgrid.frame.js +40 -20
- package/bundle/dist/application/qgrid/qgrid.types.js +8 -2
- package/bundle/dist/application/qgrid/token-subscriber.js +16 -8
- package/bundle/dist/application/qgrid/token-trigger-setup.js +3 -2
- package/bundle/dist/application/request-log/request-log.model.js +12 -7
- package/bundle/dist/application/sonamu.generated.js +11 -3
- package/bundle/dist/application/sonamu.generated.sso.js +7 -2
- package/bundle/dist/application/token/token.model.js +10 -2
- package/bundle/dist/application/token/token.types.js +5 -3
- package/bundle/dist/i18n/sd.generated.js +4 -1
- package/bundle/dist/migrations/20260630223950_alter_tokens_add1_alter1.js +16 -0
- package/bundle/dist/migrations/20260701105327_alter_request_logs_add1_alter1.js +16 -0
- package/bundle/dist/migrations/20260701105328_alter_request_log_steps_add1_alter1.js +16 -0
- package/bundle/dist/sonamu.config.js +13 -6
- package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +99 -12
- package/bundle/dist/utils/providers/anthropic/anthropic-quota.js +31 -0
- package/bundle/dist/utils/providers/anthropic/claude-session.js +8 -3
- package/bundle/dist/utils/providers/common/ttft.js +25 -0
- package/bundle/dist/utils/providers/openai/codex-worker.js +35 -7
- package/bundle/dist/utils/providers/openai/openai-dispatcher.js +237 -39
- package/bundle/dist/utils/providers/openai/openai-quota.js +30 -0
- package/bundle/src/application/qgrid/oauth.ts +17 -7
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +96 -0
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +1 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +16 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.ts +1 -0
- package/bundle/src/application/qgrid/qgrid.frame.test.ts +172 -0
- package/bundle/src/application/qgrid/qgrid.frame.ts +45 -20
- package/bundle/src/application/qgrid/qgrid.types.ts +6 -0
- package/bundle/src/application/qgrid/token-subscriber.test.ts +89 -0
- package/bundle/src/application/qgrid/token-subscriber.ts +40 -11
- package/bundle/src/application/qgrid/token-trigger-setup.ts +2 -1
- package/bundle/src/application/qgrid/tool-emulation.test.ts +7 -3
- package/bundle/src/application/request-log/request-log.entity.json +3 -0
- package/bundle/src/application/request-log/request-log.model.test.ts +92 -0
- package/bundle/src/application/request-log/request-log.model.ts +20 -6
- package/bundle/src/application/request-log-step/request-log-step.entity.json +3 -0
- package/bundle/src/application/sonamu.generated.http +7 -2
- package/bundle/src/application/sonamu.generated.sso.ts +5 -0
- package/bundle/src/application/sonamu.generated.ts +11 -1
- package/bundle/src/application/token/token.entity.json +8 -2
- package/bundle/src/application/token/token.model.test.ts +69 -0
- package/bundle/src/application/token/token.model.ts +8 -1
- package/bundle/src/application/token/token.types.test.ts +34 -0
- package/bundle/src/application/token/token.types.ts +5 -0
- package/bundle/src/i18n/sd.generated.ts +3 -0
- package/bundle/src/migrations/20260630223950_alter_tokens_add1_alter1.ts +15 -0
- package/bundle/src/migrations/20260701105327_alter_request_logs_add1_alter1.ts +15 -0
- package/bundle/src/migrations/20260701105328_alter_request_log_steps_add1_alter1.ts +15 -0
- package/bundle/src/sonamu.config.ts +8 -1
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.test.ts +183 -15
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +142 -12
- package/bundle/src/utils/providers/anthropic/anthropic-quota.test.ts +89 -0
- package/bundle/src/utils/providers/anthropic/anthropic-quota.ts +27 -0
- package/bundle/src/utils/providers/anthropic/claude-session.ts +7 -2
- package/bundle/src/utils/providers/common/provider-dispatcher.ts +1 -0
- package/bundle/src/utils/providers/common/ttft.test.ts +37 -0
- package/bundle/src/utils/providers/common/ttft.ts +26 -0
- package/bundle/src/utils/providers/openai/codex-worker.test.ts +148 -0
- package/bundle/src/utils/providers/openai/codex-worker.ts +50 -8
- package/bundle/src/utils/providers/openai/openai-dispatcher.test.ts +378 -6
- package/bundle/src/utils/providers/openai/openai-dispatcher.ts +332 -37
- package/bundle/src/utils/providers/openai/openai-quota.test.ts +85 -0
- package/bundle/src/utils/providers/openai/openai-quota.ts +46 -0
- package/bundle/web-dist/client/assets/index-5WdFEqZT.css +1 -0
- package/bundle/web-dist/client/assets/{index-DeThumA3.js → index-jnUY7nJ-.js} +3 -3
- package/bundle/web-dist/client/assets/logs-B0pWpDrg.js +1 -0
- package/bundle/web-dist/client/assets/routes-7XhVuG7o.js +5 -0
- package/bundle/web-dist/client/assets/{sd.generated-7jzAQL2_.js → sd.generated-DXhjjL2f.js} +1 -1
- package/bundle/web-dist/client/assets/{services.generated-Bx1Eh7ot.js → services.generated-B7u0U1wC.js} +1 -1
- package/bundle/web-dist/client/assets/{show-C6OofoAL.js → show-CcjZ9nr7.js} +3 -3
- package/bundle/web-dist/client/assets/tokens-DlwAm0v4.js +1 -0
- package/bundle/web-dist/client/index.html +3 -3
- package/bundle/web-dist/server/assets/{lazyRouteComponent-BEaI4mOq.js → lazyRouteComponent-B0LkbiYf.js} +1 -2
- package/bundle/web-dist/server/assets/{logs-CHM0fhfO.js → logs-dLx6gMXT.js} +17 -5
- package/bundle/web-dist/server/assets/{routes-C9xFMJ_r.js → routes-DD3Hb9xO.js} +201 -13
- package/bundle/web-dist/server/assets/{sd.generated-BeUHLWKH.js → sd.generated-DdfpD_iN.js} +131 -1
- package/bundle/web-dist/server/assets/{services.generated-C39hdSv0.js → services.generated-D3ZCvIkt.js} +5 -4
- package/bundle/web-dist/server/assets/{show-BZWqH09U.js → show-BQjeyv6A.js} +76 -25
- package/bundle/web-dist/server/assets/{tokens-IPwv3pNB.js → tokens-CSOsBpP7.js} +4 -3
- package/bundle/web-dist/server/entry-server.generated.js +6 -7
- package/dist/cli.js +67 -15
- package/package.json +1 -1
- package/bundle/web-dist/client/assets/index-B5DSo5uH.css +0 -1
- package/bundle/web-dist/client/assets/logs-CtmOVH58.js +0 -1
- package/bundle/web-dist/client/assets/routes-Cfoe9J0I.js +0 -5
- package/bundle/web-dist/client/assets/tokens-BAZq8sTo.js +0 -1
- package/bundle/web-dist/server/assets/shim-B9ZrFt3Z.js +0 -129
- /package/bundle/web-dist/server/assets/{cost-DzjfVtUr.js → cost-CSH_t17I.js} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-Dw2cE7zH.js";import{y as t}from"./vendor-tanstack-DJRQAbrY.js";import{i as n,r}from"./vendor-react-DH4kUfK2.js";import{i,r as a}from"./index-jnUY7nJ-.js";import{i as o,t as s}from"./services.generated-B7u0U1wC.js";var c=e(n()),l=r(),u=e=>(0,l.jsx)(`svg`,{viewBox:`0 0 24 24`,width:`1.2em`,height:`1.2em`,...e,children:(0,l.jsx)(`path`,{fill:`none`,stroke:`currentColor`,strokeLinecap:`round`,strokeLinejoin:`round`,strokeWidth:2,d:`M5 12h14m-7-7v14`})});function d(){let[e,n]=(0,c.useState)(!1),[r,o]=(0,c.useState)(!1),[d,f]=(0,c.useState)(``),p=t(),m=s.useOauthStartMutation(),h=s.useOauthStartOpenAIMutation(),g=async e=>{if(d.trim())if(e===`openai`){let e=window.open(`about:blank`,`_blank`);o(!0);try{let{authUrl:t}=await h.mutateAsync({name:d.trim()});e?e.location.href=t:window.open(t,`_blank`);let n=setInterval(async()=>{await p.invalidateQueries({queryKey:[`Token`]}),await p.invalidateQueries({queryKey:[`Qgrid`]})},3e3);setTimeout(()=>{clearInterval(n),o(!1)},3e5)}catch(e){console.error(`OAuth start failed:`,e),o(!1)}}else{o(!0);try{let{authUrl:e}=await m.mutateAsync({name:d.trim()});window.location.href=e}catch(e){console.error(`OAuth start failed:`,e),o(!1)}}},_=()=>{n(!1),f(``),o(!1)};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsxs)(`button`,{type:`button`,className:`px-3.5 py-1.5 text-[12px] font-medium rounded-lg bg-sienna-500 text-white hover:bg-sienna-600 disabled:opacity-50 transition-all duration-150 active:scale-[0.97] flex items-center gap-1.5 shadow-sm`,onClick:()=>n(!0),children:[(0,l.jsx)(u,{className:`size-3.5`}),`Add Token`]}),e&&(0,l.jsxs)(`div`,{className:`fixed inset-0 z-50 flex items-start justify-center pt-[15vh]`,children:[(0,l.jsx)(`div`,{className:`absolute inset-0 bg-sand-900/8 backdrop-blur-sm`,onClick:_,onKeyDown:()=>{}}),(0,l.jsxs)(`div`,{className:`relative panel shadow-xl w-full max-w-md mx-4`,children:[(0,l.jsx)(`div`,{className:`px-5 py-4 border-b border-sand-100/50`,children:(0,l.jsx)(`h2`,{className:`text-base font-medium text-sand-900`,children:`Add Token`})}),(0,l.jsxs)(`div`,{className:`px-5 py-4 space-y-4`,children:[(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`label`,{htmlFor:`token-name`,className:`text-[10px] uppercase tracking-wider text-sand-500 font-medium`,children:`Name *`}),(0,l.jsx)(a,{value:d,onChange:e=>f(e.target.value),placeholder:`e.g. your-token-name`,className:`mt-1 w-full border border-sand-200 rounded-md px-3 py-2 text-sm text-sand-900 bg-white placeholder:text-sand-300 focus:outline-none focus:border-sienna-300`})]}),(0,l.jsxs)(`div`,{className:`space-y-2`,children:[(0,l.jsx)(`button`,{type:`button`,className:`w-full py-2.5 text-sm font-medium rounded-md bg-sand-900 text-white hover:bg-sand-800 disabled:opacity-50 transition-colors duration-150 flex items-center justify-center gap-2`,disabled:!d.trim()||r,onClick:()=>g(`openai`),children:r?(0,l.jsxs)(`span`,{className:`flex items-center gap-1.5`,children:[(0,l.jsx)(`span`,{className:`w-3.5 h-3.5 border-2 border-white border-t-transparent rounded-full animate-spin`}),`Waiting for login...`]}):(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(i,{className:`size-4`}),`Login with OpenAI`]})}),(0,l.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,l.jsx)(`div`,{className:`flex-1 h-px bg-sand-200`}),(0,l.jsx)(`span`,{className:`text-[10px] text-sand-400 uppercase`,children:`or`}),(0,l.jsx)(`div`,{className:`flex-1 h-px bg-sand-200`})]}),(0,l.jsxs)(`button`,{type:`button`,className:`w-full py-2.5 text-sm font-medium rounded-md border border-sand-300 text-sand-700 hover:bg-sand-100 disabled:opacity-50 transition-colors duration-150 flex items-center justify-center gap-2`,disabled:!d.trim()||r,onClick:()=>g(`anthropic`),children:[(0,l.jsx)(i,{className:`size-4`}),`Login with Claude`]})]})]}),(0,l.jsx)(`div`,{className:`px-5 py-3 border-t border-sand-100/50 flex items-center justify-end gap-2`,children:(0,l.jsx)(`button`,{type:`button`,className:`px-3 py-1 text-xs font-medium rounded-md border border-sand-200 text-sand-600 hover:bg-sand-100 transition-colors duration-150`,onClick:_,children:`Cancel`})})]})]})]})}var f=e=>(0,l.jsx)(`svg`,{viewBox:`0 0 24 24`,width:`1.2em`,height:`1.2em`,...e,children:(0,l.jsx)(`path`,{fill:`none`,stroke:`currentColor`,strokeLinecap:`round`,strokeLinejoin:`round`,strokeWidth:2,d:`M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497zM15 5l4 4`})}),p=e=>(0,l.jsx)(`svg`,{viewBox:`0 0 24 24`,width:`1.2em`,height:`1.2em`,...e,children:(0,l.jsx)(`path`,{fill:`none`,stroke:`currentColor`,strokeLinecap:`round`,strokeLinejoin:`round`,strokeWidth:2,d:`M10 11v6m4-6v6m5-11v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2`})});function m(e){let t=e.credentials;return`expiresAt`in t&&typeof t.expiresAt==`number`?t.expiresAt:`accessTokenExpiresAt`in t&&typeof t.accessTokenExpiresAt==`number`?t.accessTokenExpiresAt:null}function h(e){if(!e)return{text:``,color:``};let t=e-Date.now();if(t<=0)return{text:`expired`,color:`text-red-500`};let n=Math.floor(t/36e5),r=Math.floor(t%36e5/6e4),i=n>0?`${n}h ${r}m`:`${r}m`;return t<36e5?{text:i,color:`text-amber-500`}:{text:i,color:`text-sand-400`}}function g(e){let t=e.credentials.accessToken;return t.length<=12?t:`${t.slice(0,8)}...${t.slice(-4)}`}function _({data:e,isLoading:n}){let[r,i]=(0,c.useState)(null),[o,u]=(0,c.useState)(null),[d,_]=(0,c.useState)(``),v=t(),y=s.useRemoveTokenMutation(),b=s.useUpdateTokenMutation(),x=s.useToggleTokenMutation(),S=()=>Promise.all([v.invalidateQueries({queryKey:[`Token`]}),v.invalidateQueries({queryKey:[`Qgrid`]})]),C=async e=>{await x.mutateAsync({id:e.id}),await S()},w=async()=>{r&&(await y.mutateAsync({id:r.id}),await S(),i(null))},T=e=>{u(e),_(e.name??``)},E=async()=>{o&&(await b.mutateAsync({id:o.id,name:d.trim(),quotaThreshold:o.quota_threshold}),await S(),u(null))};if(n)return(0,l.jsx)(`div`,{className:`space-y-2`,children:Array.from({length:3}).map((e,t)=>(0,l.jsx)(`div`,{className:`h-12 bg-sand-100 rounded-md animate-pulse`},`skeleton-${t}`))});let D=e??[];return D.length===0?(0,l.jsxs)(`div`,{className:`text-sand-400 text-center py-16 text-sm`,children:[`No tokens registered. Click `,(0,l.jsx)(`strong`,{className:`text-sand-600`,children:`Add Token`}),` to get started.`]}):(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(`div`,{className:`panel overflow-hidden`,children:(0,l.jsxs)(`table`,{className:`w-full text-[13px]`,children:[(0,l.jsx)(`thead`,{children:(0,l.jsxs)(`tr`,{className:`panel-header`,children:[(0,l.jsx)(`th`,{className:`text-left px-5 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium`,children:`Provider`}),(0,l.jsx)(`th`,{className:`text-left px-5 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium`,children:`Name`}),(0,l.jsx)(`th`,{className:`text-left px-5 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium`,children:`Token`}),(0,l.jsx)(`th`,{className:`text-left px-5 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium`,children:`Status`}),(0,l.jsx)(`th`,{className:`text-left px-5 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium`,children:`Expires`}),(0,l.jsx)(`th`,{className:`w-20 px-3 py-2.5`})]})}),(0,l.jsx)(`tbody`,{className:`divide-y divide-sand-100/80`,children:D.map(e=>{let t=h(m(e));return(0,l.jsxs)(`tr`,{className:`transition-colors duration-150 hover:bg-sand-100/60 ${e.active?``:`opacity-50`}`,children:[(0,l.jsx)(`td`,{className:`px-5 py-3`,children:(0,l.jsx)(`span`,{className:`text-xs font-medium text-sand-500 uppercase`,children:e.provider})}),(0,l.jsx)(`td`,{className:`px-5 py-3`,children:e.name?(0,l.jsx)(`span`,{className:`text-sm text-sand-700`,children:e.name}):(0,l.jsx)(`span`,{className:`text-[11px] text-sand-400`,children:`—`})}),(0,l.jsx)(`td`,{className:`px-5 py-3`,children:(0,l.jsx)(`code`,{className:`text-[13px] font-mono text-sand-800`,children:g(e)})}),(0,l.jsx)(`td`,{className:`px-5 py-3`,children:(0,l.jsx)(`button`,{type:`button`,className:`relative inline-flex h-5 w-9 items-center rounded-full transition-colors duration-200 ${e.active?`bg-sage-400`:`bg-sand-300`}`,onClick:()=>C(e),disabled:x.isPending,children:(0,l.jsx)(`span`,{className:`inline-block h-3.5 w-3.5 rounded-full bg-white transition-transform duration-200 ${e.active?`translate-x-4.5`:`translate-x-0.5`}`})})}),(0,l.jsx)(`td`,{className:`px-5 py-3`,children:t.text&&(0,l.jsx)(`span`,{className:`text-xs ${t.color}`,children:t.text})}),(0,l.jsx)(`td`,{className:`px-3 py-3`,children:(0,l.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,l.jsx)(`button`,{type:`button`,className:`p-1 rounded text-sand-400 hover:text-sienna-500 transition-colors duration-150`,onClick:()=>T(e),children:(0,l.jsx)(f,{className:`size-4`})}),(0,l.jsx)(`button`,{type:`button`,className:`p-1 rounded text-sand-400 hover:text-red-500 transition-colors duration-150`,onClick:()=>i(e),children:(0,l.jsx)(p,{className:`size-4`})})]})})]},e.id)})})]})}),o&&(0,l.jsxs)(`div`,{className:`fixed inset-0 z-50 flex items-start justify-center pt-[15vh]`,children:[(0,l.jsx)(`div`,{className:`absolute inset-0 bg-sand-900/8 backdrop-blur-sm`,onClick:()=>u(null),onKeyDown:()=>{}}),(0,l.jsxs)(`div`,{className:`relative panel shadow-xl w-full max-w-sm mx-4`,children:[(0,l.jsx)(`div`,{className:`px-5 py-4 border-b border-sand-100/60`,children:(0,l.jsx)(`h3`,{className:`text-base font-medium text-sand-900`,children:`Edit Token`})}),(0,l.jsx)(`div`,{className:`px-5 py-4 space-y-3`,children:(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`label`,{htmlFor:`token-name`,className:`text-[10px] uppercase tracking-wider text-sand-500 font-medium`,children:`Name`}),(0,l.jsx)(a,{value:d,onChange:e=>_(e.target.value),placeholder:`e.g. prod, dev, team-a`,className:`mt-1 w-full border border-sand-200 rounded-md px-3 py-2 text-sm text-sand-900 bg-white placeholder:text-sand-300 focus:outline-none focus:border-sienna-300`})]})}),(0,l.jsxs)(`div`,{className:`px-5 py-3 border-t border-sand-100/60 flex items-center justify-end gap-2`,children:[(0,l.jsx)(`button`,{type:`button`,className:`px-3 py-1 text-xs font-medium rounded-md border border-sand-200 text-sand-600 hover:bg-sand-100 transition-colors duration-150`,onClick:()=>u(null),children:`Cancel`}),(0,l.jsx)(`button`,{type:`button`,className:`px-3 py-1 text-xs font-medium rounded-md bg-sienna-400 text-white hover:bg-sienna-500 disabled:opacity-50 transition-colors duration-150`,disabled:b.isPending,onClick:E,children:b.isPending?`Saving...`:`Save`})]})]})]}),r&&(0,l.jsxs)(`div`,{className:`fixed inset-0 z-50 flex items-start justify-center pt-[15vh]`,children:[(0,l.jsx)(`div`,{className:`absolute inset-0 bg-sand-900/8 backdrop-blur-sm`,onClick:()=>i(null),onKeyDown:()=>{}}),(0,l.jsxs)(`div`,{className:`relative panel shadow-xl w-full max-w-sm mx-4`,children:[(0,l.jsxs)(`div`,{className:`px-5 py-4`,children:[(0,l.jsx)(`h3`,{className:`text-base font-medium text-sand-900`,children:`Remove Token`}),(0,l.jsxs)(`p`,{className:`text-sm text-sand-700 mt-2`,children:[`Are you sure you want to remove`,` `,(0,l.jsx)(`code`,{className:`text-[13px] font-mono text-sand-800`,children:g(r)}),r.name&&(0,l.jsxs)(`span`,{className:`text-sand-500`,children:[` (`,r.name,`)`]}),`?`]})]}),(0,l.jsxs)(`div`,{className:`px-5 py-3 border-t border-sand-100/60 flex items-center justify-end gap-2`,children:[(0,l.jsx)(`button`,{type:`button`,className:`px-3 py-1 text-xs font-medium rounded-md border border-sand-200 text-sand-600 hover:bg-sand-100 transition-colors duration-150`,onClick:()=>i(null),children:`Cancel`}),(0,l.jsx)(`button`,{type:`button`,className:`px-3 py-1 text-xs font-medium rounded-md bg-red-500 text-white hover:bg-red-600 disabled:opacity-50 transition-colors duration-150`,disabled:y.isPending,onClick:w,children:y.isPending?`Removing...`:`Remove`})]})]})]})]})}function v(){let{data:e,isLoading:t}=o.useTokens(`A`);return(0,l.jsxs)(`div`,{className:`max-w-6xl mx-auto space-y-4`,children:[(0,l.jsx)(`div`,{className:`flex items-center justify-end`,children:(0,l.jsx)(d,{})}),(0,l.jsx)(_,{data:e?.rows,isLoading:t})]})}export{v as component};
|
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/sonamu.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>Qgrid</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-jnUY7nJ-.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-Dw2cE7zH.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/preload-helper-ca-nBW7U.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-DH4kUfK2.js">
|
|
12
12
|
<link rel="modulepreload" crossorigin href="/assets/vendor-tanstack-DJRQAbrY.js">
|
|
13
|
-
<link rel="modulepreload" crossorigin href="/assets/sd.generated-
|
|
14
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
13
|
+
<link rel="modulepreload" crossorigin href="/assets/sd.generated-DXhjjL2f.js">
|
|
14
|
+
<link rel="stylesheet" crossorigin href="/assets/index-5WdFEqZT.css">
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
|
17
17
|
<div id="root"></div>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as require_shim } from "./shim-B9ZrFt3Z.js";
|
|
1
|
+
import { X as __toESM, _ as require_react, f as require_react_dom, g as require_jsx_runtime, p as require_shim, q as __commonJSMin } from "./sd.generated-DdfpD_iN.js";
|
|
3
2
|
//#region ../../node_modules/.pnpm/@tanstack+router-core@1.143.6/node_modules/@tanstack/router-core/dist/esm/utils.js
|
|
4
3
|
function last(arr) {
|
|
5
4
|
return arr[arr.length - 1];
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as TokenService, n as RequestLogService, t as QgridService } from "./services.generated-
|
|
3
|
-
import { a as Link, o as useNavigate } from "./lazyRouteComponent-
|
|
1
|
+
import { _ as require_react, c as number, g as require_jsx_runtime, l as object, u as string } from "./sd.generated-DdfpD_iN.js";
|
|
2
|
+
import { i as TokenService, n as RequestLogService, t as QgridService } from "./services.generated-D3ZCvIkt.js";
|
|
3
|
+
import { a as Link, o as useNavigate } from "./lazyRouteComponent-B0LkbiYf.js";
|
|
4
4
|
import { n as Route } from "../entry-server.generated.js";
|
|
5
|
-
import { n as formatMicroUsd, r as formatUsd, t as cacheHitRate } from "./cost-
|
|
5
|
+
import { n as formatMicroUsd, r as formatUsd, t as cacheHitRate } from "./cost-CSH_t17I.js";
|
|
6
6
|
require_react();
|
|
7
7
|
var import_jsx_runtime = require_jsx_runtime();
|
|
8
8
|
var lucideChevronLeft = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
|
|
@@ -52,6 +52,9 @@ function formatDuration(ms) {
|
|
|
52
52
|
const s = total % 60;
|
|
53
53
|
return m > 0 ? `${m}m ${s}s` : `${s}s`;
|
|
54
54
|
}
|
|
55
|
+
function formatTtft(ms) {
|
|
56
|
+
return ms >= 1e3 ? `${(ms / 1e3).toFixed(1)}s` : `${ms}ms`;
|
|
57
|
+
}
|
|
55
58
|
var COLUMNS = [
|
|
56
59
|
{
|
|
57
60
|
label: "ID",
|
|
@@ -78,6 +81,11 @@ var COLUMNS = [
|
|
|
78
81
|
align: "left",
|
|
79
82
|
width: "w-20"
|
|
80
83
|
},
|
|
84
|
+
{
|
|
85
|
+
label: "TTFT",
|
|
86
|
+
align: "left",
|
|
87
|
+
width: "w-16"
|
|
88
|
+
},
|
|
81
89
|
{
|
|
82
90
|
label: "Duration",
|
|
83
91
|
align: "left",
|
|
@@ -269,6 +277,10 @@ function RequestLogTable({ search, onSearchChange }) {
|
|
|
269
277
|
children: row.model_name ?? "—"
|
|
270
278
|
})
|
|
271
279
|
}),
|
|
280
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
|
|
281
|
+
className: "px-4 py-1.5 text-left tabular-nums text-sand-500 whitespace-nowrap",
|
|
282
|
+
children: formatTtft(row.ttft_ms)
|
|
283
|
+
}),
|
|
272
284
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
|
|
273
285
|
className: "pl-5 pr-3 py-1.5 text-left tabular-nums text-sand-500 whitespace-nowrap",
|
|
274
286
|
children: formatDuration(row.duration_ms)
|
|
@@ -355,7 +367,7 @@ function LogsPage() {
|
|
|
355
367
|
const search = Route.useSearch();
|
|
356
368
|
const navigate = Route.useNavigate();
|
|
357
369
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
358
|
-
className: "max-w-[
|
|
370
|
+
className: "max-w-[100rem] mx-auto",
|
|
359
371
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequestLogTable, {
|
|
360
372
|
search,
|
|
361
373
|
onSearchChange: (next) => navigate({ search: next })
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as TokenService, t as QgridService } from "./services.generated-
|
|
3
|
-
import { r as
|
|
1
|
+
import { X as __toESM, _ as require_react, f as require_react_dom, g as require_jsx_runtime, h as useQueryClient } from "./sd.generated-DdfpD_iN.js";
|
|
2
|
+
import { i as TokenService, t as QgridService } from "./services.generated-D3ZCvIkt.js";
|
|
3
|
+
import { r as Q } from "../entry-server.generated.js";
|
|
4
|
+
import { r as formatUsd } from "./cost-CSH_t17I.js";
|
|
4
5
|
//#region ../../node_modules/.pnpm/@dnd-kit+utilities@3.2.2_react@19.2.4/node_modules/@dnd-kit/utilities/dist/utilities.esm.js
|
|
5
6
|
var import_react_dom = /* @__PURE__ */ __toESM(require_react_dom());
|
|
6
7
|
var import_react = /* @__PURE__ */ __toESM(require_react());
|
|
@@ -2231,8 +2232,24 @@ function useSortable({ animateLayoutChanges = defaultAnimateLayoutChanges, attri
|
|
|
2231
2232
|
}
|
|
2232
2233
|
KeyboardCode.Down, KeyboardCode.Right, KeyboardCode.Up, KeyboardCode.Left;
|
|
2233
2234
|
//#endregion
|
|
2234
|
-
//#region ~icons/lucide/
|
|
2235
|
+
//#region ~icons/lucide/gauge.jsx
|
|
2235
2236
|
var import_jsx_runtime = require_jsx_runtime();
|
|
2237
|
+
var lucideGauge = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
|
|
2238
|
+
viewBox: "0 0 24 24",
|
|
2239
|
+
width: "1.2em",
|
|
2240
|
+
height: "1.2em",
|
|
2241
|
+
...props,
|
|
2242
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
|
|
2243
|
+
fill: "none",
|
|
2244
|
+
stroke: "currentColor",
|
|
2245
|
+
strokeLinecap: "round",
|
|
2246
|
+
strokeLinejoin: "round",
|
|
2247
|
+
strokeWidth: 2,
|
|
2248
|
+
d: "m12 14l4-4M3.34 19a10 10 0 1 1 17.32 0"
|
|
2249
|
+
})
|
|
2250
|
+
});
|
|
2251
|
+
//#endregion
|
|
2252
|
+
//#region ~icons/lucide/grip-vertical.jsx
|
|
2236
2253
|
var lucideGripVertical = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
|
|
2237
2254
|
viewBox: "0 0 24 24",
|
|
2238
2255
|
width: "1.2em",
|
|
@@ -2280,6 +2297,27 @@ var lucideGripVertical = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
|
2280
2297
|
});
|
|
2281
2298
|
//#endregion
|
|
2282
2299
|
//#region src/components/qgrid/UsageCard.tsx
|
|
2300
|
+
var QUOTA_THRESHOLD_PROVIDERS = new Set(["anthropic", "openai"]);
|
|
2301
|
+
function validateThreshold(raw) {
|
|
2302
|
+
const trimmed = raw.trim();
|
|
2303
|
+
if (trimmed === "") return {
|
|
2304
|
+
ok: true,
|
|
2305
|
+
value: null
|
|
2306
|
+
};
|
|
2307
|
+
if (!/^\d+$/.test(trimmed)) return {
|
|
2308
|
+
ok: false,
|
|
2309
|
+
error: "정수만 입력하세요 (0–100)"
|
|
2310
|
+
};
|
|
2311
|
+
const n = Number(trimmed);
|
|
2312
|
+
if (n > 100) return {
|
|
2313
|
+
ok: false,
|
|
2314
|
+
error: "100 이하여야 합니다"
|
|
2315
|
+
};
|
|
2316
|
+
return {
|
|
2317
|
+
ok: true,
|
|
2318
|
+
value: n === 0 ? null : n
|
|
2319
|
+
};
|
|
2320
|
+
}
|
|
2283
2321
|
var PROVIDER_THEMES = {
|
|
2284
2322
|
openai: {
|
|
2285
2323
|
stripe: "bg-openai-400",
|
|
@@ -2322,8 +2360,9 @@ function formatResets(iso) {
|
|
|
2322
2360
|
const m = Math.floor(diff % 36e5 / 6e4);
|
|
2323
2361
|
return h > 0 ? `resets ${h}h ${m}m` : `resets ${m}m`;
|
|
2324
2362
|
}
|
|
2325
|
-
function UsageRow({ label, utilization, resetsAt, theme }) {
|
|
2363
|
+
function UsageRow({ label, utilization, resetsAt, theme, threshold }) {
|
|
2326
2364
|
const pct = utilization ?? 0;
|
|
2365
|
+
const hasThreshold = threshold !== void 0 && threshold !== null;
|
|
2327
2366
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
2328
2367
|
className: "flex items-center gap-3",
|
|
2329
2368
|
children: [
|
|
@@ -2331,12 +2370,15 @@ function UsageRow({ label, utilization, resetsAt, theme }) {
|
|
|
2331
2370
|
className: "text-xs text-sand-600 w-20 shrink-0",
|
|
2332
2371
|
children: label
|
|
2333
2372
|
}),
|
|
2334
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
2335
|
-
className: "flex-1 h-2 bg-sand-200 rounded-full overflow-hidden",
|
|
2336
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
2373
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
2374
|
+
className: "relative flex-1 h-2 bg-sand-200 rounded-full overflow-hidden",
|
|
2375
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
2337
2376
|
className: `h-full rounded-full transition-all duration-300 ${barColor(pct, theme)}`,
|
|
2338
2377
|
style: { width: `${Math.min(pct, 100)}%` }
|
|
2339
|
-
})
|
|
2378
|
+
}), hasThreshold && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
2379
|
+
className: "absolute top-[-2px] bottom-[-2px] w-0.5 bg-sienna-500 rounded-full",
|
|
2380
|
+
style: { left: `calc(${Math.min(threshold, 100)}% - 1px)` }
|
|
2381
|
+
})]
|
|
2340
2382
|
}),
|
|
2341
2383
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
2342
2384
|
className: "text-xs tabular-nums text-sand-700 w-10 text-right",
|
|
@@ -2372,13 +2414,15 @@ function TokenUsage({ token, theme }) {
|
|
|
2372
2414
|
className: "text-[11px] text-sand-400 py-1",
|
|
2373
2415
|
children: "No usage data"
|
|
2374
2416
|
});
|
|
2417
|
+
const thresholdForPrimary = QUOTA_THRESHOLD_PROVIDERS.has(token.provider) ? token.quota_threshold : null;
|
|
2375
2418
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
2376
2419
|
className: "space-y-1.5 py-1",
|
|
2377
2420
|
children: [data.fiveHour && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UsageRow, {
|
|
2378
2421
|
label: "5h",
|
|
2379
2422
|
utilization: data.fiveHour.utilization,
|
|
2380
2423
|
resetsAt: data.fiveHour.resetsAt,
|
|
2381
|
-
theme
|
|
2424
|
+
theme,
|
|
2425
|
+
threshold: thresholdForPrimary
|
|
2382
2426
|
}), data.sevenDay && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UsageRow, {
|
|
2383
2427
|
label: "7d",
|
|
2384
2428
|
utilization: data.sevenDay.utilization,
|
|
@@ -2387,6 +2431,135 @@ function TokenUsage({ token, theme }) {
|
|
|
2387
2431
|
})]
|
|
2388
2432
|
});
|
|
2389
2433
|
}
|
|
2434
|
+
function stopDragPropagation(e) {
|
|
2435
|
+
e.stopPropagation();
|
|
2436
|
+
}
|
|
2437
|
+
function ThresholdControl({ token }) {
|
|
2438
|
+
const [pos, setPos] = (0, import_react.useState)(null);
|
|
2439
|
+
const [value, setValue] = (0, import_react.useState)("");
|
|
2440
|
+
const triggerRef = (0, import_react.useRef)(null);
|
|
2441
|
+
const queryClient = useQueryClient();
|
|
2442
|
+
const updateMutation = QgridService.useUpdateTokenMutation();
|
|
2443
|
+
const supported = QUOTA_THRESHOLD_PROVIDERS.has(token.provider);
|
|
2444
|
+
const open = pos !== null;
|
|
2445
|
+
const validation = validateThreshold(value);
|
|
2446
|
+
const POPOVER_WIDTH = 240;
|
|
2447
|
+
const POPOVER_EST_HEIGHT = 150;
|
|
2448
|
+
const MARGIN = 8;
|
|
2449
|
+
const GAP = 6;
|
|
2450
|
+
const openPopover = () => {
|
|
2451
|
+
const rect = triggerRef.current?.getBoundingClientRect();
|
|
2452
|
+
if (!rect) return;
|
|
2453
|
+
const left = Math.min(Math.max(rect.right - POPOVER_WIDTH, MARGIN), Math.max(window.innerWidth - POPOVER_WIDTH - MARGIN, MARGIN));
|
|
2454
|
+
const above = rect.top - GAP - POPOVER_EST_HEIGHT;
|
|
2455
|
+
const below = rect.bottom + GAP;
|
|
2456
|
+
setPos({
|
|
2457
|
+
left,
|
|
2458
|
+
top: Math.min(Math.max(above >= MARGIN ? above : below, MARGIN), Math.max(window.innerHeight - POPOVER_EST_HEIGHT - MARGIN, MARGIN))
|
|
2459
|
+
});
|
|
2460
|
+
setValue(String(token.quota_threshold ?? 100));
|
|
2461
|
+
};
|
|
2462
|
+
const close = () => setPos(null);
|
|
2463
|
+
if (!supported) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
2464
|
+
className: "inline-flex items-center gap-1 px-1.5 py-0.5 rounded-md text-[10px] text-sand-300 border border-sand-100",
|
|
2465
|
+
title: "Quota threshold는 이 provider에서 지원되지 않습니다",
|
|
2466
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucideGauge, { className: "size-3" }), "n/a"]
|
|
2467
|
+
});
|
|
2468
|
+
const adjust = (delta) => {
|
|
2469
|
+
const current = /^\d+$/.test(value.trim()) ? Number(value.trim()) : 0;
|
|
2470
|
+
const next = Math.min(Math.max(current + delta, 0), 100);
|
|
2471
|
+
setValue(String(next));
|
|
2472
|
+
};
|
|
2473
|
+
const save = async () => {
|
|
2474
|
+
if (!validation.ok) return;
|
|
2475
|
+
await updateMutation.mutateAsync({
|
|
2476
|
+
id: token.id,
|
|
2477
|
+
name: token.name ?? "",
|
|
2478
|
+
quotaThreshold: validation.value
|
|
2479
|
+
});
|
|
2480
|
+
await Promise.all([queryClient.invalidateQueries({ queryKey: ["Token"] }), queryClient.invalidateQueries({ queryKey: ["Qgrid"] })]);
|
|
2481
|
+
close();
|
|
2482
|
+
};
|
|
2483
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
2484
|
+
className: "inline-flex",
|
|
2485
|
+
onPointerDown: stopDragPropagation,
|
|
2486
|
+
onClick: stopDragPropagation,
|
|
2487
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
|
|
2488
|
+
ref: triggerRef,
|
|
2489
|
+
type: "button",
|
|
2490
|
+
title: "사용률 제한 설정",
|
|
2491
|
+
onClick: open ? close : openPopover,
|
|
2492
|
+
className: "flex items-center gap-1 px-1.5 py-0.5 rounded-md text-[10px] border border-sand-200/80 text-sand-400 hover:text-sand-600 hover:border-sand-300 transition-colors duration-150",
|
|
2493
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucideGauge, { className: "size-3" }), "Set limit"]
|
|
2494
|
+
}), open && pos && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
2495
|
+
className: "fixed inset-0 z-40",
|
|
2496
|
+
onPointerDown: close
|
|
2497
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
2498
|
+
className: "fixed z-50 w-60 panel shadow-xl p-3",
|
|
2499
|
+
style: {
|
|
2500
|
+
top: pos.top,
|
|
2501
|
+
left: pos.left
|
|
2502
|
+
},
|
|
2503
|
+
children: [
|
|
2504
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", {
|
|
2505
|
+
htmlFor: `threshold-${token.id}`,
|
|
2506
|
+
className: "text-[10px] uppercase tracking-wider text-sand-500 font-medium",
|
|
2507
|
+
children: "사용률 제한"
|
|
2508
|
+
}),
|
|
2509
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
2510
|
+
className: "mt-1 flex items-center gap-2",
|
|
2511
|
+
children: [
|
|
2512
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
2513
|
+
type: "button",
|
|
2514
|
+
onClick: () => adjust(-10),
|
|
2515
|
+
className: "size-9 shrink-0 rounded-md border border-sand-200 text-sand-600 text-base leading-none hover:bg-sand-100 transition-colors duration-150",
|
|
2516
|
+
children: "−"
|
|
2517
|
+
}),
|
|
2518
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Q, {
|
|
2519
|
+
id: `threshold-${token.id}`,
|
|
2520
|
+
value,
|
|
2521
|
+
onChange: (e) => setValue(e.target.value),
|
|
2522
|
+
inputMode: "numeric",
|
|
2523
|
+
className: `h-9 w-14 border rounded-md text-center text-sm text-sand-900 bg-white tabular-nums focus:outline-none ${validation.ok ? "border-sand-200 focus:border-sienna-300" : "border-red-300 focus:border-red-400"}`
|
|
2524
|
+
}),
|
|
2525
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
2526
|
+
type: "button",
|
|
2527
|
+
onClick: () => adjust(10),
|
|
2528
|
+
className: "size-9 shrink-0 rounded-md border border-sand-200 text-sand-600 text-base leading-none hover:bg-sand-100 transition-colors duration-150",
|
|
2529
|
+
children: "+"
|
|
2530
|
+
}),
|
|
2531
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
2532
|
+
className: "text-sm text-sand-500",
|
|
2533
|
+
children: "%"
|
|
2534
|
+
})
|
|
2535
|
+
]
|
|
2536
|
+
}),
|
|
2537
|
+
validation.ok ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
2538
|
+
className: "mt-1.5 text-[11px] text-sand-500 leading-snug",
|
|
2539
|
+
children: validation.value === null ? "제한 없음 — 사용률과 무관하게 항상 사용합니다." : "5h 사용률이 임계치에 달하면 해당 토큰을 건너뜁니다."
|
|
2540
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
2541
|
+
className: "mt-1.5 text-[11px] text-red-500",
|
|
2542
|
+
children: validation.error
|
|
2543
|
+
}),
|
|
2544
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
2545
|
+
className: "mt-2 flex items-center justify-end gap-1.5",
|
|
2546
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
2547
|
+
type: "button",
|
|
2548
|
+
className: "px-2 py-1 text-[11px] font-medium rounded-md border border-sand-200 text-sand-600 hover:bg-sand-100 transition-colors duration-150",
|
|
2549
|
+
onClick: close,
|
|
2550
|
+
children: "Cancel"
|
|
2551
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
2552
|
+
type: "button",
|
|
2553
|
+
className: "px-2 py-1 text-[11px] font-medium rounded-md bg-sienna-400 text-white hover:bg-sienna-500 disabled:opacity-50 transition-colors duration-150",
|
|
2554
|
+
disabled: updateMutation.isPending || !validation.ok,
|
|
2555
|
+
onClick: save,
|
|
2556
|
+
children: updateMutation.isPending ? "Saving..." : "Save"
|
|
2557
|
+
})]
|
|
2558
|
+
})
|
|
2559
|
+
]
|
|
2560
|
+
})] })]
|
|
2561
|
+
});
|
|
2562
|
+
}
|
|
2390
2563
|
function SortableTokenCard({ token }) {
|
|
2391
2564
|
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
|
|
2392
2565
|
id: String(token.id),
|
|
@@ -2433,9 +2606,24 @@ function SortableTokenCard({ token }) {
|
|
|
2433
2606
|
token,
|
|
2434
2607
|
theme
|
|
2435
2608
|
}),
|
|
2436
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("
|
|
2437
|
-
className:
|
|
2438
|
-
children:
|
|
2609
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
2610
|
+
className: "mt-2 flex items-center justify-end",
|
|
2611
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThresholdControl, { token })
|
|
2612
|
+
}),
|
|
2613
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
2614
|
+
className: "absolute top-2.5 right-3 flex items-center gap-1.5",
|
|
2615
|
+
children: [QUOTA_THRESHOLD_PROVIDERS.has(token.provider) && token.quota_threshold !== null && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
2616
|
+
className: "px-1.5 py-0.5 rounded-md bg-sienna-50 text-[11px] tabular-nums font-medium border border-sienna-200 text-sienna-600",
|
|
2617
|
+
title: `사용률 ${token.quota_threshold}% 이상이면 이 토큰 제외`,
|
|
2618
|
+
children: [
|
|
2619
|
+
"≤ ",
|
|
2620
|
+
token.quota_threshold,
|
|
2621
|
+
"%"
|
|
2622
|
+
]
|
|
2623
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
2624
|
+
className: `px-2 py-0.5 rounded-md bg-sand-50 text-[11px] tabular-nums font-medium border border-sand-200/80 ${theme.cost}`,
|
|
2625
|
+
children: formatUsd(costData?.usd ?? 0)
|
|
2626
|
+
})]
|
|
2439
2627
|
})
|
|
2440
2628
|
]
|
|
2441
2629
|
})]
|
|
@@ -2671,6 +2671,133 @@ var QueryClientProvider = ({ client, children }) => {
|
|
|
2671
2671
|
});
|
|
2672
2672
|
};
|
|
2673
2673
|
//#endregion
|
|
2674
|
+
//#region ../../node_modules/.pnpm/use-sync-external-store@1.6.0_react@19.2.4/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.js
|
|
2675
|
+
/**
|
|
2676
|
+
* @license React
|
|
2677
|
+
* use-sync-external-store-shim.production.js
|
|
2678
|
+
*
|
|
2679
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2680
|
+
*
|
|
2681
|
+
* This source code is licensed under the MIT license found in the
|
|
2682
|
+
* LICENSE file in the root directory of this source tree.
|
|
2683
|
+
*/
|
|
2684
|
+
var require_use_sync_external_store_shim_production = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
2685
|
+
var React = require_react();
|
|
2686
|
+
function is(x, y) {
|
|
2687
|
+
return x === y && (0 !== x || 1 / x === 1 / y) || x !== x && y !== y;
|
|
2688
|
+
}
|
|
2689
|
+
var objectIs = "function" === typeof Object.is ? Object.is : is, useState = React.useState, useEffect = React.useEffect, useLayoutEffect = React.useLayoutEffect, useDebugValue = React.useDebugValue;
|
|
2690
|
+
function useSyncExternalStore$2(subscribe, getSnapshot) {
|
|
2691
|
+
var value = getSnapshot(), _useState = useState({ inst: {
|
|
2692
|
+
value,
|
|
2693
|
+
getSnapshot
|
|
2694
|
+
} }), inst = _useState[0].inst, forceUpdate = _useState[1];
|
|
2695
|
+
useLayoutEffect(function() {
|
|
2696
|
+
inst.value = value;
|
|
2697
|
+
inst.getSnapshot = getSnapshot;
|
|
2698
|
+
checkIfSnapshotChanged(inst) && forceUpdate({ inst });
|
|
2699
|
+
}, [
|
|
2700
|
+
subscribe,
|
|
2701
|
+
value,
|
|
2702
|
+
getSnapshot
|
|
2703
|
+
]);
|
|
2704
|
+
useEffect(function() {
|
|
2705
|
+
checkIfSnapshotChanged(inst) && forceUpdate({ inst });
|
|
2706
|
+
return subscribe(function() {
|
|
2707
|
+
checkIfSnapshotChanged(inst) && forceUpdate({ inst });
|
|
2708
|
+
});
|
|
2709
|
+
}, [subscribe]);
|
|
2710
|
+
useDebugValue(value);
|
|
2711
|
+
return value;
|
|
2712
|
+
}
|
|
2713
|
+
function checkIfSnapshotChanged(inst) {
|
|
2714
|
+
var latestGetSnapshot = inst.getSnapshot;
|
|
2715
|
+
inst = inst.value;
|
|
2716
|
+
try {
|
|
2717
|
+
var nextValue = latestGetSnapshot();
|
|
2718
|
+
return !objectIs(inst, nextValue);
|
|
2719
|
+
} catch (error) {
|
|
2720
|
+
return !0;
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
function useSyncExternalStore$1(subscribe, getSnapshot) {
|
|
2724
|
+
return getSnapshot();
|
|
2725
|
+
}
|
|
2726
|
+
var shim = "undefined" === typeof window || "undefined" === typeof window.document || "undefined" === typeof window.document.createElement ? useSyncExternalStore$1 : useSyncExternalStore$2;
|
|
2727
|
+
exports.useSyncExternalStore = void 0 !== React.useSyncExternalStore ? React.useSyncExternalStore : shim;
|
|
2728
|
+
}));
|
|
2729
|
+
//#endregion
|
|
2730
|
+
//#region ../../node_modules/.pnpm/use-sync-external-store@1.6.0_react@19.2.4/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.development.js
|
|
2731
|
+
/**
|
|
2732
|
+
* @license React
|
|
2733
|
+
* use-sync-external-store-shim.development.js
|
|
2734
|
+
*
|
|
2735
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2736
|
+
*
|
|
2737
|
+
* This source code is licensed under the MIT license found in the
|
|
2738
|
+
* LICENSE file in the root directory of this source tree.
|
|
2739
|
+
*/
|
|
2740
|
+
var require_use_sync_external_store_shim_development = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
2741
|
+
"production" !== process.env.NODE_ENV && (function() {
|
|
2742
|
+
function is(x, y) {
|
|
2743
|
+
return x === y && (0 !== x || 1 / x === 1 / y) || x !== x && y !== y;
|
|
2744
|
+
}
|
|
2745
|
+
function useSyncExternalStore$2(subscribe, getSnapshot) {
|
|
2746
|
+
didWarnOld18Alpha || void 0 === React.startTransition || (didWarnOld18Alpha = !0, console.error("You are using an outdated, pre-release alpha of React 18 that does not support useSyncExternalStore. The use-sync-external-store shim will not work correctly. Upgrade to a newer pre-release."));
|
|
2747
|
+
var value = getSnapshot();
|
|
2748
|
+
if (!didWarnUncachedGetSnapshot) {
|
|
2749
|
+
var cachedValue = getSnapshot();
|
|
2750
|
+
objectIs(value, cachedValue) || (console.error("The result of getSnapshot should be cached to avoid an infinite loop"), didWarnUncachedGetSnapshot = !0);
|
|
2751
|
+
}
|
|
2752
|
+
cachedValue = useState({ inst: {
|
|
2753
|
+
value,
|
|
2754
|
+
getSnapshot
|
|
2755
|
+
} });
|
|
2756
|
+
var inst = cachedValue[0].inst, forceUpdate = cachedValue[1];
|
|
2757
|
+
useLayoutEffect(function() {
|
|
2758
|
+
inst.value = value;
|
|
2759
|
+
inst.getSnapshot = getSnapshot;
|
|
2760
|
+
checkIfSnapshotChanged(inst) && forceUpdate({ inst });
|
|
2761
|
+
}, [
|
|
2762
|
+
subscribe,
|
|
2763
|
+
value,
|
|
2764
|
+
getSnapshot
|
|
2765
|
+
]);
|
|
2766
|
+
useEffect(function() {
|
|
2767
|
+
checkIfSnapshotChanged(inst) && forceUpdate({ inst });
|
|
2768
|
+
return subscribe(function() {
|
|
2769
|
+
checkIfSnapshotChanged(inst) && forceUpdate({ inst });
|
|
2770
|
+
});
|
|
2771
|
+
}, [subscribe]);
|
|
2772
|
+
useDebugValue(value);
|
|
2773
|
+
return value;
|
|
2774
|
+
}
|
|
2775
|
+
function checkIfSnapshotChanged(inst) {
|
|
2776
|
+
var latestGetSnapshot = inst.getSnapshot;
|
|
2777
|
+
inst = inst.value;
|
|
2778
|
+
try {
|
|
2779
|
+
var nextValue = latestGetSnapshot();
|
|
2780
|
+
return !objectIs(inst, nextValue);
|
|
2781
|
+
} catch (error) {
|
|
2782
|
+
return !0;
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
2785
|
+
function useSyncExternalStore$1(subscribe, getSnapshot) {
|
|
2786
|
+
return getSnapshot();
|
|
2787
|
+
}
|
|
2788
|
+
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
|
|
2789
|
+
var React = require_react(), objectIs = "function" === typeof Object.is ? Object.is : is, useState = React.useState, useEffect = React.useEffect, useLayoutEffect = React.useLayoutEffect, useDebugValue = React.useDebugValue, didWarnOld18Alpha = !1, didWarnUncachedGetSnapshot = !1, shim = "undefined" === typeof window || "undefined" === typeof window.document || "undefined" === typeof window.document.createElement ? useSyncExternalStore$1 : useSyncExternalStore$2;
|
|
2790
|
+
exports.useSyncExternalStore = void 0 !== React.useSyncExternalStore ? React.useSyncExternalStore : shim;
|
|
2791
|
+
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
|
|
2792
|
+
})();
|
|
2793
|
+
}));
|
|
2794
|
+
//#endregion
|
|
2795
|
+
//#region ../../node_modules/.pnpm/use-sync-external-store@1.6.0_react@19.2.4/node_modules/use-sync-external-store/shim/index.js
|
|
2796
|
+
var require_shim = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2797
|
+
if (process.env.NODE_ENV === "production") module.exports = require_use_sync_external_store_shim_production();
|
|
2798
|
+
else module.exports = require_use_sync_external_store_shim_development();
|
|
2799
|
+
}));
|
|
2800
|
+
//#endregion
|
|
2674
2801
|
//#region ../../node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom.production.js
|
|
2675
2802
|
/**
|
|
2676
2803
|
* @license React
|
|
@@ -22420,6 +22547,7 @@ var entityLabels = {
|
|
|
22420
22547
|
"entity.RequestLog.cache_read_tokens": "캐시 읽기 토큰",
|
|
22421
22548
|
"entity.RequestLog.cache_creation_tokens": "캐시 생성 토큰",
|
|
22422
22549
|
"entity.RequestLog.duration_ms": "응답 소요시간(ms)",
|
|
22550
|
+
"entity.RequestLog.ttft_ms": "first gen TTFT(ms)",
|
|
22423
22551
|
"entity.RequestLog.cost_usd": "API 비용",
|
|
22424
22552
|
"entity.RequestLog.effort": "effort level",
|
|
22425
22553
|
"entity.RequestLog.history": "inject_items 히스토리",
|
|
@@ -22445,6 +22573,7 @@ var entityLabels = {
|
|
|
22445
22573
|
"entity.RequestLogStep.cache_read_tokens": "캐시 읽기 토큰",
|
|
22446
22574
|
"entity.RequestLogStep.cache_creation_tokens": "캐시 생성 토큰",
|
|
22447
22575
|
"entity.RequestLogStep.duration_ms": "소요시간(ms)",
|
|
22576
|
+
"entity.RequestLogStep.ttft_ms": "Gen TTFT(ms)",
|
|
22448
22577
|
"entity.RequestLogStep.finish_reason": "완료 사유",
|
|
22449
22578
|
"entity.RequestLogStep.reasoning_text": "reasoning 텍스트",
|
|
22450
22579
|
"entity.RequestLogStep.reasoning_tokens": "reasoning 토큰 수",
|
|
@@ -22467,6 +22596,7 @@ var entityLabels = {
|
|
|
22467
22596
|
"entity.Token.name": "토큰 이름",
|
|
22468
22597
|
"entity.Token.active": "활성 여부",
|
|
22469
22598
|
"entity.Token.ord": "정렬 순서",
|
|
22599
|
+
"entity.Token.quota_threshold": "quota 사용률 임계치(%). null이면 미설정",
|
|
22470
22600
|
"enum.TokenOrderBy.id-desc": "ID최신순",
|
|
22471
22601
|
"enum.TokenOrderBy.ord-asc": "순서순",
|
|
22472
22602
|
"enum.TokenSearchField.id": "ID",
|
|
@@ -22526,4 +22656,4 @@ SD.enumLabels = (enumName) => {
|
|
|
22526
22656
|
} });
|
|
22527
22657
|
};
|
|
22528
22658
|
//#endregion
|
|
22529
|
-
export {
|
|
22659
|
+
export { hashKey as A, shallowEqualObjects as B, Query as C, pendingThenable as D, notifyManager as E, noop$2 as F, focusManager as G, skipToken as H, partialMatchKey as I, __exportAll as J, Subscribable as K, replaceData as L, isValidTimeout as M, matchMutation as N, environmentManager as O, matchQuery as P, resolveEnabled as R, infiniteQueryBehavior as S, onlineManager as T, timeUntilStale as U, shouldThrowError as V, timeoutManager as W, __toESM as X, __require as Y, require_react as _, fetch$1 as a, hasNextPage as b, number as c, require_lib as d, require_react_dom as f, require_jsx_runtime as g, useQueryClient as h, dedupeAndFlatten as i, hashQueryKeyByOptions as j, functionalUpdate as k, object as l, QueryClientProvider as m, SUPPORTED_LOCALES as n, useRefreshable as o, require_shim as p, __commonJSMin as q, setLocale as r, useSSEStream as s, SD as t, string as u, Mutation as v, fetchState as w, hasPreviousPage as x, getDefaultState as y, resolveStaleTime as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { A as hashKey, B as shallowEqualObjects, D as pendingThenable, E as notifyManager, F as noop, G as focusManager, K as Subscribable, L as replaceData, M as isValidTimeout, O as environmentManager, R as resolveEnabled, S as infiniteQueryBehavior, U as timeUntilStale, V as shouldThrowError, W as timeoutManager, X as __toESM, _ as require_react, a as fetch, b as hasNextPage, d as require_lib, g as require_jsx_runtime, h as useQueryClient, i as dedupeAndFlatten, o as useRefreshable, s as useSSEStream, w as fetchState, x as hasPreviousPage, y as getDefaultState, z as resolveStaleTime } from "./sd.generated-DdfpD_iN.js";
|
|
2
2
|
//#region ../../node_modules/.pnpm/@tanstack+query-core@5.95.2/node_modules/@tanstack/query-core/build/modern/queryObserver.js
|
|
3
3
|
var QueryObserver = class extends Subscribable {
|
|
4
4
|
constructor(client, options) {
|
|
@@ -1036,18 +1036,19 @@ var QgridService;
|
|
|
1036
1036
|
}
|
|
1037
1037
|
_QgridService.addToken = addToken;
|
|
1038
1038
|
_QgridService.useAddTokenMutation = () => useMutation({ mutationFn: (params) => addToken(params.provider, params.credentials, params.name) });
|
|
1039
|
-
async function updateToken(id, name) {
|
|
1039
|
+
async function updateToken(id, name, quotaThreshold) {
|
|
1040
1040
|
return fetch({
|
|
1041
1041
|
method: "POST",
|
|
1042
1042
|
url: `/api/qgrid/updateToken`,
|
|
1043
1043
|
data: {
|
|
1044
1044
|
id,
|
|
1045
|
-
name
|
|
1045
|
+
name,
|
|
1046
|
+
quotaThreshold
|
|
1046
1047
|
}
|
|
1047
1048
|
});
|
|
1048
1049
|
}
|
|
1049
1050
|
_QgridService.updateToken = updateToken;
|
|
1050
|
-
_QgridService.useUpdateTokenMutation = () => useMutation({ mutationFn: (params) => updateToken(params.id, params.name) });
|
|
1051
|
+
_QgridService.useUpdateTokenMutation = () => useMutation({ mutationFn: (params) => updateToken(params.id, params.name, params.quotaThreshold) });
|
|
1051
1052
|
async function removeToken(id) {
|
|
1052
1053
|
return fetch({
|
|
1053
1054
|
method: "POST",
|