@cartanova/qgrid-cli 2.3.7 → 2.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +131 -0
- package/README.md +60 -44
- package/bundle/dist/application/qgrid/qgrid-image-generation.js +42 -0
- package/bundle/dist/application/qgrid/qgrid-response-format.js +44 -0
- package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +23 -4
- package/bundle/dist/application/qgrid/qgrid.dispatcher.js +15 -6
- package/bundle/dist/application/qgrid/qgrid.frame.js +32 -4
- package/bundle/dist/application/qgrid/qgrid.types.js +36 -12
- package/bundle/dist/application/qgrid/tool-emulation.js +16 -8
- package/bundle/dist/application/request-log/request-log.model.js +5 -2
- package/bundle/dist/application/sonamu.generated.js +13 -4
- package/bundle/dist/application/sonamu.generated.sso.js +9 -3
- package/bundle/dist/i18n/sd.generated.js +4 -1
- package/bundle/dist/migrations/20260705140614_alter_request_logs_add1_alter1.js +16 -0
- package/bundle/dist/migrations/20260706120000_alter_request_logs_add_image_cost.js +17 -0
- package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +2 -1
- package/bundle/dist/utils/providers/openai/codex-rpc.js +1 -1
- package/bundle/dist/utils/providers/openai/codex-worker.js +78 -6
- package/bundle/dist/utils/providers/openai/openai-dispatcher.js +21 -4
- package/bundle/src/application/qgrid/qgrid-image-generation.ts +62 -0
- package/bundle/src/application/qgrid/qgrid-response-format.ts +59 -0
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +105 -0
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +34 -2
- package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +33 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.ts +16 -5
- package/bundle/src/application/qgrid/qgrid.frame.test.ts +78 -0
- package/bundle/src/application/qgrid/qgrid.frame.ts +48 -5
- package/bundle/src/application/qgrid/qgrid.types.ts +22 -0
- package/bundle/src/application/qgrid/tool-emulation.test.ts +44 -1
- package/bundle/src/application/qgrid/tool-emulation.ts +27 -4
- package/bundle/src/application/request-log/request-log.entity.json +73 -47
- package/bundle/src/application/request-log/request-log.model.ts +7 -0
- package/bundle/src/application/sonamu.generated.http +16 -3
- package/bundle/src/application/sonamu.generated.sso.ts +6 -0
- package/bundle/src/application/sonamu.generated.ts +12 -0
- package/bundle/src/i18n/sd.generated.ts +3 -0
- package/bundle/src/migrations/20260705140614_alter_request_logs_add1_alter1.ts +15 -0
- package/bundle/src/migrations/20260706120000_alter_request_logs_add_image_cost.ts +14 -0
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +5 -0
- package/bundle/src/utils/providers/common/provider-dispatcher.ts +14 -0
- package/bundle/src/utils/providers/openai/codex-rpc.ts +2 -0
- package/bundle/src/utils/providers/openai/codex-worker.test.ts +219 -0
- package/bundle/src/utils/providers/openai/codex-worker.ts +154 -5
- package/bundle/src/utils/providers/openai/openai-dispatcher.test.ts +95 -1
- package/bundle/src/utils/providers/openai/openai-dispatcher.ts +42 -0
- package/bundle/web-dist/client/assets/index-Cj1iWi5i.js +78 -0
- package/bundle/web-dist/client/assets/index-VE_24EJf.css +1 -0
- package/bundle/web-dist/client/assets/{logs-B0pWpDrg.js → logs-DvGWhZTu.js} +1 -1
- package/bundle/web-dist/client/assets/{routes-7XhVuG7o.js → routes-B_xvkM-J.js} +1 -1
- package/bundle/web-dist/client/assets/{sd.generated-DXhjjL2f.js → sd.generated-BrUnRt0B.js} +1 -1
- package/bundle/web-dist/client/assets/{services.generated-B7u0U1wC.js → services.generated-AsEvHbJ7.js} +1 -1
- package/bundle/web-dist/client/assets/{show-CcjZ9nr7.js → show-C6W3ywZz.js} +3 -3
- package/bundle/web-dist/client/assets/{tokens-DlwAm0v4.js → tokens-CxjeN72g.js} +1 -1
- package/bundle/web-dist/client/index.html +3 -3
- package/bundle/web-dist/server/assets/{lazyRouteComponent-B0LkbiYf.js → lazyRouteComponent-BswulcOx.js} +1 -1
- package/bundle/web-dist/server/assets/{logs-dLx6gMXT.js → logs-B_ZLzpwY.js} +4 -4
- package/bundle/web-dist/server/assets/{routes-DD3Hb9xO.js → routes-D9OiKoqa.js} +2 -2
- package/bundle/web-dist/server/assets/{sd.generated-DdfpD_iN.js → sd.generated-DRuQSIKo.js} +3 -0
- package/bundle/web-dist/server/assets/{services.generated-D3ZCvIkt.js → services.generated-Dp0uKgpV.js} +1 -1
- package/bundle/web-dist/server/assets/{show-BQjeyv6A.js → show-CGlX9OYt.js} +104 -13
- package/bundle/web-dist/server/assets/{tokens-CSOsBpP7.js → tokens-Cjw6cQxZ.js} +2 -2
- package/bundle/web-dist/server/entry-server.generated.js +9 -8
- package/package.json +7 -3
- package/postinstall.mjs +119 -0
- package/skills/qgrid/SKILL.md +54 -0
- package/skills/qgrid/agents/openai.yaml +4 -0
- package/skills/qgrid/references/ai-sdk-provider-contract.md +100 -0
- package/skills/qgrid/references/anthropic-claude-code-runtime.md +170 -0
- package/skills/qgrid/references/cli-env-and-server-boot.md +66 -0
- package/skills/qgrid/references/decision-rationale.md +179 -0
- package/skills/qgrid/references/docs-workflow.md +32 -0
- package/skills/qgrid/references/openai-codex-runtime.md +153 -0
- package/skills/qgrid/references/prompt-cache-and-usage.md +101 -0
- package/skills/qgrid/references/provider-runtime-differences.md +54 -0
- package/skills/qgrid/references/repo-map.md +37 -0
- package/skills/qgrid/references/request-log-run-lifecycle.md +76 -0
- package/skills/qgrid/references/sonamu-api-web-flow.md +47 -0
- package/skills/qgrid/references/token-auth-quota-lifecycle.md +205 -0
- package/skills/qgrid/references/tool-calling-and-multiturn.md +144 -0
- package/skills/qgrid/references/verification-and-debugging.md +193 -0
- package/bundle/web-dist/client/assets/index-5WdFEqZT.css +0 -1
- package/bundle/web-dist/client/assets/index-jnUY7nJ-.js +0 -78
|
@@ -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-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};
|
|
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-Cj1iWi5i.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-Cj1iWi5i.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-BrUnRt0B.js">
|
|
14
|
+
<link rel="stylesheet" crossorigin href="/assets/index-VE_24EJf.css">
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
|
17
17
|
<div id="root"></div>
|
|
@@ -1,4 +1,4 @@
|
|
|
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-
|
|
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-DRuQSIKo.js";
|
|
2
2
|
//#region ../../node_modules/.pnpm/@tanstack+router-core@1.143.6/node_modules/@tanstack/router-core/dist/esm/utils.js
|
|
3
3
|
function last(arr) {
|
|
4
4
|
return arr[arr.length - 1];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { _ as require_react, c as number, g as require_jsx_runtime, l as object, u as string } from "./sd.generated-
|
|
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-DRuQSIKo.js";
|
|
2
|
+
import { i as TokenService, n as RequestLogService, t as QgridService } from "./services.generated-Dp0uKgpV.js";
|
|
3
|
+
import { a as Link, o as useNavigate } from "./lazyRouteComponent-BswulcOx.js";
|
|
4
4
|
import { n as Route } from "../entry-server.generated.js";
|
|
5
5
|
import { n as formatMicroUsd, r as formatUsd, t as cacheHitRate } from "./cost-CSH_t17I.js";
|
|
6
6
|
require_react();
|
|
@@ -311,7 +311,7 @@ function RequestLogTable({ search, onSearchChange }) {
|
|
|
311
311
|
}),
|
|
312
312
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
|
|
313
313
|
className: "px-3 py-1.5 text-left tabular-nums text-sand-700",
|
|
314
|
-
children: row.cost_usd !== null ? formatMicroUsd(row.cost_usd) : "—"
|
|
314
|
+
children: row.image_cost_usd !== null ? formatMicroUsd((row.cost_usd ?? 0) + row.image_cost_usd) : row.cost_usd !== null ? formatMicroUsd(row.cost_usd) : "—"
|
|
315
315
|
}),
|
|
316
316
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
|
|
317
317
|
className: "px-2 py-1.5",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { X as __toESM, _ as require_react, f as require_react_dom, g as require_jsx_runtime, h as useQueryClient } from "./sd.generated-
|
|
2
|
-
import { i as TokenService, t as QgridService } from "./services.generated-
|
|
1
|
+
import { X as __toESM, _ as require_react, f as require_react_dom, g as require_jsx_runtime, h as useQueryClient } from "./sd.generated-DRuQSIKo.js";
|
|
2
|
+
import { i as TokenService, t as QgridService } from "./services.generated-Dp0uKgpV.js";
|
|
3
3
|
import { r as Q } from "../entry-server.generated.js";
|
|
4
4
|
import { r as formatUsd } from "./cost-CSH_t17I.js";
|
|
5
5
|
//#region ../../node_modules/.pnpm/@dnd-kit+utilities@3.2.2_react@19.2.4/node_modules/@dnd-kit/utilities/dist/utilities.esm.js
|
|
@@ -22549,11 +22549,14 @@ var entityLabels = {
|
|
|
22549
22549
|
"entity.RequestLog.duration_ms": "응답 소요시간(ms)",
|
|
22550
22550
|
"entity.RequestLog.ttft_ms": "first gen TTFT(ms)",
|
|
22551
22551
|
"entity.RequestLog.cost_usd": "API 비용",
|
|
22552
|
+
"entity.RequestLog.image_cost_usd": "이미지 생성 추정 비용",
|
|
22553
|
+
"entity.RequestLog.image_cost_method": "이미지 비용 추정 방식",
|
|
22552
22554
|
"entity.RequestLog.effort": "effort level",
|
|
22553
22555
|
"entity.RequestLog.history": "inject_items 히스토리",
|
|
22554
22556
|
"entity.RequestLog.status": "실행 상태",
|
|
22555
22557
|
"entity.RequestLog.error_message": "에러 메시지",
|
|
22556
22558
|
"entity.RequestLog.tool_call_count": "tool call 횟수",
|
|
22559
|
+
"entity.RequestLog.is_image_generation": "이미지 생성 turn 여부 (quota 귀속용)",
|
|
22557
22560
|
"enum.RequestLogOrderBy.id-desc": "ID최신순",
|
|
22558
22561
|
"enum.RequestLogSearchField.id": "ID",
|
|
22559
22562
|
"enum.RequestLogSearchField.token_name": "토큰이름",
|
|
@@ -1,4 +1,4 @@
|
|
|
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-
|
|
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-DRuQSIKo.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) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { J as __exportAll, X as __toESM, _ as require_react, g as require_jsx_runtime, q as __commonJSMin } from "./sd.generated-
|
|
2
|
-
import { n as RequestLogService, r as RequestLogStepService } from "./services.generated-
|
|
3
|
-
import { a as Link } from "./lazyRouteComponent-
|
|
1
|
+
import { J as __exportAll, X as __toESM, _ as require_react, g as require_jsx_runtime, q as __commonJSMin } from "./sd.generated-DRuQSIKo.js";
|
|
2
|
+
import { n as RequestLogService, r as RequestLogStepService } from "./services.generated-Dp0uKgpV.js";
|
|
3
|
+
import { a as Link } from "./lazyRouteComponent-BswulcOx.js";
|
|
4
4
|
import { t as Route } from "../entry-server.generated.js";
|
|
5
5
|
import { n as formatMicroUsd, t as cacheHitRate } from "./cost-CSH_t17I.js";
|
|
6
6
|
import minpath from "node:path";
|
|
@@ -25080,6 +25080,22 @@ var lucideCopy = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
|
|
|
25080
25080
|
})
|
|
25081
25081
|
});
|
|
25082
25082
|
//#endregion
|
|
25083
|
+
//#region ~icons/lucide/x.jsx
|
|
25084
|
+
var lucideX = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
|
|
25085
|
+
viewBox: "0 0 24 24",
|
|
25086
|
+
width: "1.2em",
|
|
25087
|
+
height: "1.2em",
|
|
25088
|
+
...props,
|
|
25089
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
|
|
25090
|
+
fill: "none",
|
|
25091
|
+
stroke: "currentColor",
|
|
25092
|
+
strokeLinecap: "round",
|
|
25093
|
+
strokeLinejoin: "round",
|
|
25094
|
+
strokeWidth: 2,
|
|
25095
|
+
d: "M18 6L6 18M6 6l12 12"
|
|
25096
|
+
})
|
|
25097
|
+
});
|
|
25098
|
+
//#endregion
|
|
25083
25099
|
//#region src/routes/requests/show.tsx?tsr-split=component
|
|
25084
25100
|
function RequestShowPage() {
|
|
25085
25101
|
const { id } = Route.useSearch();
|
|
@@ -25125,21 +25141,92 @@ function CopyButton({ text }) {
|
|
|
25125
25141
|
children: copied ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucideCheck, { className: "size-3.5 text-sage-500" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucideCopy, { className: "size-3.5" })
|
|
25126
25142
|
});
|
|
25127
25143
|
}
|
|
25128
|
-
|
|
25129
|
-
|
|
25130
|
-
const
|
|
25131
|
-
|
|
25132
|
-
|
|
25144
|
+
var DATA_IMAGE_TAG_RE = /<img\s+[^>]*src=["'](data:image\/[^"']+;base64,[^"']+)["'][^>]*(?:alt=["']([^"']*)["'][^>]*)?\/?>/gi;
|
|
25145
|
+
function parseImageSegments(text) {
|
|
25146
|
+
const segments = [];
|
|
25147
|
+
let cursor = 0;
|
|
25148
|
+
for (const match of text.matchAll(DATA_IMAGE_TAG_RE)) {
|
|
25149
|
+
const index = match.index ?? 0;
|
|
25150
|
+
if (index > cursor) segments.push({
|
|
25151
|
+
type: "text",
|
|
25152
|
+
text: text.slice(cursor, index)
|
|
25153
|
+
});
|
|
25154
|
+
segments.push({
|
|
25155
|
+
type: "image",
|
|
25156
|
+
src: match[1],
|
|
25157
|
+
alt: match[2] ?? "generated image"
|
|
25158
|
+
});
|
|
25159
|
+
cursor = index + match[0].length;
|
|
25160
|
+
}
|
|
25161
|
+
if (cursor < text.length) segments.push({
|
|
25162
|
+
type: "text",
|
|
25163
|
+
text: text.slice(cursor)
|
|
25164
|
+
});
|
|
25165
|
+
return segments.filter((segment) => segment.type === "image" || segment.text.trim().length > 0);
|
|
25166
|
+
}
|
|
25167
|
+
function ImageAwareContent({ text, markdown }) {
|
|
25168
|
+
const [viewerSrc, setViewerSrc] = (0, import_react.useState)(null);
|
|
25169
|
+
const segments = parseImageSegments(text);
|
|
25170
|
+
if (!segments.some((segment) => segment.type === "image")) return markdown ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
25171
|
+
className: "prose prose-sm prose-qgrid max-w-none",
|
|
25172
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Markdown, {
|
|
25173
|
+
remarkPlugins: [remarkGfm],
|
|
25174
|
+
children: text
|
|
25175
|
+
})
|
|
25176
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", {
|
|
25177
|
+
className: "text-sm text-sand-800 whitespace-pre-wrap wrap-break-word font-mono leading-relaxed",
|
|
25178
|
+
children: text
|
|
25179
|
+
});
|
|
25180
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
25181
|
+
className: "space-y-3",
|
|
25182
|
+
children: [segments.map((segment, index) => segment.type === "text" ? markdown ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
25133
25183
|
className: "prose prose-sm prose-qgrid max-w-none",
|
|
25134
25184
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Markdown, {
|
|
25135
25185
|
remarkPlugins: [remarkGfm],
|
|
25136
|
-
children: text
|
|
25186
|
+
children: segment.text
|
|
25137
25187
|
})
|
|
25138
|
-
})
|
|
25139
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", {
|
|
25188
|
+
}, `text-${index}`) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", {
|
|
25140
25189
|
className: "text-sm text-sand-800 whitespace-pre-wrap wrap-break-word font-mono leading-relaxed",
|
|
25141
|
-
children: text
|
|
25190
|
+
children: segment.text
|
|
25191
|
+
}, `text-${index}`) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
25192
|
+
type: "button",
|
|
25193
|
+
className: "block max-w-full rounded-md border border-sand-200 overflow-hidden bg-white hover:border-sienna-300 transition-colors",
|
|
25194
|
+
onClick: () => setViewerSrc(segment.src),
|
|
25195
|
+
title: "Open image",
|
|
25196
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
|
|
25197
|
+
src: segment.src,
|
|
25198
|
+
alt: segment.alt,
|
|
25199
|
+
className: "max-h-[520px] max-w-full object-contain",
|
|
25200
|
+
loading: "lazy"
|
|
25201
|
+
})
|
|
25202
|
+
}, `image-${index}`)), viewerSrc && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
25203
|
+
className: "fixed inset-0 z-50 bg-black/70 p-4 flex items-center justify-center",
|
|
25204
|
+
onClick: () => setViewerSrc(null),
|
|
25205
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
25206
|
+
type: "button",
|
|
25207
|
+
className: "absolute top-4 right-4 p-2 rounded-full bg-white/90 text-sand-700 hover:bg-white",
|
|
25208
|
+
onClick: () => setViewerSrc(null),
|
|
25209
|
+
title: "Close image",
|
|
25210
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucideX, { className: "size-5" })
|
|
25211
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
|
|
25212
|
+
src: viewerSrc,
|
|
25213
|
+
alt: "generated image preview",
|
|
25214
|
+
className: "max-h-full max-w-full object-contain rounded-md bg-white",
|
|
25215
|
+
onClick: (e) => e.stopPropagation()
|
|
25216
|
+
})]
|
|
25217
|
+
})]
|
|
25218
|
+
});
|
|
25219
|
+
}
|
|
25220
|
+
function FormattedContent({ text, markdown }) {
|
|
25221
|
+
const parsed = tryParseJson(text);
|
|
25222
|
+
const [mode, setMode] = (0, import_react.useState)("pretty");
|
|
25223
|
+
const canRenderJsonView = parsed.ok && parsed.value !== null && (Array.isArray(parsed.value) || typeof parsed.value === "object");
|
|
25224
|
+
if (!parsed.ok || !canRenderJsonView) {
|
|
25225
|
+
if (markdown) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImageAwareContent, {
|
|
25226
|
+
text,
|
|
25227
|
+
markdown: true
|
|
25142
25228
|
});
|
|
25229
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImageAwareContent, { text: parsed.ok ? JSON.stringify(parsed.value, null, 2) : text });
|
|
25143
25230
|
}
|
|
25144
25231
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
25145
25232
|
className: "flex gap-1 mb-2",
|
|
@@ -25262,9 +25349,13 @@ function MetricsPanel({ data, toolCallCount }) {
|
|
|
25262
25349
|
value: formatTokensPerSec(data.output_tokens, data.duration_ms, data.ttft_ms, tokensPerSecEnabled)
|
|
25263
25350
|
}),
|
|
25264
25351
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Metric, {
|
|
25265
|
-
label: "Cost",
|
|
25352
|
+
label: "Driver Cost",
|
|
25266
25353
|
value: data.cost_usd !== null ? formatMicroUsd(data.cost_usd) : "—"
|
|
25267
25354
|
}),
|
|
25355
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Metric, {
|
|
25356
|
+
label: "Image Cost",
|
|
25357
|
+
value: data.image_cost_usd !== null ? formatMicroUsd(data.image_cost_usd) : "—"
|
|
25358
|
+
}),
|
|
25268
25359
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Metric, {
|
|
25269
25360
|
label: "Tool Calls",
|
|
25270
25361
|
value: `${toolCallCount}회`
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { X as __toESM, _ as require_react, g as require_jsx_runtime, h as useQueryClient } from "./sd.generated-
|
|
2
|
-
import { i as TokenService, t as QgridService } from "./services.generated-
|
|
1
|
+
import { X as __toESM, _ as require_react, g as require_jsx_runtime, h as useQueryClient } from "./sd.generated-DRuQSIKo.js";
|
|
2
|
+
import { i as TokenService, t as QgridService } from "./services.generated-Dp0uKgpV.js";
|
|
3
3
|
import { i as lucideKeyRound, r as Q } from "../entry-server.generated.js";
|
|
4
4
|
//#region ~icons/lucide/plus.jsx
|
|
5
5
|
var import_react = /* @__PURE__ */ __toESM(require_react());
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as hashKey, C as Query, E as notifyManager, F as noop$1, G as focusManager, H as skipToken, I as partialMatchKey, K as Subscribable, N as matchMutation, P as matchQuery, S as infiniteQueryBehavior, T as onlineManager, X as __toESM, Y as __require, _ as require_react, c as number, f as require_react_dom, g as require_jsx_runtime, j as hashQueryKeyByOptions, k as functionalUpdate, l as object, m as QueryClientProvider, n as SUPPORTED_LOCALES, p as require_shim, q as __commonJSMin, r as setLocale, t as SD, u as string, v as Mutation, z as resolveStaleTime } from "./assets/sd.generated-
|
|
2
|
-
import { A as decodePath, C as findRouteMatch, D as createLRUCache, E as processRouteTree, F as last, I as replaceEqualDeep, M as findLast, N as functionalUpdate$1, O as invariant, P as isPromise, S as findFlatMatch, T as processRouteMasks, _ as interpolatePath, a as Link$1, b as trimPath, c as usePrevious$1, d as useRouter, f as getRouterContext, g as cleanPath, h as isNotFound, i as createRootRouteWithContext, j as deepEqual$2, k as createControlledPromise, l as matchContext, m as rootRouteId, n as createFileRoute, p as warning, r as createLazyFileRoute, s as useLayoutEffect$3, t as lazyRouteComponent, u as useRouterState, v as joinPaths, w as findSingleMatch, x as trimPathRight, y as resolvePath } from "./assets/lazyRouteComponent-
|
|
1
|
+
import { A as hashKey, C as Query, E as notifyManager, F as noop$1, G as focusManager, H as skipToken, I as partialMatchKey, K as Subscribable, N as matchMutation, P as matchQuery, S as infiniteQueryBehavior, T as onlineManager, X as __toESM, Y as __require, _ as require_react, c as number, f as require_react_dom, g as require_jsx_runtime, j as hashQueryKeyByOptions, k as functionalUpdate, l as object, m as QueryClientProvider, n as SUPPORTED_LOCALES, p as require_shim, q as __commonJSMin, r as setLocale, t as SD, u as string, v as Mutation, z as resolveStaleTime } from "./assets/sd.generated-DRuQSIKo.js";
|
|
2
|
+
import { A as decodePath, C as findRouteMatch, D as createLRUCache, E as processRouteTree, F as last, I as replaceEqualDeep, M as findLast, N as functionalUpdate$1, O as invariant, P as isPromise, S as findFlatMatch, T as processRouteMasks, _ as interpolatePath, a as Link$1, b as trimPath, c as usePrevious$1, d as useRouter, f as getRouterContext, g as cleanPath, h as isNotFound, i as createRootRouteWithContext, j as deepEqual$2, k as createControlledPromise, l as matchContext, m as rootRouteId, n as createFileRoute, p as warning, r as createLazyFileRoute, s as useLayoutEffect$3, t as lazyRouteComponent, u as useRouterState, v as joinPaths, w as findSingleMatch, x as trimPathRight, y as resolvePath } from "./assets/lazyRouteComponent-BswulcOx.js";
|
|
3
3
|
//#region ../../node_modules/.pnpm/@tanstack+query-core@5.95.2/node_modules/@tanstack/query-core/build/modern/hydration.js
|
|
4
4
|
function defaultTransformerFn(data) {
|
|
5
5
|
return data;
|
|
@@ -22679,6 +22679,7 @@ var sections = [{
|
|
|
22679
22679
|
icon: lucideFileText
|
|
22680
22680
|
}]
|
|
22681
22681
|
}];
|
|
22682
|
+
var qgridVersion = "2.3.9";
|
|
22682
22683
|
function Sidebar({ className }) {
|
|
22683
22684
|
const pathname = useRouterState({ select: (s) => s.location.pathname });
|
|
22684
22685
|
const isActive = (path) => {
|
|
@@ -22720,9 +22721,9 @@ function Sidebar({ className }) {
|
|
|
22720
22721
|
className: "px-4 py-3 border-t border-sand-200/30",
|
|
22721
22722
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
22722
22723
|
className: "flex items-center gap-2",
|
|
22723
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "size-1.5 rounded-full bg-sage-400" }), /* @__PURE__ */ (0, import_jsx_runtime.
|
|
22724
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "size-1.5 rounded-full bg-sage-400" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
22724
22725
|
className: "text-[10px] text-sand-400",
|
|
22725
|
-
children: "
|
|
22726
|
+
children: ["v", qgridVersion]
|
|
22726
22727
|
})]
|
|
22727
22728
|
})
|
|
22728
22729
|
})
|
|
@@ -44558,11 +44559,11 @@ function RootComponent() {
|
|
|
44558
44559
|
}
|
|
44559
44560
|
//#endregion
|
|
44560
44561
|
//#region src/routes/tokens.tsx
|
|
44561
|
-
var $$splitComponentImporter$3 = () => import("./assets/tokens-
|
|
44562
|
+
var $$splitComponentImporter$3 = () => import("./assets/tokens-Cjw6cQxZ.js");
|
|
44562
44563
|
var Route$3 = createFileRoute("/tokens")({ component: lazyRouteComponent($$splitComponentImporter$3, "component") });
|
|
44563
44564
|
//#endregion
|
|
44564
44565
|
//#region src/routes/logs.tsx
|
|
44565
|
-
var $$splitComponentImporter$2 = () => import("./assets/logs-
|
|
44566
|
+
var $$splitComponentImporter$2 = () => import("./assets/logs-B_ZLzpwY.js");
|
|
44566
44567
|
var logsSearchSchema = object({
|
|
44567
44568
|
token: string().optional(),
|
|
44568
44569
|
project: string().optional(),
|
|
@@ -44574,11 +44575,11 @@ var Route$2 = createFileRoute("/logs")({
|
|
|
44574
44575
|
});
|
|
44575
44576
|
//#endregion
|
|
44576
44577
|
//#region src/routes/index.tsx
|
|
44577
|
-
var $$splitComponentImporter$1 = () => import("./assets/routes-
|
|
44578
|
+
var $$splitComponentImporter$1 = () => import("./assets/routes-D9OiKoqa.js");
|
|
44578
44579
|
var Route$1 = createFileRoute("/")({ component: lazyRouteComponent($$splitComponentImporter$1, "component") });
|
|
44579
44580
|
//#endregion
|
|
44580
44581
|
//#region src/routes/requests/show.tsx
|
|
44581
|
-
var $$splitComponentImporter = () => import("./assets/show-
|
|
44582
|
+
var $$splitComponentImporter = () => import("./assets/show-CGlX9OYt.js");
|
|
44582
44583
|
var showSearchSchema = object({ id: number() });
|
|
44583
44584
|
var Route = createFileRoute("/requests/show")({
|
|
44584
44585
|
validateSearch: showSearchSchema,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cartanova/qgrid-cli",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.9",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/cartanova-ai/qgrid"
|
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"dist",
|
|
13
|
-
"bundle"
|
|
13
|
+
"bundle",
|
|
14
|
+
"postinstall.mjs",
|
|
15
|
+
"skills",
|
|
16
|
+
"README.ko.md"
|
|
14
17
|
],
|
|
15
18
|
"type": "module",
|
|
16
19
|
"dependencies": {
|
|
@@ -51,6 +54,7 @@
|
|
|
51
54
|
},
|
|
52
55
|
"scripts": {
|
|
53
56
|
"bundle": "cd ../api && pnpm build && cd ../cli && rm -rf bundle && mkdir -p bundle/public && cp -r ../api/dist ./bundle/dist && cp -r ../api/web-dist ./bundle/web-dist && cp -r ../api/src ./bundle/src",
|
|
54
|
-
"build": "tsdown"
|
|
57
|
+
"build": "tsdown",
|
|
58
|
+
"postinstall": "node postinstall.mjs"
|
|
55
59
|
}
|
|
56
60
|
}
|
package/postinstall.mjs
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { cp, mkdir, rm, symlink } from "node:fs/promises";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const packageDir = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const sourceSkillsDir = path.join(packageDir, "skills", "qgrid");
|
|
9
|
+
|
|
10
|
+
function hasArg(name) {
|
|
11
|
+
return process.argv.slice(2).includes(name);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function findProjectRoot(startDir) {
|
|
15
|
+
let current = path.resolve(startDir);
|
|
16
|
+
let packageJsonRoot = null;
|
|
17
|
+
|
|
18
|
+
while (true) {
|
|
19
|
+
if (
|
|
20
|
+
existsSync(path.join(current, "pnpm-workspace.yaml")) ||
|
|
21
|
+
existsSync(path.join(current, ".git"))
|
|
22
|
+
) {
|
|
23
|
+
return current;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!packageJsonRoot && existsSync(path.join(current, "package.json"))) {
|
|
27
|
+
packageJsonRoot = current;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const parent = path.dirname(current);
|
|
31
|
+
if (parent === current) return packageJsonRoot ?? path.resolve(startDir);
|
|
32
|
+
current = parent;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function defaultProjectRoot() {
|
|
37
|
+
if (process.env.QGRID_SKILLS_CWD) return findProjectRoot(process.env.QGRID_SKILLS_CWD);
|
|
38
|
+
if (process.env.INIT_CWD) return findProjectRoot(process.env.INIT_CWD);
|
|
39
|
+
|
|
40
|
+
const cwd = process.cwd();
|
|
41
|
+
if (cwd.includes(`${path.sep}node_modules${path.sep}`)) return null;
|
|
42
|
+
return findProjectRoot(cwd);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function defaultTargets() {
|
|
46
|
+
const isGlobalInstall =
|
|
47
|
+
process.env.npm_config_global === "true" || process.env.npm_config_location === "global";
|
|
48
|
+
|
|
49
|
+
if (hasArg("--global") || isGlobalInstall) {
|
|
50
|
+
const codexHome = process.env.CODEX_HOME
|
|
51
|
+
? path.resolve(process.env.CODEX_HOME)
|
|
52
|
+
: path.join(os.homedir(), ".codex");
|
|
53
|
+
const claudeHome = process.env.CLAUDE_HOME
|
|
54
|
+
? path.resolve(process.env.CLAUDE_HOME)
|
|
55
|
+
: path.join(os.homedir(), ".claude");
|
|
56
|
+
return [
|
|
57
|
+
{ label: "Codex", target: path.join(codexHome, "skills", "qgrid"), useSymlink: false },
|
|
58
|
+
{ label: "Claude Code", target: path.join(claudeHome, "skills", "qgrid"), useSymlink: false },
|
|
59
|
+
];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const projectRoot = defaultProjectRoot();
|
|
63
|
+
if (!projectRoot) return null;
|
|
64
|
+
|
|
65
|
+
return [
|
|
66
|
+
{
|
|
67
|
+
label: "Codex",
|
|
68
|
+
target: path.join(projectRoot, ".agents", "skills", "qgrid"),
|
|
69
|
+
useSymlink: true,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
label: "Claude Code",
|
|
73
|
+
target: path.join(projectRoot, ".claude", "skills", "qgrid"),
|
|
74
|
+
useSymlink: true,
|
|
75
|
+
},
|
|
76
|
+
];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function syncSkill({ label, target, useSymlink }) {
|
|
80
|
+
if (!existsSync(path.join(sourceSkillsDir, "SKILL.md"))) {
|
|
81
|
+
console.log("qgrid skill source not found in qgrid CLI package.");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
await rm(target, { recursive: true, force: true });
|
|
86
|
+
await mkdir(path.dirname(target), { recursive: true });
|
|
87
|
+
|
|
88
|
+
if (useSymlink) {
|
|
89
|
+
try {
|
|
90
|
+
await symlink(sourceSkillsDir, target, "dir");
|
|
91
|
+
console.log(`qgrid skill linked for ${label}: ${target}`);
|
|
92
|
+
return;
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.log(
|
|
95
|
+
`qgrid skill symlink failed for ${label}: ${error instanceof Error ? error.message : String(error)}`,
|
|
96
|
+
);
|
|
97
|
+
console.log("falling back to copy");
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
await cp(sourceSkillsDir, target, { recursive: true });
|
|
102
|
+
console.log(`qgrid skill copied for ${label}: ${target}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const targetConfigs = defaultTargets();
|
|
106
|
+
|
|
107
|
+
if (!targetConfigs) {
|
|
108
|
+
console.log("qgrid skill sync skipped: project root not found.");
|
|
109
|
+
process.exit(0);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
for (const targetConfig of targetConfigs) {
|
|
114
|
+
await syncSkill(targetConfig);
|
|
115
|
+
}
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.error(`qgrid skill sync failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qgrid
|
|
3
|
+
description: Work on the qgrid repository, an LLM subscription-token proxy with OpenAI Codex app-server workers, Anthropic Claude Code fresh-spawn runtime, AI SDK provider compatibility, Sonamu API/web generation, token routing, prompt-cache behavior, request logging, quota thresholds, and dashboard flows. Use when implementing, debugging, reviewing, or planning qgrid code, docs, migrations, provider integrations, CLI/runtime behavior, request logs, or SDK behavior.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Qgrid
|
|
7
|
+
|
|
8
|
+
## Start Here
|
|
9
|
+
|
|
10
|
+
Use this skill for qgrid repository work. Treat qgrid as a runtime-contract-heavy system: model input travels through the active AI SDK provider, Sonamu API, provider dispatcher, provider-specific runtime, response mapping, request logging, and dashboard display.
|
|
11
|
+
|
|
12
|
+
Before changing code, identify the affected path:
|
|
13
|
+
|
|
14
|
+
- Public AI SDK provider: read `references/ai-sdk-provider-contract.md`.
|
|
15
|
+
- CLI startup, env vars, server boot, OAuth callback URL: read `references/cli-env-and-server-boot.md`.
|
|
16
|
+
- OpenAI models or Codex worker/thread/cache behavior: read `references/openai-codex-runtime.md`.
|
|
17
|
+
- Anthropic models or Claude Code spawn/stream-json behavior: read `references/anthropic-claude-code-runtime.md`.
|
|
18
|
+
- Token registration, OAuth, token sync, active/inactive behavior, or quota thresholds: read `references/token-auth-quota-lifecycle.md`.
|
|
19
|
+
- Provider comparisons, routing, or cross-provider bugs: read `references/provider-runtime-differences.md`.
|
|
20
|
+
- Tool calling, AI SDK multi-step loops, or tool-call request logs: read `references/tool-calling-and-multiturn.md`.
|
|
21
|
+
- `sessionKey`, `threadCoord`, prompt cache metrics, usage accounting, or cost: read `references/prompt-cache-and-usage.md`.
|
|
22
|
+
- Design rationale, prior decisions, or "why is this feature shaped this way?": read `references/decision-rationale.md`.
|
|
23
|
+
- Dashboard changes: read `references/sonamu-api-web-flow.md`.
|
|
24
|
+
- Request log lifecycle, tool-call steps, telemetry/logger behavior: read `references/request-log-run-lifecycle.md`.
|
|
25
|
+
- Choosing tests, smoke scripts, or debugging common runtime errors: read `references/verification-and-debugging.md`.
|
|
26
|
+
- Project planning/review/documentation workflow: read `references/docs-workflow.md`.
|
|
27
|
+
- Repository orientation: read `references/repo-map.md`.
|
|
28
|
+
|
|
29
|
+
## Setup Guardrails
|
|
30
|
+
|
|
31
|
+
When helping a user set up local `@cartanova/qgrid-ai-sdk`, `createQgridLogger`, or qgrid CLI-backed workflows, ensure request-log project naming is configured. Check for `QGRID_PROJECT_NAME` in the calling app/runtime environment or `projectName` in qgrid provider/logger config. If neither is present, ask the user for a stable project/workflow name or add the obvious repository/app name when the surrounding setup convention makes that appropriate.
|
|
32
|
+
|
|
33
|
+
Prefer `QGRID_PROJECT_NAME` as the project-wide default. Use config `projectName` only for a deliberate per-call/per-provider override. Do not add `projectName` or `project_name` under `providerOptions.qgrid`; current code does not read it there.
|
|
34
|
+
|
|
35
|
+
## Non-Negotiable Boundaries
|
|
36
|
+
|
|
37
|
+
- Use `packages/ai-sdk` as the active public SDK surface.
|
|
38
|
+
- Treat `packages/sdk` as deprecated. Read it only for legacy context or migration clues. Do not add new examples or features on top of it unless explicitly asked for legacy work.
|
|
39
|
+
- Route provider models by prefix: `openai/*` goes to the OpenAI Codex runtime, `anthropic/*` goes to the Anthropic Claude Code runtime. Prefix-less model fallback is not implemented.
|
|
40
|
+
- Treat dashboard work as Sonamu API/model/generated-client/web work, not isolated frontend work.
|
|
41
|
+
- Keep OpenAI Codex built-in tools, apps, plugins, skills, web search, shell, and environment instruction blocks disabled unless the user explicitly asks for agentic Codex behavior.
|
|
42
|
+
- Treat OpenAI image generation as an opt-in Codex `image_generation` tool path. Inspect current code before modifying it; it is not a direct Images API call and its image cost is an estimate.
|
|
43
|
+
|
|
44
|
+
## Verification
|
|
45
|
+
|
|
46
|
+
Choose verification by blast radius:
|
|
47
|
+
|
|
48
|
+
- Type/lint/format: `pnpm check`.
|
|
49
|
+
- Package tests: use the relevant package test command or targeted Vitest files.
|
|
50
|
+
- Provider runtime changes: run targeted tests for `packages/api/src/utils/providers/**` and, when practical, the relevant smoke script in `scripts/` or `packages/api/scripts/`.
|
|
51
|
+
- AI SDK changes: run `packages/ai-sdk` tests and inspect generated request payload behavior.
|
|
52
|
+
- Sonamu API/model changes: check generated files and both API and web consumers.
|
|
53
|
+
|
|
54
|
+
Do not rely on one provider's behavior to infer the other provider's behavior. OpenAI/Codex and Anthropic/Claude Code have different process lifetimes, cache behavior, usage accounting, and structured-output paths.
|