@krtclcdy/tersio 2.22.0 → 2.23.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 (47) hide show
  1. package/README.md +38 -30
  2. package/cli/common.js +43 -39
  3. package/cli/currency.js +2 -2
  4. package/cli/dashboard.js +60 -116
  5. package/cli/doctor-fix.js +35 -29
  6. package/cli/doctor.js +26 -15
  7. package/cli/install.js +15 -34
  8. package/cli/profile.js +2 -1
  9. package/cli/settings.js +6 -6
  10. package/cli/update.js +12 -11
  11. package/cli/usage.js +6 -1
  12. package/dashboard/dist/index.html +65 -0
  13. package/extensions/ai-addons-updater/index.js +7 -3
  14. package/extensions/ai-addons-updater/index.ts +15 -3
  15. package/extensions/caveman-session/index.js +17 -12
  16. package/extensions/caveman-session/index.ts +17 -12
  17. package/extensions/caveman-session/rule.md +90 -0
  18. package/extensions/combo-toggle/index.js +22 -2
  19. package/extensions/combo-toggle/index.ts +26 -2
  20. package/extensions/lib/utils.js +20 -4
  21. package/extensions/lib/utils.ts +18 -4
  22. package/extensions/rtk-session/index.js +11 -10
  23. package/extensions/rtk-session/index.ts +10 -11
  24. package/extensions/shared/plugin-settings.js +37 -3
  25. package/extensions/shared/plugin-settings.ts +34 -3
  26. package/extensions/shared/rtk-gain.js +2 -2
  27. package/extensions/shared/rtk-gain.ts +3 -3
  28. package/extensions/shared/session-state.js +5 -3
  29. package/extensions/shared/session-state.ts +4 -3
  30. package/extensions/shared/types.ts +5 -0
  31. package/extensions/shared/usage-ledger.js +114 -4
  32. package/extensions/shared/usage-ledger.ts +122 -4
  33. package/extensions/tersio-commands/index.js +10 -13
  34. package/extensions/tersio-commands/index.ts +10 -13
  35. package/package.json +21 -12
  36. package/tersio.js +10 -10
  37. package/dashboard/charts.js +0 -1208
  38. package/dashboard/core.js +0 -357
  39. package/dashboard/settings.js +0 -166
  40. package/dashboard/share.js +0 -218
  41. package/dashboard/styles.css +0 -379
  42. package/dashboard/template.html +0 -515
  43. package/extensions/shared/mode-reinforcement.ts +0 -29
  44. package/gain/dist/brand.webp +0 -0
  45. package/gain/dist/index.html +0 -65
  46. package/gain/dist/vite.svg +0 -1
  47. /package/dashboard/{brand.webp → dist/brand.webp} +0 -0
