@oh-my-pi/omp-stats 18.3.5 → 18.4.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 (192) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +13 -11
  3. package/build.ts +5 -49
  4. package/dist/client/index.css +1 -1
  5. package/dist/client/index.html +2 -2
  6. package/dist/client/index.js +105 -126
  7. package/dist/types/aggregator.d.ts +25 -22
  8. package/dist/types/client/api.d.ts +11 -7
  9. package/dist/types/client/app/LiveChip.d.ts +2 -0
  10. package/dist/types/client/app/Shell.d.ts +16 -0
  11. package/dist/types/client/app/ThemeToggle.d.ts +1 -0
  12. package/dist/types/client/app/nav.d.ts +18 -0
  13. package/dist/types/client/charts/BarList.d.ts +17 -0
  14. package/dist/types/client/charts/Chart.d.ts +49 -0
  15. package/dist/types/client/charts/Legend.d.ts +16 -0
  16. package/dist/types/client/charts/ShareBar.d.ts +11 -0
  17. package/dist/types/client/charts/Sparkline.d.ts +11 -0
  18. package/dist/types/client/charts/TimeChart.d.ts +9 -0
  19. package/dist/types/client/charts/index.d.ts +7 -0
  20. package/dist/types/client/charts/types.d.ts +25 -0
  21. package/dist/types/client/charts/useWidth.d.ts +3 -0
  22. package/dist/types/client/data/colors.d.ts +25 -0
  23. package/dist/types/client/data/formatters.d.ts +9 -1
  24. package/dist/types/client/data/live.d.ts +29 -0
  25. package/dist/types/client/data/query.d.ts +35 -0
  26. package/dist/types/client/data/range.d.ts +31 -0
  27. package/dist/types/client/data/series.d.ts +28 -0
  28. package/dist/types/client/data/useHashRoute.d.ts +18 -4
  29. package/dist/types/client/data/view-models.d.ts +111 -28
  30. package/dist/types/client/index.d.ts +0 -1
  31. package/dist/types/client/routes/CostsRoute.d.ts +2 -2
  32. package/dist/types/client/routes/ErrorsRoute.d.ts +2 -2
  33. package/dist/types/client/routes/FrustrationRoute.d.ts +7 -0
  34. package/dist/types/client/routes/GainRoute.d.ts +1 -2
  35. package/dist/types/client/routes/ModelsRoute.d.ts +2 -2
  36. package/dist/types/client/routes/OverviewRoute.d.ts +1 -2
  37. package/dist/types/client/routes/ProjectsRoute.d.ts +2 -2
  38. package/dist/types/client/routes/ProvidersRoute.d.ts +2 -2
  39. package/dist/types/client/routes/RequestsRoute.d.ts +1 -2
  40. package/dist/types/client/routes/ToolsRoute.d.ts +2 -2
  41. package/dist/types/client/routes/TracesRoute.d.ts +2 -2
  42. package/dist/types/client/routes/index.d.ts +1 -1
  43. package/dist/types/client/traces/AggregatesPanel.d.ts +4 -3
  44. package/dist/types/client/traces/SummaryStrip.d.ts +2 -2
  45. package/dist/types/client/traces/trace-colors.d.ts +18 -12
  46. package/dist/types/client/ui/Badge.d.ts +19 -0
  47. package/dist/types/client/ui/Card.d.ts +25 -0
  48. package/dist/types/client/ui/Drawer.d.ts +25 -0
  49. package/dist/types/client/ui/JsonBlock.d.ts +2 -2
  50. package/dist/types/client/ui/Modal.d.ts +23 -0
  51. package/dist/types/client/ui/RequestDrawer.d.ts +10 -1
  52. package/dist/types/client/ui/SearchInput.d.ts +8 -0
  53. package/dist/types/client/ui/Segmented.d.ts +15 -0
  54. package/dist/types/client/ui/Stat.d.ts +36 -0
  55. package/dist/types/client/ui/States.d.ts +41 -0
  56. package/dist/types/client/ui/Table.d.ts +48 -0
  57. package/dist/types/client/ui/index.d.ts +9 -10
  58. package/dist/types/db.d.ts +90 -106
  59. package/dist/types/frustration.d.ts +70 -0
  60. package/dist/types/index.d.ts +3 -1
  61. package/dist/types/live.d.ts +30 -0
  62. package/dist/types/rollup.d.ts +115 -0
  63. package/dist/types/server.d.ts +6 -1
  64. package/dist/types/shared-types.d.ts +116 -56
  65. package/dist/types/types.d.ts +4 -0
  66. package/dist/types/user-metrics.d.ts +8 -0
  67. package/package.json +7 -13
  68. package/src/aggregator.ts +276 -211
  69. package/src/client/App.tsx +38 -80
  70. package/src/client/api.ts +65 -7
  71. package/src/client/app/LiveChip.tsx +97 -0
  72. package/src/client/app/Shell.tsx +181 -0
  73. package/src/client/app/ThemeToggle.tsx +5 -2
  74. package/src/client/app/nav.ts +78 -0
  75. package/src/client/charts/BarList.tsx +48 -0
  76. package/src/client/charts/Chart.tsx +388 -0
  77. package/src/client/charts/Legend.tsx +61 -0
  78. package/src/client/charts/ShareBar.tsx +26 -0
  79. package/src/client/charts/Sparkline.tsx +38 -0
  80. package/src/client/charts/TimeChart.tsx +22 -0
  81. package/src/client/charts/index.ts +7 -0
  82. package/src/client/charts/types.ts +27 -0
  83. package/src/client/charts/useWidth.ts +19 -0
  84. package/src/client/data/colors.ts +45 -0
  85. package/src/client/data/formatters.ts +30 -9
  86. package/src/client/data/live.tsx +85 -0
  87. package/src/client/data/query.ts +166 -0
  88. package/src/client/data/range.ts +82 -0
  89. package/src/client/data/series.ts +85 -0
  90. package/src/client/data/useHashRoute.ts +41 -83
  91. package/src/client/data/view-models.ts +347 -140
  92. package/src/client/index.tsx +3 -6
  93. package/src/client/routes/CostsRoute.tsx +394 -222
  94. package/src/client/routes/ErrorsRoute.tsx +401 -98
  95. package/src/client/routes/FrustrationRoute.tsx +924 -0
  96. package/src/client/routes/GainRoute.tsx +209 -206
  97. package/src/client/routes/ModelsRoute.tsx +540 -431
  98. package/src/client/routes/OverviewRoute.tsx +283 -311
  99. package/src/client/routes/ProjectsRoute.tsx +298 -156
  100. package/src/client/routes/ProvidersRoute.tsx +948 -416
  101. package/src/client/routes/RequestsRoute.tsx +295 -107
  102. package/src/client/routes/ToolsRoute.tsx +495 -398
  103. package/src/client/routes/TracesRoute.tsx +136 -117
  104. package/src/client/routes/costs.css +24 -0
  105. package/src/client/routes/errors.css +60 -0
  106. package/src/client/routes/frustration.css +123 -0
  107. package/src/client/routes/index.ts +1 -1
  108. package/src/client/routes/models.css +43 -0
  109. package/src/client/routes/projects.css +6 -0
  110. package/src/client/routes/providers.css +28 -0
  111. package/src/client/routes/tools.css +14 -0
  112. package/src/client/styles.css +1396 -1299
  113. package/src/client/traces/AggregatesPanel.tsx +55 -74
  114. package/src/client/traces/Minimap.tsx +6 -15
  115. package/src/client/traces/SpanDrawer.tsx +128 -194
  116. package/src/client/traces/SummaryStrip.tsx +21 -24
  117. package/src/client/traces/TimelineCanvas.tsx +27 -44
  118. package/src/client/traces/TraceView.tsx +175 -130
  119. package/src/client/traces/TranscriptList.tsx +13 -41
  120. package/src/client/traces/trace-colors.ts +60 -53
  121. package/src/client/traces/traces.css +279 -0
  122. package/src/client/ui/Badge.tsx +29 -0
  123. package/src/client/ui/Card.tsx +61 -0
  124. package/src/client/ui/Drawer.tsx +93 -0
  125. package/src/client/ui/JsonBlock.tsx +26 -44
  126. package/src/client/ui/Modal.tsx +106 -0
  127. package/src/client/ui/RequestDrawer.tsx +163 -188
  128. package/src/client/ui/SearchInput.tsx +25 -0
  129. package/src/client/ui/Segmented.tsx +61 -0
  130. package/src/client/ui/Stat.tsx +104 -0
  131. package/src/client/ui/States.tsx +81 -0
  132. package/src/client/ui/Table.tsx +229 -0
  133. package/src/client/ui/index.ts +9 -10
  134. package/src/client/ui/modal.css +54 -0
  135. package/src/client/ui/request-drawer.css +40 -0
  136. package/src/db.ts +379 -983
  137. package/src/frustration.ts +473 -0
  138. package/src/index.ts +22 -22
  139. package/src/live.ts +259 -0
  140. package/src/parser.ts +55 -66
  141. package/src/rollup.ts +951 -0
  142. package/src/server.ts +123 -40
  143. package/src/shared-types.ts +120 -56
  144. package/src/trace.ts +14 -7
  145. package/src/types.ts +4 -0
  146. package/src/user-metrics.ts +13 -0
  147. package/dist/client/styles.css +0 -1976
  148. package/dist/types/client/app/AppLayout.d.ts +0 -16
  149. package/dist/types/client/app/NavRail.d.ts +0 -7
  150. package/dist/types/client/app/RangeControl.d.ts +0 -7
  151. package/dist/types/client/app/SyncButton.d.ts +0 -14
  152. package/dist/types/client/app/TopBar.d.ts +0 -15
  153. package/dist/types/client/app/routes.d.ts +0 -12
  154. package/dist/types/client/components/AgentTokenShare.d.ts +0 -5
  155. package/dist/types/client/components/chart-shared.d.ts +0 -178
  156. package/dist/types/client/components/models-table-shared.d.ts +0 -175
  157. package/dist/types/client/components/range-meta.d.ts +0 -21
  158. package/dist/types/client/data/charts.d.ts +0 -1
  159. package/dist/types/client/data/useResource.d.ts +0 -13
  160. package/dist/types/client/routes/BehaviorRoute.d.ts +0 -7
  161. package/dist/types/client/ui/AsyncBoundary.d.ts +0 -12
  162. package/dist/types/client/ui/DataTable.d.ts +0 -17
  163. package/dist/types/client/ui/EmptyState.d.ts +0 -7
  164. package/dist/types/client/ui/ErrorState.d.ts +0 -6
  165. package/dist/types/client/ui/MetricCluster.d.ts +0 -5
  166. package/dist/types/client/ui/Panel.d.ts +0 -7
  167. package/dist/types/client/ui/SegmentedControl.d.ts +0 -12
  168. package/dist/types/client/ui/Skeleton.d.ts +0 -8
  169. package/dist/types/client/ui/StatusPill.d.ts +0 -7
  170. package/src/client/app/AppLayout.tsx +0 -93
  171. package/src/client/app/NavRail.tsx +0 -44
  172. package/src/client/app/RangeControl.tsx +0 -39
  173. package/src/client/app/SyncButton.tsx +0 -75
  174. package/src/client/app/TopBar.tsx +0 -73
  175. package/src/client/app/routes.ts +0 -93
  176. package/src/client/components/AgentTokenShare.tsx +0 -68
  177. package/src/client/components/chart-shared.tsx +0 -273
  178. package/src/client/components/models-table-shared.tsx +0 -255
  179. package/src/client/components/range-meta.ts +0 -73
  180. package/src/client/data/charts.ts +0 -14
  181. package/src/client/data/useResource.ts +0 -154
  182. package/src/client/routes/BehaviorRoute.tsx +0 -623
  183. package/src/client/ui/AsyncBoundary.tsx +0 -54
  184. package/src/client/ui/DataTable.tsx +0 -122
  185. package/src/client/ui/EmptyState.tsx +0 -16
  186. package/src/client/ui/ErrorState.tsx +0 -25
  187. package/src/client/ui/MetricCluster.tsx +0 -92
  188. package/src/client/ui/Panel.tsx +0 -24
  189. package/src/client/ui/SegmentedControl.tsx +0 -36
  190. package/src/client/ui/Skeleton.tsx +0 -17
  191. package/src/client/ui/StatusPill.tsx +0 -15
  192. package/tailwind.config.js +0 -40
