@cartanova/qgrid-cli 1.0.2 → 1.0.4

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 (114) hide show
  1. package/bundle/dist/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/decorate.js +9 -0
  2. package/bundle/dist/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/decorateMetadata.js +6 -0
  3. package/bundle/dist/dist/_virtual/_rolldown/runtime.js +15 -0
  4. package/bundle/dist/dist/application/qgrid/oauth.js +140 -0
  5. package/bundle/dist/dist/application/qgrid/pool.js +100 -0
  6. package/bundle/dist/dist/application/qgrid/qgrid.frame.js +280 -0
  7. package/bundle/dist/dist/application/qgrid/qgrid.types.js +79 -0
  8. package/bundle/dist/dist/application/qgrid/worker.js +183 -0
  9. package/bundle/dist/dist/application/queries.generated.js +31 -0
  10. package/bundle/dist/dist/application/request-log/request-log.model.js +113 -0
  11. package/bundle/dist/dist/application/request-log/request-log.types.js +13 -0
  12. package/bundle/dist/dist/application/sonamu.generated.js +99 -0
  13. package/bundle/dist/dist/application/sonamu.generated.sso.js +34 -0
  14. package/bundle/dist/dist/application/token/token.model.js +157 -0
  15. package/bundle/dist/dist/application/token/token.types.js +22 -0
  16. package/bundle/dist/dist/i18n/en.js +63 -0
  17. package/bundle/dist/dist/i18n/ko.js +62 -0
  18. package/bundle/dist/dist/i18n/sd.generated.js +272 -0
  19. package/bundle/dist/dist/index.js +11 -0
  20. package/bundle/dist/dist/migrations/20260410171405_create__request_logs.js +26 -0
  21. package/bundle/dist/dist/migrations/20260410171406_create__tokens.js +24 -0
  22. package/bundle/dist/dist/migrations/20260411120624_alter_tokens_alter2.js +16 -0
  23. package/bundle/dist/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +155 -0
  24. package/bundle/dist/dist/node_modules/.pnpm/@vitest_expect@4.1.2/node_modules/@vitest/expect/dist/index.js +1484 -0
  25. package/bundle/dist/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.2/node_modules/@vitest/pretty-format/dist/index.js +887 -0
  26. package/bundle/dist/dist/node_modules/.pnpm/@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/chunk-artifact.js +2746 -0
  27. package/bundle/dist/dist/node_modules/.pnpm/@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/index.js +8 -0
  28. package/bundle/dist/dist/node_modules/.pnpm/@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/utils.js +8 -0
  29. package/bundle/dist/dist/node_modules/.pnpm/@vitest_snapshot@4.1.2/node_modules/@vitest/snapshot/dist/index.js +662 -0
  30. package/bundle/dist/dist/node_modules/.pnpm/@vitest_spy@4.1.2/node_modules/@vitest/spy/dist/index.js +386 -0
  31. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +82 -0
  32. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/constants.js +48 -0
  33. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/diff.js +1307 -0
  34. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/display.js +558 -0
  35. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/error.js +33 -0
  36. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/helpers.js +226 -0
  37. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/offset.js +27 -0
  38. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/serialize.js +77 -0
  39. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/source-map.js +374 -0
  40. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/timers.js +37 -0
  41. package/bundle/dist/dist/node_modules/.pnpm/chai@6.2.2/node_modules/chai/index.js +2886 -0
  42. package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.js +10 -0
  43. package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.js +109 -0
  44. package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.js +10 -0
  45. package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.js +10 -0
  46. package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.js +10 -0
  47. package/bundle/dist/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +1127 -0
  48. package/bundle/dist/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.js +21 -0
  49. package/bundle/dist/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +432 -0
  50. package/bundle/dist/dist/node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.js +506 -0
  51. package/bundle/dist/dist/node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js +86 -0
  52. package/bundle/dist/dist/node_modules/.pnpm/vite@8.0.3_@emnapi_core@1.9.2_@emnapi_runtime@1.9.2_@types_node@25.0.7_esbuild@0.27.4_jiti@2.6.1_sass@1.98.0_tsx@4.21.0/node_modules/vite/dist/node/module-runner.js +426 -0
  53. package/bundle/dist/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/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js +6 -0
  54. package/bundle/dist/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/node_modules/vitest/dist/chunks/benchmark.CX_oY03V.js +41 -0
  55. package/bundle/dist/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/node_modules/vitest/dist/chunks/evaluatedModules.Dg1zASAC.js +19 -0
  56. package/bundle/dist/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/node_modules/vitest/dist/chunks/index.Chj8NDwU.js +202 -0
  57. package/bundle/dist/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/node_modules/vitest/dist/chunks/index.DOa3dzoN.js +16 -0
  58. package/bundle/dist/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/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js +59 -0
  59. package/bundle/dist/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/node_modules/vitest/dist/chunks/test.p_J6dB8a.js +2910 -0
  60. package/bundle/dist/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/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js +44 -0
  61. package/bundle/dist/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/node_modules/vitest/dist/index.js +28 -0
  62. package/bundle/dist/dist/sonamu.config.js +196 -0
  63. package/bundle/dist/dist/testing/fixture.js +8 -0
  64. package/bundle/dist/dist/testing/global.js +9 -0
  65. package/bundle/dist/dist/testing/setup-mocks.js +17 -0
  66. package/bundle/dist/dist/utils/subset-loaders.js +12 -0
  67. package/bundle/src/src/application/qgrid/oauth.ts +181 -0
  68. package/bundle/src/src/application/qgrid/pool.ts +132 -0
  69. package/bundle/src/src/application/qgrid/qgrid.frame.ts +275 -0
  70. package/bundle/src/src/application/qgrid/qgrid.types.ts +117 -0
  71. package/bundle/src/src/application/qgrid/worker.ts +234 -0
  72. package/bundle/src/src/application/queries.generated.ts +59 -0
  73. package/bundle/src/src/application/request-log/request-log.entity.json +75 -0
  74. package/bundle/src/src/application/request-log/request-log.model.ts +155 -0
  75. package/bundle/src/src/application/request-log/request-log.types.ts +15 -0
  76. package/bundle/src/src/application/sonamu.generated.http +187 -0
  77. package/bundle/src/src/application/sonamu.generated.sso.ts +66 -0
  78. package/bundle/src/src/application/sonamu.generated.ts +135 -0
  79. package/bundle/src/src/application/token/token.entity.json +37 -0
  80. package/bundle/src/src/application/token/token.model.ts +160 -0
  81. package/bundle/src/src/application/token/token.types.ts +26 -0
  82. package/bundle/src/src/i18n/en.ts +59 -0
  83. package/bundle/src/src/i18n/ko.ts +59 -0
  84. package/bundle/src/src/i18n/sd.generated.ts +384 -0
  85. package/bundle/src/src/index.ts +6 -0
  86. package/bundle/src/src/migrations/20260410171405_create__request_logs.ts +23 -0
  87. package/bundle/src/src/migrations/20260410171406_create__tokens.ts +21 -0
  88. package/bundle/src/src/migrations/20260411120624_alter_tokens_alter2.ts +15 -0
  89. package/bundle/src/src/sonamu.config.ts +248 -0
  90. package/bundle/src/src/testing/fixture.ts +6 -0
  91. package/bundle/src/src/testing/global.ts +6 -0
  92. package/bundle/src/src/testing/setup-mocks.ts +44 -0
  93. package/bundle/src/src/typings/fastify.d.ts +8 -0
  94. package/bundle/src/src/typings/sonamu.d.ts +17 -0
  95. package/bundle/src/src/utils/subset-loaders.ts +11 -0
  96. package/bundle/web-dist/web-dist/client/assets/index-DlPchHBY.js +116 -0
  97. package/bundle/web-dist/web-dist/client/assets/index-vZsvyuFn.css +1 -0
  98. package/bundle/web-dist/web-dist/client/assets/rolldown-runtime-Dw2cE7zH.js +1 -0
  99. package/bundle/web-dist/web-dist/client/assets/routes-CagDz23B.js +1 -0
  100. package/bundle/web-dist/web-dist/client/assets/sd.generated-BrQoQXvv.js +47 -0
  101. package/bundle/web-dist/web-dist/client/assets/services.generated-BspO2L0j.js +1 -0
  102. package/bundle/web-dist/web-dist/client/assets/show-aXUGa0gm.js +29 -0
  103. package/bundle/web-dist/web-dist/client/assets/tokens-DRkXtZ3Q.js +1 -0
  104. package/bundle/web-dist/web-dist/client/assets/vendor-react-DH4kUfK2.js +9 -0
  105. package/bundle/web-dist/web-dist/client/assets/vendor-tanstack-CUxlo6YN.js +1 -0
  106. package/bundle/web-dist/web-dist/client/index.html +18 -0
  107. package/bundle/web-dist/web-dist/server/assets/react-dom-CGIzOSuj.js +335 -0
  108. package/bundle/web-dist/web-dist/server/assets/routes-ClzReRep.js +490 -0
  109. package/bundle/web-dist/web-dist/server/assets/sd.generated-BnonqqKr.js +21694 -0
  110. package/bundle/web-dist/web-dist/server/assets/services.generated-D5ABD5fr.js +836 -0
  111. package/bundle/web-dist/web-dist/server/assets/show-C9pcdSxc.js +23364 -0
  112. package/bundle/web-dist/web-dist/server/assets/tokens-JH6FsnWZ.js +860 -0
  113. package/bundle/web-dist/web-dist/server/entry-server.generated.js +44646 -0
  114. package/package.json +10 -9
