@cartanova/qgrid-cli 1.6.0 → 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 (50) hide show
  1. package/bundle/dist/application/qgrid/qgrid.dispatcher.js +3 -2
  2. package/bundle/dist/application/qgrid/qgrid.frame.js +19 -3
  3. package/bundle/dist/application/qgrid/qgrid.types.js +2 -1
  4. package/bundle/dist/application/queries.generated.js +2 -1
  5. package/bundle/dist/application/request-log/request-log.model.js +15 -2
  6. package/bundle/dist/application/request-log/request-log.types.js +6 -2
  7. package/bundle/dist/application/sonamu.generated.js +14 -6
  8. package/bundle/dist/application/sonamu.generated.sso.js +5 -2
  9. package/bundle/dist/i18n/sd.generated.js +6 -3
  10. package/bundle/dist/migrations/20260423180818_alter_request_logs_add1_alter1.js +17 -0
  11. package/bundle/dist/migrations/20260423182017_alter_request_logs_add2_drop1_alter1.js +19 -0
  12. package/bundle/dist/migrations/20260423183613_alter_request_logs_add1_alter1.js +16 -0
  13. package/bundle/src/application/qgrid/qgrid.dispatcher.ts +1 -1
  14. package/bundle/src/application/qgrid/qgrid.frame.ts +10 -1
  15. package/bundle/src/application/qgrid/qgrid.types.ts +1 -0
  16. package/bundle/src/application/queries.generated.ts +3 -0
  17. package/bundle/src/application/request-log/request-log.entity.json +33 -17
  18. package/bundle/src/application/request-log/request-log.model.ts +26 -2
  19. package/bundle/src/application/request-log/request-log.types.ts +6 -2
  20. package/bundle/src/application/sonamu.generated.http +16 -2
  21. package/bundle/src/application/sonamu.generated.sso.ts +9 -6
  22. package/bundle/src/application/sonamu.generated.ts +25 -5
  23. package/bundle/src/i18n/sd.generated.ts +5 -2
  24. package/bundle/src/migrations/20260423180818_alter_request_logs_add1_alter1.ts +18 -0
  25. package/bundle/src/migrations/20260423182017_alter_request_logs_add2_drop1_alter1.ts +20 -0
  26. package/bundle/src/migrations/20260423183613_alter_request_logs_add1_alter1.ts +15 -0
  27. package/bundle/web-dist/client/assets/index-BfL_bTVI.css +1 -0
  28. package/bundle/web-dist/client/assets/index-CMOHJBal.js +78 -0
  29. package/bundle/web-dist/client/assets/logs-B2pDXaji.js +1 -0
  30. package/bundle/web-dist/client/assets/{routes-DQKecVGa.js → routes-fpJMuLAs.js} +1 -1
  31. package/bundle/web-dist/client/assets/{sd.generated-NHYHS_-0.js → sd.generated-CIOZewtL.js} +1 -1
  32. package/bundle/web-dist/client/assets/{services.generated-DDVXMid7.js → services.generated-B2N0iPav.js} +1 -1
  33. package/bundle/web-dist/client/assets/{show-D2z1qxJ5.js → show-DFVBcmXm.js} +2 -2
  34. package/bundle/web-dist/client/assets/tokens--LyDCm10.js +1 -0
  35. package/bundle/web-dist/client/index.html +3 -3
  36. package/bundle/web-dist/server/assets/{copy-BVWDOV2T.js → copy-CKCGxwII.js} +1 -1
  37. package/bundle/web-dist/server/assets/{lazyRouteComponent-BJmwxFyJ.js → lazyRouteComponent-BlvOfJIF.js} +2 -2
  38. package/bundle/web-dist/server/assets/{logs-DgIbufNf.js → logs-BYIBD0yv.js} +172 -80
  39. package/bundle/web-dist/server/assets/{routes-x7-hqUm0.js → routes-p2n4SfAB.js} +2 -2
  40. package/bundle/web-dist/server/assets/{sd.generated-BZPIp4uL.js → sd.generated-CIg_jf8e.js} +5 -2
  41. package/bundle/web-dist/server/assets/{services.generated-BA0gbdmd.js → services.generated-DIeiDdqy.js} +20 -4
  42. package/bundle/web-dist/server/assets/{shim-DGrmZkac.js → shim-Dq_Izqnc.js} +1 -1
  43. package/bundle/web-dist/server/assets/{show-Bk3NayMH.js → show-DZ_U1u-N.js} +30 -9
  44. package/bundle/web-dist/server/assets/{tokens-CVSwt0x0.js → tokens-DOybPnNU.js} +16 -7
  45. package/bundle/web-dist/server/entry-server.generated.js +12 -8
  46. package/package.json +1 -1
  47. package/bundle/web-dist/client/assets/index-BRZCFaFz.css +0 -1
  48. package/bundle/web-dist/client/assets/index-D8eEjsZj.js +0 -78
  49. package/bundle/web-dist/client/assets/logs-CKnJzuH6.js +0 -1
  50. package/bundle/web-dist/client/assets/tokens-BaywaQkm.js +0 -1
