hermium 0.2.0 → 0.3.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 (172) hide show
  1. package/bin/hermium.mjs +103 -58
  2. package/dist/api.mjs +35 -0
  3. package/dist/public/assets/css/styles-o9LLzp-x.css +1 -0
  4. package/dist/public/assets/js/{ChatInputBlock-Bw7AL70H.js → ChatInputBlock-BgJMx5nW.js} +1 -1
  5. package/dist/public/assets/js/{MarkdownMessage-8d7Y6VL-.js → MarkdownMessage-Dd6VsKhk.js} +1 -1
  6. package/dist/public/assets/js/{base-ui-BvQbAt_1.js → base-ui-Ls-HE_Zl.js} +1 -1
  7. package/dist/public/assets/js/{chat._sessionId-BG6lVraH.js → chat._sessionId-Yif-J0_7.js} +1 -1
  8. package/dist/public/assets/js/{chat.index-D2zdMPTT.js → chat.index-QgwoSqOs.js} +1 -1
  9. package/dist/public/assets/js/{index-C0AK45FU.js → index-BDLsrzTe.js} +26 -26
  10. package/dist/public/assets/js/{index-Cx5En4FK.js → index-DRH0t4ti.js} +1 -1
  11. package/dist/public/assets/js/{memory-CeSRdTkW.js → memory-CHpNNtU2.js} +1 -1
  12. package/dist/public/assets/js/{router-8uDKazL-.js → router-B8BATVn7.js} +1 -1
  13. package/dist/public/assets/js/{settings-Bc3Y5zXO.js → settings-CRV3Pp8x.js} +1 -1
  14. package/dist/public/assets/js/{skills-DZv7sA_5.js → skills-C8G72gXr.js} +1 -1
  15. package/dist/public/assets/js/{usage-DXQsT9_b.js → usage-Bev8hqwh.js} +1 -1
  16. package/dist/server/__23tanstack-start-plugin-adapters-Cwee5PKy.mjs +6 -0
  17. package/dist/server/_chunks/ssr-renderer.mjs +22 -0
  18. package/dist/server/_libs/bail.mjs +8 -0
  19. package/dist/server/_libs/base-ui__react.mjs +9858 -0
  20. package/dist/server/_libs/base-ui__utils.mjs +1106 -0
  21. package/dist/server/_libs/ccount.mjs +16 -0
  22. package/dist/server/_libs/character-entities.mjs +2130 -0
  23. package/dist/server/_libs/class-variance-authority.mjs +44 -0
  24. package/dist/server/_libs/clsx.mjs +16 -0
  25. package/dist/server/_libs/comma-separated-tokens.mjs +10 -0
  26. package/dist/server/_libs/cookie-es.mjs +1 -0
  27. package/dist/server/_libs/croner.mjs +1 -0
  28. package/dist/server/_libs/crossws.mjs +1 -0
  29. package/dist/server/_libs/decode-named-character-reference+[...].mjs +8 -0
  30. package/dist/server/_libs/devlop.mjs +8 -0
  31. package/dist/server/_libs/escape-string-regexp.mjs +9 -0
  32. package/dist/server/_libs/estree-util-is-identifier-name.mjs +11 -0
  33. package/dist/server/_libs/extend.mjs +97 -0
  34. package/dist/server/_libs/floating-ui__core.mjs +663 -0
  35. package/dist/server/_libs/floating-ui__dom.mjs +624 -0
  36. package/dist/server/_libs/floating-ui__react-dom.mjs +279 -0
  37. package/dist/server/_libs/floating-ui__utils.mjs +322 -0
  38. package/dist/server/_libs/h3.mjs +408 -0
  39. package/dist/server/_libs/hast-util-is-element.mjs +75 -0
  40. package/dist/server/_libs/hast-util-to-jsx-runtime.mjs +388 -0
  41. package/dist/server/_libs/hast-util-to-text.mjs +305 -0
  42. package/dist/server/_libs/hast-util-whitespace.mjs +10 -0
  43. package/dist/server/_libs/highlight.js.mjs +14756 -0
  44. package/dist/server/_libs/hookable.mjs +1 -0
  45. package/dist/server/_libs/html-url-attributes.mjs +26 -0
  46. package/dist/server/_libs/inline-style-parser.mjs +142 -0
  47. package/dist/server/_libs/is-plain-obj.mjs +10 -0
  48. package/dist/server/_libs/isbot.mjs +21 -0
  49. package/dist/server/_libs/longest-streak.mjs +25 -0
  50. package/dist/server/_libs/lowlight.mjs +262 -0
  51. package/dist/server/_libs/markdown-table.mjs +142 -0
  52. package/dist/server/_libs/mdast-util-find-and-replace.mjs +109 -0
  53. package/dist/server/_libs/mdast-util-from-markdown.mjs +717 -0
  54. package/dist/server/_libs/mdast-util-gfm-autolink-literal+[...].mjs +156 -0
  55. package/dist/server/_libs/mdast-util-gfm-footnote.mjs +117 -0
  56. package/dist/server/_libs/mdast-util-gfm-strikethrough.mjs +54 -0
  57. package/dist/server/_libs/mdast-util-gfm-table.mjs +157 -0
  58. package/dist/server/_libs/mdast-util-gfm-task-list-item.mjs +77 -0
  59. package/dist/server/_libs/mdast-util-gfm.mjs +29 -0
  60. package/dist/server/_libs/mdast-util-phrasing.mjs +30 -0
  61. package/dist/server/_libs/mdast-util-to-hast.mjs +710 -0
  62. package/dist/server/_libs/mdast-util-to-markdown.mjs +798 -0
  63. package/dist/server/_libs/mdast-util-to-string.mjs +38 -0
  64. package/dist/server/_libs/micromark-core-commonmark.mjs +2259 -0
  65. package/dist/server/_libs/micromark-extension-gfm-autolink-literal+[...].mjs +344 -0
  66. package/dist/server/_libs/micromark-extension-gfm-footnote+[...].mjs +279 -0
  67. package/dist/server/_libs/micromark-extension-gfm-strikethrough+[...].mjs +98 -0
  68. package/dist/server/_libs/micromark-extension-gfm-table.mjs +491 -0
  69. package/dist/server/_libs/micromark-extension-gfm-tagfilter+[...].mjs +1 -0
  70. package/dist/server/_libs/micromark-extension-gfm-task-list-item+[...].mjs +77 -0
  71. package/dist/server/_libs/micromark-extension-gfm.mjs +18 -0
  72. package/dist/server/_libs/micromark-factory-destination.mjs +94 -0
  73. package/dist/server/_libs/micromark-factory-label.mjs +63 -0
  74. package/dist/server/_libs/micromark-factory-space.mjs +24 -0
  75. package/dist/server/_libs/micromark-factory-title.mjs +65 -0
  76. package/dist/server/_libs/micromark-factory-whitespace.mjs +22 -0
  77. package/dist/server/_libs/micromark-util-character.mjs +44 -0
  78. package/dist/server/_libs/micromark-util-chunked.mjs +36 -0
  79. package/dist/server/_libs/micromark-util-classify-character+[...].mjs +12 -0
  80. package/dist/server/_libs/micromark-util-combine-extensions+[...].mjs +41 -0
  81. package/dist/server/_libs/micromark-util-decode-numeric-character-reference+[...].mjs +19 -0
  82. package/dist/server/_libs/micromark-util-decode-string.mjs +21 -0
  83. package/dist/server/_libs/micromark-util-encode.mjs +1 -0
  84. package/dist/server/_libs/micromark-util-html-tag-name.mjs +69 -0
  85. package/dist/server/_libs/micromark-util-normalize-identifier+[...].mjs +6 -0
  86. package/dist/server/_libs/micromark-util-resolve-all.mjs +15 -0
  87. package/dist/server/_libs/micromark-util-sanitize-uri.mjs +41 -0
  88. package/dist/server/_libs/micromark-util-subtokenize.mjs +346 -0
  89. package/dist/server/_libs/micromark.mjs +906 -0
  90. package/dist/server/_libs/ocache.mjs +1 -0
  91. package/dist/server/_libs/ohash.mjs +1 -0
  92. package/dist/server/_libs/property-information.mjs +1209 -0
  93. package/dist/server/_libs/react-dom.mjs +10779 -0
  94. package/dist/server/_libs/react-markdown.mjs +147 -0
  95. package/dist/server/_libs/react.mjs +513 -0
  96. package/dist/server/_libs/rehype-highlight.mjs +94 -0
  97. package/dist/server/_libs/remark-gfm.mjs +20 -0
  98. package/dist/server/_libs/remark-parse.mjs +19 -0
  99. package/dist/server/_libs/remark-rehype.mjs +21 -0
  100. package/dist/server/_libs/reselect.mjs +1 -0
  101. package/dist/server/_libs/rou3.mjs +8 -0
  102. package/dist/server/_libs/seroval-plugins.mjs +1 -0
  103. package/dist/server/_libs/seroval.mjs +1 -0
  104. package/dist/server/_libs/space-separated-tokens.mjs +6 -0
  105. package/dist/server/_libs/srvx.mjs +781 -0
  106. package/dist/server/_libs/style-to-js.mjs +72 -0
  107. package/dist/server/_libs/style-to-object.mjs +38 -0
  108. package/dist/server/_libs/tabler__icons-react.mjs +140 -0
  109. package/dist/server/_libs/tailwind-merge.mjs +3255 -0
  110. package/dist/server/_libs/tanstack__history.mjs +29 -0
  111. package/dist/server/_libs/tanstack__react-router.mjs +1120 -0
  112. package/dist/server/_libs/tanstack__react-store.mjs +2 -0
  113. package/dist/server/_libs/tanstack__router-core.mjs +3594 -0
  114. package/dist/server/_libs/tanstack__store.mjs +1 -0
  115. package/dist/server/_libs/trim-lines.mjs +41 -0
  116. package/dist/server/_libs/trough.mjs +85 -0
  117. package/dist/server/_libs/ufo.mjs +54 -0
  118. package/dist/server/_libs/unctx.mjs +1 -0
  119. package/dist/server/_libs/ungap__structured-clone.mjs +224 -0
  120. package/dist/server/_libs/unified.mjs +661 -0
  121. package/dist/server/_libs/unist-util-find-after.mjs +41 -0
  122. package/dist/server/_libs/unist-util-is.mjs +100 -0
  123. package/dist/server/_libs/unist-util-position.mjs +27 -0
  124. package/dist/server/_libs/unist-util-stringify-position.mjs +27 -0
  125. package/dist/server/_libs/unist-util-visit-parents.mjs +83 -0
  126. package/dist/server/_libs/unist-util-visit.mjs +24 -0
  127. package/dist/server/_libs/unstorage.mjs +1 -0
  128. package/dist/server/_libs/use-sync-external-store.mjs +139 -0
  129. package/dist/server/_libs/vfile-message.mjs +138 -0
  130. package/dist/server/_libs/vfile.mjs +467 -0
  131. package/dist/server/_libs/zustand.mjs +43 -0
  132. package/dist/server/_libs/zwitch.mjs +1 -0
  133. package/dist/server/_ssr/ChatInputBlock-Bu2-iop_.mjs +220 -0
  134. package/dist/server/_ssr/MarkdownMessage-CNS7OSKN.mjs +68 -0
  135. package/dist/server/_ssr/chat._sessionId-P02iSfut.mjs +477 -0
  136. package/dist/server/_ssr/chat.index-BYB_48NC.mjs +64 -0
  137. package/dist/server/_ssr/index-C1mT_2d8.mjs +4890 -0
  138. package/dist/server/_ssr/index-DFV9_oCk.mjs +43 -0
  139. package/dist/server/_ssr/memory-CW_fSOG9.mjs +257 -0
  140. package/dist/server/_ssr/router-CUAfx91O.mjs +2035 -0
  141. package/dist/server/_ssr/settings-DoXurzvn.mjs +10 -0
  142. package/dist/server/_ssr/skills-Cs7A5ZwO.mjs +422 -0
  143. package/dist/server/_ssr/theme-BK4-7E2h.mjs +42 -0
  144. package/dist/server/_ssr/usage-Bs2-LXGz.mjs +298 -0
  145. package/dist/server/_tanstack-start-manifest_v-C7Upe2TI.mjs +4 -0
  146. package/dist/server/index.mjs +506 -0
  147. package/dist/server/public/assets/css/index-Dfs9RUU9.css +1 -0
  148. package/dist/server/public/assets/css/styles-o9LLzp-x.css +1 -0
  149. package/dist/server/public/assets/js/ChatInputBlock-BgJMx5nW.js +1 -0
  150. package/dist/server/public/assets/js/MarkdownMessage-Dd6VsKhk.js +1 -0
  151. package/dist/server/public/assets/js/base-ui-Ls-HE_Zl.js +1 -0
  152. package/dist/server/public/assets/js/chat._sessionId-Yif-J0_7.js +1 -0
  153. package/dist/server/public/assets/js/chat.index-QgwoSqOs.js +1 -0
  154. package/dist/server/public/assets/js/index-BDLsrzTe.js +60 -0
  155. package/dist/server/public/assets/js/index-DRH0t4ti.js +1 -0
  156. package/dist/server/public/assets/js/memory-CHpNNtU2.js +3 -0
  157. package/dist/server/public/assets/js/router-B8BATVn7.js +1 -0
  158. package/dist/server/public/assets/js/settings-CRV3Pp8x.js +1 -0
  159. package/dist/server/public/assets/js/skills-C8G72gXr.js +1 -0
  160. package/dist/server/public/assets/js/theme-CPkdkpaj.js +1 -0
  161. package/dist/server/public/assets/js/usage-Bev8hqwh.js +1 -0
  162. package/dist/server/public/assets/woff2/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  163. package/dist/server/public/assets/woff2/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  164. package/dist/server/public/assets/woff2/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  165. package/dist/server/public/assets/woff2/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  166. package/dist/server/public/assets/woff2/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  167. package/dist/server/public/favicon.ico +0 -0
  168. package/dist/server/public/logo.png +0 -0
  169. package/dist/server/public/manifest.json +25 -0
  170. package/dist/server/public/robots.txt +3 -0
  171. package/package.json +4 -3
  172. package/dist/public/assets/css/styles-B8p6jk5Z.css +0 -1
