@cartanova/qgrid-cli 2.10.5 → 2.10.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/bundle/dist/application/monit/monit.frame.js +1 -1
  2. package/bundle/dist/application/qgrid/expired-token-reminder.js +1 -1
  3. package/bundle/dist/application/qgrid/oauth.js +1 -1
  4. package/bundle/dist/application/qgrid/qgrid-image-generation.js +7 -11
  5. package/bundle/dist/application/qgrid/qgrid-response-format.js +4 -4
  6. package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +24 -7
  7. package/bundle/dist/application/qgrid/qgrid.dispatcher.js +8 -3
  8. package/bundle/dist/application/qgrid/qgrid.frame.js +24 -10
  9. package/bundle/dist/application/qgrid/token-death.js +1 -1
  10. package/bundle/dist/application/qgrid/token-window-keepalive.js +1 -1
  11. package/bundle/dist/application/qgrid/tool-emulation.js +1 -1
  12. package/bundle/dist/application/request-log/request-log.model.js +2 -2
  13. package/bundle/dist/i18n/sd.generated.js +3 -3
  14. package/bundle/dist/sonamu.config.js +2 -2
  15. package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +1 -1
  16. package/bundle/dist/utils/providers/anthropic/anthropic-thinking.js +1 -1
  17. package/bundle/dist/utils/providers/openai/openai-backend-protocol.js +13 -2
  18. package/bundle/dist/utils/providers/openai/openai-direct-client.js +5 -4
  19. package/bundle/dist/utils/providers/openai/openai-dispatcher.js +111 -57
  20. package/bundle/dist/utils/providers/openai/openai-image-generation.js +25 -17
  21. package/bundle/dist/utils/providers/openai/openai-refresh.js +1 -1
  22. package/bundle/src/application/qgrid/qgrid-image-generation.test.ts +19 -8
  23. package/bundle/src/application/qgrid/qgrid-image-generation.ts +17 -24
  24. package/bundle/src/application/qgrid/qgrid-response-format.test.ts +4 -2
  25. package/bundle/src/application/qgrid/qgrid-response-format.ts +7 -10
  26. package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +87 -9
  27. package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +45 -5
  28. package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +136 -2
  29. package/bundle/src/application/qgrid/qgrid.dispatcher.ts +11 -1
  30. package/bundle/src/application/qgrid/qgrid.frame.test.ts +73 -0
  31. package/bundle/src/application/qgrid/qgrid.frame.ts +39 -4
  32. package/bundle/src/application/request-log/request-log.entity.json +2 -2
  33. package/bundle/src/application/sonamu.generated.http +2 -2
  34. package/bundle/src/i18n/sd.generated.ts +2 -2
  35. package/bundle/src/utils/providers/openai/openai-backend-protocol.test.ts +23 -1
  36. package/bundle/src/utils/providers/openai/openai-backend-protocol.ts +24 -2
  37. package/bundle/src/utils/providers/openai/openai-direct-client.test.ts +15 -0
  38. package/bundle/src/utils/providers/openai/openai-direct-client.ts +14 -4
  39. package/bundle/src/utils/providers/openai/openai-dispatcher.test.ts +223 -32
  40. package/bundle/src/utils/providers/openai/openai-dispatcher.ts +174 -72
  41. package/bundle/src/utils/providers/openai/openai-image-generation.test.ts +89 -0
  42. package/bundle/src/utils/providers/openai/openai-image-generation.ts +26 -15
  43. package/bundle/web-dist/client/assets/cost-DH2jZbrw.js +1 -0
  44. package/bundle/web-dist/client/assets/{index-Dxw7DiXF.js → index-D9ryIyL-.js} +4 -4
  45. package/bundle/web-dist/client/assets/logs-CLf2VNfk.js +1 -0
  46. package/bundle/web-dist/client/assets/{monit-E8eGW1Sj.js → monit-DojxOLj6.js} +1 -1
  47. package/bundle/web-dist/client/assets/{routes-7spLfIGZ.js → routes-DXJhNvbI.js} +2 -2
  48. package/bundle/web-dist/client/assets/{services.generated-jnPHYMER.js → services.generated-DqFYgWsY.js} +1 -1
  49. package/bundle/web-dist/client/assets/{settings-BdosZFNC.js → settings-bopyz9pa.js} +1 -1
  50. package/bundle/web-dist/client/assets/{show-b2PFNI3D.js → show-DbLD3MzB.js} +1 -1
  51. package/bundle/web-dist/client/assets/{tokens-CBdHb2_U.js → tokens-2-AIi9sZ.js} +1 -1
  52. package/bundle/web-dist/client/assets/{use-oauth-login-flow-Cyn3YPqW.js → use-oauth-login-flow-CnqTWs_H.js} +1 -1
  53. package/bundle/web-dist/client/assets/{use-update-token-mutation-DQCwCYfR.js → use-update-token-mutation-Cxb9K0fM.js} +1 -1
  54. package/bundle/web-dist/client/index.html +2 -2
  55. package/bundle/web-dist/server/assets/{cost-59jBdx-I.js → cost-eEHeTRT5.js} +4 -5
  56. package/bundle/web-dist/server/assets/{lazyRouteComponent-CUR-kWzI.js → lazyRouteComponent-Bi0fYGLs.js} +2 -2
  57. package/bundle/web-dist/server/assets/{logs-CaaWO9-Z.js → logs-CIVFxfoi.js} +10 -9
  58. package/bundle/web-dist/server/assets/{monit-CBil92fJ.js → monit-DBXezg7R.js} +4 -4
  59. package/bundle/web-dist/server/assets/{plus-Bvdj8Pwx.js → plus-BH-t4cm_.js} +1 -1
  60. package/bundle/web-dist/server/assets/{react-dom-CyuShs9K.js → react-dom-CZ2eynd8.js} +1 -1
  61. package/bundle/web-dist/server/assets/{refresh-cw-3QAiSWBd.js → refresh-cw-CosAdcz0.js} +1 -1
  62. package/bundle/web-dist/server/assets/{routes-DtVf9yqo.js → routes-COWYIvA-.js} +6 -7
  63. package/bundle/web-dist/server/assets/{services.generated-FPwsG9p3.js → services.generated-607iwhMI.js} +2 -2
  64. package/bundle/web-dist/server/assets/{settings-DeHNwoMv.js → settings-C_6dpK5p.js} +3 -3
  65. package/bundle/web-dist/server/assets/{show-8NNdRxhM.js → show-DY396-LD.js} +8 -20
  66. package/bundle/web-dist/server/assets/{tokens-odgS2-9q.js → tokens-COvV7qUP.js} +4 -4
  67. package/bundle/web-dist/server/assets/{use-oauth-login-flow-DTQKdYBO.js → use-oauth-login-flow-VYCYf3uv.js} +1 -1
  68. package/bundle/web-dist/server/assets/{use-update-token-mutation-xvXbPrCI.js → use-update-token-mutation-D8XYV5of.js} +1 -1
  69. package/bundle/web-dist/server/entry-server.generated.js +10 -10
  70. package/package.json +1 -1
  71. package/skills/qgrid/SKILL.md +9 -8
  72. package/skills/qgrid/references/ai-sdk-provider-contract.md +25 -16
  73. package/skills/qgrid/references/decision-rationale.md +8 -8
  74. package/skills/qgrid/references/openai-codex-runtime.md +19 -11
  75. package/skills/qgrid/references/request-log-run-lifecycle.md +4 -2
  76. package/skills/qgrid/references/sonamu-api-web-flow.md +2 -2
  77. package/skills/qgrid/references/verification-and-debugging.md +23 -9
  78. package/bundle/web-dist/client/assets/cost-CY2BJEPC.js +0 -1
  79. package/bundle/web-dist/client/assets/logs-3n_U4qnI.js +0 -1
