@linxiraos/pi-stats 1.1.7 → 1.1.9
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.
- package/CHANGELOG.md +4 -4
- package/package.json +87 -94
- package/src/client/App.tsx +11 -1
- package/src/client/api.ts +23 -0
- package/src/client/app/routes.ts +7 -0
- package/src/client/data/useHashRoute.ts +28 -10
- package/src/client/routes/ProvidersRoute.tsx +1 -0
- package/src/client/routes/TracesRoute.tsx +182 -0
- package/src/client/routes/index.ts +1 -0
- package/src/client/styles.css +433 -111
- package/src/client/traces/AggregatesPanel.tsx +88 -0
- package/src/client/traces/Minimap.tsx +177 -0
- package/src/client/traces/SpanDrawer.tsx +309 -0
- package/src/client/traces/SummaryStrip.tsx +37 -0
- package/src/client/traces/TimelineCanvas.tsx +768 -0
- package/src/client/traces/TraceView.tsx +344 -0
- package/src/client/traces/TranscriptList.tsx +166 -0
- package/src/client/traces/time-scale.ts +250 -0
- package/src/client/traces/trace-colors.ts +77 -0
- package/src/db.ts +77 -0
- package/src/gain-aggregator.ts +1 -1
- package/src/index.ts +1 -6
- package/src/parser.ts +55 -2
- package/src/server.ts +69 -17
- package/src/shared-types.ts +138 -0
- package/src/trace.ts +1002 -0
- package/src/types.ts +45 -1
- package/THIRD-PARTY-NOTICES.txt +0 -22909
- package/dist/client/index.css +0 -1
- package/dist/client/index.html +0 -24
- package/dist/client/index.js +0 -257
- package/dist/client/styles.css +0 -1692
- package/dist/types/aggregator.d.ts +0 -103
- package/dist/types/client/App.d.ts +0 -1
- package/dist/types/client/api.d.ts +0 -22
- package/dist/types/client/app/AppLayout.d.ts +0 -16
- package/dist/types/client/app/NavRail.d.ts +0 -7
- package/dist/types/client/app/RangeControl.d.ts +0 -7
- package/dist/types/client/app/SyncButton.d.ts +0 -14
- package/dist/types/client/app/ThemeToggle.d.ts +0 -1
- package/dist/types/client/app/TopBar.d.ts +0 -15
- package/dist/types/client/app/routes.d.ts +0 -12
- package/dist/types/client/components/AgentTokenShare.d.ts +0 -5
- package/dist/types/client/components/chart-shared.d.ts +0 -178
- package/dist/types/client/components/models-table-shared.d.ts +0 -175
- package/dist/types/client/components/range-meta.d.ts +0 -21
- package/dist/types/client/data/charts.d.ts +0 -1
- package/dist/types/client/data/formatters.d.ts +0 -13
- package/dist/types/client/data/useHashRoute.d.ts +0 -8
- package/dist/types/client/data/useResource.d.ts +0 -13
- package/dist/types/client/data/view-models.d.ts +0 -75
- package/dist/types/client/index.d.ts +0 -2
- package/dist/types/client/routes/BehaviorRoute.d.ts +0 -7
- package/dist/types/client/routes/CostsRoute.d.ts +0 -7
- package/dist/types/client/routes/ErrorsRoute.d.ts +0 -8
- package/dist/types/client/routes/GainRoute.d.ts +0 -7
- package/dist/types/client/routes/ModelsRoute.d.ts +0 -7
- package/dist/types/client/routes/OverviewRoute.d.ts +0 -8
- package/dist/types/client/routes/ProjectsRoute.d.ts +0 -7
- package/dist/types/client/routes/ProvidersRoute.d.ts +0 -7
- package/dist/types/client/routes/RequestsRoute.d.ts +0 -8
- package/dist/types/client/routes/ToolsRoute.d.ts +0 -7
- package/dist/types/client/routes/index.d.ts +0 -10
- package/dist/types/client/types.d.ts +0 -63
- package/dist/types/client/ui/AsyncBoundary.d.ts +0 -12
- package/dist/types/client/ui/DataTable.d.ts +0 -17
- package/dist/types/client/ui/EmptyState.d.ts +0 -7
- package/dist/types/client/ui/ErrorState.d.ts +0 -6
- package/dist/types/client/ui/JsonBlock.d.ts +0 -7
- package/dist/types/client/ui/MetricCluster.d.ts +0 -5
- package/dist/types/client/ui/Panel.d.ts +0 -7
- package/dist/types/client/ui/RequestDrawer.d.ts +0 -5
- package/dist/types/client/ui/SegmentedControl.d.ts +0 -12
- package/dist/types/client/ui/Skeleton.d.ts +0 -8
- package/dist/types/client/ui/StatusPill.d.ts +0 -7
- package/dist/types/client/ui/index.d.ts +0 -11
- package/dist/types/client/useSystemTheme.d.ts +0 -11
- package/dist/types/db.d.ts +0 -160
- package/dist/types/embedded-client.d.ts +0 -18
- package/dist/types/gain-aggregator.d.ts +0 -26
- package/dist/types/index.d.ts +0 -17
- package/dist/types/parser.d.ts +0 -53
- package/dist/types/port-conflict.d.ts +0 -16
- package/dist/types/server.d.ts +0 -14
- package/dist/types/shared-types.d.ts +0 -421
- package/dist/types/sync-worker.d.ts +0 -31
- package/dist/types/types.d.ts +0 -164
- package/dist/types/usage-windows.d.ts +0 -72
- package/dist/types/user-metrics.d.ts +0 -81
package/src/client/styles.css
CHANGED
|
@@ -1,46 +1,41 @@
|
|
|
1
1
|
@import "tailwindcss/index.css";
|
|
2
2
|
|
|
3
3
|
/* ==========================================================================
|
|
4
|
-
|
|
4
|
+
OMP Theme Variables & Color Scheme
|
|
5
5
|
========================================================================== */
|
|
6
6
|
:root {
|
|
7
7
|
color-scheme: dark;
|
|
8
|
-
/*
|
|
9
|
-
|
|
10
|
-
--
|
|
11
|
-
--
|
|
12
|
-
--
|
|
13
|
-
--
|
|
14
|
-
--
|
|
15
|
-
--
|
|
16
|
-
--
|
|
17
|
-
--
|
|
18
|
-
--
|
|
19
|
-
--
|
|
20
|
-
--accent:
|
|
21
|
-
--
|
|
22
|
-
--
|
|
23
|
-
--
|
|
24
|
-
--
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
/* Backward-compat aliases for existing class references */
|
|
30
|
-
--page: var(--bg);
|
|
31
|
-
--surface: var(--bg-panel);
|
|
32
|
-
--surface-2: var(--bg-hover);
|
|
33
|
-
--muted: var(--text-muted);
|
|
34
|
-
--dim: var(--text-dim);
|
|
35
|
-
|
|
36
|
-
/* Bridge view-component token vocabulary */
|
|
8
|
+
/* OMP brand palette — packages/collab-web/src/styles/tokens.css:
|
|
9
|
+
deep-purple surfaces (hue 307), pink accent #ed4abf, cyan focus ring #5ad8e6. */
|
|
10
|
+
--page: oklch(0.16 0.02 307);
|
|
11
|
+
--surface: oklch(0.19 0.022 307);
|
|
12
|
+
--surface-2: oklch(0.235 0.026 307);
|
|
13
|
+
--border: oklch(1 0 0 / 9%);
|
|
14
|
+
--border-strong: oklch(1 0 0 / 13%);
|
|
15
|
+
--text: oklch(0.92 0.01 307);
|
|
16
|
+
--muted: oklch(0.71 0.016 307);
|
|
17
|
+
--dim: oklch(0.53 0.018 307);
|
|
18
|
+
--accent: oklch(0.674 0.23 341); /* brand pink #ed4abf */
|
|
19
|
+
--accent-fg: oklch(0.2 0.07 341); /* ink on accent fills */
|
|
20
|
+
--accent-muted: oklch(0.674 0.23 341 / 18%);
|
|
21
|
+
--link: oklch(0.817 0.112 205); /* brand cyan #5ad8e6 */
|
|
22
|
+
--success: oklch(0.76 0.14 150);
|
|
23
|
+
--danger: oklch(0.66 0.19 25);
|
|
24
|
+
--warning: oklch(0.79 0.14 85);
|
|
25
|
+
|
|
26
|
+
/* Bridge the view components' token vocabulary to the OMP base tokens so
|
|
27
|
+
muted/secondary text and semantic accents resolve instead of silently
|
|
28
|
+
falling back to inherited text color. Re-resolve per theme via var(). */
|
|
37
29
|
--text-primary: var(--text);
|
|
38
|
-
--text-secondary: var(--
|
|
30
|
+
--text-secondary: var(--muted);
|
|
31
|
+
--text-muted: var(--dim);
|
|
39
32
|
--border-subtle: var(--border);
|
|
40
33
|
--accent-red: var(--danger);
|
|
41
34
|
--accent-green: var(--success);
|
|
42
35
|
--accent-cyan: var(--link);
|
|
43
|
-
--bg-
|
|
36
|
+
--bg-hover: var(--surface-2);
|
|
37
|
+
--bg-elevated: var(--surface-2);
|
|
38
|
+
--select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23999' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
|
|
44
39
|
|
|
45
40
|
--radius-sm: 3px;
|
|
46
41
|
--radius-md: 6px;
|
|
@@ -52,89 +47,44 @@
|
|
|
52
47
|
@media (prefers-color-scheme: light) {
|
|
53
48
|
:root:not([data-theme]) {
|
|
54
49
|
color-scheme: light;
|
|
55
|
-
--
|
|
56
|
-
--
|
|
57
|
-
--
|
|
58
|
-
--
|
|
59
|
-
--
|
|
60
|
-
--
|
|
61
|
-
--
|
|
62
|
-
--
|
|
63
|
-
--
|
|
64
|
-
--
|
|
65
|
-
--accent:
|
|
66
|
-
--
|
|
67
|
-
--
|
|
68
|
-
--
|
|
69
|
-
--
|
|
70
|
-
--
|
|
71
|
-
--danger: #dc2626;
|
|
72
|
-
--warning: #d97706;
|
|
73
|
-
/* Backward-compat aliases */
|
|
74
|
-
--page: var(--bg);
|
|
75
|
-
--surface: var(--bg-panel);
|
|
76
|
-
--surface-2: var(--bg-hover);
|
|
77
|
-
--muted: var(--text-muted);
|
|
78
|
-
--dim: var(--text-dim);
|
|
50
|
+
--page: oklch(0.985 0.004 307);
|
|
51
|
+
--surface: oklch(1 0 0);
|
|
52
|
+
--surface-2: oklch(0.965 0.006 307);
|
|
53
|
+
--border: oklch(0 0 0 / 10%);
|
|
54
|
+
--border-strong: oklch(0 0 0 / 15%);
|
|
55
|
+
--text: oklch(0.26 0.03 307);
|
|
56
|
+
--muted: oklch(0.46 0.03 307);
|
|
57
|
+
--dim: oklch(0.58 0.025 307);
|
|
58
|
+
--accent: oklch(0.62 0.23 341);
|
|
59
|
+
--accent-fg: oklch(0.99 0.01 341);
|
|
60
|
+
--accent-muted: oklch(0.62 0.23 341 / 14%);
|
|
61
|
+
--link: oklch(0.58 0.13 230);
|
|
62
|
+
--success: oklch(0.55 0.13 150);
|
|
63
|
+
--danger: oklch(0.55 0.19 25);
|
|
64
|
+
--select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23555' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
|
|
65
|
+
--warning: oklch(0.6 0.13 85);
|
|
79
66
|
}
|
|
80
67
|
}
|
|
81
68
|
|
|
82
69
|
/* Explicit theme override (toggle or persisted preference). */
|
|
83
70
|
[data-theme="light"] {
|
|
84
71
|
color-scheme: light;
|
|
85
|
-
--
|
|
86
|
-
--
|
|
87
|
-
--
|
|
88
|
-
--
|
|
89
|
-
--
|
|
90
|
-
--
|
|
91
|
-
--
|
|
92
|
-
--
|
|
93
|
-
--
|
|
94
|
-
--
|
|
95
|
-
--accent:
|
|
96
|
-
--
|
|
97
|
-
--
|
|
98
|
-
--
|
|
99
|
-
--
|
|
100
|
-
--
|
|
101
|
-
--danger: #dc2626;
|
|
102
|
-
--warning: #d97706;
|
|
103
|
-
/* Backward-compat aliases */
|
|
104
|
-
--page: var(--bg);
|
|
105
|
-
--surface: var(--bg-panel);
|
|
106
|
-
--surface-2: var(--bg-hover);
|
|
107
|
-
--muted: var(--text-muted);
|
|
108
|
-
--dim: var(--text-dim);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/* Zeta Starfield theme — NASA-punk deep-space HUD, aligned with web-ui globals.css */
|
|
112
|
-
[data-theme="starfield"] {
|
|
113
|
-
color-scheme: dark;
|
|
114
|
-
--bg: #08090d;
|
|
115
|
-
--bg-panel: #0d1117;
|
|
116
|
-
--bg-hover: #161d2e;
|
|
117
|
-
--bg-selected: #1a2540;
|
|
118
|
-
--bg-subtle: rgba(217,155,38,0.05);
|
|
119
|
-
--border: #1e2d45;
|
|
120
|
-
--border-strong: rgba(217,155,38,0.2);
|
|
121
|
-
--text: #e8eeff;
|
|
122
|
-
--text-muted: #8fa3c0;
|
|
123
|
-
--text-dim: #3d5070;
|
|
124
|
-
--accent: #d99b26; /* Zeta Starfield gold */
|
|
125
|
-
--accent-hover: #f0b840;
|
|
126
|
-
--accent-fg: #0f172a;
|
|
127
|
-
--accent-muted: rgba(217,155,38,0.18);
|
|
128
|
-
--link: #d99b26;
|
|
129
|
-
--success: #22c55e;
|
|
130
|
-
--danger: #c81d25;
|
|
131
|
-
--warning: #e05a2b;
|
|
132
|
-
/* Backward-compat aliases */
|
|
133
|
-
--page: var(--bg);
|
|
134
|
-
--surface: var(--bg-panel);
|
|
135
|
-
--surface-2: var(--bg-hover);
|
|
136
|
-
--muted: var(--text-muted);
|
|
137
|
-
--dim: var(--text-dim);
|
|
72
|
+
--page: oklch(0.985 0.004 307);
|
|
73
|
+
--surface: oklch(1 0 0);
|
|
74
|
+
--surface-2: oklch(0.965 0.006 307);
|
|
75
|
+
--border: oklch(0 0 0 / 10%);
|
|
76
|
+
--border-strong: oklch(0 0 0 / 15%);
|
|
77
|
+
--text: oklch(0.26 0.03 307);
|
|
78
|
+
--muted: oklch(0.46 0.03 307);
|
|
79
|
+
--dim: oklch(0.58 0.025 307);
|
|
80
|
+
--accent: oklch(0.62 0.23 341);
|
|
81
|
+
--accent-fg: oklch(0.99 0.01 341);
|
|
82
|
+
--accent-muted: oklch(0.62 0.23 341 / 14%);
|
|
83
|
+
--link: oklch(0.58 0.13 230);
|
|
84
|
+
--success: oklch(0.55 0.13 150);
|
|
85
|
+
--danger: oklch(0.55 0.19 25);
|
|
86
|
+
--select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23555' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
|
|
87
|
+
--warning: oklch(0.6 0.13 85);
|
|
138
88
|
}
|
|
139
89
|
|
|
140
90
|
/* ==========================================================================
|
|
@@ -517,6 +467,62 @@
|
|
|
517
467
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
|
|
518
468
|
}
|
|
519
469
|
|
|
470
|
+
/* Select (native <select>, themed to match RangeControl/Buttons) */
|
|
471
|
+
.stats-select {
|
|
472
|
+
appearance: none;
|
|
473
|
+
padding: 6px 28px 6px 12px;
|
|
474
|
+
font-size: 13px;
|
|
475
|
+
font-weight: 500;
|
|
476
|
+
font-family: inherit;
|
|
477
|
+
color: var(--text);
|
|
478
|
+
background-color: var(--surface-2);
|
|
479
|
+
/* Chevron follows theme: light stroke on dark, dark stroke on light. */
|
|
480
|
+
background-image: var(--select-chevron);
|
|
481
|
+
background-repeat: no-repeat;
|
|
482
|
+
background-position: right 10px center;
|
|
483
|
+
border: 1px solid var(--border);
|
|
484
|
+
border-radius: var(--radius-md);
|
|
485
|
+
cursor: pointer;
|
|
486
|
+
transition: border-color 0.15s ease, background-color 0.15s ease;
|
|
487
|
+
max-width: 100%;
|
|
488
|
+
text-overflow: ellipsis;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
.stats-select:hover:not(:disabled) {
|
|
492
|
+
border-color: var(--border-strong);
|
|
493
|
+
background-color: var(--bg-hover);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
.stats-select:focus-visible {
|
|
497
|
+
outline: 2px solid var(--link);
|
|
498
|
+
outline-offset: 1px;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
.stats-select:disabled {
|
|
502
|
+
opacity: 0.5;
|
|
503
|
+
cursor: not-allowed;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/* Prevent iOS from zooming the viewport when a select receives focus. */
|
|
507
|
+
@media (pointer: coarse) {
|
|
508
|
+
.stats-select {
|
|
509
|
+
font-size: 16px;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/* Dropdown list itself follows the page theme via color-scheme. */
|
|
514
|
+
.stats-select option {
|
|
515
|
+
background-color: var(--surface);
|
|
516
|
+
color: var(--text);
|
|
517
|
+
}
|
|
518
|
+
/* Forced-colors (Windows High Contrast) suppresses background images, so the
|
|
519
|
+
custom chevron vanishes; restore the native indicator instead. */
|
|
520
|
+
@media (forced-colors: active) {
|
|
521
|
+
.stats-select {
|
|
522
|
+
appearance: auto;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
520
526
|
/* Sync Button & Container */
|
|
521
527
|
.stats-sync-container {
|
|
522
528
|
display: flex;
|
|
@@ -1287,7 +1293,7 @@
|
|
|
1287
1293
|
}
|
|
1288
1294
|
|
|
1289
1295
|
/* ==========================================================================
|
|
1290
|
-
Brand mark on the
|
|
1296
|
+
Brand mark on the OMP wordmark (both rail + mobile drawer headers)
|
|
1291
1297
|
========================================================================== */
|
|
1292
1298
|
.stats-logo-container {
|
|
1293
1299
|
display: grid;
|
|
@@ -1302,7 +1308,7 @@
|
|
|
1302
1308
|
width: 16px;
|
|
1303
1309
|
height: 16px;
|
|
1304
1310
|
border-radius: 4px;
|
|
1305
|
-
background: linear-gradient(135deg, #
|
|
1311
|
+
background: linear-gradient(135deg, #ed4abf 0%, #9b4dff 50%, #5ad8e6 100%); /* OMP brand gradient mark */
|
|
1306
1312
|
}
|
|
1307
1313
|
|
|
1308
1314
|
.stats-logo-text,
|
|
@@ -1382,3 +1388,319 @@
|
|
|
1382
1388
|
transition: none;
|
|
1383
1389
|
}
|
|
1384
1390
|
}
|
|
1391
|
+
|
|
1392
|
+
/* ==========================================================================
|
|
1393
|
+
Traces (session flamegraph)
|
|
1394
|
+
========================================================================== */
|
|
1395
|
+
.stats-trace-view {
|
|
1396
|
+
display: flex;
|
|
1397
|
+
flex-direction: column;
|
|
1398
|
+
gap: 14px;
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
.stats-trace-header {
|
|
1402
|
+
display: flex;
|
|
1403
|
+
align-items: center;
|
|
1404
|
+
gap: 12px;
|
|
1405
|
+
flex-wrap: wrap;
|
|
1406
|
+
min-width: 0;
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
.stats-trace-back {
|
|
1410
|
+
display: inline-flex;
|
|
1411
|
+
align-items: center;
|
|
1412
|
+
gap: 6px;
|
|
1413
|
+
padding: 6px 12px;
|
|
1414
|
+
font-size: 12px;
|
|
1415
|
+
color: var(--muted);
|
|
1416
|
+
background: var(--surface);
|
|
1417
|
+
border: 1px solid var(--border);
|
|
1418
|
+
border-radius: var(--radius-md);
|
|
1419
|
+
cursor: pointer;
|
|
1420
|
+
transition: color 0.14s ease, border-color 0.14s ease;
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
.stats-trace-back:hover {
|
|
1424
|
+
color: var(--text);
|
|
1425
|
+
border-color: var(--border-strong);
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
.stats-trace-back:focus-visible {
|
|
1429
|
+
outline: 2px solid var(--link);
|
|
1430
|
+
outline-offset: 2px;
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
.stats-trace-title {
|
|
1434
|
+
font-size: 15px;
|
|
1435
|
+
font-weight: 600;
|
|
1436
|
+
color: var(--text);
|
|
1437
|
+
margin: 0;
|
|
1438
|
+
min-width: 0;
|
|
1439
|
+
overflow: hidden;
|
|
1440
|
+
text-overflow: ellipsis;
|
|
1441
|
+
white-space: nowrap;
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
.stats-trace-cwd {
|
|
1445
|
+
font-size: 11px;
|
|
1446
|
+
color: var(--dim);
|
|
1447
|
+
border: 1px solid var(--border);
|
|
1448
|
+
border-radius: 999px;
|
|
1449
|
+
padding: 3px 10px;
|
|
1450
|
+
max-width: 280px;
|
|
1451
|
+
overflow: hidden;
|
|
1452
|
+
text-overflow: ellipsis;
|
|
1453
|
+
white-space: nowrap;
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
/* Summary strip: one bordered card, hairline-divided stat columns. */
|
|
1457
|
+
.stats-trace-summary {
|
|
1458
|
+
display: flex;
|
|
1459
|
+
flex-wrap: wrap;
|
|
1460
|
+
background: var(--surface);
|
|
1461
|
+
border: 1px solid var(--border);
|
|
1462
|
+
border-radius: var(--radius-lg);
|
|
1463
|
+
overflow: hidden;
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
.stats-trace-summary-cell {
|
|
1467
|
+
display: flex;
|
|
1468
|
+
flex-direction: column;
|
|
1469
|
+
gap: 3px;
|
|
1470
|
+
padding: 10px 16px;
|
|
1471
|
+
border-right: 1px solid var(--border);
|
|
1472
|
+
min-width: 76px;
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
.stats-trace-summary-cell:last-child {
|
|
1476
|
+
border-right: none;
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
.stats-trace-summary-label {
|
|
1480
|
+
font-size: 9px;
|
|
1481
|
+
text-transform: uppercase;
|
|
1482
|
+
letter-spacing: 0.07em;
|
|
1483
|
+
color: var(--dim);
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
.stats-trace-summary-value {
|
|
1487
|
+
font-size: 13px;
|
|
1488
|
+
font-weight: 500;
|
|
1489
|
+
color: var(--text);
|
|
1490
|
+
font-variant-numeric: tabular-nums;
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
/* Toolbar row above the timeline. */
|
|
1494
|
+
.stats-trace-toolbar {
|
|
1495
|
+
display: flex;
|
|
1496
|
+
align-items: center;
|
|
1497
|
+
gap: 12px;
|
|
1498
|
+
flex-wrap: wrap;
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
.stats-trace-toolbar-hint {
|
|
1502
|
+
font-size: 10px;
|
|
1503
|
+
color: var(--dim);
|
|
1504
|
+
margin-left: auto;
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
.stats-trace-input {
|
|
1508
|
+
background: var(--surface);
|
|
1509
|
+
border: 1px solid var(--border);
|
|
1510
|
+
border-radius: var(--radius-md);
|
|
1511
|
+
color: var(--text);
|
|
1512
|
+
font-size: 12px;
|
|
1513
|
+
padding: 6px 10px;
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
.stats-trace-input:focus-visible {
|
|
1517
|
+
outline: 2px solid var(--link);
|
|
1518
|
+
outline-offset: 1px;
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
.stats-trace-input::placeholder {
|
|
1522
|
+
color: var(--dim);
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
.stats-trace-check {
|
|
1526
|
+
display: inline-flex;
|
|
1527
|
+
align-items: center;
|
|
1528
|
+
gap: 6px;
|
|
1529
|
+
font-size: 12px;
|
|
1530
|
+
color: var(--muted);
|
|
1531
|
+
cursor: pointer;
|
|
1532
|
+
user-select: none;
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
.stats-trace-icon-btn {
|
|
1536
|
+
display: inline-flex;
|
|
1537
|
+
align-items: center;
|
|
1538
|
+
justify-content: center;
|
|
1539
|
+
width: 26px;
|
|
1540
|
+
height: 26px;
|
|
1541
|
+
background: transparent;
|
|
1542
|
+
border: 1px solid var(--border);
|
|
1543
|
+
border-radius: var(--radius-md);
|
|
1544
|
+
color: var(--muted);
|
|
1545
|
+
cursor: pointer;
|
|
1546
|
+
transition: color 0.14s ease, border-color 0.14s ease;
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
.stats-trace-icon-btn:hover:not(:disabled) {
|
|
1550
|
+
color: var(--text);
|
|
1551
|
+
border-color: var(--border-strong);
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
.stats-trace-icon-btn:focus-visible {
|
|
1555
|
+
outline: 2px solid var(--link);
|
|
1556
|
+
outline-offset: 2px;
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
.stats-trace-icon-btn:disabled {
|
|
1560
|
+
opacity: 0.4;
|
|
1561
|
+
cursor: default;
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
/* Timeline card: minimap + canvas share one bordered surface. */
|
|
1565
|
+
.stats-trace-timeline-card {
|
|
1566
|
+
background: var(--surface);
|
|
1567
|
+
border: 1px solid var(--border);
|
|
1568
|
+
border-radius: var(--radius-lg);
|
|
1569
|
+
padding: 12px;
|
|
1570
|
+
display: flex;
|
|
1571
|
+
flex-direction: column;
|
|
1572
|
+
gap: 10px;
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
.stats-trace-timeline {
|
|
1576
|
+
position: relative;
|
|
1577
|
+
display: flex;
|
|
1578
|
+
max-height: 560px;
|
|
1579
|
+
overflow-y: auto;
|
|
1580
|
+
overflow-x: hidden;
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
.stats-trace-canvas {
|
|
1584
|
+
cursor: grab;
|
|
1585
|
+
outline: none;
|
|
1586
|
+
touch-action: none;
|
|
1587
|
+
border-radius: var(--radius-sm);
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
.stats-trace-canvas:focus-visible {
|
|
1591
|
+
outline: 2px solid var(--link);
|
|
1592
|
+
outline-offset: 2px;
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
.stats-trace-canvas:active {
|
|
1596
|
+
cursor: grabbing;
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
.stats-trace-chevron {
|
|
1600
|
+
display: inline-flex;
|
|
1601
|
+
background: none;
|
|
1602
|
+
border: none;
|
|
1603
|
+
padding: 0;
|
|
1604
|
+
cursor: pointer;
|
|
1605
|
+
color: var(--muted);
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
.stats-trace-chevron:hover {
|
|
1609
|
+
color: var(--text);
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
.stats-trace-gutter-track {
|
|
1613
|
+
font-size: 11px;
|
|
1614
|
+
font-weight: 500;
|
|
1615
|
+
color: var(--text);
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
.stats-trace-gutter-model {
|
|
1619
|
+
font-size: 9px;
|
|
1620
|
+
color: var(--dim);
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
.stats-trace-gutter-lane {
|
|
1624
|
+
position: absolute;
|
|
1625
|
+
font-size: 8px;
|
|
1626
|
+
color: var(--dim);
|
|
1627
|
+
text-transform: uppercase;
|
|
1628
|
+
letter-spacing: 0.08em;
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
/* Transcript list under the timeline. */
|
|
1632
|
+
.stats-trace-list {
|
|
1633
|
+
background: var(--surface);
|
|
1634
|
+
border: 1px solid var(--border);
|
|
1635
|
+
border-radius: var(--radius-lg);
|
|
1636
|
+
height: 340px;
|
|
1637
|
+
overflow-y: auto;
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
.stats-trace-row {
|
|
1641
|
+
display: flex;
|
|
1642
|
+
align-items: center;
|
|
1643
|
+
gap: 10px;
|
|
1644
|
+
height: 28px;
|
|
1645
|
+
width: 100%;
|
|
1646
|
+
padding: 0 12px;
|
|
1647
|
+
background: transparent;
|
|
1648
|
+
border: none;
|
|
1649
|
+
border-bottom: 1px solid var(--border);
|
|
1650
|
+
text-align: left;
|
|
1651
|
+
cursor: pointer;
|
|
1652
|
+
transition: background 0.1s ease;
|
|
1653
|
+
}
|
|
1654
|
+
|
|
1655
|
+
.stats-trace-row:hover {
|
|
1656
|
+
background: var(--bg-hover);
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
.stats-trace-row:focus-visible {
|
|
1660
|
+
outline: 2px solid var(--link);
|
|
1661
|
+
outline-offset: -2px;
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
.stats-trace-row[data-selected="true"] {
|
|
1665
|
+
background: var(--accent-muted);
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1668
|
+
.stats-trace-row-static {
|
|
1669
|
+
cursor: default;
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
.stats-trace-row-static:hover {
|
|
1673
|
+
background: transparent;
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
.stats-trace-kind {
|
|
1677
|
+
flex-shrink: 0;
|
|
1678
|
+
width: 58px;
|
|
1679
|
+
font-size: 8px;
|
|
1680
|
+
text-transform: uppercase;
|
|
1681
|
+
letter-spacing: 0.06em;
|
|
1682
|
+
border-radius: 3px;
|
|
1683
|
+
padding: 2px 0;
|
|
1684
|
+
text-align: center;
|
|
1685
|
+
overflow: hidden;
|
|
1686
|
+
text-overflow: ellipsis;
|
|
1687
|
+
white-space: nowrap;
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
.stats-trace-row-meta {
|
|
1691
|
+
flex-shrink: 0;
|
|
1692
|
+
margin-left: auto;
|
|
1693
|
+
font-size: 10px;
|
|
1694
|
+
color: var(--dim);
|
|
1695
|
+
font-variant-numeric: tabular-nums;
|
|
1696
|
+
display: flex;
|
|
1697
|
+
gap: 10px;
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1701
|
+
.stats-trace-back,
|
|
1702
|
+
.stats-trace-icon-btn,
|
|
1703
|
+
.stats-trace-row {
|
|
1704
|
+
transition: none;
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collapsible per-tool duration aggregates for one trace, sorted by total
|
|
3
|
+
* time descending (as produced by the server).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ChevronDown, ChevronRight } from "lucide-react";
|
|
7
|
+
import { useMemo, useState } from "react";
|
|
8
|
+
import { formatDurationMs, formatInteger } from "../data/formatters";
|
|
9
|
+
import type { TraceToolStat } from "../types";
|
|
10
|
+
import { DataTable } from "../ui/DataTable";
|
|
11
|
+
|
|
12
|
+
export interface AggregatesPanelProps {
|
|
13
|
+
toolStats: TraceToolStat[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function AggregatesPanel({ toolStats }: AggregatesPanelProps) {
|
|
17
|
+
const [open, setOpen] = useState(false);
|
|
18
|
+
|
|
19
|
+
const columns = useMemo(
|
|
20
|
+
() => [
|
|
21
|
+
{ key: "tool", header: "Tool", render: (item: TraceToolStat) => item.tool },
|
|
22
|
+
{ key: "calls", header: "Calls", numeric: true, render: (item: TraceToolStat) => formatInteger(item.calls) },
|
|
23
|
+
{
|
|
24
|
+
key: "errors",
|
|
25
|
+
header: "Errors",
|
|
26
|
+
numeric: true,
|
|
27
|
+
render: (item: TraceToolStat) => formatInteger(item.errors),
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
key: "total",
|
|
31
|
+
header: "Total",
|
|
32
|
+
numeric: true,
|
|
33
|
+
render: (item: TraceToolStat) => formatDurationMs(item.totalMs),
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
key: "avg",
|
|
37
|
+
header: "Avg",
|
|
38
|
+
numeric: true,
|
|
39
|
+
render: (item: TraceToolStat) => formatDurationMs(item.calls > 0 ? item.totalMs / item.calls : 0),
|
|
40
|
+
},
|
|
41
|
+
{ key: "max", header: "Max", numeric: true, render: (item: TraceToolStat) => formatDurationMs(item.maxMs) },
|
|
42
|
+
],
|
|
43
|
+
[],
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
if (toolStats.length === 0) return null;
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<div className="stats-panel">
|
|
50
|
+
<button
|
|
51
|
+
type="button"
|
|
52
|
+
onClick={() => setOpen(prev => !prev)}
|
|
53
|
+
aria-expanded={open}
|
|
54
|
+
style={{
|
|
55
|
+
display: "flex",
|
|
56
|
+
alignItems: "center",
|
|
57
|
+
gap: 6,
|
|
58
|
+
width: "100%",
|
|
59
|
+
background: "none",
|
|
60
|
+
border: "none",
|
|
61
|
+
padding: "10px 14px",
|
|
62
|
+
cursor: "pointer",
|
|
63
|
+
textAlign: "left",
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
{open ? (
|
|
67
|
+
<ChevronDown size={14} className="stats-text-muted" aria-hidden="true" />
|
|
68
|
+
) : (
|
|
69
|
+
<ChevronRight size={14} className="stats-text-muted" aria-hidden="true" />
|
|
70
|
+
)}
|
|
71
|
+
<span className="stats-panel-title">Tool Aggregates</span>
|
|
72
|
+
<span className="stats-text-muted" style={{ fontSize: 11 }}>
|
|
73
|
+
{toolStats.length} tools
|
|
74
|
+
</span>
|
|
75
|
+
</button>
|
|
76
|
+
{open && (
|
|
77
|
+
<div className="stats-panel-body">
|
|
78
|
+
<DataTable
|
|
79
|
+
columns={columns}
|
|
80
|
+
data={toolStats}
|
|
81
|
+
keyExtractor={item => item.tool}
|
|
82
|
+
emptyText="No tool calls"
|
|
83
|
+
/>
|
|
84
|
+
</div>
|
|
85
|
+
)}
|
|
86
|
+
</div>
|
|
87
|
+
);
|
|
88
|
+
}
|