@cartanova/qgrid-cli 1.5.6 → 1.6.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.
Files changed (59) hide show
  1. package/bundle/dist/application/qgrid/oauth.js +1 -1
  2. package/bundle/dist/application/qgrid/qgrid.dispatcher.js +167 -0
  3. package/bundle/dist/application/qgrid/qgrid.frame.js +45 -37
  4. package/bundle/dist/application/qgrid/qgrid.types.js +6 -16
  5. package/bundle/dist/application/queries.generated.js +2 -1
  6. package/bundle/dist/application/request-log/request-log.model.js +15 -2
  7. package/bundle/dist/application/request-log/request-log.types.js +6 -2
  8. package/bundle/dist/application/sonamu.generated.js +14 -6
  9. package/bundle/dist/application/sonamu.generated.sso.js +5 -2
  10. package/bundle/dist/i18n/sd.generated.js +7 -4
  11. package/bundle/dist/migrations/20260423180818_alter_request_logs_add1_alter1.js +17 -0
  12. package/bundle/dist/migrations/20260423182017_alter_request_logs_add2_drop1_alter1.js +19 -0
  13. package/bundle/dist/migrations/20260423183613_alter_request_logs_add1_alter1.js +16 -0
  14. package/bundle/dist/sonamu.config.js +6 -9
  15. package/bundle/src/application/qgrid/oauth.ts +1 -1
  16. package/bundle/src/application/qgrid/qgrid.dispatcher.ts +184 -0
  17. package/bundle/src/application/qgrid/qgrid.frame.ts +38 -51
  18. package/bundle/src/application/qgrid/qgrid.types.ts +3 -14
  19. package/bundle/src/application/queries.generated.ts +3 -0
  20. package/bundle/src/application/request-log/request-log.entity.json +33 -17
  21. package/bundle/src/application/request-log/request-log.model.ts +26 -2
  22. package/bundle/src/application/request-log/request-log.types.ts +6 -2
  23. package/bundle/src/application/sonamu.generated.http +17 -2
  24. package/bundle/src/application/sonamu.generated.sso.ts +9 -6
  25. package/bundle/src/application/sonamu.generated.ts +25 -5
  26. package/bundle/src/i18n/sd.generated.ts +6 -3
  27. package/bundle/src/migrations/20260423180818_alter_request_logs_add1_alter1.ts +18 -0
  28. package/bundle/src/migrations/20260423182017_alter_request_logs_add2_drop1_alter1.ts +20 -0
  29. package/bundle/src/migrations/20260423183613_alter_request_logs_add1_alter1.ts +15 -0
  30. package/bundle/src/sonamu.config.ts +4 -7
  31. package/bundle/web-dist/client/assets/index-BfL_bTVI.css +1 -0
  32. package/bundle/web-dist/client/assets/index-CMOHJBal.js +78 -0
  33. package/bundle/web-dist/client/assets/logs-B2pDXaji.js +1 -0
  34. package/bundle/web-dist/client/assets/{routes-CqzIoGYg.js → routes-fpJMuLAs.js} +1 -1
  35. package/bundle/web-dist/client/assets/{sd.generated-Duipc8HN.js → sd.generated-CIOZewtL.js} +1 -1
  36. package/bundle/web-dist/client/assets/services.generated-B2N0iPav.js +1 -0
  37. package/bundle/web-dist/client/assets/{show-BuMxiSr1.js → show-DFVBcmXm.js} +2 -2
  38. package/bundle/web-dist/client/assets/tokens--LyDCm10.js +1 -0
  39. package/bundle/web-dist/client/index.html +3 -3
  40. package/bundle/web-dist/server/assets/{copy-BPyN_0Dp.js → copy-CKCGxwII.js} +1 -1
  41. package/bundle/web-dist/server/assets/{lazyRouteComponent-Bmjwy0OA.js → lazyRouteComponent-BlvOfJIF.js} +2 -2
  42. package/bundle/web-dist/server/assets/{logs-BgcF7jVg.js → logs-BYIBD0yv.js} +172 -80
  43. package/bundle/web-dist/server/assets/{routes-DVA-nsZ-.js → routes-p2n4SfAB.js} +2 -2
  44. package/bundle/web-dist/server/assets/{sd.generated-CDVQy4CJ.js → sd.generated-CIg_jf8e.js} +6 -3
  45. package/bundle/web-dist/server/assets/{services.generated-DWyvb1vb.js → services.generated-DIeiDdqy.js} +21 -4
  46. package/bundle/web-dist/server/assets/{shim-CqVZY710.js → shim-Dq_Izqnc.js} +1 -1
  47. package/bundle/web-dist/server/assets/{show-BnKnfNFP.js → show-DZ_U1u-N.js} +30 -9
  48. package/bundle/web-dist/server/assets/{tokens-7z55hPRV.js → tokens-DOybPnNU.js} +19 -21
  49. package/bundle/web-dist/server/entry-server.generated.js +12 -8
  50. package/package.json +1 -1
  51. package/bundle/dist/application/qgrid/pool.js +0 -128
  52. package/bundle/dist/application/qgrid/worker.js +0 -189
  53. package/bundle/src/application/qgrid/pool.ts +0 -165
  54. package/bundle/src/application/qgrid/worker.ts +0 -240
  55. package/bundle/web-dist/client/assets/index-BRZCFaFz.css +0 -1
  56. package/bundle/web-dist/client/assets/index-BnqlZB1V.js +0 -78
  57. package/bundle/web-dist/client/assets/logs-KoJtGoEG.js +0 -1
  58. package/bundle/web-dist/client/assets/services.generated-Ccs6tru4.js +0 -1
  59. package/bundle/web-dist/client/assets/tokens--z-eVto5.js +0 -1