@@ -128,15 +128,25 @@ AI SDK tools plus structured output:
128
128
 
129
129
  Image generation:
130
130
 
131
- - `packages/api/scripts/smoke-test-image-generation.ts`
131
+ - `packages/api/e2e/image-generation.ts`
132
132
  - Human-initiated only.
133
133
  - Requires active OpenAI token with image entitlement and applicable migration.
134
134
  - For 2.9.8 chat, verify the actual browser POST and served bundle, not only a direct function test. A globally installed CLI on port 44900 can serve stale assets while repository tests pass; identify the listening process and its executable before assuming a rebuild or refresh affects it.
135
- - Cover auto text-only replies, native ordinary generation, server-side transparent editing, and replay of prior generated images. Explicit `true` must retain its image-required behavior. Verify driver usage stays separate from image usage and auto text replies are not image logs.
136
- - Verify extension, decoded bytes, and natural dimensions in chat image previews. A format request in prose is not evidence: the 2026-09-29 WebP probe returned PNG from a prompt-only request and WebP from explicit `outputFormat: "webp"`. Transparent output remains PNG.
137
- - Env: `QGRID_URL`, `QGRID_OPENAI_MODEL`.
135
+ - Cover auto text-only replies and the single server-side `generate_image` function for ordinary generation and transparent editing. Zero selected references must create a fresh image despite older history; positive counts must select only the last N conversation images in order, up to five. Explicit raw `true` must retain its image-required hosted behavior for non-transparent chat-model requests. Verify driver usage stays separate from image usage and auto text replies are not image logs.
136
+ - Verify extension, decoded bytes, and natural dimensions in chat image previews. A format request in prose is not evidence: the 2026-09-29 hosted-route WebP probe returned PNG from a prompt-only request and WebP from explicit `outputFormat: "webp"`. Auto chat and standalone output remain PNG-only and must reject explicit non-PNG options.
137
+ - Requires `QGRID_REAL_PROVIDER_ACCEPTANCE=1`, explicit `QGRID_URL` and `QGRID_OPENAI_MODEL`. Optional `QGRID_TOKEN_NAME` pins a subscription token. `QGRID_IMAGE_SMOKE_CASES` selects named cases; the default covers eight images plus text, rejected inputs, and cancellation. Optional `batch`, `logger-off`, and `cancel-direct` cover SDK batching, no-log calls, and cancellation during direct Images requests. Never replay generations automatically.
138
+ - Set `QGRID_IMAGE_E2E_OUTPUT` for PNGs and sanitized usage/cost/log evidence; `QGRID_IMAGE_E2E_PROJECT` groups test logs. Use an isolated DB and access-only test token, with notifications and keepalive disabled. For final acceptance, build the current API and cold-start `sonamu start` against that isolated DB rather than relying on HMR. HMR can leave a fresh dispatcher uninitialized; readiness alone does not prove the intended module version. The suite checks readiness before live calls.
139
+ - Subscription `response.completed.tool_usage.image_gen` can be present with all-zero usage for text-only or function-tool replies. This metadata alone is not a hosted image execution. Keep the zero-usage regression test and verify auto text against the real backend.
140
+ - Run auto text and generation with both Luna and Astra when changing the internal tool schema. Astra's private backend failed with `strict: true` even with bounds removed, while the same schema succeeded with `strict: false`. Keep `strict: false` and server-side validation; do not add a runtime fallback/retry.
138
141
  - Not part of CI; it consumes ChatGPT subscription quota.