@@ -0,0 +1,490 @@
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 = 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);
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);
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 ? /* @__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),
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
+ function UsageCard() {
395
+ const [currentIndex, setCurrentIndex] = (0, import_react.useState)(0);
396
+ const { data, isLoading } = TokenService.useTokens("A");
397
+ if (isLoading) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
398
+ className: "rounded-lg bg-sand-50 px-5 py-4 animate-pulse",
399
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-3 w-20 bg-sand-200 rounded mb-3" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-2 w-full bg-sand-200 rounded-full" })]
400
+ });
401
+ const tokens = data?.rows ?? [];
402
+ if (tokens.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
403
+ className: "rounded-lg bg-sand-50 px-5 py-4",
404
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
405
+ className: "text-sand-400 text-sm",
406
+ children: "No tokens registered"
407
+ })
408
+ });
409
+ const safeIndex = Math.min(currentIndex, tokens.length - 1);
410
+ const token = tokens[safeIndex];
411
+ const hasPrev = safeIndex > 0;
412
+ const hasNext = safeIndex < tokens.length - 1;
413
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
414
+ className: "rounded-lg bg-sand-50 px-5 py-3",
415
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
416
+ className: "flex items-center justify-between mb-1",
417
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
418
+ className: "flex items-center gap-2",
419
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
420
+ className: "text-sm font-medium text-sand-800",
421
+ children: token.name ?? "Unnamed"
422
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
423
+ className: `text-[10px] px-1.5 py-0.5 rounded-full ${token.active ? "bg-sage-100 text-sage-600" : "bg-sand-200 text-sand-500"}`,
424
+ children: token.active ? "Active" : "Inactive"
425
+ })]
426
+ }), tokens.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
427
+ className: "flex items-center gap-1",
428
+ children: [
429
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
430
+ type: "button",
431
+ className: "p-0.5 rounded text-sand-400 hover:text-sand-600 disabled:opacity-30 transition-colors",
432
+ disabled: !hasPrev,
433
+ onClick: () => setCurrentIndex(safeIndex - 1),
434
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucideChevronLeft, { className: "size-4" })
435
+ }),
436
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
437
+ className: "text-[10px] text-sand-400 tabular-nums",
438
+ children: [
439
+ safeIndex + 1,
440
+ " / ",
441
+ tokens.length
442
+ ]
443
+ }),
444
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
445
+ type: "button",
446
+ className: "p-0.5 rounded text-sand-400 hover:text-sand-600 disabled:opacity-30 transition-colors",
447
+ disabled: !hasNext,
448
+ onClick: () => setCurrentIndex(safeIndex + 1),
449
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucideChevronRight, { className: "size-4" })
450
+ })
451
+ ]
452
+ })]
453
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TokenUsage, { token })]
454
+ });
455
+ }
456
+ //#endregion
457
+ //#region src/routes/index.tsx?tsr-split=component
458
+ function Dashboard() {
459
+ const { data: healthData, isLoading: healthLoading, isError: healthError } = QgridService.useHealth();
460
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
461
+ className: "space-y-5 max-w-300 mx-auto -translate-x-4",
462
+ children: [
463
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", {
464
+ className: "text-xl font-medium text-sand-900 tracking-tight",
465
+ children: "Dashboard"
466
+ }),
467
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HealthCard, {
468
+ data: healthData,
469
+ isLoading: healthLoading,
470
+ isError: healthError
471
+ }),
472
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
473
+ className: "text-[10px] uppercase tracking-wider text-sand-500 font-medium",
474
+ children: "Usage"
475
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
476
+ className: "mt-2",
477
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UsageCard, {})
478
+ })] }),
479
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
480
+ className: "text-[10px] uppercase tracking-wider text-sand-500 font-medium",
481
+ children: "Request Log"
482
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
483
+ className: "mt-2",
484
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequestLogTable, {})
485
+ })] })
486
+ ]
487
+ });
488
+ }
489
+ //#endregion
490
+ export { Dashboard as component };