@@ -1,10 +1,9 @@
1
- import { D as require_jsx_runtime, O as require_react, st as __toESM } from "./sd.generated-CDVQy4CJ.js";
2
- import { n as RequestLogService, r as TokenService, t as QgridService } from "./services.generated-DWyvb1vb.js";
3
- import { a as Link, o as useNavigate } from "./lazyRouteComponent-Bmjwy0OA.js";
1
+ import { D as require_react, E as require_jsx_runtime, b as object, x as string, y as number } from "./sd.generated-CIg_jf8e.js";
2
+ import { n as RequestLogService, r as TokenService, t as QgridService } from "./services.generated-DIeiDdqy.js";
3
+ import { a as Link, o as useNavigate } from "./lazyRouteComponent-BlvOfJIF.js";
4
4
  import { n as Route } from "../entry-server.generated.js";
5
5
  import { n as formatUsd, t as formatMicroUsd } from "./cost-DdHTzQDR.js";
6
- //#region ~icons/lucide/chevron-left.jsx
7
- var import_react = /* @__PURE__ */ __toESM(require_react());
6
+ require_react();
8
7
  var import_jsx_runtime = require_jsx_runtime();
9
8
  var lucideChevronLeft = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
10
9
  viewBox: "0 0 24 24",
@@ -39,6 +38,7 @@ var lucideChevronRight = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
39
38
  //#endregion
40
39
  //#region src/components/qgrid/RequestLogTable.tsx
41
40
  var PAGE_SIZE = 50;