139
142
 
143
+ Image failure accounting:
144
+
145
+ - `packages/api/e2e/image-failure-accounting.ts` calls the real subscription chat model and compares its completed usage with the persisted failed/aborted request and generate step.
146
+ - Start a separate built local API with `NODE_OPTIONS=--import=<absolute path>/packages/api/e2e/image-failure-preload.mjs`. This test-only preload intercepts standalone Images requests with HTTP errors, network errors, invalid image responses, cancellation waits, or a synthetic success control. It never forwards Images requests upstream; no production test switch or fallback is added.
147
+ - Both processes require `QGRID_REAL_PROVIDER_ACCEPTANCE=1`, `QGRID_IMAGE_E2E_FAULT_FILE`, and `QGRID_IMAGE_E2E_TRACE_FILE`. The preload requires `HOST=127.0.0.1` and an isolated `SONAMU_DB_NAME` starting with `qgrid_e2e_`. The runner also requires `QGRID_URL`, `QGRID_TOKEN_NAME`, and `QGRID_IMAGE_E2E_OUTPUT`.
148
+ - Verify one completed driver step and exact input/output/cache usage and cost on failure; parent status and original errors stay failed/aborted, image cost stays unknown, and `logger: false` creates no records. The success control must not double-count driver usage. Trace files retain only completed model/usage metadata, never credentials or image bytes.
149
+
140
150
  Other scripts under `scripts/smoke-test-*` and `scripts/debug-*` are ad hoc probes. Read the script header and env vars before running.