@@ -0,0 +1,298 @@
1
+ import { j as jsxRuntimeExports, r as reactExports } from "../_libs/react.mjs";
2
+ import { r as request } from "./router-CUAfx91O.mjs";
3
+ import "../_libs/tanstack__react-router.mjs";
4
+ import "../_libs/tanstack__router-core.mjs";
5
+ import "../_libs/tanstack__history.mjs";
6
+ import "node:stream/web";
7
+ import "node:stream";
8
+ import "../_libs/react-dom.mjs";
9
+ import "util";
10
+ import "crypto";
11
+ import "async_hooks";
12
+ import "stream";
13
+ import "../_libs/isbot.mjs";
14
+ import "../_libs/clsx.mjs";
15
+ import "../_libs/tailwind-merge.mjs";
16
+ import "../_libs/class-variance-authority.mjs";
17
+ import "../_libs/zustand.mjs";
18
+ import "../_libs/tabler__icons-react.mjs";
19
+ import "../_libs/base-ui__react.mjs";
20
+ import "../_libs/base-ui__utils.mjs";
21
+ import "../_libs/use-sync-external-store.mjs";
22
+ import "../_libs/floating-ui__utils.mjs";
23
+ import "../_libs/floating-ui__react-dom.mjs";
24
+ import "../_libs/floating-ui__dom.mjs";
25
+ import "../_libs/floating-ui__core.mjs";
26
+ async function fetchUsageStats(days = 30) {
27
+ const params = new URLSearchParams({ days: String(days) });
28
+ return request(`/api/hermes/usage/stats?${params}`);
29
+ }
30
+ const MODEL_COLORS = ["#4fd1c5", "#63b3ed", "#f6ad55", "#b794f4", "#68d391", "#fc8181", "#f687b3", "#90cdf4", "#fbd38d", "#9ae6b4"];
31
+ function normalizeModel(model) {
32
+ return (model || "").trim() || "unknown";
33
+ }
34
+ function getModelColor(model) {
35
+ const normalized = normalizeModel(model);
36
+ let hash = 0;
37
+ for (let i = 0; i < normalized.length; i++) {
38
+ hash = (hash << 5) - hash + normalized.charCodeAt(i);
39
+ hash |= 0;
40
+ }
41
+ return MODEL_COLORS[Math.abs(hash) % MODEL_COLORS.length];
42
+ }
43
+ function formatTokens(n) {
44
+ if (n >= 1e6) return (n / 1e6).toFixed(1) + "M";
45
+ if (n >= 1e3) return (n / 1e3).toFixed(1) + "K";
46
+ return String(n);
47
+ }
48
+ function formatCost(n) {
49
+ if (n === 0) return "$0.00";
50
+ if (n < 0.01) return "<$0.01";
51
+ return "$" + n.toFixed(2);
52
+ }
53
+ function percent(part, total) {
54
+ if (total <= 0) return 0;
55
+ return part / total * 100;
56
+ }
57
+ function cacheHitRate(input, cacheRead) {
58
+ const total = input + cacheRead;
59
+ if (total === 0) return "--";
60
+ return (cacheRead / total * 100).toFixed(1) + "%";
61
+ }
62
+ function useUsageStats(days = 30) {
63
+ const [stats, setStats] = reactExports.useState(null);
64
+ const [loading, setLoading] = reactExports.useState(false);
65
+ reactExports.useEffect(() => {
66
+ setLoading(true);
67
+ fetchUsageStats(days).then(setStats).catch(console.error).finally(() => setLoading(false));
68
+ }, [days]);
69
+ return {
70
+ stats,
71
+ loading
72
+ };
73
+ }
74
+ function StatCard({
75
+ label,
76
+ value,
77
+ sub
78
+ }) {
79
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-lg border bg-card p-4", children: [
80
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground mb-1", children: label }),
81
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xl font-semibold", children: value }),
82
+ sub && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-muted-foreground mt-1", children: sub })
83
+ ] });
84
+ }
85
+ function StatCards({
86
+ stats
87
+ }) {
88
+ const totalTokens = stats.total_input_tokens + stats.total_output_tokens;
89
+ const totalCache = stats.total_cache_read_tokens;
90
+ const cacheRate = totalTokens + totalCache > 0 ? (totalCache / (stats.total_input_tokens + totalCache) * 100).toFixed(1) + "%" : "--";
91
+ const daysWithActivity = stats.daily_usage.filter((d) => d.sessions > 0).length;
92
+ const avgPerDay = daysWithActivity > 0 ? (stats.total_sessions / daysWithActivity).toFixed(1) : "0.0";
93
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-3 mb-5", children: [
94
+ /* @__PURE__ */ jsxRuntimeExports.jsx(StatCard, { label: "Total Tokens", value: formatTokens(totalTokens), sub: `${formatTokens(stats.total_input_tokens)} input / ${formatTokens(stats.total_output_tokens)} output` }),
95
+ /* @__PURE__ */ jsxRuntimeExports.jsx(StatCard, { label: "Total Sessions", value: String(stats.total_sessions), sub: `${avgPerDay} avg/day` }),
96
+ /* @__PURE__ */ jsxRuntimeExports.jsx(StatCard, { label: "Estimated Cost", value: formatCost(stats.total_cost ?? 0) }),
97
+ /* @__PURE__ */ jsxRuntimeExports.jsx(StatCard, { label: "Cache Hit Rate", value: cacheRate, sub: totalCache > 0 ? `${formatTokens(totalCache)} tokens` : void 0 })
98
+ ] });
99
+ }
100
+ function DailyTrend({
101
+ stats
102
+ }) {
103
+ const daily = reactExports.useMemo(() => {
104
+ return (stats.daily_usage ?? []).map((d) => {
105
+ const visual = d.input_tokens + d.output_tokens + d.cache_read_tokens;
106
+ return {
107
+ ...d,
108
+ visualTokens: visual,
109
+ inputPercent: percent(d.input_tokens, visual),
110
+ outputPercent: percent(d.output_tokens, visual),
111
+ cachePercent: percent(d.cache_read_tokens, visual)
112
+ };
113
+ });
114
+ }, [stats]);
115
+ const maxTokens = reactExports.useMemo(() => Math.max(...daily.map((d) => d.visualTokens), 1), [daily]);
116
+ if (daily.length === 0) return null;
117
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-lg border bg-card p-4 mb-5", children: [
118
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-semibold text-secondary-foreground mb-3", children: "Daily Trend" }),
119
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex gap-0.5 mb-2", children: daily.map((d) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0 flex flex-col items-center relative group", children: [
120
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-full h-36 bg-muted/40 rounded-t-sm flex items-end overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full flex flex-col-reverse justify-start transition-all", style: {
121
+ height: `${d.visualTokens / maxTokens * 100}%`
122
+ }, children: [
123
+ d.output_tokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-full bg-emerald-500/80", style: {
124
+ height: `${d.outputPercent}%`
125
+ } }),
126
+ d.input_tokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-full bg-indigo-500/80", style: {
127
+ height: `${d.inputPercent}%`
128
+ } }),
129
+ d.cache_read_tokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-full bg-amber-400/80", style: {
130
+ height: `${d.cachePercent}%`
131
+ } })
132
+ ] }) }),
133
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "hidden group-hover:block absolute bottom-[calc(100%+8px)] left-1/2 -translate-x-1/2 bg-popover text-popover-foreground text-[11px] whitespace-nowrap z-10 rounded-md border px-2 py-1.5 shadow-md", children: [
134
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-semibold mb-0.5", children: d.date }),
135
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
136
+ "Input: ",
137
+ formatTokens(d.input_tokens)
138
+ ] }),
139
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
140
+ "Output: ",
141
+ formatTokens(d.output_tokens)
142
+ ] }),
143
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
144
+ "Cache read: ",
145
+ formatTokens(d.cache_read_tokens)
146
+ ] }),
147
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
148
+ "Cache write: ",
149
+ formatTokens(d.cache_write_tokens)
150
+ ] }),
151
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
152
+ "Hit rate: ",
153
+ cacheHitRate(d.input_tokens, d.cache_read_tokens)
154
+ ] }),
155
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
156
+ "Sessions: ",
157
+ d.sessions
158
+ ] }),
159
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
160
+ "Cost: ",
161
+ formatCost(d.cost ?? 0)
162
+ ] })
163
+ ] })
164
+ ] }, d.date)) }),
165
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-[10px] text-muted-foreground mb-3", children: [
166
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: daily[0]?.date.slice(5) }),
167
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: daily[daily.length - 1]?.date.slice(5) })
168
+ ] }),
169
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap gap-x-3 gap-y-1 text-[11px] text-muted-foreground mb-4", children: [
170
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1", children: [
171
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-2 h-2 rounded-sm bg-indigo-500/80" }),
172
+ " Input"
173
+ ] }),
174
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1", children: [
175
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-2 h-2 rounded-sm bg-emerald-500/80" }),
176
+ " Output"
177
+ ] }),
178
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1", children: [
179
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-2 h-2 rounded-sm bg-amber-400/80" }),
180
+ " Cache read"
181
+ ] })
182
+ ] }),
183
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("table", { className: "w-full text-[11px] border-collapse", children: [
184
+ /* @__PURE__ */ jsxRuntimeExports.jsx("thead", { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { className: "text-muted-foreground text-left", children: [
185
+ /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "pb-1.5 pr-2 font-medium", children: "Date" }),
186
+ /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "pb-1.5 pr-2 font-medium text-right", children: "Input" }),
187
+ /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "pb-1.5 pr-2 font-medium text-right", children: "Output" }),
188
+ /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "pb-1.5 pr-2 font-medium text-right", children: "Cache read" }),
189
+ /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "pb-1.5 pr-2 font-medium text-right", children: "Cache write" }),
190
+ /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "pb-1.5 pr-2 font-medium text-right", children: "Hit rate" }),
191
+ /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "pb-1.5 pr-2 font-medium text-right", children: "Sessions" }),
192
+ /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "pb-1.5 pr-2 font-medium text-right", children: "Cost" })
193
+ ] }) }),
194
+ /* @__PURE__ */ jsxRuntimeExports.jsx("tbody", { children: [...daily].reverse().map((d) => /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { className: "border-t", children: [
195
+ /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1.5 pr-2", children: d.date }),
196
+ /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1.5 pr-2 text-right", children: formatTokens(d.input_tokens) }),
197
+ /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1.5 pr-2 text-right", children: formatTokens(d.output_tokens) }),
198
+ /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1.5 pr-2 text-right", children: formatTokens(d.cache_read_tokens) }),
199
+ /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1.5 pr-2 text-right", children: formatTokens(d.cache_write_tokens) }),
200
+ /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1.5 pr-2 text-right", children: cacheHitRate(d.input_tokens, d.cache_read_tokens) }),
201
+ /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1.5 pr-2 text-right", children: d.sessions }),
202
+ /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1.5 pr-2 text-right", children: formatCost(d.cost ?? 0) })
203
+ ] }, d.date)) })
204
+ ] }) })
205
+ ] });
206
+ }
207
+ function ModelBreakdown({
208
+ stats
209
+ }) {
210
+ const models = reactExports.useMemo(() => {
211
+ return (stats.model_usage ?? []).map((m) => {
212
+ const total = m.input_tokens + m.output_tokens;
213
+ const visual = total + m.cache_read_tokens;
214
+ return {
215
+ model: normalizeModel(m.model),
216
+ inputTokens: m.input_tokens,
217
+ outputTokens: m.output_tokens,
218
+ cacheTokens: m.cache_read_tokens,
219
+ cacheWriteTokens: m.cache_write_tokens,
220
+ totalTokens: total,
221
+ visualTokens: visual,
222
+ sessions: m.sessions,
223
+ color: getModelColor(m.model),
224
+ inputPercent: percent(m.input_tokens, visual),
225
+ outputPercent: percent(m.output_tokens, visual),
226
+ cachePercent: percent(m.cache_read_tokens, visual)
227
+ };
228
+ }).sort((a, b) => b.visualTokens - a.visualTokens);
229
+ }, [stats]);
230
+ const maxTokens = reactExports.useMemo(() => Math.max(...models.map((m) => m.visualTokens), 1), [models]);
231
+ if (models.length === 0) return null;
232
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-lg border bg-card p-4 mb-5", children: [
233
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-semibold text-secondary-foreground mb-3", children: "Model Breakdown" }),
234
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap gap-x-3 gap-y-1 text-[11px] text-muted-foreground mb-3", children: [
235
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1", children: [
236
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-2 h-2 rounded-sm bg-indigo-500/80" }),
237
+ " Input"
238
+ ] }),
239
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1", children: [
240
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-2 h-2 rounded-sm bg-emerald-500/80" }),
241
+ " Output"
242
+ ] }),
243
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1", children: [
244
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-2 h-2 rounded-sm bg-amber-400/80" }),
245
+ " Cache read"
246
+ ] })
247
+ ] }),
248
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-col gap-2", children: models.map((m) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2.5", children: [
249
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-2 h-2 rounded-sm shrink-0", style: {
250
+ background: m.color
251
+ } }),
252
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-mono text-secondary-foreground w-32 shrink-0 truncate", title: m.model, children: m.model }),
253
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 h-4 bg-muted/40 rounded-sm overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-full flex min-w-[2px] transition-all", style: {
254
+ width: `${m.visualTokens / maxTokens * 100}%`
255
+ }, children: [
256
+ m.inputTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full bg-indigo-500/80", style: {
257
+ width: `${m.inputPercent}%`
258
+ } }),
259
+ m.outputTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full bg-emerald-500/80", style: {
260
+ width: `${m.outputPercent}%`
261
+ } }),
262
+ m.cacheTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full bg-amber-400/80", style: {
263
+ width: `${m.cachePercent}%`
264
+ } })
265
+ ] }) }),
266
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs text-muted-foreground w-20 text-right shrink-0", children: [
267
+ formatTokens(m.totalTokens),
268
+ m.cacheTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] text-amber-500 ml-1", children: [
269
+ "+",
270
+ formatTokens(m.cacheTokens)
271
+ ] })
272
+ ] })
273
+ ] }, m.model)) })
274
+ ] });
275
+ }
276
+ function UsagePage() {
277
+ const {
278
+ stats,
279
+ loading
280
+ } = useUsageStats(30);
281
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto p-4 md:p-6", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mx-auto max-w-5xl", children: [
282
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("header", { className: "mb-5", children: [
283
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { className: "text-lg font-semibold", children: "Usage" }),
284
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-muted-foreground", children: "Token consumption and cost estimates over the last 30 days." })
285
+ ] }),
286
+ loading && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm text-muted-foreground py-8", children: "Loading usage stats…" }),
287
+ !loading && !stats && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm text-muted-foreground py-8", children: "Failed to load usage data." }),
288
+ !loading && stats && stats.total_sessions === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm text-muted-foreground py-8", children: "No usage data yet." }),
289
+ !loading && stats && stats.total_sessions > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
290
+ /* @__PURE__ */ jsxRuntimeExports.jsx(StatCards, { stats }),
291
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ModelBreakdown, { stats }),
292
+ /* @__PURE__ */ jsxRuntimeExports.jsx(DailyTrend, { stats })
293
+ ] })
294
+ ] }) });
295
+ }
296
+ export {
297
+ UsagePage as component
298
+ };
@@ -0,0 +1,4 @@
1
+ const tsrStartManifest = () => ({ routes: { __root__: { filePath: "/home/abbskhnv/Desktop/hermium-new/packages/web/src/routes/__root.tsx", children: ["/", "/memory", "/settings", "/skills", "/usage", "/chat/$sessionId", "/chat/"], assets: [{ tag: "link", attrs: { rel: "stylesheet", href: "/assets/css/index-Dfs9RUU9.css", type: "text/css" } }], preloads: ["/assets/js/index-BDLsrzTe.js", "/assets/js/base-ui-Ls-HE_Zl.js", "/assets/js/router-B8BATVn7.js"] }, "/": { filePath: "/home/abbskhnv/Desktop/hermium-new/packages/web/src/routes/index.tsx", children: void 0, assets: [], preloads: ["/assets/js/index-DRH0t4ti.js", "/assets/js/ChatInputBlock-BgJMx5nW.js"] }, "/memory": { filePath: "/home/abbskhnv/Desktop/hermium-new/packages/web/src/routes/memory.tsx", children: void 0, assets: [], preloads: ["/assets/js/memory-CHpNNtU2.js", "/assets/js/MarkdownMessage-Dd6VsKhk.js"] }, "/settings": { filePath: "/home/abbskhnv/Desktop/hermium-new/packages/web/src/routes/settings.tsx", children: void 0, assets: [], preloads: ["/assets/js/settings-CRV3Pp8x.js"] }, "/skills": { filePath: "/home/abbskhnv/Desktop/hermium-new/packages/web/src/routes/skills.tsx", children: void 0, assets: [], preloads: ["/assets/js/skills-C8G72gXr.js", "/assets/js/MarkdownMessage-Dd6VsKhk.js"] }, "/usage": { filePath: "/home/abbskhnv/Desktop/hermium-new/packages/web/src/routes/usage.tsx", children: void 0, assets: [], preloads: ["/assets/js/usage-Bev8hqwh.js"] }, "/chat/$sessionId": { filePath: "/home/abbskhnv/Desktop/hermium-new/packages/web/src/routes/chat.$sessionId.tsx", children: void 0, assets: [], preloads: ["/assets/js/chat._sessionId-Yif-J0_7.js", "/assets/js/MarkdownMessage-Dd6VsKhk.js", "/assets/js/ChatInputBlock-BgJMx5nW.js"] }, "/chat/": { filePath: "/home/abbskhnv/Desktop/hermium-new/packages/web/src/routes/chat.index.tsx", children: void 0, assets: [], preloads: ["/assets/js/chat.index-QgwoSqOs.js"] } }, clientEntry: "/assets/js/index-BDLsrzTe.js" });
2
+ export {
3
+ tsrStartManifest
4
+ };