@@ -1,10 +1,9 @@
1
- import { D as require_react, E as require_jsx_runtime, ot as __toESM } from "./sd.generated-BZPIp4uL.js";
2
- import { n as RequestLogService, r as TokenService, t as QgridService } from "./services.generated-BA0gbdmd.js";
3
- import { a as Link, o as useNavigate } from "./lazyRouteComponent-BJmwxFyJ.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 { C as require_react_dom, D as require_react, E as require_jsx_runtime, T as useQueryClient, ot as __toESM } from "./sd.generated-BZPIp4uL.js";
2
- import { r as TokenService, t as QgridService } from "./services.generated-BA0gbdmd.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": "등록일시",
@@ -1,4 +1,4 @@
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-BZPIp4uL.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,7 +835,7 @@ var RequestLogService;
835
835
  })(RequestLogService || (RequestLogService = {}));
836
836
  var QgridService;
837
837
  (function(_QgridService) {
838
- async function query(prompt, system, timeout, model) {
838
+ async function query(prompt, system, timeout, model, projectName) {
839
839
  return fetch({
840
840
  method: "POST",
841
841
  url: `/api/qgrid/query`,
@@ -843,12 +843,13 @@ var QgridService;
843
843
  prompt,
844
844
  system,
845
845
  timeout,
846
- model
846
+ model,
847
+ projectName
847
848
  }
848
849
  });
849
850
  }
850
851
  _QgridService.query = query;
851
- _QgridService.useQueryMutation = () => useMutation({ mutationFn: (params) => query(params.prompt, params.system, params.timeout, params.model) });
852
+ _QgridService.useQueryMutation = () => useMutation({ mutationFn: (params) => query(params.prompt, params.system, params.timeout, params.model, params.projectName) });
852
853
  async function stats() {
853
854
  return fetch({
854
855
  method: "GET",
@@ -883,6 +884,21 @@ var QgridService;
883
884
  ...totalCostQueryOptions(tokenName),
884
885
  ...options
885
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
+ }));
886
902
  async function addToken(token, name, refreshToken) {
887
903
  return fetch({
888
904
  method: "POST",
@@ -1,4 +1,4 @@
1
- import { D as require_react, rt as __commonJSMin } from "./sd.generated-BZPIp4uL.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_react, E as require_jsx_runtime, it as __exportAll, ot as __toESM, rt as __commonJSMin } from "./sd.generated-BZPIp4uL.js";
2
- import { n as RequestLogService } from "./services.generated-BA0gbdmd.js";
3
- import { a as Link } from "./lazyRouteComponent-BJmwxFyJ.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-BVWDOV2T.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_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-BZPIp4uL.js";
2
- import { r as TokenService, t as QgridService } from "./services.generated-BA0gbdmd.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-BVWDOV2T.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(),
@@ -356,6 +364,7 @@ object({
356
364
  object({
357
365
  text: string(),
358
366
  tokenName: string().optional(),
367
+ model: string().optional(),
359
368
  usage: object({
360
369
  input_tokens: number(),
361
370
  output_tokens: number(),
@@ -1,6 +1,6 @@
1
- import { B as hashKey, C as require_react_dom, D as require_react, E as require_jsx_runtime, F as onlineManager, G as noop$1, I as notifyManager, K as partialMatchKey, M as infiniteQueryBehavior, N as Query, O as Mutation, Q as skipToken, U as matchMutation, V as hashQueryKeyByOptions, W as matchQuery, Y as resolveStaleTime, at as __require, b as object, d as ZodObject, f as ZodOptional, l as ZodArray, n as SUPPORTED_LOCALES, nt as Subscribable, ot as __toESM, r as setLocale, rt as __commonJSMin, t as SD, tt as focusManager, u as ZodNullable, w as QueryClientProvider, y as number, z as functionalUpdate } from "./assets/sd.generated-BZPIp4uL.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-BJmwxFyJ.js";
3
- import { t as require_shim } from "./assets/shim-DGrmZkac.js";
1
+ import { B as hashKey, C as require_react_dom, D as require_react, E as require_jsx_runtime, F as onlineManager, G as noop$1, I as notifyManager, K as partialMatchKey, M as infiniteQueryBehavior, N as Query, O as Mutation, Q as skipToken, U as matchMutation, V as hashQueryKeyByOptions, W as matchQuery, Y as resolveStaleTime, at as __require, b as object, d as ZodObject, f as ZodOptional, l as ZodArray, n as SUPPORTED_LOCALES, nt as Subscribable, ot as __toESM, r as setLocale, rt as __commonJSMin, t as SD, tt as focusManager, u as ZodNullable, w as QueryClientProvider, x as string, y as number, z as functionalUpdate } from "./assets/sd.generated-CIg_jf8e.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-BlvOfJIF.js";
3
+ import { t as require_shim } from "./assets/shim-Dq_Izqnc.js";
4
4
  //#region ../../node_modules/.pnpm/@tanstack+query-core@5.95.2/node_modules/@tanstack/query-core/build/modern/hydration.js
5
5
  function defaultTransformerFn(data) {
6
6
  return data;
@@ -44599,23 +44599,27 @@ function RootComponent() {
44599
44599
  }
44600
44600
  //#endregion
44601
44601
  //#region src/routes/tokens.tsx
44602
- var $$splitComponentImporter$3 = () => import("./assets/tokens-CVSwt0x0.js");
44602
+ var $$splitComponentImporter$3 = () => import("./assets/tokens-DOybPnNU.js");
44603
44603
  var Route$3 = createFileRoute("/tokens")({ component: lazyRouteComponent($$splitComponentImporter$3, "component") });
44604
44604
  //#endregion
44605
44605
  //#region src/routes/logs.tsx
44606
- var $$splitComponentImporter$2 = () => import("./assets/logs-DgIbufNf.js");
44607
- var logsSearchSchema = object({ page: number().optional().default(1) });
44606
+ var $$splitComponentImporter$2 = () => import("./assets/logs-BYIBD0yv.js");
44607
+ var logsSearchSchema = object({
44608
+ token: string().optional(),
44609
+ project: string().optional(),
44610
+ page: number().optional().default(1)
44611
+ });
44608
44612
  var Route$2 = createFileRoute("/logs")({
44609
44613
  validateSearch: logsSearchSchema,
44610
44614
  component: lazyRouteComponent($$splitComponentImporter$2, "component")
44611
44615
  });
44612
44616
  //#endregion
44613
44617
  //#region src/routes/index.tsx
44614
- var $$splitComponentImporter$1 = () => import("./assets/routes-x7-hqUm0.js");
44618
+ var $$splitComponentImporter$1 = () => import("./assets/routes-p2n4SfAB.js");
44615
44619
  var Route$1 = createFileRoute("/")({ component: lazyRouteComponent($$splitComponentImporter$1, "component") });
44616
44620
  //#endregion
44617
44621
  //#region src/routes/requests/show.tsx
44618
- var $$splitComponentImporter = () => import("./assets/show-Bk3NayMH.js");
44622
+ var $$splitComponentImporter = () => import("./assets/show-DZ_U1u-N.js");
44619
44623
  var showSearchSchema = object({ id: number() });
44620
44624
  var Route = createFileRoute("/requests/show")({
44621
44625
  validateSearch: showSearchSchema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cartanova/qgrid-cli",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/cartanova-ai/qgrid"