141
151
 
142
152
  ## Common Error Triage
@@ -188,21 +198,25 @@ Generated SSE handlers missing a newly added event field:
188
198
  - Treat as a real error, not a recoverable partial result.
189
199
  - Check schema strictness and `stream-json-adapter` behavior.
190
200
 
191
- `qgrid: imageGeneration is not supported with streamText`:
201
+ `qgrid: imageGeneration and imageGenerationOptions were removed from language-model options`:
202
+
203
+ - Either removed key makes `generateText` and `streamText` fail before transport. Use `generateImage` with `qgrid.image()` and flat `QgridImageProviderOptions` for image output.
204
+
205
+ `qgrid language models do not support image input`:
192
206
 
193
- - Image generation is non-stream only. Use `generateText`.
207
+ - General vision remains unsupported by the language adapter; it ignores image parts with this warning. Reference-image editing belongs in `generateImage`'s `prompt: { text, images }`.
194
208
 
195
209
  `image generation is not supported on the Anthropic route`:
196
210
 
197
211
  - Image generation is OpenAI/Codex-only.
198
212
 
199
- `imageGeneration was requested but the response contained no image`:
213
+ `qgrid.image: expected one image from the direct subscription Images route`:
200
214
 
201
- - 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.
215
+ - Image-provider version-skew guard. Each call requires exactly one image with `generation.route: "codex-images"`. Check that the server supports the explicit image model and update the server and SDK together.
202
216
 
203
217
  `reference image input is too large for JSON transport`:
204
218
 
205
- - 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.
219
+ - 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 `generateImage`, preferably as WebP/JPEG.
206
220
 
207
221
  `qgrid query transport failed: response headers timed out`:
208
222
 
