@cartanova/qgrid-cli 1.1.5 → 1.2.0

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/sonamu.generated.js +10 -5
  2. package/bundle/dist/application/sonamu.generated.sso.js +3 -2
  3. package/bundle/dist/application/token/token.model.js +21 -3
  4. package/bundle/dist/application/token/token.types.js +3 -2
  5. package/bundle/dist/i18n/sd.generated.js +3 -1
  6. package/bundle/dist/migrations/20260415113716_alter_tokens_add_ord.js +16 -0
  7. package/bundle/dist/migrations/20260415134649_alter_request_logs_alter1.js +14 -0
  8. package/bundle/dist/node_modules/.pnpm/{vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980 → vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_msw@2.13.3_@types_node@25.0.7__ba64bc4dd2e2bdde58df187864f65496}/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js +2 -2
  9. package/bundle/dist/node_modules/.pnpm/{vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980 → vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_msw@2.13.3_@types_node@25.0.7__ba64bc4dd2e2bdde58df187864f65496}/node_modules/vitest/dist/chunks/benchmark.CX_oY03V.js +2 -2
  10. package/bundle/dist/node_modules/.pnpm/{vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980 → vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_msw@2.13.3_@types_node@25.0.7__ba64bc4dd2e2bdde58df187864f65496}/node_modules/vitest/dist/chunks/evaluatedModules.Dg1zASAC.js +2 -2
  11. package/bundle/dist/node_modules/.pnpm/{vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980 → vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_msw@2.13.3_@types_node@25.0.7__ba64bc4dd2e2bdde58df187864f65496}/node_modules/vitest/dist/chunks/index.Chj8NDwU.js +2 -2
  12. package/bundle/dist/node_modules/.pnpm/{vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980 → vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_msw@2.13.3_@types_node@25.0.7__ba64bc4dd2e2bdde58df187864f65496}/node_modules/vitest/dist/chunks/index.DOa3dzoN.js +2 -2
  13. package/bundle/dist/node_modules/.pnpm/{vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980 → vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_msw@2.13.3_@types_node@25.0.7__ba64bc4dd2e2bdde58df187864f65496}/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js +2 -2
  14. package/bundle/dist/node_modules/.pnpm/{vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980 → vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_msw@2.13.3_@types_node@25.0.7__ba64bc4dd2e2bdde58df187864f65496}/node_modules/vitest/dist/chunks/test.p_J6dB8a.js +2 -2
  15. package/bundle/dist/node_modules/.pnpm/{vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980 → vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_msw@2.13.3_@types_node@25.0.7__ba64bc4dd2e2bdde58df187864f65496}/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js +2 -2
  16. package/bundle/dist/node_modules/.pnpm/{vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980 → vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_msw@2.13.3_@types_node@25.0.7__ba64bc4dd2e2bdde58df187864f65496}/node_modules/vitest/dist/index.js +1 -1
  17. package/bundle/dist/sonamu.config.js +9 -9
  18. package/bundle/dist/testing/setup-mocks.js +2 -2
  19. package/bundle/src/application/request-log/request-log.entity.json +9 -3
  20. package/bundle/src/application/sonamu.generated.http +13 -1
  21. package/bundle/src/application/sonamu.generated.sso.ts +1 -0
  22. package/bundle/src/application/sonamu.generated.ts +5 -2
  23. package/bundle/src/application/token/token.entity.json +5 -3
  24. package/bundle/src/application/token/token.model.ts +15 -1
  25. package/bundle/src/application/token/token.types.ts +1 -0
  26. package/bundle/src/i18n/sd.generated.ts +2 -0
  27. package/bundle/src/migrations/20260415113716_alter_tokens_add_ord.ts +13 -0
  28. package/bundle/src/migrations/20260415134649_alter_request_logs_alter1.ts +13 -0
  29. package/bundle/src/sonamu.config.ts +8 -8
  30. package/bundle/web-dist/client/assets/index-BP0XRvKL.css +1 -0
  31. package/bundle/web-dist/client/assets/{index-Dyn67Y0R.js → index-BowrnLVe.js} +3 -3
  32. package/bundle/web-dist/client/assets/routes-DRU2rj_p.js +5 -0
  33. package/bundle/web-dist/client/assets/{sd.generated-BrQoQXvv.js → sd.generated-CkJCx4Bp.js} +1 -1
  34. package/bundle/web-dist/client/assets/services.generated-CAJQk7Wk.js +1 -0
  35. package/bundle/web-dist/client/assets/{show-DIzwg78k.js → show-DjQUOob1.js} +1 -1
  36. package/bundle/web-dist/client/assets/tokens-B6y-rxlU.js +1 -0
  37. package/bundle/web-dist/client/index.html +3 -3
  38. package/bundle/web-dist/server/assets/routes-CQY28Uq3.js +2855 -0
  39. package/bundle/web-dist/server/assets/{sd.generated-BnonqqKr.js → sd.generated-BeEKgSOs.js} +336 -1
  40. package/bundle/web-dist/server/assets/{services.generated-D5ABD5fr.js → services.generated-DjxCLdMu.js} +10 -1
  41. package/bundle/web-dist/server/assets/{show-C9pcdSxc.js → show-BEFi1cKV.js} +2 -2
  42. package/bundle/web-dist/server/assets/{tokens-ARL5AOAh.js → tokens-Dyi6qMmP.js} +9 -6
  43. package/bundle/web-dist/server/entry-server.generated.js +18 -19
  44. package/package.json +1 -1
  45. package/bundle/web-dist/client/assets/index-p3clzhWX.css +0 -1
  46. package/bundle/web-dist/client/assets/routes-ytPY-kr9.js +0 -1
  47. package/bundle/web-dist/client/assets/services.generated-BspO2L0j.js +0 -1
  48. package/bundle/web-dist/client/assets/tokens-CiU_LVOp.js +0 -1
  49. package/bundle/web-dist/server/assets/react-dom-CGIzOSuj.js +0 -335
  50. package/bundle/web-dist/server/assets/routes-BQmURFK9.js +0 -492