@@ -1,515 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="color-scheme" content="dark light">
7
- <script>(function(){try{var t=localStorage.getItem('tersio-theme');if(t==='light'||t==='dark')document.documentElement.setAttribute('data-theme',t);else document.documentElement.removeAttribute('data-theme');}catch(e){}})();</script>
8
- <title>Tersio Dashboard</title>
9
- <link rel="icon" type="image/png" href="brand.webp">
10
- <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
11
- <script src="https://unpkg.com/lucide@latest"></script>
12
- <script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
13
- <script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/ScrollTrigger.min.js"></script>
14
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/outfit@5/index.css">
15
- <link rel="stylesheet" href="styles.css">
16
- </head>
17
- <body class="min-h-[100dvh] antialiased">
18
- <div class="bg-blueprint pointer-events-none fixed inset-0" aria-hidden="true"></div>
19
-
20
- <main class="overflow-x-clip w-full max-w-full">
21
- <div class="relative mx-auto max-w-7xl px-4 sm:px-6 pb-16">
22
- <!-- Scroll progress rail: fixed left ticks, accent fill by scroll fraction -->
23
- <nav id="rail" class="rail hidden md:flex" aria-label="Scroll progress"></nav>
24
-
25
- <!-- Floating dock navbar -->
26
- <header class="dock mt-4 flex w-full items-center gap-2 px-3 py-2">
27
- <a href="#" class="flex shrink-0 items-center gap-2.5 pl-1 pr-2" aria-label="Tersio dashboard home">
28
- <img src="brand.webp" alt="Tersio" width="32" height="32" class="brand size-8 rounded-full">
29
- <span class="leading-tight text-left">
30
- <span class="block font-bold tracking-tight text-sm">TERSIO DASHBOARD</span>
31
- <span class="mono block text-[11px]" style="color: var(--dim)">live token number feed</span>
32
- </span>
33
- </a>
34
- <span class="mono hidden shrink-0 sm:flex items-center gap-2 text-xs px-2 ml-auto" style="color: var(--dim)">
35
- <span class="live-dot inline-block size-2 rounded-full"></span>
36
- <span id="clock">--:--</span>
37
- </span>
38
- <span class="hidden sm:block w-px h-5 shrink-0" style="background: var(--line)" aria-hidden="true"></span>
39
- <button id="shareBtn" class="btn-push flex shrink-0 items-center p-2 rounded-xl" style="border: 1px solid var(--line); color: var(--ink)" aria-label="Share your usage">
40
- <i data-lucide="share-2" class="size-4"></i>
41
- </button>
42
- <button id="settingsBtn" class="btn-push flex shrink-0 items-center p-2 rounded-xl" style="border: 1px solid var(--line); color: var(--ink)" aria-label="Open settings">
43
- <i data-lucide="settings" class="size-4"></i>
44
- </button>
45
- </header>
46
-
47
- <!-- Settings modal (ChatGPT pattern): sidebar nav + content panes -->
48
- <dialog id="settings" class="dlg setdlg" aria-labelledby="settingsTitle">
49
- <div class="set-shell">
50
- <aside class="set-side" aria-label="Settings sections">
51
- <div class="set-search">
52
- <i data-lucide="search" class="size-4"></i>
53
- <input id="setSearch" type="search" placeholder="Search settings" aria-label="Search settings" autocomplete="off">
54
- </div>
55
- <nav class="set-nav" id="setNav" aria-label="Settings">
56
- <button class="set-navitem on" data-pane="general"><i data-lucide="settings" class="size-4"></i><span>General</span></button>
57
- <button class="set-navitem" data-pane="connection"><i data-lucide="plug" class="size-4"></i><span>Connection</span></button>
58
- <button class="set-navitem" data-pane="diagnosis"><i data-lucide="stethoscope" class="size-4"></i><span>Diagnosis</span></button>
59
- <button class="set-navitem" data-pane="data"><i data-lucide="database" class="size-4"></i><span>Data</span></button>
60
- </nav>
61
- <p class="mono set-ver" id="verChip">tersio</p>
62
- </aside>
63
- <div class="set-main">
64
- <div class="set-head">
65
- <p class="dlg-title" id="settingsTitle">General</p>
66
- <button id="settingsClose" class="btn-push flex shrink-0 items-center p-2 rounded-xl" style="border: 1px solid var(--line); color: var(--ink)" aria-label="Close settings">
67
- <i data-lucide="x" class="size-4"></i>
68
- </button>
69
- </div>
70
- <div class="set-panes">
71
- <section class="set-pane on" data-pane="general" aria-label="General">
72
- <p class="dlg-label">Appearance</p>
73
- <div class="dlg-row">
74
- <div class="min-w-0">
75
- <p class="dlg-name">Theme</p>
76
- <p class="dlg-hint">Light, dark, or follow the system.</p>
77
- </div>
78
- <div class="seg mono text-xs flex items-center gap-1 p-1 rounded-[10px]" style="border: 1px solid var(--line); background: var(--panel)" role="tablist" aria-label="Theme">
79
- <button data-theme-val="light" class="px-2.5 py-1.5" role="tab" aria-label="Light" title="Light"><i data-lucide="sun" class="size-4"></i></button>
80
- <button data-theme-val="dark" class="px-2.5 py-1.5" role="tab" aria-label="Dark" title="Dark"><i data-lucide="moon" class="size-4"></i></button>
81
- <button data-theme-val="system" class="px-2.5 py-1.5" role="tab" aria-label="System" title="System"><i data-lucide="monitor" class="size-4"></i></button>
82
- </div>
83
- </div>
84
- <div class="dlg-row">
85
- <div class="min-w-0">
86
- <p class="dlg-name">Currency</p>
87
- <p class="dlg-hint">Display currency for cost figures. Persists to tersio settings.</p>
88
- </div>
89
- <span class="selwrap">
90
- <button id="setCurBtn" class="selbtn mono" aria-haspopup="listbox" aria-expanded="false"><span id="setCurLabel">USD</span><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg></button>
91
- <span id="setCurPanel" class="selpanel hidden" role="listbox" aria-label="Display currency"></span>
92
- </span>
93
- </div>
94
- </section>
95
- <section class="set-pane" data-pane="connection" aria-label="Connection">
96
- <div class="set-list" id="setHealth"></div>
97
- </section>
98
- <section class="set-pane" data-pane="diagnosis" aria-label="Diagnosis">
99
- <p class="dlg-hint set-note">What works and what does not. Repair with <span class="mono">tersio doctor --fix</span>.</p>
100
- <div class="dlg-row">
101
- <div class="min-w-0">
102
- <p class="dlg-name">Auto-check</p>
103
- <p class="dlg-hint" id="setDiagChecked">Never checked.</p>
104
- </div>
105
- <span class="selwrap">
106
- <button id="setSchedBtn" class="selbtn mono" aria-haspopup="listbox" aria-expanded="false"><span id="setSchedLabel">Manual</span><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg></button>
107
- <span id="setSchedPanel" class="selpanel hidden" role="listbox" aria-label="Diagnosis schedule"></span>
108
- </span>
109
- </div>
110
- <div class="dlg-row">
111
- <div class="min-w-0">
112
- <p class="dlg-name">Scan</p>
113
- <p class="dlg-hint">Runs every check fresh and refreshes the list below.</p>
114
- </div>
115
- <button id="setDiagRefresh" class="btn-push mono flex shrink-0 items-center gap-2 text-xs pl-2.5 pr-3 py-2 rounded-xl" style="border: 1px solid var(--line); color: var(--ink)" aria-label="Scan now">
116
- <i data-lucide="scan-line" class="size-3.5"></i><span>Scan</span>
117
- </button>
118
- </div>
119
- <div class="set-list" id="setDoctor"></div>
120
- <div class="set-fixbox">
121
- <div class="min-w-0">
122
- <p class="dlg-name">Fix issues</p>
123
- <p class="dlg-hint">Repairs extension files, config registrations, and the bundled ponytail copy. RTK binary and CLI update stay manual.</p>
124
- </div>
125
- <button id="setFixIssues" class="btn-push mono flex shrink-0 items-center gap-2 text-xs pl-2.5 pr-3 py-2 rounded-xl" style="border: 1px solid var(--line); color: var(--ink)" aria-label="Fix diagnosed issues">
126
- <i data-lucide="wrench" class="size-3.5"></i><span id="setFixLabel">Fix issues</span>
127
- </button>
128
- </div>
129
- </section>
130
- </section>
131
- <section class="set-pane" data-pane="data" aria-label="Data">
132
- <div class="dlg-row">
133
- <div class="min-w-0">
134
- <p class="dlg-name">Reload</p>
135
- <p class="dlg-hint">Re-read statistics from disk.</p>
136
- </div>
137
- <button id="reload" class="btn-push mono flex shrink-0 items-center gap-2 text-xs pl-2.5 pr-3 py-2 rounded-xl" style="border: 1px solid var(--line); color: var(--ink)" aria-label="Reload data">
138
- <i data-lucide="refresh-cw" class="size-3.5"></i><span>Reload</span>
139
- </button>
140
- </div>
141
- <div class="dlg-paths">
142
- <div class="dlg-path">
143
- <p class="dlg-name">Usage DB <span class="dlg-own">tersio-owned · local hosted</span></p>
144
- <p class="mono dlg-file" id="pathUsageDb" title="">–</p>
145
- </div>
146
- </div>
147
- <div class="dlg-danger">
148
- <p class="dlg-label">Danger zone</p>
149
- <div class="dlg-row">
150
- <div class="min-w-0">
151
- <p class="dlg-name">Reset statistics</p>
152
- <p class="dlg-hint">Clears tersio statistics. Host-owned files stay intact. Click twice to confirm.</p>
153
- </div>
154
- <button id="reset" class="btn-push mono flex shrink-0 items-center gap-2 text-xs pl-2.5 pr-3 py-2 rounded-xl" style="border: 1px solid var(--danger-border)" aria-label="Reset tersio statistics">
155
- <i data-lucide="rotate-ccw" class="size-3.5"></i><span id="resetLabel">Reset</span>
156
- </button>
157
- </div>
158
- </div>
159
- </section>
160
- </div>
161
- </div>
162
- </div>
163
- </dialog>
164
-
165
- <!-- Model detail dialog (shadcn chart language, native modal): kpi strip,
166
- gradient area chart with range tabs, rounded bars, token-mix donut. -->
167
- <dialog id="modelDialog" class="dlg mdlg" aria-labelledby="mdTitle">
168
- <div class="dlg-head">
169
- <div class="min-w-0 flex items-center gap-3">
170
- <span id="mdBadge"></span>
171
- <div class="min-w-0">
172
- <p class="dlg-title truncate" id="mdTitle">Model</p>
173
- <p class="dlg-desc mono" id="mdSub">–</p>
174
- </div>
175
- </div>
176
- <div class="flex shrink-0 items-center gap-2">
177
- <span class="md-rankpill mono" id="mdRank">#–</span>
178
- <button id="mdClose" class="btn-push flex shrink-0 items-center p-2 rounded-xl" style="border: 1px solid var(--line); color: var(--ink)" aria-label="Close model details">
179
- <i data-lucide="x" class="size-4"></i>
180
- </button>
181
- </div>
182
- </div>
183
- <div class="md-body">
184
- <div class="md-kpis" id="mdKpis"></div>
185
- <div class="md-chart">
186
- <div class="md-chart-head">
187
- <div class="min-w-0">
188
- <p class="md-chart-title">Token volume</p>
189
- <p class="md-chart-sub mono" id="mdMomRange">–</p>
190
- </div>
191
- <div class="flex shrink-0 items-center gap-2">
192
- <span class="md-trend mono" id="mdTrend"></span>
193
- <span class="seg mono text-xs flex items-center gap-1 p-1 rounded-[10px]" style="border: 1px solid var(--line)" role="group" aria-label="Chart range">
194
- <button data-mdspan="30" class="px-2.5 py-1" role="button">30D</button>
195
- <button data-mdspan="90" class="px-2.5 py-1" role="button">90D</button>
196
- <button data-mdspan="all" class="on px-2.5 py-1" role="button">ALL</button>
197
- </span>
198
- </div>
199
- </div>
200
- <svg id="mdSpark" viewBox="0 0 560 190" preserveAspectRatio="none" aria-hidden="true"></svg>
201
- <div class="md-tip mono" id="mdTip"></div>
202
- <div class="md-months mono" id="mdMonths" aria-hidden="true"></div>
203
- </div>
204
- <div class="md-cols">
205
- <div class="md-chart">
206
- <div class="md-chart-head">
207
- <div class="min-w-0">
208
- <p class="md-chart-title">Daily activity</p>
209
- <p class="md-chart-sub mono" id="mdBarsSub">tokens per day</p>
210
- </div>
211
- <span class="md-trend mono" id="mdActive"></span>
212
- </div>
213
- <div class="md-bars" id="mdBars" aria-hidden="true"></div>
214
- <div class="md-months mono" id="mdBarsMonths" aria-hidden="true"></div>
215
- <div class="md-note mono" id="mdBarsNote"></div>
216
- </div>
217
- <div class="md-chart">
218
- <div class="md-chart-head">
219
- <div class="min-w-0">
220
- <p class="md-chart-title">Token mix</p>
221
- <p class="md-chart-sub mono">input vs output vs cache</p>
222
- </div>
223
- </div>
224
- <div class="md-donut-wrap">
225
- <svg id="mdMix" viewBox="0 0 140 140" aria-hidden="true"></svg>
226
- <div class="md-donut-center"><p class="mono" id="mdMixTotal">–</p></div>
227
- </div>
228
- <div class="md-legend mono" id="mdMixLegend"></div>
229
- </div>
230
- </div>
231
- <div class="md-grid" id="mdStats"></div>
232
- </div>
233
- </dialog>
234
-
235
- <!-- Hero: centered total -->
236
- <section class="mx-auto max-w-6xl text-center pt-14 pb-10 relative">
237
- <div class="hero-glow" aria-hidden="true"></div>
238
- <p class="hero-in mono text-[11px] uppercase tracking-[0.22em] mb-4 relative" style="color: var(--accent)">Live token feed</p>
239
- <p class="hero-in mono font-bold tracking-tighter leading-none text-7xl md:text-8xl relative herototal" id="total">0</p>
240
- <div class="hero-in relative mt-6 overflow-hidden" aria-hidden="true" style="mask-image: linear-gradient(90deg, transparent, black 12%, black 88%, transparent)">
241
- <div class="ticker mono text-xs whitespace-nowrap inline-block" id="ticker" style="color: var(--dim)"></div>
242
- </div>
243
- </section>
244
-
245
- <!-- Savings bento: big USD card + nested right rail -->
246
- <section class="grid grid-cols-12 grid-flow-dense gap-3" aria-label="Savings">
247
- <div class="rise col-span-12 lg:col-span-7 lg:row-span-2 rounded-xl p-6 flex flex-col justify-between" style="border: 1px solid var(--line); background: var(--panel)">
248
- <div>
249
- <div class="flex items-center justify-between gap-2">
250
- <p class="mono text-[11px] uppercase tracking-[0.14em]" style="color: var(--dim)" id="costLabel">usd cost</p>
251
- <span class="relative">
252
- <button id="fxBtn" class="pill mono fxbtn" aria-haspopup="listbox" aria-expanded="false"><span id="fxCur">🇺🇸 USD</span><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg></button>
253
- <div id="fxPanel" class="fxpanel hidden" role="listbox" aria-label="Display currency"></div>
254
- </span>
255
- </div>
256
- <p class="mono font-bold tracking-tighter leading-none mt-2 text-6xl lg:text-7xl" id="usd">-</p>
257
- </div>
258
- <div class="mt-4">
259
- <div class="spark h-16" id="usdSpark"></div>
260
- <div class="flex gap-4 mt-3 mono text-xs" style="color: var(--dim)">
261
- <span>avg <span id="usdPerDay" style="color: var(--ink)">-</span>/day</span>
262
- <span>top <span id="usdTopDay" style="color: var(--ink)">-</span></span>
263
- <span title="Cache savings per $1 spent, vs full input price">x<span id="usdLeverage" style="color: var(--accent)">-</span> cache leverage</span>
264
- </div>
265
- </div>
266
- <p class="mono text-[11px] mt-3" style="color: var(--dim)" id="usdNote">per-model price table</p>
267
- </div>
268
- <div class="col-span-12 lg:col-span-5 lg:row-span-2 grid grid-cols-2 grid-flow-dense gap-3 h-full grid-rows-[auto_1fr]">
269
- <div class="rise col-span-2 rounded-xl p-5" style="border: 1px solid var(--line); background: var(--panel)">
270
- <div class="flex items-center justify-between gap-2">
271
- <div><p class="mono text-[11px] uppercase tracking-[0.14em]" style="color: var(--dim)">saved by cache</p>
272
- <p class="mono font-bold text-3xl mt-1" style="color: var(--accent)" id="saved">-</p></div>
273
- <span class="pill flat mono" title="Modeled estimate, not measured">est.</span>
274
- </div>
275
- <p class="mono text-[11px] mt-2" style="color: var(--dim)">est. vs full input price</p>
276
- </div>
277
- <div class="rise col-span-1 rounded-xl p-5" style="border: 1px solid var(--line); background: var(--panel)">
278
- <div class="flex items-center justify-between gap-2">
279
- <div><p class="mono text-[11px] uppercase tracking-[0.14em]" style="color: var(--dim)">co2</p>
280
- <p class="mono font-bold text-3xl mt-1" id="co2">-</p>
281
- <p class="mt-2"><span class="pill flat mono" title="Single-stream ceiling divided by 32-way served concurrency">served ÷32</span></p></div>
282
- </div>
283
- <p class="mono text-[11px] mt-2" style="color: var(--dim)">est. from output</p>
284
- </div>
285
- <div class="rise col-span-1 rounded-xl p-5" style="border: 1px solid var(--line); background: var(--panel)">
286
- <div class="flex items-center justify-between gap-2">
287
- <div><p class="mono text-[11px] uppercase tracking-[0.14em]" style="color: var(--dim)">cache share</p>
288
- <p class="mono font-bold text-3xl mt-1" id="cacheShare">-</p>
289
- <p class="mt-2"><span class="pill good mono" id="cacheDelta">-</span></p></div>
290
- </div>
291
- <p class="mono text-[11px] mt-2" style="color: var(--dim)">of tokens cached</p>
292
- </div>
293
- </div>
294
- </section>
295
-
296
- <!-- Token strip: nonzero buckets only -->
297
- <section class="rise mt-3 flex rounded-xl overflow-hidden" style="border: 1px solid var(--line); background: var(--panel)" id="tokens" aria-label="Tokens by bucket"></section>
298
-
299
- <!-- Activity: full-width year heatmap -->
300
- <section id="activity" class="rise mt-8" style="scroll-margin-top: 90px" aria-label="Activity graph">
301
- <div class="flex items-center gap-2 mb-1">
302
- <i data-lucide="calendar-days" class="size-4" style="color: var(--accent)"></i>
303
- <h2 class="display font-bold tracking-tight text-xl truncate min-w-0">Activity</h2>
304
- <div class="seg mono text-xs flex items-center gap-1 ml-auto p-1 rounded-[10px]" style="border: 1px solid var(--line); background: var(--panel)" role="tablist" aria-label="Graph range">
305
- <button data-gmode="daily" class="on px-3 py-1.5" role="tab">Daily</button>
306
- <button data-gmode="weekly" class="px-3 py-1.5" role="tab">Weekly</button>
307
- <button data-gmode="cumulative" class="px-3 py-1.5" role="tab">Cumulative</button>
308
- </div>
309
- </div>
310
- <p class="mono text-xs mb-4 truncate" style="color: var(--dim)"><span id="graphRange"></span> · <span id="graphCap">daily values / trailing 12 months</span></p>
311
- <div class="rounded-xl p-5 overflow-hidden" style="border: 1px solid var(--line); background: var(--panel)">
312
- <div class="pb-1">
313
- <div class="grid w-full" style="grid-template-columns: repeat(53, minmax(0, 1fr)); gap: 3px;" id="graph"></div>
314
- </div>
315
- <div class="mono text-[11px] mt-3 flex items-center gap-1.5" style="color: var(--dim)">
316
- <span>less</span>
317
- <span class="cell key"></span><span class="cell key l1"></span><span class="cell key l2"></span><span class="cell key l3"></span><span class="cell key l4"></span>
318
- <span>more</span>
319
- </div>
320
- <div class="heatmonth mono mt-2 grid w-full" style="color: var(--dim); grid-template-columns: repeat(53, minmax(0, 1fr)); gap: 3px;" id="graphMonths"></div>
321
- <div id="emptyGraph" class="empty hidden">
322
- <span class="empty-icon"><i data-lucide="calendar-x" class="size-5"></i></span>
323
- <p class="empty-title">No activity yet</p>
324
- <p class="empty-desc">Daily token activity will chart here once sessions report tokens.</p>
325
- </div>
326
- </div>
327
- </section>
328
-
329
- <!-- Top models: 3 columns -->
330
- <section class="mt-8 modelsSection" aria-label="Top models">
331
- <div class="flex items-center gap-2 mb-1">
332
- <i data-lucide="cpu" class="size-4" style="color: var(--accent)"></i>
333
- <h2 class="display font-bold tracking-tight text-xl truncate min-w-0">Top models</h2>
334
- <span class="mono text-xs ml-auto" style="color: var(--dim)">usage across sessions</span>
335
- </div>
336
- <div class="grid grid-cols-1 md:grid-cols-3 gap-3" id="modelCards"></div>
337
- </section>
338
-
339
-
340
- <!-- Models: own full-width section (split out of the old 50/50 twin card) -->
341
- <section class="rise mt-8 rounded-xl p-5 overflow-hidden flex flex-col modelsSection" style="border: 1px solid var(--line); background: var(--panel)" aria-label="All models">
342
- <div class="flex items-center gap-2 mb-1">
343
- <i data-lucide="layers" class="size-4" style="color: var(--accent)"></i>
344
- <h2 class="display font-bold tracking-tight text-xl truncate min-w-0">Models</h2>
345
- <span class="mono text-xs ml-auto truncate shrink-0" style="color: var(--dim)" id="modelsCount"></span>
346
- </div>
347
- <p class="mono text-xs mb-4" style="color: var(--dim)">ranked by tokens / top 10</p>
348
- <div class="scrollarea"><ol id="models" class="overflow-hidden"></ol></div>
349
- <div class="mono text-xs mt-4 pt-4 flex flex-wrap items-center gap-x-4 gap-y-3 mt-auto" style="color: var(--dim); border-top: 1px solid var(--line)">
350
- <span id="modelRange">Showing 0 of 0</span>
351
- <span class="seg flex items-center gap-1 p-1 rounded-[10px]" style="border: 1px solid var(--line)" role="group" aria-label="Models per page">
352
- <button data-pp="10" class="on px-2.5 py-1" role="button">10</button>
353
- <button data-pp="15" class="px-2.5 py-1" role="button">15</button>
354
- <button data-pp="25" class="px-2.5 py-1" role="button">25</button>
355
- <button data-pp="50" class="px-2.5 py-1" role="button">50</button>
356
- </span>
357
- <span class="ml-auto flex items-center gap-1" id="modelPages" role="navigation" aria-label="Model pages"></span>
358
- </div>
359
- <div id="emptyModels" class="empty hidden">
360
- <span class="empty-icon"><i data-lucide="boxes" class="size-5"></i></span>
361
- <p class="empty-title">No models yet</p>
362
- <p class="empty-desc">Model token totals will appear here once sessions report tokens.</p>
363
- </div>
364
- </section>
365
-
366
- <!-- Recent requests: full-width, sitting with the other per-request views
367
- right after Models. When is absolutely stamped, so the column reads as
368
- a real timeline and sorts honestly against Time. -->
369
- <section class="rise mt-8 rounded-xl p-5 overflow-hidden flex flex-col" style="border: 1px solid var(--line); background: var(--panel); scroll-margin-top: 90px" aria-label="Recent requests">
370
- <div class="flex items-center gap-2 mb-1">
371
- <i data-lucide="history" class="size-4" style="color: var(--accent)"></i>
372
- <h2 class="display font-bold tracking-tight text-xl truncate min-w-0">Recent requests</h2>
373
- <span class="mono text-xs ml-auto truncate shrink-0" style="color: var(--dim)" id="recentCount"></span>
374
- </div>
375
- <p class="mono text-xs mb-4 truncate" style="color: var(--dim)" title="Time = elapsed time with the model; Speed = output tokens per second">latest assistant messages · local time · sort any column · cost is measured when the host recorded it</p>
376
- <div class="scrollarea overflow-x-auto" style="max-height: 560px">
377
- <table class="w-full mono text-[13px]" id="recentTable">
378
- <colgroup><col><col style="width:96px"><col style="width:96px"><col style="width:120px"><col style="width:116px"><col style="width:120px"><col style="width:158px"></colgroup>
379
- <thead>
380
- <tr class="text-left text-[11px] uppercase tracking-[0.14em]" style="color: var(--dim)">
381
- <th class="font-normal py-2 pr-3" aria-sort="none"><button class="thsort" data-sort="model">Model <span class="arr">⇅</span></button></th>
382
- <th class="font-normal text-right py-2 pr-3" aria-sort="none"><button class="thsort num" data-sort="input">Input <span class="arr">⇅</span></button></th>
383
- <th class="font-normal text-right py-2 pr-3" aria-sort="none"><button class="thsort num" data-sort="output">Output <span class="arr">⇅</span></button></th>
384
- <th class="font-normal text-right py-2 pr-3" aria-sort="none"><button class="thsort num" data-sort="time" title="Elapsed time with the model / output token speed">Time <span class="arr">⇅</span></button></th>
385
- <th class="font-normal py-2 pr-3" aria-sort="none"><button class="thsort" data-sort="status">Status <span class="arr">⇅</span></button></th>
386
- <th class="font-normal text-right py-2 pr-3" aria-sort="none"><button class="thsort num" data-sort="cost">Cost <span class="arr">⇅</span></button></th>
387
- <th class="font-normal text-right py-2" aria-sort="none"><button class="thsort num" data-sort="when" title="Local timestamp: month day, hour:minute:second">When <span class="arr">⇅</span></button></th>
388
- </tr>
389
- </thead>
390
- <tbody id="recent"></tbody>
391
- </table>
392
- </div>
393
- <div id="emptyRecent" class="empty hidden">
394
- <span class="empty-icon"><i data-lucide="inbox" class="size-5"></i></span>
395
- <p class="empty-title">No requests yet</p>
396
- <p class="empty-desc">Recent assistant messages will show here once sessions report tokens.</p>
397
- </div>
398
- <div class="mono text-xs mt-4 pt-4 flex flex-wrap items-center gap-x-4 gap-y-3 mt-auto" style="color: var(--dim); border-top: 1px solid var(--line)">
399
- <span id="recentRange">Showing 0 of 0</span>
400
- <span class="seg flex items-center gap-1 p-1 rounded-[10px]" style="border: 1px solid var(--line)" role="group" aria-label="Requests per page">
401
- <button data-pp="10" class="px-2.5 py-1" role="button">10</button>
402
- <button data-pp="15" class="px-2.5 py-1" role="button">15</button>
403
- <button data-pp="25" class="on px-2.5 py-1" role="button">25</button>
404
- <button data-pp="50" class="px-2.5 py-1" role="button">50</button>
405
- </span>
406
- <span class="ml-auto flex items-center gap-1" id="recentPages" role="navigation" aria-label="Recent pages"></span>
407
- </div>
408
- </section>
409
-
410
- <!-- Command tools: own card, header outside like Models -->
411
- <section id="tools" class="rise mt-8 rounded-xl p-5 overflow-hidden" style="border: 1px solid var(--line); background: var(--panel); scroll-margin-top: 90px" aria-label="Command tools">
412
- <div class="flex items-center gap-2 mb-1">
413
- <i data-lucide="terminal" class="size-4" style="color: var(--accent)"></i>
414
- <h2 class="display font-bold tracking-tight text-xl truncate min-w-0">Command tools</h2>
415
- <div class="flex items-center gap-2 ml-auto min-w-0">
416
- <span class="mono text-xs truncate min-w-0" style="color: var(--dim)" id="toolsScope">tool calls in sessions</span>
417
- </div>
418
- </div>
419
- <p class="mono text-xs mb-4 truncate" style="color: var(--dim)">count · tokens saved · avg rate · avg time · share of executions</p>
420
- <div class="overflow-x-auto">
421
- <table class="w-full mono text-[13px]" id="cmdTable">
422
- <colgroup><col style="width:40px"><col><col style="width:90px"><col style="width:90px"><col style="width:90px"><col style="width:90px"><col style="width:140px"></colgroup>
423
- <thead>
424
- <tr class="text-left text-[11px] uppercase tracking-[0.14em]" style="color: var(--dim)">
425
- <th class="font-normal text-right pr-3 py-2 w-10">#</th>
426
- <th class="font-normal py-2 pr-3" aria-sort="none"><button class="thsort" data-sort="name">Tool / Command <span class="arr">⇅</span></button></th>
427
- <th class="font-normal text-right py-2 pr-3" aria-sort="descending"><button class="thsort num" data-sort="count">Count <span class="arr">↓</span></button></th>
428
- <th class="font-normal text-right py-2 pr-3" aria-sort="none"><button class="thsort num" data-sort="saved">Saved <span class="arr">⇅</span></button></th>
429
- <th class="font-normal text-right py-2 pr-3" aria-sort="none"><button class="thsort num" data-sort="avgPct">Avg% <span class="arr">⇅</span></button></th>
430
- <th class="font-normal text-right py-2 pr-3" aria-sort="none"><button class="thsort num" data-sort="avgMs">Time <span class="arr">⇅</span></button></th>
431
- <th class="font-normal py-2 min-w-32">Impact</th>
432
- </tr>
433
- </thead>
434
- <tbody id="cmdBody"></tbody>
435
- </table>
436
- </div>
437
- <div id="emptyCmd" class="empty hidden">
438
- <span class="empty-icon"><i data-lucide="wrench" class="size-5"></i></span>
439
- <p class="empty-title">No tool data yet</p>
440
- <p class="empty-desc">Session tool calls and RTK measurements will appear here once recorded.</p>
441
- </div>
442
- <div id="cmdPager" class="mono text-xs mt-4 flex flex-wrap items-center gap-x-4 gap-y-3" style="color: var(--dim)">
443
- <span id="cmdRange">Showing 0 of 0</span>
444
- <span class="seg flex items-center gap-1 p-1 rounded-[10px]" style="border: 1px solid var(--line)" role="group" aria-label="Rows per page">
445
- <button data-pp="10" class="px-2.5 py-1" role="button">10</button>
446
- <button data-pp="15" class="on px-2.5 py-1" role="button">15</button>
447
- <button data-pp="25" class="px-2.5 py-1" role="button">25</button>
448
- <button data-pp="50" class="px-2.5 py-1" role="button">50</button>
449
- </span>
450
- <span class="ml-auto flex items-center gap-1" id="cmdPages" role="navigation" aria-label="Pages"></span>
451
- </div>
452
- <p class="mono text-[11px] mt-3" style="color: var(--dim)">bash commands run through the rtk-wired OMP hook meter automatically; rows without metering show –. caveman + ponytail gains are instruction-following, bench-measured in BENCHMARK.md.</p>
453
- </section>
454
-
455
- <!-- Share dialog: stats card preview + social actions -->
456
- <dialog id="shareDialog" class="dlg shdlg" aria-labelledby="shareTitle">
457
- <div class="sh-glow" aria-hidden="true"></div>
458
- <div class="dlg-head">
459
- <div class="min-w-0">
460
- <p class="dlg-title" id="shareTitle">Share your usage</p>
461
- <p class="dlg-desc">Download the card or post your stats.</p>
462
- </div>
463
- <button id="shareClose" class="btn-push flex shrink-0 items-center p-2 rounded-xl" style="border: 1px solid var(--line); color: var(--ink)" aria-label="Close share">
464
- <i data-lucide="x" class="size-4"></i>
465
- </button>
466
- </div>
467
- <div class="share-card sh-card" aria-hidden="false">
468
- <span class="ghosticon" aria-hidden="true"><i data-lucide="zap"></i></span>
469
- <img src="brand.webp" alt="" width="44" height="44" class="share-logo" aria-hidden="true">
470
- <p class="mono share-kicker">tersio · usage profile</p>
471
- <p class="mono share-total" id="shareTotal">-</p>
472
- <p class="mono share-sub" id="shareRuns">-</p>
473
- <div class="sh-heat" id="shareHeat" aria-hidden="true"></div>
474
- <div class="share-grid mono">
475
- <div><p class="share-mini-k">avg / run</p><p class="share-mini-v" id="shareAvg">-</p></div>
476
- <div><p class="share-mini-k">saved</p><p class="share-mini-v" id="shareSaved">-</p></div>
477
- <div><p class="share-mini-k">day streak</p><p class="share-mini-v" id="shareStreak">-</p></div>
478
- <div><p class="share-mini-k">best day</p><p class="share-mini-v" id="shareBest">-</p></div>
479
- <div><p class="share-mini-k">est. cost</p><p class="share-mini-v" id="shareCost">-</p></div>
480
- <div><p class="share-mini-k">models</p><p class="share-mini-v" id="shareModels">-</p></div>
481
- </div>
482
- </div>
483
- <div class="mono text-xs mt-4 flex flex-wrap items-center gap-2">
484
- <span class="flex items-center gap-2">
485
- <button id="shareX" class="btn-push share-btn share-icon" aria-label="Share on X" title="Share on X"><svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg></button>
486
- <button id="shareReddit" class="btn-push share-btn share-icon" aria-label="Share on Reddit" title="Share on Reddit"><svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0zm5.01 4.744c.688 0 1.25.561 1.25 1.249a1.25 1.25 0 0 1-2.498.056l-2.597-.547-.8 3.747c1.824.07 3.48.632 4.674 1.488.308-.309.73-.491 1.207-.491.968 0 1.754.786 1.754 1.754 0 .716-.435 1.333-1.01 1.614a3.111 3.111 0 0 1 .042.52c0 2.694-3.13 4.87-7.004 4.87-3.874 0-7.004-2.176-7.004-4.87 0-.183.015-.366.043-.534A1.748 1.748 0 0 1 4.028 12c0-.968.786-1.754 1.754-1.754.463 0 .898.196 1.207.49 1.207-.883 2.878-1.43 4.744-1.487l.885-4.182a.342.342 0 0 1 .14-.197.35.35 0 0 1 .238-.042l2.906.617a1.214 1.214 0 0 1 1.108-.701zM9.25 12C8.561 12 8 12.562 8 13.25c0 .687.561 1.248 1.25 1.248.687 0 1.248-.561 1.248-1.249 0-.688-.561-1.249-1.249-1.249zm5.5 0c-.687 0-1.248.561-1.248 1.25 0 .687.561 1.248 1.249 1.248.688 0 1.249-.561 1.249-1.249 0-.688-.562-1.249-1.25-1.249zm-5.466 3.99a.327.327 0 0 0-.231.094.33.33 0 0 0 0 .463c.842.842 2.484.913 2.961.913.477 0 2.105-.056 2.961-.913a.361.361 0 0 0 .029-.463.33.33 0 0 0-.464 0c-.547.533-1.684.73-2.512.73-.828 0-1.979-.196-2.512-.73a.326.326 0 0 0-.232-.095z"/></svg></button>
487
- <button id="shareLinkedIn" class="btn-push share-btn share-icon" aria-label="Share on LinkedIn" title="Share on LinkedIn"><svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg></button>
488
- </span>
489
- <span class="flex items-center gap-2 ml-auto">
490
- <button id="shareCopy" class="btn-push share-btn" aria-label="Copy card image"><i data-lucide="copy" class="size-3.5"></i><span>Copy</span></button>
491
- <button id="sharePng" class="btn-push share-btn" aria-label="Download card as PNG"><i data-lucide="download" class="size-3.5"></i><span>Download</span></button>
492
- </span>
493
- </div>
494
- </dialog>
495
-
496
- <footer class="mono text-xs mt-12 pt-4" style="color: var(--dim); border-top: 1px solid var(--line)">
497
- <div class="flex flex-wrap items-center gap-x-4 gap-y-3">
498
- <span>© 2026 Tersio. KurutoDenzeru. All rights reserved.</span>
499
- <span class="ml-auto flex items-center gap-1" style="color: var(--ink)">
500
- <a href="https://github.com/KurutoDenzeru/tersio" target="_blank" rel="noopener" aria-label="GitHub" class="btn-push social grid size-8 place-items-center rounded-lg"><img height="16" width="16" src="https://cdn.jsdelivr.net/npm/simple-icons@v16/icons/github.svg" alt="GitHub"></a>
501
- <a href="https://linkedin.com/in/kurtcalacday/" target="_blank" rel="noopener" aria-label="LinkedIn" class="btn-push social grid size-8 place-items-center rounded-lg"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg></a>
502
- <a href="https://instagram.com/krtclcdy/" target="_blank" rel="noopener" aria-label="Instagram" class="btn-push social grid size-8 place-items-center rounded-lg"><img height="16" width="16" src="https://cdn.jsdelivr.net/npm/simple-icons@v16/icons/instagram.svg" alt="Instagram"></a>
503
- </span>
504
- </div>
505
- </footer>
506
- </div>
507
- </main>
508
-
509
- <script>window.__TERSIO_SNAP = null;</script>
510
- <script src="core.js" defer></script>
511
- <script src="charts.js" defer></script>
512
- <script src="settings.js" defer></script>
513
- <script src="share.js" defer></script>
514
- </body>
515
- </html>
@@ -1,29 +0,0 @@
1
- import { asPromptArray, reconcileSharedComboEntries, sessionEntries, systemPromptIncludes } from './session-state.ts';
2
- import type { ExtensionApi, SystemPromptEvent } from './types.ts';
3
-
4
- const MARKER = 'SUPREME TOKEN SAVER MODES ACTIVE';
5
-
6
- function instruction(state: { caveman: string; rtk: string; ponytail: string }): string | null {
7
- const modes = [
8
- state.caveman !== 'off' && `caveman=${state.caveman}`,
9
- state.rtk === 'on' && 'rtk=on',
10
- state.ponytail !== 'off' && `ponytail=${state.ponytail}`,
11
- ].filter(Boolean);
12
- if (!modes.length) return null;
13
-
14
- return `${MARKER}: ${modes.join(' · ')}. Keep these active for the entire response: concise Caveman prose, RTK for eligible noisy shell output, and the smallest correct Ponytail solution. Do not weaken or disable a mode unless the user explicitly asks.`;
15
- }
16
-
17
- export default function modeReinforcementExtension(pi: ExtensionApi): void {
18
- pi.setLabel?.('Tersio mode reinforcement');
19
-
20
- pi.on('before_agent_start', async (event: SystemPromptEvent, ctx) => {
21
- if (!ctx?.hasUI) return;
22
- const text = instruction(reconcileSharedComboEntries(sessionEntries(ctx)));
23
- if (!text) return;
24
-
25
- const base = asPromptArray(event.systemPrompt);
26
- if (systemPromptIncludes(base, MARKER)) return;
27
- return { systemPrompt: [...base, text] };
28
- });
29
- }
Binary file