41
+ var UNASSIGNED = "__unassigned__";
42
42
  function formatDateTime(iso) {
43
43
  const d = new Date(iso);
44
44
  return `${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")} ${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
@@ -51,36 +51,117 @@ function calcCacheHitRate(row) {
51
51
  if (denom === 0) return "—";
52
52
  return `${Math.round(row.cache_read_tokens / denom * 100)}%`;
53
53
  }
54
- function trimQuery(q, maxLen = 30) {
54
+ function trimText(q, maxLen = 60) {
55
55
  return q.length > maxLen ? `${q.slice(0, maxLen)}...` : q;
56
56
  }
57
- function RequestLogTable({ page: externalPage, onPageChange } = {}) {
57
+ function PromptCell({ value, maxWidth }) {
58
+ if (!value) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
59
+ className: "text-sand-400",
60
+ children: "—"
61
+ });
62
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
63
+ className: `text-sand-700 truncate ${maxWidth} inline-block align-bottom`,
64
+ title: value,
65
+ children: trimText(value)
66
+ });
67
+ }
68
+ var COLUMNS = [
69
+ {
70
+ label: "ID",
71
+ align: "left",
72
+ width: "w-12"
73
+ },
74
+ {
75
+ label: "Date",
76
+ align: "left",
77
+ width: "w-20"
78
+ },
79
+ {
80
+ label: "Project",
81
+ align: "left",
82
+ width: "w-20"
83
+ },
84
+ {
85
+ label: "Token",
86
+ align: "left",
87
+ width: "w-24"
88
+ },
89
+ {
90
+ label: "Model",
91
+ align: "left",
92
+ width: "w-20"
93
+ },
94
+ {
95
+ label: "System",
96
+ align: "left"
97
+ },
98
+ {
99
+ label: "User",
100
+ align: "left"
101
+ },
102
+ {
103
+ label: "In",
104
+ align: "right"
105
+ },
106
+ {
107
+ label: "Out",
108
+ align: "right"
109
+ },
110
+ {
111
+ label: "C.Read",
112
+ align: "right"
113
+ },
114
+ {
115
+ label: "C.Write",
116
+ align: "right"
117
+ },
118
+ {
119
+ label: "Hit",
120
+ align: "right"
121
+ },
122
+ {
123
+ label: "Cost",
124
+ align: "right"
125
+ }
126
+ ];
127
+ function RequestLogTable({ search, onSearchChange }) {
58
128
  const navigate = useNavigate();
59
- const [internalPage, setInternalPage] = (0, import_react.useState)(1);
60
- const page = externalPage ?? internalPage;
61
- const setPage = onPageChange ?? setInternalPage;
62
- const [tokenFilter, setTokenFilter] = (0, import_react.useState)("");
129
+ const page = search.page ?? 1;
130
+ const tokenFilter = search.token ?? "";
131
+ const projectFilter = search.project ?? "";
63
132
  const { data: tokensData } = TokenService.useTokens("A");
64
133
  const tokenNames = (tokensData?.rows ?? []).map((t) => t.name).filter(Boolean);
134
+ const { data: projectData } = QgridService.useProjectNames();
135
+ const projectNames = projectData?.names ?? [];
136
+ const projectFilterParam = (() => {
137
+ if (projectFilter === UNASSIGNED) return { project_name_is_null: true };
138
+ if (projectFilter) return { project_name: projectFilter };
139
+ return {};
140
+ })();
65
141
  const { data, isLoading } = RequestLogService.useRequestLogs("A", {
66
142
  num: PAGE_SIZE,
67
143
  page,
68
144
  orderBy: "id-desc",
69
- ...tokenFilter ? { token_name: tokenFilter } : {}
145
+ ...tokenFilter ? { token_name: tokenFilter } : {},
146
+ ...projectFilterParam
70
147
  });
71
148
  const { data: costData } = QgridService.useTotalCost(tokenFilter || void 0);
72
149
  const rows = data?.rows ?? [];
73
150
  const total = data?.total ?? 0;
74
151
  const totalPages = Math.ceil(total / PAGE_SIZE);
152
+ const updateFilter = (patch) => {
153
+ onSearchChange({
154
+ ...search,
155
+ ...patch,
156
+ page: 1
157
+ });
158
+ };
75
159
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
76
160
  className: "flex items-center gap-2 mb-3 flex-wrap",
77
161
  children: [
78
162
  tokenNames.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", {
79
163
  value: tokenFilter,
80
- onChange: (e) => {
81
- setTokenFilter(e.target.value);
82
- setPage(1);
83
- },
164
+ onChange: (e) => updateFilter({ token: e.target.value || void 0 }),
84
165
  className: "border border-sand-200 rounded-md px-2 py-1 text-xs text-sand-700 bg-white focus:outline-none focus:border-sienna-300",
85
166
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
86
167
  value: "",
@@ -90,6 +171,25 @@ function RequestLogTable({ page: externalPage, onPageChange } = {}) {
90
171
  children: name
91
172
  }, name))]
92
173
  }),
174
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", {
175
+ value: projectFilter,
176
+ onChange: (e) => updateFilter({ project: e.target.value || void 0 }),
177
+ className: "border border-sand-200 rounded-md px-2 py-1 text-xs text-sand-700 bg-white focus:outline-none focus:border-sienna-300",
178
+ children: [
179
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
180
+ value: "",
181
+ children: "All Projects"
182
+ }),
183
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
184
+ value: UNASSIGNED,
185
+ children: "(unassigned)"
186
+ }),
187
+ projectNames.map((name) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
188
+ value: name,
189
+ children: name
190
+ }, name))
191
+ ]
192
+ }),
93
193
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
94
194
  className: "text-[11px] text-sand-400",
95
195
  children: [total, " results"]
@@ -111,49 +211,10 @@ function RequestLogTable({ page: externalPage, onPageChange } = {}) {
111
211
  className: "w-full text-sm",
112
212
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", {
113
213
  className: "border-b border-sand-200",
114
- children: [
115
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
116
- className: "text-left px-3 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
117
- children: "ID"
118
- }),
119
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
120
- className: "text-left px-3 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
121
- children: "Date"
122
- }),
123
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
124
- className: "text-left px-3 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
125
- children: "Token"
126
- }),
127
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
128
- className: "text-left px-3 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
129
- children: "Query"
130
- }),
131
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
132
- className: "text-right px-3 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
133
- children: "In"
134
- }),
135
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
136
- className: "text-right px-3 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
137
- children: "Out"
138
- }),
139
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
140
- className: "text-right px-3 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
141
- children: "C.Read"
142
- }),
143
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
144
- className: "text-right px-3 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
145
- children: "C.Write"
146
- }),
147
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
148
- className: "text-right px-3 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
149
- children: "Hit"
150
- }),
151
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
152
- className: "text-right px-3 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
153
- children: "Cost"
154
- }),
155
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: "w-8 px-2 py-2.5" })
156
- ]
214
+ children: [COLUMNS.map((col) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
215
+ className: `text-${col.align} ${col.width ?? ""} ${col.width ? "whitespace-nowrap" : ""} px-2 py-1.5 text-[10px] uppercase text-sand-400 font-medium`,
216
+ children: col.label
217
+ }, col.label)), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: "w-8 px-2 py-1.5" })]
157
218
  }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", {
158
219
  className: "divide-y divide-sand-200/60",
159
220
  children: rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", {
@@ -170,7 +231,7 @@ function RequestLogTable({ page: externalPage, onPageChange } = {}) {
170
231
  },
171
232
  children: [
172
233
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
173
- className: "px-3 py-2.5",
234
+ className: "px-2 py-1.5 whitespace-nowrap",
174
235
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Link, {
175
236
  to: "/requests/show",
176
237
  search: { id: row.id },
@@ -180,53 +241,73 @@ function RequestLogTable({ page: externalPage, onPageChange } = {}) {
180
241
  })
181
242
  }),
182
243
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
183
- className: "px-3 py-2.5",
244
+ className: "px-2 py-1.5 whitespace-nowrap",
184
245
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
185
- className: "text-[10px] text-sand-400 tabular-nums whitespace-nowrap",
246
+ className: "text-xs text-sand-400 tabular-nums",
186
247
  children: formatDateTime(row.created_at)
187
248
  })
188
249
  }),
189
250
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
190
- className: "px-3 py-2.5",
251
+ className: "px-2 py-1.5 whitespace-nowrap",
252
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
253
+ className: "text-xs text-sand-600",
254
+ children: row.project_name ?? "—"
255
+ })
256
+ }),
257
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
258
+ className: "px-2 py-1.5 whitespace-nowrap",
191
259
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
192
260
  className: "text-xs text-sand-500",
193
261
  children: row.token_name
194
262
  })
195
263
  }),
196
264
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
197
- className: "px-3 py-2.5",
265
+ className: "px-2 py-1.5 whitespace-nowrap",
198
266
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
199
- className: "text-sand-800 truncate max-w-48",
200
- title: row.query,
201
- children: trimQuery(row.query)
267
+ className: "text-xs text-sand-500",
268
+ children: row.model_name ?? "—"
269
+ })
270
+ }),
271
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
272
+ className: "px-3 py-1.5",
273
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PromptCell, {
274
+ value: row.system_prompt,
275
+ maxWidth: "max-w-80"
202
276
  })
203
277
  }),
204
278
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
205
- className: "px-3 py-2.5 text-right tabular-nums text-sand-700",
279
+ className: "px-3 py-1.5",
280
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PromptCell, {
281
+ value: row.user_prompt,
282
+ maxWidth: "max-w-96"
283
+ })
284
+ }),
285
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
286
+ className: "px-3 py-1.5 text-right tabular-nums text-sand-700",
206
287
  children: formatNum(row.input_tokens)
207
288
  }),
208
289
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
209
- className: "px-3 py-2.5 text-right tabular-nums text-sand-700",
290
+ className: "px-3 py-1.5 text-right tabular-nums text-sand-700",
210
291
  children: formatNum(row.output_tokens)
211
292
  }),
212
293
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
213
- className: "px-3 py-2.5 text-right tabular-nums text-sand-700",
294
+ className: "px-3 py-1.5 text-right tabular-nums text-sand-700",
214
295
  children: formatNum(row.cache_read_tokens)
215
296
  }),
216
297
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
217
- className: "px-3 py-2.5 text-right tabular-nums text-sand-700",
298
+ className: "px-3 py-1.5 text-right tabular-nums text-sand-700",
218
299
  children: formatNum(row.cache_creation_tokens)
219
300
  }),
220
301
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
221
- className: "px-3 py-2.5 text-right tabular-nums text-sand-700",
302
+ className: "px-3 py-1.5 text-right tabular-nums text-sand-700",
222
303
  children: calcCacheHitRate(row)
223
304
  }),
224
305
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
225
- className: "px-3 py-2.5 text-right tabular-nums text-sand-700",
226
- children: row.cost_usd !== null ? formatMicroUsd(row.cost_usd) : "-"
306
+ className: "px-3 py-1.5 text-right tabular-nums text-sand-700",
307
+ children: row.cost_usd !== null ? formatMicroUsd(row.cost_usd) : ""
227
308
  }),
228
309
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
229
- className: "px-2 py-2.5",
310
+ className: "px-2 py-1.5",
230
311
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucideChevronRight, { className: "size-4 text-sand-400" })
231
312
  })
232
313
  ]
@@ -240,7 +321,10 @@ function RequestLogTable({ page: externalPage, onPageChange } = {}) {
240
321
  type: "button",
241
322
  className: "p-1 rounded text-sand-400 hover:text-sand-600 disabled:opacity-30 transition-colors",
242
323
  disabled: page === 1,
243
- onClick: () => setPage(page - 1),
324
+ onClick: () => onSearchChange({
325
+ ...search,
326
+ page: page - 1
327
+ }),
244
328
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucideChevronLeft, { className: "size-4" })
245
329
  }),
246
330
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
@@ -255,7 +339,10 @@ function RequestLogTable({ page: externalPage, onPageChange } = {}) {
255
339
  type: "button",
256
340
  className: "p-1 rounded text-sand-400 hover:text-sand-600 disabled:opacity-30 transition-colors",
257
341
  disabled: page === totalPages,
258
- onClick: () => setPage(page + 1),
342
+ onClick: () => onSearchChange({
343
+ ...search,
344
+ page: page + 1
345
+ }),
259
346
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucideChevronRight, { className: "size-4" })
260
347
  })
261
348
  ]
@@ -263,8 +350,13 @@ function RequestLogTable({ page: externalPage, onPageChange } = {}) {
263
350
  }
264
351
  //#endregion
265
352
  //#region src/routes/logs.tsx?tsr-split=component
353
+ object({
354
+ token: string().optional(),
355
+ project: string().optional(),
356
+ page: number().optional().default(1)
357
+ });
266
358
  function LogsPage() {
267
- const { page } = Route.useSearch();
359
+ const search = Route.useSearch();
268
360
  const navigate = Route.useNavigate();
269
361
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
270
362
  className: "space-y-5 max-w-300 mx-auto -translate-x-4",
@@ -272,8 +364,8 @@ function LogsPage() {
272
364
  className: "text-xl font-medium text-sand-900 tracking-tight",
273
365
  children: "Request Logs"
274
366
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequestLogTable, {
275
- page,
276
- onPageChange: (p) => navigate({ search: { page: p } })
367
+ search,
368
+ onSearchChange: (next) => navigate({ search: next })
277
369
  })]
278
370
  });
279
371
  }
@@ -1,5 +1,5 @@
1
- import { D as require_jsx_runtime, E as useQueryClient, O as require_react, st as __toESM, w as require_react_dom } from "./sd.generated-CDVQy4CJ.js";
2
- import { r as TokenService, t as QgridService } from "./services.generated-DWyvb1vb.js";
1
+ import { C as require_react_dom, D as require_react, E as require_jsx_runtime, T as useQueryClient, ot as __toESM } from "./sd.generated-CIg_jf8e.js";
2
+ import { r as TokenService, t as QgridService } from "./services.generated-DIeiDdqy.js";
3
3
  import { n as formatUsd } from "./cost-DdHTzQDR.js";
4
4
  //#region ../../node_modules/.pnpm/@dnd-kit+utilities@3.2.2_react@19.2.4/node_modules/@dnd-kit/utilities/dist/utilities.esm.js
5
5
  var import_react_dom = /* @__PURE__ */ __toESM(require_react_dom());
@@ -22067,7 +22067,10 @@ var entityLabels = {
22067
22067
  "entity.RequestLog.id": "ID",
22068
22068
  "entity.RequestLog.created_at": "등록일시",
22069
22069
  "entity.RequestLog.token_name": "토큰 이름",
22070
- "entity.RequestLog.query": "prompt 전문",
22070
+ "entity.RequestLog.project_name": "프로젝트 이름",
22071
+ "entity.RequestLog.model_name": "모델 이름",
22072
+ "entity.RequestLog.user_prompt": "사용자 프롬프트",
22073
+ "entity.RequestLog.system_prompt": "시스템 프롬프트",
22071
22074
  "entity.RequestLog.response": "llm 응답 전문",
22072
22075
  "entity.RequestLog.input_tokens": "입력 토큰",
22073
22076
  "entity.RequestLog.output_tokens": "출력 토큰",
@@ -22078,7 +22081,7 @@ var entityLabels = {
22078
22081
  "enum.RequestLogOrderBy.id-desc": "ID최신순",
22079
22082
  "enum.RequestLogSearchField.id": "ID",
22080
22083
  "enum.RequestLogSearchField.token_name": "토큰이름",
22081
- "enum.RequestLogSearchField.query": "쿼리",
22084
+ "enum.RequestLogSearchField.user_prompt": "사용자 프롬프트",
22082
22085
  "entity.Token": "Token",
22083
22086
  "entity.Token.id": "ID",
22084
22087
  "entity.Token.created_at": "등록일시",
@@ -22148,4 +22151,4 @@ SD.enumLabels = (enumName) => {
22148
22151
  } });
22149
22152
  };
22150
22153
  //#endregion
22151
- export { skipToken as $, getDefaultState as A, functionalUpdate as B, require_lib as C, require_jsx_runtime as D, useQueryClient as E, fetchState as F, matchQuery as G, hashQueryKeyByOptions as H, onlineManager as I, replaceData as J, noop$1 as K, notifyManager as L, hasPreviousPage as M, infiniteQueryBehavior as N, require_react as O, Query as P, shouldThrowError as Q, pendingThenable as R, string as S, QueryClientProvider as T, isValidTimeout as U, hashKey as V, matchMutation as W, resolveStaleTime as X, resolveEnabled as Y, shallowEqualObjects as Z, custom as _, dedupeAndFlatten as a, __exportAll as at, number as b, zArrayable as c, ZodObject as d, timeUntilStale as et, ZodOptional as f, boolean as g, bigint as h, SonamuQueryMode as i, __commonJSMin as it, hasNextPage as j, Mutation as k, ZodArray as l, array as m, SUPPORTED_LOCALES as n, focusManager as nt, fetch$1 as o, __require as ot, _enum as p, partialMatchKey as q, setLocale as r, Subscribable as rt, useRefreshable as s, __toESM as st, SD as t, timeoutManager as tt, ZodNullable as u, date as v, require_react_dom as w, object as x, int as y, environmentManager as z };
22154
+ export { timeUntilStale as $, hasNextPage as A, hashKey as B, require_react_dom as C, require_react as D, require_jsx_runtime as E, onlineManager as F, noop$1 as G, isValidTimeout as H, notifyManager as I, resolveEnabled as J, partialMatchKey as K, pendingThenable as L, infiniteQueryBehavior as M, Query as N, Mutation as O, fetchState as P, skipToken as Q, environmentManager as R, require_lib as S, useQueryClient as T, matchMutation as U, hashQueryKeyByOptions as V, matchQuery as W, shallowEqualObjects as X, resolveStaleTime as Y, shouldThrowError as Z, date as _, dedupeAndFlatten as a, __require as at, object as b, zArrayable as c, ZodObject as d, timeoutManager as et, ZodOptional as f, custom as g, boolean as h, SonamuQueryMode as i, __exportAll as it, hasPreviousPage as j, getDefaultState as k, ZodArray as l, bigint as m, SUPPORTED_LOCALES as n, Subscribable as nt, fetch$1 as o, __toESM as ot, _enum as p, replaceData as q, setLocale as r, __commonJSMin as rt, useRefreshable as s, SD as t, focusManager as tt, ZodNullable as u, int as v, QueryClientProvider as w, string as x, number as y, functionalUpdate as z };
@@ -1,4 +1,4 @@
1
- import { A as getDefaultState, C as require_lib, D as require_jsx_runtime, E as useQueryClient, F as fetchState, J as replaceData, K as noop, L as notifyManager, M as hasPreviousPage, N as infiniteQueryBehavior, O as require_react, Q as shouldThrowError, R as pendingThenable, U as isValidTimeout, V as hashKey, X as resolveStaleTime, Y as resolveEnabled, Z as shallowEqualObjects, a as dedupeAndFlatten, et as timeUntilStale, j as hasNextPage, nt as focusManager, o as fetch, rt as Subscribable, s as useRefreshable, st as __toESM, tt as timeoutManager, z as environmentManager } from "./sd.generated-CDVQy4CJ.js";
1
+ import { $ as timeUntilStale, A as hasNextPage, B as hashKey, D as require_react, E as require_jsx_runtime, G as noop, H as isValidTimeout, I as notifyManager, J as resolveEnabled, L as pendingThenable, M as infiniteQueryBehavior, P as fetchState, R as environmentManager, S as require_lib, T as useQueryClient, X as shallowEqualObjects, Y as resolveStaleTime, Z as shouldThrowError, a as dedupeAndFlatten, et as timeoutManager, j as hasPreviousPage, k as getDefaultState, nt as Subscribable, o as fetch, ot as __toESM, q as replaceData, s as useRefreshable, tt as focusManager } from "./sd.generated-CIg_jf8e.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) {
@@ -835,19 +835,21 @@ var RequestLogService;
835
835
  })(RequestLogService || (RequestLogService = {}));
836
836
  var QgridService;
837
837
  (function(_QgridService) {
838
- async function query(prompt, system, timeout) {
838
+ async function query(prompt, system, timeout, model, projectName) {
839
839
  return fetch({
840
840
  method: "POST",
841
841
  url: `/api/qgrid/query`,
842
842
  data: {
843
843
  prompt,
844
844
  system,
845
- timeout
845
+ timeout,
846
+ model,
847
+ projectName
846
848
  }
847
849
  });
848
850
  }
849
851
  _QgridService.query = query;
850
- _QgridService.useQueryMutation = () => useMutation({ mutationFn: (params) => query(params.prompt, params.system, params.timeout) });
852
+ _QgridService.useQueryMutation = () => useMutation({ mutationFn: (params) => query(params.prompt, params.system, params.timeout, params.model, params.projectName) });
851
853
  async function stats() {
852
854
  return fetch({
853
855
  method: "GET",
@@ -882,6 +884,21 @@ var QgridService;
882
884
  ...totalCostQueryOptions(tokenName),
883
885
  ...options
884
886
  }));
887
+ async function projectNames() {
888
+ return fetch({
889
+ method: "GET",
890
+ url: `/api/qgrid/projectNames`
891
+ });
892
+ }
893
+ _QgridService.projectNames = projectNames;
894
+ const projectNamesQueryOptions = _QgridService.projectNamesQueryOptions = () => queryOptions({
895
+ queryKey: ["Qgrid", "projectNames"],
896
+ queryFn: () => projectNames()
897
+ });
898
+ _QgridService.useProjectNames = (options) => useRefreshable(useQuery({
899
+ ...projectNamesQueryOptions(),
900
+ ...options
901
+ }));
885
902
  async function addToken(token, name, refreshToken) {
886
903
  return fetch({
887
904
  method: "POST",
@@ -1,4 +1,4 @@
1
- import { O as require_react, it as __commonJSMin } from "./sd.generated-CDVQy4CJ.js";
1
+ import { D as require_react, rt as __commonJSMin } from "./sd.generated-CIg_jf8e.js";
2
2
  //#region ../../node_modules/.pnpm/use-sync-external-store@1.6.0_react@19.2.4/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.js
3
3
  /**
4
4
  * @license React
@@ -1,8 +1,8 @@
1
- import { D as require_jsx_runtime, O as require_react, at as __exportAll, it as __commonJSMin, st as __toESM } from "./sd.generated-CDVQy4CJ.js";
2
- import { n as RequestLogService } from "./services.generated-DWyvb1vb.js";
3
- import { a as Link } from "./lazyRouteComponent-Bmjwy0OA.js";
1
+ import { D as require_react, E as require_jsx_runtime, it as __exportAll, ot as __toESM, rt as __commonJSMin } from "./sd.generated-CIg_jf8e.js";
2
+ import { n as RequestLogService } from "./services.generated-DIeiDdqy.js";
3
+ import { a as Link } from "./lazyRouteComponent-BlvOfJIF.js";
4
4
  import { t as Route } from "../entry-server.generated.js";
5
- import { n as lucideCheck, t as lucideCopy } from "./copy-BPyN_0Dp.js";
5
+ import { n as lucideCheck, t as lucideCopy } from "./copy-CKCGxwII.js";
6
6
  import minpath from "node:path";
7
7
  import minproc from "node:process";
8
8
  import { fileURLToPath as urlToPath } from "node:url";
@@ -23457,13 +23457,20 @@ function RequestDetail({ id }) {
23457
23457
  children: "Request Detail"
23458
23458
  }),
23459
23459
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Section, {
23460
- title: "Query",
23461
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
23462
- className: "rounded-lg bg-sand-50 px-4 py-3",
23463
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FormattedContent, { text: data.query })
23460
+ title: "System",
23461
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23462
+ className: "relative rounded-lg bg-sand-50 px-4 py-3",
23463
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CopyButton, { text: data.system_prompt ?? "null" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FormattedContent, { text: data.system_prompt ?? "null" })]
23464
+ })
23465
+ }),
23466
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Section, {
23467
+ title: "User",
23468
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23469
+ className: "relative rounded-lg bg-sand-50 px-4 py-3",
23470
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CopyButton, { text: data.user_prompt ?? "null" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FormattedContent, { text: data.user_prompt ?? "null" })]
23464
23471
  })
23465
23472
  }),
23466
- data.response && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Section, {
23473
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Section, {
23467
23474
  title: "Response",
23468
23475
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23469
23476
  className: "relative rounded-lg bg-sand-50 px-4 py-3",
@@ -23534,6 +23541,13 @@ function RequestDetail({ id }) {
23534
23541
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tbody", {
23535
23542
  className: "text-sand-700",
23536
23543
  children: [
23544
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
23545
+ className: "py-1.5 text-sand-500",
23546
+ children: "Project"
23547
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
23548
+ className: "py-1.5 text-right font-medium text-sand-800",
23549
+ children: data.project_name ?? "—"
23550
+ })] }),
23537
23551
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
23538
23552
  className: "py-1.5 text-sand-500",
23539
23553
  children: "Token"
@@ -23541,6 +23555,13 @@ function RequestDetail({ id }) {
23541
23555
  className: "py-1.5 text-right font-medium text-sand-800",
23542
23556
  children: data.token_name
23543
23557
  })] }),
23558
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
23559
+ className: "py-1.5 text-sand-500",
23560
+ children: "Model"
23561
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
23562
+ className: "py-1.5 text-right font-medium text-sand-800",
23563
+ children: data.model_name ?? "—"
23564
+ })] }),
23544
23565
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
23545
23566
  className: "py-1.5 text-sand-500",
23546
23567
  children: "Time"
@@ -1,7 +1,7 @@
1
- import { D as require_jsx_runtime, E as useQueryClient, O as require_react, S as string, _ as custom, b as number, c as zArrayable, g as boolean, h as bigint, i as SonamuQueryMode, m as array, p as _enum, st as __toESM, v as date, x as object, y as int } from "./sd.generated-CDVQy4CJ.js";
2
- import { r as TokenService, t as QgridService } from "./services.generated-DWyvb1vb.js";
1
+ import { D as require_react, E as require_jsx_runtime, T as useQueryClient, _ as date, b as object, c as zArrayable, g as custom, h as boolean, i as SonamuQueryMode, m as bigint, ot as __toESM, p as _enum, v as int, x as string, y as number } from "./sd.generated-CIg_jf8e.js";
2
+ import { r as TokenService, t as QgridService } from "./services.generated-DIeiDdqy.js";
3
3
  import { a as lucideKeyRound, i as ro, r as Q } from "../entry-server.generated.js";
4
- import { n as lucideCheck, t as lucideCopy } from "./copy-BPyN_0Dp.js";
4
+ import { n as lucideCheck, t as lucideCopy } from "./copy-CKCGxwII.js";
5
5
  //#region ~icons/lucide/eye.jsx
6
6
  var import_react = /* @__PURE__ */ __toESM(require_react());
7
7
  var import_jsx_runtime = require_jsx_runtime();
@@ -65,7 +65,7 @@ var RequestLogOrderBy = _enum(["id-desc"]).describe("RequestLogOrderBy");
65
65
  var RequestLogSearchField = _enum([
66
66
  "id",
67
67
  "token_name",
68
- "query"
68
+ "user_prompt"
69
69
  ]).describe("RequestLogSearchField");
70
70
  var TokenOrderBy = _enum(["id-desc", "ord-asc"]).describe("TokenOrderBy");
71
71
  var TokenSearchField = _enum(["id", "name"]).describe("TokenSearchField");
@@ -73,7 +73,10 @@ object({
73
73
  id: int(),
74
74
  created_at: date(),
75
75
  token_name: string().max(100),
76
- query: string(),
76
+ project_name: string().max(50).nullable(),
77
+ model_name: string().max(50).nullable(),
78
+ user_prompt: string().nullable(),
79
+ system_prompt: string().nullable(),
77
80
  response: string(),
78
81
  input_tokens: int(),
79
82
  output_tokens: int(),
@@ -102,7 +105,9 @@ object({
102
105
  queryMode: SonamuQueryMode,
103
106
  id: zArrayable(number().int().positive()),
104
107
  sonamuFilter: custom(),
105
- token_name: string().max(100)
108
+ token_name: string().max(100),
109
+ project_name: string().max(50).nullable(),
110
+ model_name: string().max(50).nullable()
106
111
  }).partial();
107
112
  object({
108
113
  num: number().int().nonnegative(),
@@ -119,7 +124,10 @@ object({
119
124
  id: int(),
120
125
  created_at: date(),
121
126
  token_name: string().max(100),
122
- query: string(),
127
+ project_name: string().max(50).nullable(),
128
+ model_name: string().max(50).nullable(),
129
+ user_prompt: string().nullable(),
130
+ system_prompt: string().nullable(),
123
131
  response: string(),
124
132
  input_tokens: int(),
125
133
  output_tokens: int(),
@@ -350,10 +358,13 @@ var lucideTrash2 = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg",
350
358
  object({
351
359
  system: string().optional(),
352
360
  prompt: string(),
361
+ model: string().optional(),
353
362
  timeout: number().optional()
354
363
  });
355
364
  object({
356
365
  text: string(),
366
+ tokenName: string().optional(),
367
+ model: string().optional(),
357
368
  usage: object({
358
369
  input_tokens: number(),
359
370
  output_tokens: number(),
@@ -363,17 +374,6 @@ object({
363
374
  durationMs: number(),
364
375
  costUsd: number()
365
376
  });
366
- object({
367
- tokens: array(object({
368
- token: string(),
369
- name: string()
370
- })),
371
- size: number().optional(),
372
- model: string().optional(),
373
- timeout: number().optional(),
374
- cwd: string().optional(),
375
- maxCalls: number().optional()
376
- });
377
377
  object({
378
378
  token: string(),
379
379
  name: string()
@@ -382,8 +382,7 @@ object({ token: string() });
382
382
  object({
383
383
  token: string(),
384
384
  name: string(),
385
- requests: number(),
386
- active: boolean()
385
+ requests: number()
387
386
  });
388
387
  object({ authUrl: string() });
389
388
  var RateLimit = object({
@@ -407,7 +406,6 @@ object({
407
406
  });
408
407
  object({
409
408
  status: string(),
410
- workers: number(),
411
409
  activeTokens: number()
412
410
  });
413
411
  function maskToken(token) {