@@ -1,492 +0,0 @@
1
- import { b as require_jsx_runtime, tt as __toESM, x as require_react } from "./sd.generated-BnonqqKr.js";
2
- import { n as RequestLogService, r as TokenService, t as QgridService } from "./services.generated-D5ABD5fr.js";
3
- import { i as lucideKeyRound, o as useNavigate } from "../entry-server.generated.js";
4
- //#region ~icons/lucide/activity.jsx
5
- var import_react = /* @__PURE__ */ __toESM(require_react());
6
- var import_jsx_runtime = require_jsx_runtime();
7
- var lucideActivity = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
8
- viewBox: "0 0 24 24",
9
- width: "1.2em",
10
- height: "1.2em",
11
- ...props,
12
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
13
- fill: "none",
14
- stroke: "currentColor",
15
- strokeLinecap: "round",
16
- strokeLinejoin: "round",
17
- strokeWidth: 2,
18
- d: "M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2"
19
- })
20
- });
21
- //#endregion
22
- //#region ~icons/lucide/cpu.jsx
23
- var lucideCpu = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
24
- viewBox: "0 0 24 24",
25
- width: "1.2em",
26
- height: "1.2em",
27
- ...props,
28
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("g", {
29
- fill: "none",
30
- stroke: "currentColor",
31
- strokeLinecap: "round",
32
- strokeLinejoin: "round",
33
- strokeWidth: 2,
34
- children: [
35
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 20v2m0-20v2m5 16v2m0-20v2M2 12h2m-2 5h2M2 7h2m16 5h2m-2 5h2M20 7h2M7 20v2M7 2v2" }),
36
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", {
37
- width: 16,
38
- height: 16,
39
- x: 4,
40
- y: 4,
41
- rx: 2
42
- }),
43
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", {
44
- width: 8,
45
- height: 8,
46
- x: 8,
47
- y: 8,
48
- rx: 1
49
- })
50
- ]
51
- })
52
- });
53
- //#endregion
54
- //#region src/components/qgrid/HealthCard.tsx
55
- function MetricCard({ label, icon: Icon, children }) {
56
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
57
- className: "rounded-lg bg-sand-50 px-5 py-4",
58
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
59
- className: "flex items-center justify-between mb-2",
60
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
61
- className: "text-[10px] uppercase tracking-wider text-sand-400 font-medium",
62
- children: label
63
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className: "size-4 text-sand-400" })]
64
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children })]
65
- });
66
- }
67
- function HealthCard({ data, isLoading, isError }) {
68
- if (isLoading) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
69
- className: "grid grid-cols-1 sm:grid-cols-3 gap-4",
70
- children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
71
- className: "rounded-lg bg-sand-50 px-5 py-4 animate-pulse",
72
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-3 w-16 bg-sand-200 rounded mb-3" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-6 w-12 bg-sand-200 rounded" })]
73
- }, `skeleton-${i}`))
74
- });
75
- const isOnline = (isError ? "offline" : data?.status ?? "unknown") === "ok";
76
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
77
- className: "grid grid-cols-1 sm:grid-cols-3 gap-4",
78
- children: [
79
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MetricCard, {
80
- label: "Status",
81
- icon: lucideActivity,
82
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
83
- className: "flex items-center gap-2",
84
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: `size-2 rounded-full ${isOnline ? "bg-sage-400" : "bg-red-400"}` }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
85
- className: "text-base font-semibold text-sand-800",
86
- children: isOnline ? "Online" : "Offline"
87
- })]
88
- })
89
- }),
90
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MetricCard, {
91
- label: "Workers",
92
- icon: lucideCpu,
93
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
94
- className: "text-base font-semibold text-sand-800",
95
- children: data?.workers ?? 0
96
- })
97
- }),
98
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MetricCard, {
99
- label: "Active Tokens",
100
- icon: lucideKeyRound,
101
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
102
- className: "text-base font-semibold text-sand-800",
103
- children: data?.activeTokens ?? 0
104
- })
105
- })
106
- ]
107
- });
108
- }
109
- //#endregion
110
- //#region ~icons/lucide/chevron-right.jsx
111
- var lucideChevronRight = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
112
- viewBox: "0 0 24 24",
113
- width: "1.2em",
114
- height: "1.2em",
115
- ...props,
116
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
117
- fill: "none",
118
- stroke: "currentColor",
119
- strokeLinecap: "round",
120
- strokeLinejoin: "round",
121
- strokeWidth: 2,
122
- d: "m9 18l6-6l-6-6"
123
- })
124
- });
125
- //#endregion
126
- //#region src/components/qgrid/RequestLogTable.tsx
127
- var PAGE_SIZE$1 = 50;
128
- function formatTime(iso) {
129
- const d = new Date(iso);
130
- return `${d.getHours().toString().padStart(2, "0")}:${d.getMinutes().toString().padStart(2, "0")}`;
131
- }
132
- function formatNum(n) {
133
- return n.toLocaleString();
134
- }
135
- function calcCacheHitRate(row) {
136
- const denom = row.input_tokens + row.cache_read_tokens + row.cache_creation_tokens;
137
- if (denom === 0) return "—";
138
- return `${Math.round(row.cache_read_tokens / denom * 100)}%`;
139
- }
140
- function trimQuery(q, maxLen = 30) {
141
- return q.length > maxLen ? `${q.slice(0, maxLen)}...` : q;
142
- }
143
- function RequestLogTable() {
144
- const navigate = useNavigate();
145
- const [num, setNum] = (0, import_react.useState)(PAGE_SIZE$1);
146
- const [tokenFilter, setTokenFilter] = (0, import_react.useState)("");
147
- const { data: statsData } = QgridService.useStats();
148
- const tokenNames = (statsData ?? []).map((t) => t.name).filter(Boolean);
149
- const { data, isLoading } = RequestLogService.useRequestLogs("A", {
150
- num,
151
- page: 1,
152
- orderBy: "id-desc",
153
- ...tokenFilter ? { token_name: tokenFilter } : {}
154
- });
155
- const rows = data?.rows ?? [];
156
- const total = data?.total ?? 0;
157
- const hasMore = num < total;
158
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
159
- className: "flex items-center gap-2 mb-3",
160
- children: [tokenNames.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", {
161
- value: tokenFilter,
162
- onChange: (e) => {
163
- setTokenFilter(e.target.value);
164
- setNum(PAGE_SIZE$1);
165
- },
166
- 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",
167
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
168
- value: "",
169
- children: "All Tokens"
170
- }), tokenNames.map((name) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
171
- value: name,
172
- children: name
173
- }, name))]
174
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
175
- className: "text-[11px] text-sand-400",
176
- children: [total, " results"]
177
- })]
178
- }), isLoading && num === PAGE_SIZE$1 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
179
- className: "space-y-2",
180
- children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-8 bg-sand-100 rounded animate-pulse" }, `skel-${i}`))
181
- }) : rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
182
- className: "text-sand-400 text-center py-12 text-sm",
183
- children: "No requests yet."
184
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
185
- className: "rounded-lg bg-sand-50 overflow-hidden",
186
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", {
187
- className: "w-full text-sm",
188
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", {
189
- className: "border-b border-sand-200",
190
- children: [
191
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
192
- className: "text-left px-3 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
193
- children: "Token"
194
- }),
195
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
196
- className: "text-left px-3 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
197
- children: "Query"
198
- }),
199
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
200
- className: "text-right px-3 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
201
- children: "In"
202
- }),
203
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
204
- className: "text-right px-3 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
205
- children: "Out"
206
- }),
207
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
208
- className: "text-right px-3 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
209
- children: "C.Read"
210
- }),
211
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
212
- className: "text-right px-3 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
213
- children: "C.Write"
214
- }),
215
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
216
- className: "text-right px-3 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
217
- children: "Hit"
218
- }),
219
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: "w-8 px-2 py-2.5" })
220
- ]
221
- }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", {
222
- className: "divide-y divide-sand-200/60",
223
- children: rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", {
224
- className: "transition-colors duration-150 hover:bg-sand-100/60 cursor-pointer",
225
- onClick: () => navigate({
226
- to: "/requests/show",
227
- search: { id: row.id }
228
- }),
229
- children: [
230
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
231
- className: "px-3 py-2.5",
232
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
233
- className: "text-xs text-sand-500",
234
- children: row.token_name
235
- })
236
- }),
237
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
238
- className: "px-3 py-2.5",
239
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
240
- className: "flex items-center gap-2",
241
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
242
- className: "text-[10px] text-sand-400 shrink-0",
243
- children: formatTime(row.created_at)
244
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
245
- className: "text-sand-800 truncate max-w-48",
246
- title: row.query,
247
- children: trimQuery(row.query)
248
- })]
249
- })
250
- }),
251
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
252
- className: "px-3 py-2.5 text-right tabular-nums text-sand-700",
253
- children: formatNum(row.input_tokens)
254
- }),
255
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
256
- className: "px-3 py-2.5 text-right tabular-nums text-sand-700",
257
- children: formatNum(row.output_tokens)
258
- }),
259
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
260
- className: "px-3 py-2.5 text-right tabular-nums text-sand-700",
261
- children: formatNum(row.cache_read_tokens)
262
- }),
263
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
264
- className: "px-3 py-2.5 text-right tabular-nums text-sand-700",
265
- children: formatNum(row.cache_creation_tokens)
266
- }),
267
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
268
- className: "px-3 py-2.5 text-right tabular-nums text-sand-700",
269
- children: calcCacheHitRate(row)
270
- }),
271
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
272
- className: "px-2 py-2.5",
273
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucideChevronRight, { className: "size-4 text-sand-400" })
274
- })
275
- ]
276
- }, row.id))
277
- })]
278
- })
279
- }), hasMore && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
280
- type: "button",
281
- className: "mt-3 w-full py-2 text-xs text-sand-500 hover:text-sienna-500 transition-colors",
282
- onClick: () => setNum((prev) => prev + PAGE_SIZE$1),
283
- children: [
284
- "Load more (",
285
- total - num,
286
- " remaining)"
287
- ]
288
- })] })] });
289
- }
290
- //#endregion
291
- //#region ~icons/lucide/chevron-left.jsx
292
- var lucideChevronLeft = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
293
- viewBox: "0 0 24 24",
294
- width: "1.2em",
295
- height: "1.2em",
296
- ...props,
297
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
298
- fill: "none",
299
- stroke: "currentColor",
300
- strokeLinecap: "round",
301
- strokeLinejoin: "round",
302
- strokeWidth: 2,
303
- d: "m15 18l-6-6l6-6"
304
- })
305
- });
306
- //#endregion
307
- //#region src/components/qgrid/UsageCard.tsx
308
- function barColor(pct) {
309
- if (pct >= 95) return "bg-red-500";
310
- if (pct >= 80) return "bg-amber-400";
311
- return "bg-sienna-400";
312
- }
313
- function formatResets(iso) {
314
- if (!iso) return "";
315
- const diff = new Date(iso).getTime() - Date.now();
316
- if (diff <= 0) return "resetting...";
317
- const h = Math.floor(diff / 36e5);
318
- const m = Math.floor(diff % 36e5 / 6e4);
319
- return h > 0 ? `resets ${h}h ${m}m` : `resets ${m}m`;
320
- }
321
- function UsageRow({ label, utilization, resetsAt }) {
322
- const pct = utilization ?? 0;
323
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
324
- className: "flex items-center gap-3",
325
- children: [
326
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
327
- className: "text-xs text-sand-600 w-20 shrink-0",
328
- children: label
329
- }),
330
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
331
- className: "flex-1 h-2 bg-sand-200 rounded-full overflow-hidden",
332
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
333
- className: `h-full rounded-full transition-all duration-300 ${barColor(pct)}`,
334
- style: { width: `${Math.min(pct, 100)}%` }
335
- })
336
- }),
337
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
338
- className: "text-xs tabular-nums text-sand-700 w-10 text-right",
339
- children: [pct, "%"]
340
- }),
341
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
342
- className: "text-[10px] text-sand-400 w-24 text-right",
343
- children: formatResets(resetsAt)
344
- })
345
- ]
346
- });
347
- }
348
- function TokenUsage({ token }) {
349
- const { data, isLoading } = QgridService.useUsage(token.name);
350
- if (isLoading) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
351
- className: "animate-pulse space-y-2 py-2",
352
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-2 w-full bg-sand-200 rounded-full" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-2 w-3/4 bg-sand-200 rounded-full" })]
353
- });
354
- if (data?.error) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
355
- className: "py-1",
356
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
357
- className: "text-[11px] text-amber-600",
358
- children: "Session expired"
359
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
360
- className: "text-[10px] text-sand-400 mt-0.5",
361
- children: "Please re-login via OAuth or update your token"
362
- })]
363
- });
364
- if (!data?.five_hour) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
365
- className: "text-[11px] text-sand-400 py-1",
366
- children: "No usage data"
367
- });
368
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
369
- className: "space-y-1.5 py-1",
370
- children: [
371
- data.five_hour && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UsageRow, {
372
- label: "5h",
373
- utilization: data.five_hour.utilization,
374
- resetsAt: data.five_hour.resets_at
375
- }),
376
- data.seven_day && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UsageRow, {
377
- label: "7d All",
378
- utilization: data.seven_day.utilization,
379
- resetsAt: data.seven_day.resets_at
380
- }),
381
- data.seven_day_sonnet && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UsageRow, {
382
- label: "7d Sonnet",
383
- utilization: data.seven_day_sonnet.utilization,
384
- resetsAt: data.seven_day_sonnet.resets_at
385
- }),
386
- data.seven_day_opus && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UsageRow, {
387
- label: "7d Opus",
388
- utilization: data.seven_day_opus.utilization,
389
- resetsAt: data.seven_day_opus.resets_at
390
- })
391
- ]
392
- });
393
- }
394
- var PAGE_SIZE = 6;
395
- function UsageCard() {
396
- const [page, setPage] = (0, import_react.useState)(0);
397
- const { data, isLoading } = TokenService.useTokens("A");
398
- if (isLoading) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
399
- className: "grid grid-cols-2 gap-3",
400
- children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
401
- className: "rounded-lg bg-sand-50 px-4 py-3 animate-pulse",
402
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-3 w-16 bg-sand-200 rounded mb-3" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-2 w-full bg-sand-200 rounded-full" })]
403
- }, `skel-${i}`))
404
- });
405
- const tokens = data?.rows ?? [];
406
- if (tokens.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
407
- className: "rounded-lg bg-sand-50 px-5 py-4",
408
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
409
- className: "text-sand-400 text-sm",
410
- children: "No tokens registered"
411
- })
412
- });
413
- const totalPages = Math.ceil(tokens.length / PAGE_SIZE);
414
- const safePage = Math.min(page, totalPages - 1);
415
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
416
- className: "grid grid-cols-2 gap-3",
417
- children: tokens.slice(safePage * PAGE_SIZE, (safePage + 1) * PAGE_SIZE).map((token) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
418
- className: "rounded-lg bg-sand-50 px-4 py-3",
419
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
420
- className: "flex items-center gap-2 mb-2",
421
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
422
- className: "text-sm font-medium text-sand-800 truncate",
423
- children: token.name ?? "Unnamed"
424
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
425
- className: `text-[10px] px-1.5 py-0.5 rounded-full shrink-0 ${token.active ? "bg-sage-100 text-sage-600" : "bg-sand-200 text-sand-500"}`,
426
- children: token.active ? "Active" : "Inactive"
427
- })]
428
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TokenUsage, { token })]
429
- }, token.id))
430
- }), totalPages > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
431
- className: "flex items-center justify-center gap-2 mt-3",
432
- children: [
433
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
434
- type: "button",
435
- className: "p-0.5 rounded text-sand-400 hover:text-sand-600 disabled:opacity-30 transition-colors",
436
- disabled: safePage === 0,
437
- onClick: () => setPage(safePage - 1),
438
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucideChevronLeft, { className: "size-4" })
439
- }),
440
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
441
- className: "text-[10px] text-sand-400 tabular-nums",
442
- children: [
443
- safePage + 1,
444
- " / ",
445
- totalPages
446
- ]
447
- }),
448
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
449
- type: "button",
450
- className: "p-0.5 rounded text-sand-400 hover:text-sand-600 disabled:opacity-30 transition-colors",
451
- disabled: safePage === totalPages - 1,
452
- onClick: () => setPage(safePage + 1),
453
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucideChevronRight, { className: "size-4" })
454
- })
455
- ]
456
- })] });
457
- }
458
- //#endregion
459
- //#region src/routes/index.tsx?tsr-split=component
460
- function Dashboard() {
461
- const { data: healthData, isLoading: healthLoading, isError: healthError } = QgridService.useHealth();
462
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
463
- className: "space-y-5 max-w-300 mx-auto -translate-x-4",
464
- children: [
465
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", {
466
- className: "text-xl font-medium text-sand-900 tracking-tight",
467
- children: "Dashboard"
468
- }),
469
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HealthCard, {
470
- data: healthData,
471
- isLoading: healthLoading,
472
- isError: healthError
473
- }),
474
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
475
- className: "text-[10px] uppercase tracking-wider text-sand-500 font-medium",
476
- children: "Usage"
477
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
478
- className: "mt-2",
479
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UsageCard, {})
480
- })] }),
481
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
482
- className: "text-[10px] uppercase tracking-wider text-sand-500 font-medium",
483
- children: "Request Log"
484
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
485
- className: "mt-2",
486
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequestLogTable, {})
487
- })] })
488
- ]
489
- });
490
- }
491
- //#endregion
492
- export { Dashboard as component };