@@ -1 +0,0 @@
1
- var e=1e6,t=4;function n(t){return t/e}function r(e,n=!1){return`${n?`Known `:``}$${e.toFixed(t)}`}function i(e){return r(n(e))}function a(e){let t=e.is_image_generation&&e.image_cost_usd===null;return e.cost_usd===null&&e.image_cost_usd===null?t?`Unknown`:`—`:r(n((e.cost_usd??0)+(e.image_cost_usd??0)),t)}function o(e){return e.input_tokens<=0?`—`:`${Math.round(e.cache_read_tokens/e.input_tokens*100)}%`}export{r as i,i as n,a as r,o as t};
@@ -1 +0,0 @@
1
- import"./rolldown-runtime-Dw2cE7zH.js";import{l as e,u as t}from"./vendor-tanstack-DJRQAbrY.js";import{i as n,r}from"./vendor-react-DH4kUfK2.js";import{C as i,S as a,n as o,o as s,r as c}from"./services.generated-jnPHYMER.js";import{i as l,n as u,r as d}from"./index-Dxw7DiXF.js";import{i as f,r as p,t as m}from"./cost-CY2BJEPC.js";import{t as h}from"./refresh-cw-NNcU0Cmq.js";import{t as g}from"./request-model-D4CZPmnG.js";n();var _=r(),v=e=>(0,_.jsx)(`svg`,{viewBox:`0 0 24 24`,width:`1.2em`,height:`1.2em`,...e,children:(0,_.jsx)(`path`,{fill:`none`,stroke:`currentColor`,strokeLinecap:`round`,strokeLinejoin:`round`,strokeWidth:2,d:`m15 18l-6-6l6-6`})}),y=e=>(0,_.jsx)(`svg`,{viewBox:`0 0 24 24`,width:`1.2em`,height:`1.2em`,...e,children:(0,_.jsx)(`path`,{fill:`none`,stroke:`currentColor`,strokeLinecap:`round`,strokeLinejoin:`round`,strokeWidth:2,d:`m9 18l6-6l-6-6`})}),b=50,x=`__unassigned__`;function S(e){let t=new Date(e);return`${String(t.getMonth()+1).padStart(2,`0`)}-${String(t.getDate()).padStart(2,`0`)} ${String(t.getHours()).padStart(2,`0`)}:${String(t.getMinutes()).padStart(2,`0`)}`}function C(e){return e.toLocaleString()}function w(e){let t=Math.round(e/1e3),n=Math.floor(t/60),r=t%60;return n>0?`${n}m ${r}s`:`${r}s`}function T({status:e,requestedModel:t,servedModel:n,imageCostMethod:r,fallbackCount:i}){if(e===`running`)return(0,_.jsx)(`span`,{className:`text-[9px] px-1.5 py-0.5 rounded-full bg-blue-100 text-blue-600 font-medium whitespace-nowrap`,children:`실행 중`});let a=g({status:e,requestedModel:t,servedModel:n,imageCostMethod:r}),o=t!==null&&n===null;return(0,_.jsxs)(_.Fragment,{children:[(0,_.jsx)(`span`,{className:`text-xs text-sand-500`,children:a.label}),o&&(0,_.jsx)(`span`,{className:`ml-1 text-[9px] text-sand-400`,children:`요청`}),(i??0)>0&&(0,_.jsxs)(`span`,{className:`ml-1 text-[9px] text-caution-500`,children:[`×`,i]})]})}function E(e){return e<=0?`—`:e>=1e3?`${(e/1e3).toFixed(1)}s`:`${e}ms`}var D=[{label:`ID`,align:`left`,width:`w-12`,sortKey:`id`},{label:`Date`,align:`left`,width:`w-20`,sortKey:`created_at`},{label:`Project`,align:`left`,width:`w-20`},{label:`Token`,align:`left`,width:`w-24`},{label:`Model`,align:`left`,width:`w-20`},{label:`Fmt`,align:`left`,width:`w-12`},{label:`TTFT`,align:`right`,width:`w-16`,sortKey:`ttft_ms`},{label:`Duration`,align:`right`,width:`w-20`,sortKey:`duration_ms`},{label:`In`,align:`right`,width:`w-16`,sortKey:`input_tokens`},{label:`Out`,align:`right`,width:`w-20`,sortKey:`output_tokens`},{label:`C.Read`,align:`right`,width:`w-20`,sortKey:`cache_read_tokens`},{label:`C.Write`,align:`right`,width:`w-20`,sortKey:`cache_creation_tokens`},{label:`Hit`,align:`right`,width:`w-14`},{label:`Tools`,align:`right`,width:`w-14`},{label:`Cost`,align:`right`,width:`w-20`,sortKey:`cost_usd`}];function O({search:n,onSearchChange:r}){let i=t(),a=n.page??1,u=n.token??``,d=n.project??``,g=n.model??``,{data:O}=s.useTokens(`A`),k=(O?.rows??[]).map(e=>e.name).filter(Boolean),{data:A}=o.useProjectNames(),j=A?.names??[],{data:M}=o.useModelNames(),N=M?.names??[],P=d===x?{project_name_is_null:!0}:d?{project_name:d}:{},F={...u?{token_name:u}:{},...P,...g?{model_name:g}:{}},I=n.sort??`id-desc`,L=I.lastIndexOf(`-`),R=I.slice(0,L),z=I.slice(L+1)===`asc`?`asc`:`desc`,{data:B,isLoading:V,isError:H,refresh:U,isRefreshing:W}=c.useRequestLogs(`P`,{num:b,page:a,orderBy:I,...F}),{data:G,isError:K,refresh:q}=o.useTotalCost({num:0,page:1,...F}),J=B?.rows??[],Y=B?.total??0,X=Math.ceil(Y/b),Z=e=>{r({...n,...e,page:1})};return(0,_.jsxs)(`div`,{className:`panel overflow-hidden`,children:[(0,_.jsxs)(`div`,{className:`panel-header flex items-center gap-2 px-3 py-2.5 flex-wrap sm:gap-3 sm:px-5`,children:[(0,_.jsxs)(`select`,{value:u,onChange:e=>Z({token:e.target.value||void 0}),disabled:k.length===0,className:`border border-sand-200/80 rounded-lg px-2.5 py-1.5 text-[11px] text-sand-700 bg-sand-50/50 focus:outline-none focus:border-sienna-300 disabled:text-sand-300 disabled:cursor-not-allowed`,children:[(0,_.jsx)(`option`,{value:``,children:k.length>0?`All Tokens`:`Tokens —`}),k.map(e=>(0,_.jsx)(`option`,{value:e,children:e},e))]}),(0,_.jsxs)(`select`,{value:d,onChange:e=>Z({project:e.target.value||void 0}),className:`border border-sand-200/80 rounded-lg px-2.5 py-1.5 text-[11px] text-sand-700 bg-sand-50/50 focus:outline-none focus:border-sienna-300`,children:[(0,_.jsx)(`option`,{value:``,children:`All Projects`}),(0,_.jsx)(`option`,{value:x,children:`(unassigned)`}),j.map(e=>(0,_.jsx)(`option`,{value:e,children:e},e))]}),(0,_.jsxs)(`select`,{value:g,onChange:e=>Z({model:e.target.value||void 0}),disabled:N.length===0,className:`border border-sand-200/80 rounded-lg px-2.5 py-1.5 text-[11px] text-sand-700 bg-sand-50/50 focus:outline-none focus:border-sienna-300 disabled:text-sand-300 disabled:cursor-not-allowed`,children:[(0,_.jsx)(`option`,{value:``,children:N.length>0?`All Models`:`Models —`}),N.map(e=>(0,_.jsx)(`option`,{value:e,children:e},e))]}),(0,_.jsx)(`button`,{type:`button`,onClick:()=>void Promise.all([U(),q()]),disabled:W,"aria-label":`Reload`,title:`Reload`,className:`p-1 rounded text-sand-400 hover:text-sand-600 disabled:opacity-30 transition-colors`,children:(0,_.jsx)(h,{className:W?`size-3.5 animate-spin`:`size-3.5`})}),(0,_.jsx)(`div`,{className:`flex-1`}),(0,_.jsxs)(`span`,{className:`text-[11px] text-sand-400`,children:[H||!B?`—`:Y,` results`]}),K?(0,_.jsx)(`span`,{role:`alert`,className:`text-[11px] text-danger-500`,children:`Failed to load total cost.`}):(0,_.jsx)(`span`,{className:`text-[11px] tabular-nums font-medium text-sienna-600`,title:G&&G.unknownImageCostCount>0?`${G.unknownImageCostCount} image requests have unknown image costs. Only known costs are included.`:void 0,children:G?f(G.usd,G.unknownImageCostCount>0):`—`})]}),H?(0,_.jsx)(`div`,{role:`alert`,className:`text-danger-500 text-center py-12 text-sm`,children:`Failed to load request logs.`}):V?(0,_.jsx)(`div`,{className:`space-y-2`,children:Array.from({length:5}).map((e,t)=>(0,_.jsx)(`div`,{className:`h-8 bg-sand-100 rounded animate-pulse`},`skel-${t}`))}):J.length===0?(0,_.jsx)(`div`,{className:`text-sand-400 text-center py-12 text-sm`,children:`No requests yet.`}):(0,_.jsxs)(_.Fragment,{children:[(0,_.jsx)(`div`,{className:`overflow-x-auto px-3 py-3 sm:px-5`,children:(0,_.jsxs)(`table`,{className:`w-full min-w-[900px] text-[13px]`,children:[(0,_.jsx)(`thead`,{children:(0,_.jsxs)(`tr`,{className:`border-b border-sand-100/60`,children:[D.map(e=>{let t=e.label===`Duration`?`pl-5 pr-3`:e.width?`px-4`:`px-3`,n=e.sortKey===R;return(0,_.jsx)(`th`,{className:`${e.align===`right`?`text-right`:`text-left`} ${e.width??``} ${e.width?`whitespace-nowrap`:``} ${t} py-1.5 text-[10px] uppercase font-medium ${n?`text-sienna-600`:`text-sand-400`}`,children:e.sortKey?(0,_.jsxs)(`button`,{type:`button`,onClick:()=>Z({sort:l.parse(`${e.sortKey}-${n&&z===`desc`?`asc`:`desc`}`)}),className:`inline-flex items-center gap-0.5 text-[10px] uppercase font-medium hover:text-sienna-500 transition-colors duration-150 ${e.align===`right`?`justify-end w-full`:``}`,children:[e.label,(0,_.jsx)(`span`,{className:n?``:`text-sand-300`,children:n?z===`desc`?`↓`:`↑`:`↕`})]}):e.label},e.label)}),(0,_.jsx)(`th`,{className:`w-8`})]})}),(0,_.jsx)(`tbody`,{className:`divide-y divide-sand-100/60`,children:J.map(t=>(0,_.jsxs)(`tr`,{className:`transition-colors duration-150 hover:bg-sand-100/60 cursor-pointer`,onClick:e=>{if(e.metaKey||e.ctrlKey){window.open(`/requests/show?id=${t.id}`,`_blank`);return}i({to:`/requests/show`,search:{id:t.id}})},children:[(0,_.jsx)(`td`,{className:`px-4 py-1.5 whitespace-nowrap`,children:(0,_.jsx)(e,{to:`/requests/show`,search:{id:t.id},onClick:e=>e.stopPropagation(),className:`text-xs text-sand-500 tabular-nums hover:text-sienna-500`,children:t.id})}),(0,_.jsx)(`td`,{className:`px-4 py-1.5 whitespace-nowrap`,children:(0,_.jsx)(`span`,{className:`text-xs text-sand-400 tabular-nums`,children:S(t.created_at)})}),(0,_.jsx)(`td`,{className:`px-4 py-1.5 whitespace-nowrap`,children:(0,_.jsx)(`span`,{className:`text-xs text-sand-600`,children:t.project_name??`—`})}),(0,_.jsx)(`td`,{className:`px-4 py-1.5 whitespace-nowrap`,children:(0,_.jsx)(`span`,{className:`text-xs text-sand-500`,children:t.token_name})}),(0,_.jsxs)(`td`,{className:`px-4 py-1.5 whitespace-nowrap`,children:[(0,_.jsx)(T,{status:t.status,requestedModel:t.requested_model_name,servedModel:t.model_name,imageCostMethod:t.image_cost_method,fallbackCount:t.fallback_count}),t.response_json_ok===!1&&(0,_.jsx)(`span`,{title:`structured 요청의 응답이 JSON 파싱에 실패했습니다`,className:`ml-1.5 rounded-full bg-caution-400/15 px-1.5 py-0.5 text-[9px] font-semibold text-caution-500`,children:`broken`})]}),(0,_.jsx)(`td`,{className:`px-4 py-1.5 whitespace-nowrap`,children:t.is_structured?(0,_.jsx)(`span`,{className:`rounded bg-sienna-100 px-1.5 py-0.5 font-mono text-[10px] text-sienna-700`,children:`json`}):(0,_.jsx)(`span`,{className:`font-mono text-[10px] text-sand-400`,children:`text`})}),(0,_.jsx)(`td`,{className:`px-4 py-1.5 text-right tabular-nums text-sand-500 whitespace-nowrap`,children:E(t.ttft_ms)}),(0,_.jsx)(`td`,{className:`pl-5 pr-3 py-1.5 text-right tabular-nums text-sand-500 whitespace-nowrap`,children:w(t.duration_ms)}),(0,_.jsx)(`td`,{className:`px-3 py-1.5 text-right tabular-nums text-sand-700`,children:C(t.input_tokens)}),(0,_.jsx)(`td`,{className:`px-3 py-1.5 text-right tabular-nums text-sand-700`,children:C(t.output_tokens)}),(0,_.jsx)(`td`,{className:`px-3 py-1.5 text-right tabular-nums text-sand-700`,children:C(t.cache_read_tokens)}),(0,_.jsx)(`td`,{className:`px-3 py-1.5 text-right tabular-nums text-sand-700`,children:C(t.cache_creation_tokens)}),(0,_.jsx)(`td`,{className:`px-3 py-1.5 text-right tabular-nums text-sand-700`,children:m(t)}),(0,_.jsx)(`td`,{className:`px-3 py-1.5 text-right tabular-nums text-sand-500`,children:t.tool_call_count>0?t.tool_call_count:`—`}),(0,_.jsx)(`td`,{className:`px-3 py-1.5 text-right tabular-nums text-sand-700 whitespace-nowrap`,title:t.is_image_generation&&t.image_cost_usd===null?`Image cost is unknown. Only known costs are shown.`:void 0,children:p(t)}),(0,_.jsx)(`td`,{className:`px-2 py-1.5`,children:(0,_.jsx)(y,{className:`size-4 text-sand-400`})})]},t.id))})]})}),X>1&&(0,_.jsxs)(`div`,{className:`flex items-center justify-center gap-3 px-5 py-2.5 border-t border-sand-100/60`,children:[(0,_.jsx)(`button`,{type:`button`,className:`p-1 rounded text-sand-400 hover:text-sand-600 disabled:opacity-30 transition-colors`,disabled:a===1,onClick:()=>r({...n,page:a-1}),children:(0,_.jsx)(v,{className:`size-4`})}),(0,_.jsxs)(`span`,{className:`text-[11px] text-sand-400 tabular-nums`,children:[a,` / `,X]}),(0,_.jsx)(`button`,{type:`button`,className:`p-1 rounded text-sand-400 hover:text-sand-600 disabled:opacity-30 transition-colors`,disabled:a===X,onClick:()=>r({...n,page:a+1}),children:(0,_.jsx)(y,{className:`size-4`})})]})]})]})}a({token:i().optional(),project:i().optional(),model:i().optional(),sort:l.optional(),page:d.shape.page.default(1)});function k(){let e=u.useSearch(),t=u.useNavigate();return(0,_.jsx)(`div`,{className:`max-w-[100rem] mx-auto`,children:(0,_.jsx)(O,{search:e,onSearchChange:e=>t({search:e})})})}export{k as component};