@@ -182,65 +182,91 @@ export interface AgentTypeStats {
182
182
  totalCost: number;
183
183
  }
184
184
  /**
185
- * Behavior time-series point (daily bucket, per responding model).
185
+ * Frustration tallies over a set of user messages. Each message counts once,
186
+ * classified by its cached judge verdict when one exists, else by the regex
187
+ * behavior signals stored at ingest (see `frustration.ts` for both rules).
186
188
  */
187
- export interface BehaviorTimeSeriesPoint {
188
- /** Bucket timestamp (start of day) */
189
- timestamp: number;
190
- /** Responding model ("unknown" if user msg never got a reply) */
191
- model: string;
192
- /** Responding provider */
193
- provider: string;
194
- /** Number of user messages in bucket */
189
+ export interface FrustrationCounts {
190
+ /** User messages with non-empty prose. */
195
191
  messages: number;
196
- /** Total yelling sentences in bucket */
197
- yelling: number;
198
- /** Total profanity hits in bucket */
199
- profanity: number;
200
- /** Total anguish signal in bucket */
201
- anguish: number;
202
- /** Total corrective-negation hits in bucket */
203
- negation: number;
204
- /** Total user-repeating-themselves hits in bucket */
205
- repetition: number;
206
- /** Total second-person blame hits in bucket */
207
- blame: number;
208
- /** Total characters in bucket */
209
- chars: number;
210
- }
211
- export interface BehaviorOverallStats {
212
- totalMessages: number;
213
- totalYelling: number;
214
- totalProfanity: number;
215
- totalAnguish: number;
216
- totalNegation: number;
217
- totalRepetition: number;
218
- totalBlame: number;
219
- totalChars: number;
220
- firstTimestamp: number;
221
- lastTimestamp: number;
192
+ /** Messages whose prose has a cached judge verdict; the rest use regex fallback. */
193
+ judged: number;
194
+ /** Annoyed at anything (the assistant, tooling, other people, ...). */
195
+ annoyed: number;
196
+ /** Annoyed and aimed at the assistant. Subset of `annoyed`. */
197
+ atAssistant: number;
198
+ /** Aimed at the assistant and hostile/angry. Subset of `atAssistant`. */
199
+ angry: number;
222
200
  }
223
201
  /**
224
- * Per-model behavioral aggregate over the active range.
202
+ * Frustration tallies for one model version. Provider/spelling variants of the
203
+ * same model (`claude-opus-4.6`, `anthropic/claude-opus-4-6`) merge under one
204
+ * catalog identity.
225
205
  */
226
- export interface BehaviorModelStats {
227
- model: string;
228
- provider: string;
229
- totalMessages: number;
230
- totalYelling: number;
231
- totalProfanity: number;
232
- totalAnguish: number;
233
- totalNegation: number;
234
- totalRepetition: number;
235
- totalBlame: number;
236
- totalChars: number;
237
- lastTimestamp: number;
238
- }
239
- export interface BehaviorDashboardStats {
240
- overall: BehaviorOverallStats;
241
- byModel: BehaviorModelStats[];
242
- behaviorSeries: BehaviorTimeSeriesPoint[];
243
- }
206
+ export interface FrustrationModelStats extends FrustrationCounts {
207
+ /** Stable key: `class/family/revision` when classified, else the raw model id. */
208
+ key: string;
209
+ /** Display label, e.g. `opus 4.5`; the raw model id when unclassified. */
210
+ label: string;
211
+ /** Catalog identity class, e.g. `anthropic`; `unknown` when unclassified. */
212
+ modelClass: string;
213
+ /** Catalog family within the class, e.g. `opus`. */
214
+ family: string | null;
215
+ /** Canonical `major.minor.patch`, e.g. `4.5.0`. */
216
+ revision: string | null;
217
+ /** Raw model ids merged into this row. */
218
+ models: string[];
219
+ /** Earliest message timestamp (ms) in range. */
220
+ firstSeen: number;
221
+ }
222
+ /** Lifecycle of the dashboard-host judge run that classifies unjudged messages. */
223
+ export type FrustrationJobState = "idle" | "running" | "done" | "cancelled" | "failed";
224
+ /** Progress of the (single, process-wide) frustration judge run. */
225
+ export interface FrustrationJobStatus {
226
+ state: FrustrationJobState;
227
+ /** Unique prose texts queued for judgment. */
228
+ total: number;
229
+ /** Texts judged successfully. */
230
+ done: number;
231
+ /** Texts that exhausted their retries. */
232
+ failed: number;
233
+ /** Accumulated USD cost of every judge attempt, retries included. */
234
+ cost: number;
235
+ /** Judge label (`provider/model`) of the run, when known. */
236
+ judge: string | null;
237
+ /** Why the run failed; null otherwise. */
238
+ error: string | null;
239
+ startedAt: number | null;
240
+ finishedAt: number | null;
241
+ /** Judge requests the run currently keeps in flight (adapts to the judge's rate limits). */
242
+ concurrency: number;
243
+ }
244
+ /** Payload of `GET /api/stats/frustration`. */
245
+ export interface FrustrationDashboardStats {
246
+ overall: FrustrationCounts;
247
+ /** Every model with messages in range, ordered by class, then revision, then family. */
248
+ byModel: FrustrationModelStats[];
249
+ /** Whether this dashboard host can run the judge (standalone `omp-stats` cannot). */
250
+ judgeAvailable: boolean;
251
+ job: FrustrationJobStatus;
252
+ }
253
+ /** Payload of `GET /api/frustration/estimate`: the pre-run cost quote shown before judging. */
254
+ export type FrustrationEstimate = {
255
+ available: true;
256
+ /** Unique unjudged prose texts in range (identical messages share one verdict). */
257
+ messages: number;
258
+ /** Total prose characters sent. */
259
+ chars: number;
260
+ /** Estimated billed input tokens. */
261
+ inputTokens: number;
262
+ /** Estimated USD cost. */
263
+ cost: number;
264
+ /** Judge label (`provider/model`) the run will route to first. */
265
+ judge: string;
266
+ } | {
267
+ available: false;
268
+ reason: string;
269
+ };
244
270
  /** Token savings from a single source type. */
245
271
  export interface GainSourceTotals {
246
272
  savedTokens: number;
@@ -425,13 +451,47 @@ export interface ProviderWindowInsight {
425
451
  /** Transitions into an exhausted state observed in range. */
426
452
  exhaustedEvents: number;
427
453
  }
428
- /** Complete providers dashboard payload. */
454
+ /** Ingest state of the dashboard host's background session sync. */
455
+ export interface LiveSyncStatus {
456
+ phase: "idle" | "syncing" | "error";
457
+ /** Files completed in the running sync (0 when not yet known). */
458
+ current: number;
459
+ /** Files in the running sync's work set (0 while listing → indeterminate). */
460
+ total: number;
461
+ /** Rows inserted by the running (or last) sync. */
462
+ processed: number;
463
+ /** Wall-clock time the last sync finished, if any. */
464
+ lastSyncedAt: number | null;
465
+ /** Failure message of the last sync when `phase` is `"error"`. */
466
+ error: string | null;
467
+ }
468
+ /**
469
+ * Payload of every `GET /api/events` server-sent event (and `GET /api/status`).
470
+ * `version` increases whenever stored stats may have changed, so clients
471
+ * revalidate their queries when it moves.
472
+ */
473
+ export interface LiveStatus {
474
+ version: number;
475
+ sync: LiveSyncStatus;
476
+ /** Hours whose rollups are still being (re)built; ranges covering them may be incomplete. */
477
+ indexingHours: number;
478
+ }
479
+ /** Providers dashboard payload: local request stats only (fast, DB-backed). */
429
480
  export interface ProviderDashboardStats {
430
481
  providers: ProviderAggregate[];
431
482
  hourly: ProviderHourlyPoint[];
432
483
  series: ProviderTimeSeriesPoint[];
433
- usageSeries: UsageWindowSeries[];
484
+ }
485
+ /**
486
+ * Subscription-window payload (`GET /api/stats/provider-windows`). Snapshots
487
+ * may come from the auth broker over the network, so it is fetched separately
488
+ * from {@link ProviderDashboardStats}. `usageSeries` only carries the
489
+ * requested provider's series (empty without a provider) — all of them can be
490
+ * thousands of series.
491
+ */
492
+ export interface ProviderWindowStats {
434
493
  windowInsights: ProviderWindowInsight[];
494
+ usageSeries: UsageWindowSeries[];
435
495
  }
436
496
  /**
437
497
  * One row of the Traces session list: a root session with every child
@@ -162,6 +162,10 @@ export interface UserMessageStats {
162
162
  repetition: number;
163
163
  /** Second-person reproach ("you didnt", "why did you", "stop X-ing") */
164
164
  blame: number;
165
+ /** Judge-facing prose (see `judgeProse`); empty when the message was all markup. */
166
+ prose: string;
167
+ /** Hex `Bun.hash` of `prose`, keying the shared verdict cache; empty when `prose` is. */
168
+ proseHash: string;
165
169
  }
166
170
  /**
167
171
  * Pair emitted by the parser when it sees an assistant message whose
@@ -71,6 +71,14 @@ export interface UserMessageMetrics {
71
71
  */
72
72
  blame: number;
73
73
  }
