@cartanova/qgrid-cli 2.4.0 → 2.4.1
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/conv-routing.js +21 -1
- package/bundle/dist/application/qgrid/qgrid-response-format.js +50 -3
- package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +3 -14
- package/bundle/dist/application/qgrid/qgrid.frame.js +3 -14
- package/bundle/dist/application/qgrid/qgrid.types.js +11 -2
- package/bundle/dist/application/sonamu.generated.js +11 -3
- package/bundle/dist/application/sonamu.generated.sso.js +9 -2
- package/bundle/src/application/qgrid/conv-routing.test.ts +31 -0
- package/bundle/src/application/qgrid/conv-routing.ts +13 -0
- package/bundle/src/application/qgrid/qgrid-response-format.test.ts +77 -0
- package/bundle/src/application/qgrid/qgrid-response-format.ts +79 -6
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +11 -21
- package/bundle/src/application/qgrid/qgrid.frame.test.ts +36 -0
- package/bundle/src/application/qgrid/qgrid.frame.ts +14 -22
- package/bundle/src/application/qgrid/qgrid.types.ts +14 -0
- package/bundle/src/application/request-log-step/request-log-step.entity.json +2 -1
- package/bundle/src/application/sonamu.generated.http +18 -0
- package/bundle/src/application/sonamu.generated.sso.ts +7 -0
- package/bundle/src/application/sonamu.generated.ts +7 -1
- package/bundle/web-dist/client/assets/{index-DVdnvcvo.js → index-CHRDevod.js} +3 -3
- package/bundle/web-dist/client/assets/index-Dc-qeEPm.css +1 -0
- package/bundle/web-dist/client/assets/logs-CFw7oJgw.js +1 -0
- package/bundle/web-dist/client/assets/{routes-CvCEcpZ7.js → routes-vhw9Wsg6.js} +1 -1
- package/bundle/web-dist/client/assets/{show-DWRh--ML.js → show-CKIx8CD_.js} +3 -3
- package/bundle/web-dist/client/assets/{tokens-DOu_ZFUL.js → tokens-Di4RowSm.js} +1 -1
- package/bundle/web-dist/client/index.html +2 -2
- package/bundle/web-dist/server/assets/{logs-B_ZLzpwY.js → logs-Bk9C0ELo.js} +1 -0
- package/bundle/web-dist/server/assets/{show-CGlX9OYt.js → show-3GokIDEJ.js} +94 -12
- package/bundle/web-dist/server/entry-server.generated.js +3 -3
- package/package.json +1 -1
- package/postinstall.mjs +14 -2
- package/skills/qgrid/references/ai-sdk-provider-contract.md +4 -0
- package/skills/qgrid/references/decision-rationale.md +2 -2
- package/skills/qgrid/references/openai-codex-runtime.md +2 -0
- package/skills/qgrid/references/request-log-run-lifecycle.md +2 -0
- package/skills/qgrid/references/sonamu-api-web-flow.md +2 -0
- package/skills/qgrid/references/verification-and-debugging.md +4 -0
- package/bundle/web-dist/client/assets/index-VE_24EJf.css +0 -1
- package/bundle/web-dist/client/assets/logs-B82PGnxD.js +0 -1
|
@@ -1 +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-DVdnvcvo.js";import{i as o,t as s}from"./services.generated-AsEvHbJ7.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};
|
|
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-CHRDevod.js";import{i as o,t as s}from"./services.generated-AsEvHbJ7.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-CHRDevod.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
13
|
<link rel="modulepreload" crossorigin href="/assets/sd.generated-BrUnRt0B.js">
|
|
14
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
14
|
+
<link rel="stylesheet" crossorigin href="/assets/index-Dc-qeEPm.css">
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
|
17
17
|
<div id="root"></div>
|
|
@@ -25210,7 +25210,7 @@ function ImageAwareContent({ text, markdown }) {
|
|
|
25210
25210
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucideX, { className: "size-5" })
|
|
25211
25211
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
|
|
25212
25212
|
src: viewerSrc,
|
|
25213
|
-
alt: "generated
|
|
25213
|
+
alt: "generated preview",
|
|
25214
25214
|
className: "max-h-full max-w-full object-contain rounded-md bg-white",
|
|
25215
25215
|
onClick: (e) => e.stopPropagation()
|
|
25216
25216
|
})]
|
|
@@ -25342,7 +25342,7 @@ function MetricsPanel({ data, toolCallCount }) {
|
|
|
25342
25342
|
}),
|
|
25343
25343
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Metric, {
|
|
25344
25344
|
label: "TTFT",
|
|
25345
|
-
value:
|
|
25345
|
+
value: formatRunTtftMs(data.ttft_ms)
|
|
25346
25346
|
}),
|
|
25347
25347
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Metric, {
|
|
25348
25348
|
label: "Tokens/sec",
|
|
@@ -25392,6 +25392,10 @@ function formatDurationMs(ms) {
|
|
|
25392
25392
|
if (ms === null || ms === void 0) return "—";
|
|
25393
25393
|
return ms >= 1e3 ? `${(ms / 1e3).toFixed(1)}s` : `${ms}ms`;
|
|
25394
25394
|
}
|
|
25395
|
+
function formatRunTtftMs(ms) {
|
|
25396
|
+
if (ms === null || ms === void 0 || ms <= 0) return "—";
|
|
25397
|
+
return formatDurationMs(ms);
|
|
25398
|
+
}
|
|
25395
25399
|
function detectTokenRateProvider(source) {
|
|
25396
25400
|
const modelName = source.model_name?.trim().toLowerCase();
|
|
25397
25401
|
if (modelName) {
|
|
@@ -25409,7 +25413,7 @@ function isTokensPerSecEnabled(source) {
|
|
|
25409
25413
|
return provider !== null && TOKENS_PER_SEC_PROVIDERS.has(provider);
|
|
25410
25414
|
}
|
|
25411
25415
|
function formatTokensPerSec(outputTokens, durationMs, ttftMs, enabled) {
|
|
25412
|
-
if (!enabled || outputTokens === null || outputTokens === void 0 || durationMs === null || durationMs === void 0 || ttftMs === null || ttftMs === void 0) return "—";
|
|
25416
|
+
if (!enabled || outputTokens === null || outputTokens === void 0 || durationMs === null || durationMs === void 0 || ttftMs === null || ttftMs === void 0 || ttftMs <= 0) return "—";
|
|
25413
25417
|
const generationMs = durationMs - ttftMs;
|
|
25414
25418
|
if (outputTokens <= 0 || generationMs <= 0) return "—";
|
|
25415
25419
|
return `${Math.round(outputTokens / (generationMs / 1e3)).toLocaleString()} tok/s`;
|
|
@@ -25423,11 +25427,85 @@ function CompactMetric({ label, value }) {
|
|
|
25423
25427
|
children: value
|
|
25424
25428
|
})] });
|
|
25425
25429
|
}
|
|
25430
|
+
function readToolInputImages(args) {
|
|
25431
|
+
if (!args || typeof args !== "object" || Array.isArray(args)) return [];
|
|
25432
|
+
const inputImages = args.inputImages;
|
|
25433
|
+
return Array.isArray(inputImages) ? inputImages : void 0;
|
|
25434
|
+
}
|
|
25435
|
+
function getToolInputImages(args) {
|
|
25436
|
+
return (readToolInputImages(args) ?? []).filter((item) => {
|
|
25437
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) return false;
|
|
25438
|
+
const image = item;
|
|
25439
|
+
return typeof image.url === "string" && image.url.length > 0 || typeof image.data === "string" && image.data.length > 0;
|
|
25440
|
+
});
|
|
25441
|
+
}
|
|
25442
|
+
function hideToolInputImages(args) {
|
|
25443
|
+
if (!args || typeof args !== "object" || Array.isArray(args)) return args;
|
|
25444
|
+
const record = args;
|
|
25445
|
+
const inputImages = readToolInputImages(record);
|
|
25446
|
+
if (!inputImages) return args;
|
|
25447
|
+
return {
|
|
25448
|
+
...record,
|
|
25449
|
+
inputImages: inputImages.map((item) => {
|
|
25450
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) return item;
|
|
25451
|
+
const image = item;
|
|
25452
|
+
const maskedUrl = typeof image.url === "string" && image.url.toLowerCase().startsWith("data:") ? `[data-url ${image.url.length} chars]` : image.url;
|
|
25453
|
+
return {
|
|
25454
|
+
mediaType: image.mediaType,
|
|
25455
|
+
byteSize: image.byteSize,
|
|
25456
|
+
...maskedUrl ? { url: maskedUrl } : {},
|
|
25457
|
+
...image.data ? { data: `[base64 ${image.data.length} chars]` } : {}
|
|
25458
|
+
};
|
|
25459
|
+
})
|
|
25460
|
+
};
|
|
25461
|
+
}
|
|
25462
|
+
function ToolInputImages({ images }) {
|
|
25463
|
+
const renderableImages = images.map((image, index) => {
|
|
25464
|
+
const urlSrc = image.url && !image.url.startsWith("[") ? image.url : void 0;
|
|
25465
|
+
const dataSrc = image.data ? `data:${image.mediaType ?? "image/png"};base64,${image.data}` : "";
|
|
25466
|
+
const src = urlSrc ?? dataSrc;
|
|
25467
|
+
return src ? {
|
|
25468
|
+
image,
|
|
25469
|
+
index,
|
|
25470
|
+
src
|
|
25471
|
+
} : null;
|
|
25472
|
+
}).filter((item) => item !== null);
|
|
25473
|
+
if (renderableImages.length === 0) return null;
|
|
25474
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
25475
|
+
className: "text-[10px] uppercase tracking-wider text-sand-400 font-medium px-2",
|
|
25476
|
+
children: "Input Images"
|
|
25477
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
25478
|
+
className: "mt-1 grid grid-cols-1 sm:grid-cols-2 gap-2",
|
|
25479
|
+
children: renderableImages.map(({ image, index, src }) => {
|
|
25480
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
25481
|
+
className: "rounded-md border border-sand-200 bg-white overflow-hidden",
|
|
25482
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
|
|
25483
|
+
src,
|
|
25484
|
+
alt: `reference ${index + 1}`,
|
|
25485
|
+
className: "max-h-64 w-full object-contain bg-white",
|
|
25486
|
+
loading: "lazy"
|
|
25487
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
25488
|
+
className: "px-2 py-1 text-[10px] text-sand-500 font-mono border-t border-sand-100",
|
|
25489
|
+
children: [
|
|
25490
|
+
image.mediaType ?? "image",
|
|
25491
|
+
" ·",
|
|
25492
|
+
" ",
|
|
25493
|
+
image.byteSize !== void 0 ? `${image.byteSize.toLocaleString()} bytes` : "url"
|
|
25494
|
+
]
|
|
25495
|
+
})]
|
|
25496
|
+
}, `${image.mediaType ?? "image"}-${index}`);
|
|
25497
|
+
})
|
|
25498
|
+
})] });
|
|
25499
|
+
}
|
|
25500
|
+
function RequestInputImages({ stepId }) {
|
|
25501
|
+
const { data: detail } = RequestLogStepService.useRequestLogStep("I", stepId ?? 0, { enabled: stepId !== null });
|
|
25502
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToolInputImages, { images: getToolInputImages(detail ? safeParseJson(detail.tool_args) : null) });
|
|
25503
|
+
}
|
|
25426
25504
|
function ToolCallItem({ entry }) {
|
|
25427
25505
|
const hasError = !!entry.error;
|
|
25428
25506
|
const [opened, setOpened] = (0, import_react.useState)(false);
|
|
25429
25507
|
const { data: detail } = RequestLogStepService.useRequestLogStep("A", entry.id, { enabled: opened });
|
|
25430
|
-
const
|
|
25508
|
+
const displayArgs = hideToolInputImages(detail ? safeParseJson(detail.tool_args) : null);
|
|
25431
25509
|
const result = detail ? safeParseJson(detail.tool_result) : null;
|
|
25432
25510
|
const error = detail?.error ?? entry.error;
|
|
25433
25511
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", {
|
|
@@ -25462,7 +25540,7 @@ function ToolCallItem({ entry }) {
|
|
|
25462
25540
|
children: "Request"
|
|
25463
25541
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
25464
25542
|
className: "mt-1 rounded-md bg-sand-50 p-3 overflow-auto",
|
|
25465
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FormattedContent, { text: detail ? JSON.stringify(
|
|
25543
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FormattedContent, { text: detail ? JSON.stringify(displayArgs) : "Loading..." })
|
|
25466
25544
|
})] }),
|
|
25467
25545
|
error && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
25468
25546
|
className: "text-[10px] uppercase tracking-wider text-red-500 font-medium px-2",
|
|
@@ -25562,7 +25640,7 @@ function StepTreeItem({ entry, tokensPerSecEnabled }) {
|
|
|
25562
25640
|
}),
|
|
25563
25641
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CompactMetric, {
|
|
25564
25642
|
label: "TTFT",
|
|
25565
|
-
value:
|
|
25643
|
+
value: formatRunTtftMs(generate.ttftMs)
|
|
25566
25644
|
}),
|
|
25567
25645
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CompactMetric, {
|
|
25568
25646
|
label: "Tokens/sec",
|
|
@@ -25712,6 +25790,7 @@ function RequestDetail({ id }) {
|
|
|
25712
25790
|
page: 1,
|
|
25713
25791
|
orderBy: "id-asc"
|
|
25714
25792
|
});
|
|
25793
|
+
const stepTree = buildStepTree(stepsData?.rows ?? []);
|
|
25715
25794
|
if (isLoading) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
25716
25795
|
className: "max-w-6xl mx-auto space-y-4",
|
|
25717
25796
|
children: [
|
|
@@ -25731,8 +25810,8 @@ function RequestDetail({ id }) {
|
|
|
25731
25810
|
children: "Request not found."
|
|
25732
25811
|
})]
|
|
25733
25812
|
});
|
|
25734
|
-
const stepTree = buildStepTree(stepsData?.rows ?? []);
|
|
25735
25813
|
const toolCalls = stepTree.flatMap((step) => step.toolCalls);
|
|
25814
|
+
const firstImageGenerationStepId = toolCalls.find((toolCall) => toolCall.toolName === "image_generation")?.id ?? null;
|
|
25736
25815
|
const hasSteps = stepTree.length > 0;
|
|
25737
25816
|
const tokensPerSecEnabled = isTokensPerSecEnabled(data);
|
|
25738
25817
|
const history = data.history ?? null;
|
|
@@ -25751,11 +25830,14 @@ function RequestDetail({ id }) {
|
|
|
25751
25830
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Section, {
|
|
25752
25831
|
title: "User",
|
|
25753
25832
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
25754
|
-
className: "
|
|
25755
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.
|
|
25756
|
-
|
|
25757
|
-
|
|
25758
|
-
|
|
25833
|
+
className: "space-y-3",
|
|
25834
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
25835
|
+
className: "relative",
|
|
25836
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CopyButton, { text: data.user_prompt ?? "null" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FormattedContent, {
|
|
25837
|
+
text: data.user_prompt ?? "null",
|
|
25838
|
+
markdown: true
|
|
25839
|
+
})]
|
|
25840
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequestInputImages, { stepId: firstImageGenerationStepId })]
|
|
25759
25841
|
})
|
|
25760
25842
|
})]
|
|
25761
25843
|
});
|
|
@@ -22679,7 +22679,7 @@ var sections = [{
|
|
|
22679
22679
|
icon: lucideFileText
|
|
22680
22680
|
}]
|
|
22681
22681
|
}];
|
|
22682
|
-
var qgridVersion = "2.4.
|
|
22682
|
+
var qgridVersion = "2.4.1";
|
|
22683
22683
|
function Sidebar({ className }) {
|
|
22684
22684
|
const pathname = useRouterState({ select: (s) => s.location.pathname });
|
|
22685
22685
|
const isActive = (path) => {
|
|
@@ -44563,7 +44563,7 @@ var $$splitComponentImporter$3 = () => import("./assets/tokens-Cjw6cQxZ.js");
|
|
|
44563
44563
|
var Route$3 = createFileRoute("/tokens")({ component: lazyRouteComponent($$splitComponentImporter$3, "component") });
|
|
44564
44564
|
//#endregion
|
|
44565
44565
|
//#region src/routes/logs.tsx
|
|
44566
|
-
var $$splitComponentImporter$2 = () => import("./assets/logs-
|
|
44566
|
+
var $$splitComponentImporter$2 = () => import("./assets/logs-Bk9C0ELo.js");
|
|
44567
44567
|
var logsSearchSchema = object({
|
|
44568
44568
|
token: string().optional(),
|
|
44569
44569
|
project: string().optional(),
|
|
@@ -44579,7 +44579,7 @@ var $$splitComponentImporter$1 = () => import("./assets/routes-D9OiKoqa.js");
|
|
|
44579
44579
|
var Route$1 = createFileRoute("/")({ component: lazyRouteComponent($$splitComponentImporter$1, "component") });
|
|
44580
44580
|
//#endregion
|
|
44581
44581
|
//#region src/routes/requests/show.tsx
|
|
44582
|
-
var $$splitComponentImporter = () => import("./assets/show-
|
|
44582
|
+
var $$splitComponentImporter = () => import("./assets/show-3GokIDEJ.js");
|
|
44583
44583
|
var showSearchSchema = object({ id: number() });
|
|
44584
44584
|
var Route = createFileRoute("/requests/show")({
|
|
44585
44585
|
validateSearch: showSearchSchema,
|
package/package.json
CHANGED
package/postinstall.mjs
CHANGED
|
@@ -42,6 +42,11 @@ function defaultProjectRoot() {
|
|
|
42
42
|
return findProjectRoot(cwd);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
function isInside(parentDir, childDir) {
|
|
46
|
+
const relative = path.relative(path.resolve(parentDir), path.resolve(childDir));
|
|
47
|
+
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
|
48
|
+
}
|
|
49
|
+
|
|
45
50
|
function defaultTargets() {
|
|
46
51
|
const isGlobalInstall =
|
|
47
52
|
process.env.npm_config_global === "true" || process.env.npm_config_location === "global";
|
|
@@ -61,6 +66,11 @@ function defaultTargets() {
|
|
|
61
66
|
|
|
62
67
|
const projectRoot = defaultProjectRoot();
|
|
63
68
|
if (!projectRoot) return null;
|
|
69
|
+
const isInstalledPackage = packageDir.split(path.sep).includes("node_modules");
|
|
70
|
+
if (!isInstalledPackage && isInside(projectRoot, sourceSkillsDir)) {
|
|
71
|
+
console.log("qgrid skill sync skipped: running inside qgrid repository.");
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
64
74
|
|
|
65
75
|
return [
|
|
66
76
|
{
|
|
@@ -104,7 +114,7 @@ async function syncSkill({ label, target, useSymlink }) {
|
|
|
104
114
|
|
|
105
115
|
const targetConfigs = defaultTargets();
|
|
106
116
|
|
|
107
|
-
if (
|
|
117
|
+
if (targetConfigs === null) {
|
|
108
118
|
console.log("qgrid skill sync skipped: project root not found.");
|
|
109
119
|
process.exit(0);
|
|
110
120
|
}
|
|
@@ -114,6 +124,8 @@ try {
|
|
|
114
124
|
await syncSkill(targetConfig);
|
|
115
125
|
}
|
|
116
126
|
} catch (error) {
|
|
117
|
-
console.error(
|
|
127
|
+
console.error(
|
|
128
|
+
`qgrid skill sync failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
129
|
+
);
|
|
118
130
|
process.exit(1);
|
|
119
131
|
}
|
|
@@ -64,6 +64,8 @@ Payload responsibilities:
|
|
|
64
64
|
- Preserve and resend `runContext` for tool-call follow-ups.
|
|
65
65
|
- Store/resend OpenAI `threadCoord` by `sessionKey`.
|
|
66
66
|
- Send `imageGeneration` and `imageGenerationOptions` when configured.
|
|
67
|
+
- Send AI SDK multimodal image/file message parts as qgrid `input` only when `imageGeneration` is enabled. Normal non-image-generation calls keep `user_prompt` text-only and do not forward image input.
|
|
68
|
+
- Reject oversized reference-image data URLs before the request leaves the SDK. Reference images travel as JSON data URLs; callers should compress/resize large photos, preferably to WebP/JPEG.
|
|
67
69
|
|
|
68
70
|
Tools and `jsonSchema` cannot be used together at qgrid dispatcher level.
|
|
69
71
|
|
|
@@ -71,6 +73,8 @@ When tools are present, qgrid sends tool definitions to the server as `tools`; i
|
|
|
71
73
|
|
|
72
74
|
Image generation is different from AI SDK client tools: it is an opt-in Codex-hosted tool exposed by qgrid through `providerOptions.qgrid.imageGeneration`. Use `generateText`; `streamText` rejects image generation before opening the stream.
|
|
73
75
|
|
|
76
|
+
Reference images for image generation use normal AI SDK multimodal message parts. The provider wraps image/file base64 as `data:${mediaType};base64,...` qgrid `input` items. This is intentionally scoped to image-generation requests, not general vision/chat behavior.
|
|
77
|
+
|
|
74
78
|
## Response mapping
|
|
75
79
|
|
|
76
80
|
qgrid response content maps to AI SDK content:
|
|
@@ -172,8 +172,8 @@ Key decisions:
|
|
|
172
172
|
- It is non-stream only. Codex returns completed base64 image payloads, not useful image deltas.
|
|
173
173
|
- Image turns are cold one-shot threads and are excluded from thread reuse. This prevents base64 payloads from entering reusable conversation state and cache prefixes.
|
|
174
174
|
- qgrid performs preflight capability/model gates and postflight "image count must be greater than zero" checks. Codex can otherwise silently return text when image generation is unavailable or unused.
|
|
175
|
-
- Returned images are inline base64 content parts for consumers and AI SDK `file` parts.
|
|
175
|
+
- Returned images are inline base64 content parts for consumers and AI SDK `file` parts. Reference images are accepted through AI SDK multimodal message parts only on the `imageGeneration` path, and are transported as JSON data URLs with SDK-side size guarding.
|
|
176
176
|
- `imageGenerationOptions` currently supports quality and size. The worker instruction and request-log pricing assumption use `gpt-image-2`, with defaults `medium` and `1536x1024`.
|
|
177
|
-
- qgrid does not manage generated images as durable assets through a `generated_images` table or object-storage layer. Current request logs can still contain inline image data URLs for inspection and synthetic `image_generation` tool-call steps.
|
|
177
|
+
- qgrid does not manage generated or reference images as durable assets through a `generated_images` table or object-storage layer. Current request logs can still contain inline image data URLs for inspection and synthetic `image_generation` tool-call steps; reference input images live in the first synthetic step's `tool_args.inputImages`.
|
|
178
178
|
- Image cost is stored separately in `request_logs.image_cost_usd`; `request_logs.cost_usd` remains the Codex driver model token cost. Because Codex does not expose exact image tool usage, `image_cost_usd` is a price-table estimate and may be inaccurate.
|
|
179
179
|
- Inspect current plans, tests, and implementation before changing behavior; the Codex tool surface can change underneath qgrid.
|
|
@@ -145,9 +145,11 @@ Image generation is OpenAI/Codex-only and implemented as an opt-in Codex `image_
|
|
|
145
145
|
- It enables `features.image_generation` only on that thread; global config remains disabled.
|
|
146
146
|
- It swaps the normal "text only" base instruction for an image-permitting instruction on that thread.
|
|
147
147
|
- It gates on provider capability and model multimodality.
|
|
148
|
+
- AI SDK reference images are accepted only on this image-generation path. They arrive as qgrid `input` image data URLs and should be compressed/resized by callers before JSON transport.
|
|
148
149
|
- Failure kinds are `gate`, `not_called`, and `incomplete`.
|
|
149
150
|
- Codex notifications expose image items through `item/started` and `item/completed`; qgrid treats non-empty base64 `result` as the completion signal, not the item `status` string.
|
|
150
151
|
- Completed images are surfaced as qgrid `image` content parts and AI SDK `file` parts with `mediaType: "image/png"`.
|
|
151
152
|
- qgrid uses `gpt-image-2` as the image-tool pricing/model assumption. Codex does not expose exact image tool token usage, so `image_cost_usd` is an estimate from the public price table, not exact billing.
|
|
153
|
+
- Codex may return multiple completed image outputs. qgrid maps each one to a separate image content part and a synthetic `image_generation` request-log tool step.
|
|
152
154
|
|
|
153
155
|
Before modifying this area, inspect latest docs/plans/brainstorms and current tests.
|
|
@@ -58,6 +58,8 @@ Anthropic: normalize native mutually exclusive categories by summing input + cac
|
|
|
58
58
|
|
|
59
59
|
For image requests, keep `cost_usd` as the Codex driver model token cost. Image output cost is separate because qgrid observes Codex's `image_generation` result, not the OpenAI Images API usage object. Treat `image_cost_usd` as a price-table estimate that may be inaccurate if Codex changes its underlying image accounting.
|
|
60
60
|
|
|
61
|
+
Reference images for image generation are not stored in `request_logs.user_prompt`; that field remains the text prompt. For inspection in the detail view, qgrid stores reference image metadata/base64 in the synthetic `image_generation` step's `tool_args.inputImages`. If Codex returns multiple image outputs, store `inputImages` only on the first synthetic image tool step so multi-output logs do not duplicate the same input payload on every output.
|
|
62
|
+
|
|
61
63
|
## Legacy normalization
|
|
62
64
|
|
|
63
65
|
`RequestLogModel` normalizes legacy Anthropic rows where stored `input_tokens` may not include cache read/write. Keep this in mind when changing cost or display logic.
|
|
@@ -37,6 +37,8 @@ Check list and detail views. Avoid loading large text columns in list views unle
|
|
|
37
37
|
|
|
38
38
|
Image-generation request logs add `is_image_generation`, `image_cost_usd`, and `image_cost_method`. The list view displays driver plus image cost as the total cost cell; the detail view shows driver cost and image cost separately and renders generated image data URLs from response/tool-step content.
|
|
39
39
|
|
|
40
|
+
Reference input images for image generation render in the detail view under the user prompt from the first synthetic `image_generation` step's `tool_args.inputImages`. Keep the prompt itself text-only, redact large base64 in request JSON views, and avoid rendering duplicate input previews for multi-output image turns.
|
|
41
|
+
|
|
40
42
|
## Verification
|
|
41
43
|
|
|
42
44
|
After API shape changes:
|
|
@@ -164,6 +164,10 @@ Other scripts under `scripts/smoke-test-*` and `scripts/debug-*` are ad hoc prob
|
|
|
164
164
|
|
|
165
165
|
- AI SDK version-skew guard. The client requested image generation, but the server returned text-only content. Check server version and the OpenAI image-generation path.
|
|
166
166
|
|
|
167
|
+
`reference image input is too large for JSON transport`:
|
|
168
|
+
|
|
169
|
+
- AI SDK reference-image guard. The client passed a base64 image data URL large enough to likely exceed qgrid's JSON request body transport. Compress or resize the image before calling `generateText`, preferably as WebP/JPEG.
|
|
170
|
+
|
|
167
171
|
OpenAI `ImageGenerationError` kinds:
|
|
168
172
|
|
|
169
173
|
- `gate`: capability/model check failed before the turn.
|