74
+ /** Cap on the judge-facing prose stored per user message; longer prose is truncated. */
75
+ export declare const PROSE_MAX_CHARS = 4000;
76
+ /**
77
+ * The prose a user message contributes to frustration judging: the same
78
+ * structured-content strip the regex signals score on, trimmed and capped at
79
+ * {@link PROSE_MAX_CHARS}. Empty when the message was nothing but markup.
80
+ */
81
+ export declare function judgeProse(text: string): string;
74
82
  /**
75
83
  * Compute behavioral metrics for a user message.
76
84
  *
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/omp-stats",
4
- "version": "18.3.5",
5
- "description": "Local observability dashboard for pi AI usage statistics",
4
+ "version": "18.4.0",
5
+ "description": "Local observability dashboard for omp AI usage statistics",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": {
8
8
  "name": "Stencil Labs, Inc.",
@@ -42,22 +42,17 @@
42
42
  "fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
43
43
  },
44
44
  "dependencies": {
45
- "@oh-my-pi/pi-ai": "18.3.5",
46
- "@oh-my-pi/pi-catalog": "18.3.5",
47
- "@oh-my-pi/pi-utils": "18.3.5",
48
- "@tailwindcss/node": "^4.3.2",
49
- "chart.js": "^4.5.1",
45
+ "@oh-my-pi/pi-ai": "18.4.0",
46
+ "@oh-my-pi/pi-catalog": "18.4.0",
47
+ "@oh-my-pi/pi-utils": "18.4.0",
50
48
  "lucide-react": "^1.24.0",
51
49
  "react": "19.2.7",
52
- "react-chartjs-2": "^5.3.1",
53
- "react-dom": "19.2.7",
54
- "tailwindcss": "^4.3.2"
50
+ "react-dom": "19.2.7"
55
51
  },
56
52
  "devDependencies": {
57
53
  "@types/bun": "^1.3.14",
58
54
  "@types/react": "^19.2.17",
59
- "@types/react-dom": "^19.2.3",
60
- "postcss": "^8.5.16"
55
+ "@types/react-dom": "^19.2.3"
61
56
  },
62
57
  "engines": {
63
58
  "bun": ">=1.3.14"
@@ -65,7 +60,6 @@
65
60
  "files": [
66
61
  "src",
67
62
  "build.ts",
68
- "tailwind.config.js",
69
63
  "README.md",
70
64
  "CHANGELOG.md",
71
65
  "LICENSE",