@oh-my-pi/omp-stats 18.0.11 → 18.1.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 (50) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/client/index.css +1 -1
  3. package/dist/client/index.js +101 -101
  4. package/dist/client/styles.css +265 -0
  5. package/dist/types/client/api.d.ts +7 -1
  6. package/dist/types/client/app/routes.d.ts +1 -1
  7. package/dist/types/client/data/useHashRoute.d.ts +2 -0
  8. package/dist/types/client/routes/TracesRoute.d.ts +11 -0
  9. package/dist/types/client/routes/index.d.ts +1 -0
  10. package/dist/types/client/traces/AggregatesPanel.d.ts +9 -0
  11. package/dist/types/client/traces/Minimap.d.ts +14 -0
  12. package/dist/types/client/traces/SpanDrawer.d.ts +14 -0
  13. package/dist/types/client/traces/SummaryStrip.d.ts +9 -0
  14. package/dist/types/client/traces/TimelineCanvas.d.ts +25 -0
  15. package/dist/types/client/traces/TraceView.d.ts +11 -0
  16. package/dist/types/client/traces/TranscriptList.d.ts +24 -0
  17. package/dist/types/client/traces/time-scale.d.ts +40 -0
  18. package/dist/types/client/traces/trace-colors.d.ts +31 -0
  19. package/dist/types/db.d.ts +24 -1
  20. package/dist/types/index.d.ts +1 -1
  21. package/dist/types/parser.d.ts +8 -0
  22. package/dist/types/server.d.ts +3 -2
  23. package/dist/types/shared-types.d.ts +130 -0
  24. package/dist/types/trace.d.ts +33 -0
  25. package/dist/types/types.d.ts +35 -1
  26. package/package.json +8 -8
  27. package/src/client/App.tsx +11 -1
  28. package/src/client/api.ts +23 -0
  29. package/src/client/app/routes.ts +7 -0
  30. package/src/client/data/useHashRoute.ts +28 -10
  31. package/src/client/routes/ProvidersRoute.tsx +1 -0
  32. package/src/client/routes/TracesRoute.tsx +182 -0
  33. package/src/client/routes/index.ts +1 -0
  34. package/src/client/styles.css +316 -0
  35. package/src/client/traces/AggregatesPanel.tsx +88 -0
  36. package/src/client/traces/Minimap.tsx +177 -0
  37. package/src/client/traces/SpanDrawer.tsx +309 -0
  38. package/src/client/traces/SummaryStrip.tsx +37 -0
  39. package/src/client/traces/TimelineCanvas.tsx +768 -0
  40. package/src/client/traces/TraceView.tsx +344 -0
  41. package/src/client/traces/TranscriptList.tsx +166 -0
  42. package/src/client/traces/time-scale.ts +250 -0
  43. package/src/client/traces/trace-colors.ts +77 -0
  44. package/src/db.ts +77 -0
  45. package/src/index.ts +1 -6
  46. package/src/parser.ts +55 -2
  47. package/src/server.ts +69 -17
  48. package/src/shared-types.ts +138 -0
  49. package/src/trace.ts +1002 -0
  50. package/src/types.ts +45 -1
@@ -1584,6 +1584,271 @@
1584
1584
  transition: none;
1585
1585
  }
1586
1586
  }
1587
+ .stats-trace-view {
1588
+ display: flex;
1589
+ flex-direction: column;
1590
+ gap: 14px;
1591
+ }
1592
+ .stats-trace-header {
1593
+ display: flex;
1594
+ align-items: center;
1595
+ gap: 12px;
1596
+ flex-wrap: wrap;
1597
+ min-width: 0;
1598
+ }
1599
+ .stats-trace-back {
1600
+ display: inline-flex;
1601
+ align-items: center;
1602
+ gap: 6px;
1603
+ padding: 6px 12px;
1604
+ font-size: 12px;
1605
+ color: var(--muted);
1606
+ background: var(--surface);
1607
+ border: 1px solid var(--border);
1608
+ border-radius: var(--radius-md);
1609
+ cursor: pointer;
1610
+ transition: color 0.14s ease, border-color 0.14s ease;
1611
+ }
1612
+ .stats-trace-back:hover {
1613
+ color: var(--text);
1614
+ border-color: var(--border-strong);
1615
+ }
1616
+ .stats-trace-back:focus-visible {
1617
+ outline: 2px solid var(--link);
1618
+ outline-offset: 2px;
1619
+ }
1620
+ .stats-trace-title {
1621
+ font-size: 15px;
1622
+ font-weight: 600;
1623
+ color: var(--text);
1624
+ margin: 0;
1625
+ min-width: 0;
1626
+ overflow: hidden;
1627
+ text-overflow: ellipsis;
1628
+ white-space: nowrap;
1629
+ }
1630
+ .stats-trace-cwd {
1631
+ font-size: 11px;
1632
+ color: var(--dim);
1633
+ border: 1px solid var(--border);
1634
+ border-radius: 999px;
1635
+ padding: 3px 10px;
1636
+ max-width: 280px;
1637
+ overflow: hidden;
1638
+ text-overflow: ellipsis;
1639
+ white-space: nowrap;
1640
+ }
1641
+ .stats-trace-summary {
1642
+ display: flex;
1643
+ flex-wrap: wrap;
1644
+ background: var(--surface);
1645
+ border: 1px solid var(--border);
1646
+ border-radius: var(--radius-lg);
1647
+ overflow: hidden;
1648
+ }
1649
+ .stats-trace-summary-cell {
1650
+ display: flex;
1651
+ flex-direction: column;
1652
+ gap: 3px;
1653
+ padding: 10px 16px;
1654
+ border-right: 1px solid var(--border);
1655
+ min-width: 76px;
1656
+ }
1657
+ .stats-trace-summary-cell:last-child {
1658
+ border-right: none;
1659
+ }
1660
+ .stats-trace-summary-label {
1661
+ font-size: 9px;
1662
+ text-transform: uppercase;
1663
+ letter-spacing: 0.07em;
1664
+ color: var(--dim);
1665
+ }
1666
+ .stats-trace-summary-value {
1667
+ font-size: 13px;
1668
+ font-weight: 500;
1669
+ color: var(--text);
1670
+ font-variant-numeric: tabular-nums;
1671
+ }
1672
+ .stats-trace-toolbar {
1673
+ display: flex;
1674
+ align-items: center;
1675
+ gap: 12px;
1676
+ flex-wrap: wrap;
1677
+ }
1678
+ .stats-trace-toolbar-hint {
1679
+ font-size: 10px;
1680
+ color: var(--dim);
1681
+ margin-left: auto;
1682
+ }
1683
+ .stats-trace-input {
1684
+ background: var(--surface);
1685
+ border: 1px solid var(--border);
1686
+ border-radius: var(--radius-md);
1687
+ color: var(--text);
1688
+ font-size: 12px;
1689
+ padding: 6px 10px;
1690
+ }
1691
+ .stats-trace-input:focus-visible {
1692
+ outline: 2px solid var(--link);
1693
+ outline-offset: 1px;
1694
+ }
1695
+ .stats-trace-input::placeholder {
1696
+ color: var(--dim);
1697
+ }
1698
+ .stats-trace-check {
1699
+ display: inline-flex;
1700
+ align-items: center;
1701
+ gap: 6px;
1702
+ font-size: 12px;
1703
+ color: var(--muted);
1704
+ cursor: pointer;
1705
+ user-select: none;
1706
+ }
1707
+ .stats-trace-icon-btn {
1708
+ display: inline-flex;
1709
+ align-items: center;
1710
+ justify-content: center;
1711
+ width: 26px;
1712
+ height: 26px;
1713
+ background: transparent;
1714
+ border: 1px solid var(--border);
1715
+ border-radius: var(--radius-md);
1716
+ color: var(--muted);
1717
+ cursor: pointer;
1718
+ transition: color 0.14s ease, border-color 0.14s ease;
1719
+ }
1720
+ .stats-trace-icon-btn:hover:not(:disabled) {
1721
+ color: var(--text);
1722
+ border-color: var(--border-strong);
1723
+ }
1724
+ .stats-trace-icon-btn:focus-visible {
1725
+ outline: 2px solid var(--link);
1726
+ outline-offset: 2px;
1727
+ }
1728
+ .stats-trace-icon-btn:disabled {
1729
+ opacity: 0.4;
1730
+ cursor: default;
1731
+ }
1732
+ .stats-trace-timeline-card {
1733
+ background: var(--surface);
1734
+ border: 1px solid var(--border);
1735
+ border-radius: var(--radius-lg);
1736
+ padding: 12px;
1737
+ display: flex;
1738
+ flex-direction: column;
1739
+ gap: 10px;
1740
+ }
1741
+ .stats-trace-timeline {
1742
+ position: relative;
1743
+ display: flex;
1744
+ max-height: 560px;
1745
+ overflow-y: auto;
1746
+ overflow-x: hidden;
1747
+ }
1748
+ .stats-trace-canvas {
1749
+ cursor: grab;
1750
+ outline: none;
1751
+ touch-action: none;
1752
+ border-radius: var(--radius-sm);
1753
+ }
1754
+ .stats-trace-canvas:focus-visible {
1755
+ outline: 2px solid var(--link);
1756
+ outline-offset: 2px;
1757
+ }
1758
+ .stats-trace-canvas:active {
1759
+ cursor: grabbing;
1760
+ }
1761
+ .stats-trace-chevron {
1762
+ display: inline-flex;
1763
+ background: none;
1764
+ border: none;
1765
+ padding: 0;
1766
+ cursor: pointer;
1767
+ color: var(--muted);
1768
+ }
1769
+ .stats-trace-chevron:hover {
1770
+ color: var(--text);
1771
+ }
1772
+ .stats-trace-gutter-track {
1773
+ font-size: 11px;
1774
+ font-weight: 500;
1775
+ color: var(--text);
1776
+ }
1777
+ .stats-trace-gutter-model {
1778
+ font-size: 9px;
1779
+ color: var(--dim);
1780
+ }
1781
+ .stats-trace-gutter-lane {
1782
+ position: absolute;
1783
+ font-size: 8px;
1784
+ color: var(--dim);
1785
+ text-transform: uppercase;
1786
+ letter-spacing: 0.08em;
1787
+ }
1788
+ .stats-trace-list {
1789
+ background: var(--surface);
1790
+ border: 1px solid var(--border);
1791
+ border-radius: var(--radius-lg);
1792
+ height: 340px;
1793
+ overflow-y: auto;
1794
+ }
1795
+ .stats-trace-row {
1796
+ display: flex;
1797
+ align-items: center;
1798
+ gap: 10px;
1799
+ height: 28px;
1800
+ width: 100%;
1801
+ padding: 0 12px;
1802
+ background: transparent;
1803
+ border: none;
1804
+ border-bottom: 1px solid var(--border);
1805
+ text-align: left;
1806
+ cursor: pointer;
1807
+ transition: background 0.1s ease;
1808
+ }
1809
+ .stats-trace-row:hover {
1810
+ background: var(--bg-hover);
1811
+ }
1812
+ .stats-trace-row:focus-visible {
1813
+ outline: 2px solid var(--link);
1814
+ outline-offset: -2px;
1815
+ }
1816
+ .stats-trace-row[data-selected="true"] {
1817
+ background: var(--accent-muted);
1818
+ }
1819
+ .stats-trace-row-static {
1820
+ cursor: default;
1821
+ }
1822
+ .stats-trace-row-static:hover {
1823
+ background: transparent;
1824
+ }
1825
+ .stats-trace-kind {
1826
+ flex-shrink: 0;
1827
+ width: 58px;
1828
+ font-size: 8px;
1829
+ text-transform: uppercase;
1830
+ letter-spacing: 0.06em;
1831
+ border-radius: 3px;
1832
+ padding: 2px 0;
1833
+ text-align: center;
1834
+ overflow: hidden;
1835
+ text-overflow: ellipsis;
1836
+ white-space: nowrap;
1837
+ }
1838
+ .stats-trace-row-meta {
1839
+ flex-shrink: 0;
1840
+ margin-left: auto;
1841
+ font-size: 10px;
1842
+ color: var(--dim);
1843
+ font-variant-numeric: tabular-nums;
1844
+ display: flex;
1845
+ gap: 10px;
1846
+ }
1847
+ @media (prefers-reduced-motion: reduce) {
1848
+ .stats-trace-back, .stats-trace-icon-btn, .stats-trace-row {
1849
+ transition: none;
1850
+ }
1851
+ }
1587
1852
  @property --tw-space-y-reverse {
1588
1853
  syntax: "*";
1589
1854
  inherits: false;
@@ -1,4 +1,4 @@
1
- import type { BehaviorDashboardStats, CostDashboardStats, FolderStats, GainDashboardStats, MessageStats, ModelDashboardStats, OverviewStats, ProviderDashboardStats, RequestDetails, TimeRange, ToolDashboardStats } from "./types.js";
1
+ import type { BehaviorDashboardStats, CostDashboardStats, FolderStats, GainDashboardStats, MessageStats, ModelDashboardStats, OverviewStats, ProviderDashboardStats, RequestDetails, SessionSummary, SessionTrace, TimeRange, ToolDashboardStats } from "./types.js";
2
2
  export declare class ApiError extends Error {
3
3
  status: number;
4
4
  endpoint: string;
@@ -20,3 +20,9 @@ export declare function getFolderStats(range?: TimeRange, signal?: AbortSignal):
20
20
  export declare function getGainDashboardStats(range?: TimeRange, project?: string | null, signal?: AbortSignal): Promise<GainDashboardStats>;
21
21
  export declare function getToolDashboardStats(range?: TimeRange, signal?: AbortSignal): Promise<ToolDashboardStats>;
22
22
  export declare function getProviderDashboardStats(range?: TimeRange, signal?: AbortSignal): Promise<ProviderDashboardStats>;
23
+ export declare function getSessions(limit?: number, q?: string, signal?: AbortSignal): Promise<SessionSummary[]>;
24
+ export declare function getSessionTrace(file: string, signal?: AbortSignal): Promise<SessionTrace>;
25
+ /** Fetch one full journal entry for the span drawer. Entries are opaque JSON. */
26
+ export declare function getSessionEntryDetail(file: string, id: string, signal?: AbortSignal): Promise<{
27
+ entry: unknown;
28
+ }>;
@@ -1,5 +1,5 @@
1
1
  import type React from "react";
2
- export type DashboardSection = "overview" | "requests" | "errors" | "models" | "providers" | "tools" | "costs" | "behavior" | "projects" | "gain";
2
+ export type DashboardSection = "overview" | "requests" | "traces" | "errors" | "models" | "providers" | "tools" | "costs" | "behavior" | "projects" | "gain";
3
3
  export interface DashboardRoute {
4
4
  id: DashboardSection;
5
5
  label: string;
@@ -5,4 +5,6 @@ export declare function useHashRoute(): {
5
5
  setSection: (newSection: DashboardSection) => void;
6
6
  range: TimeRange;
7
7
  setRange: (newRange: string) => void;
8
+ session: string | null;
9
+ setSession: (file: string | null) => void;
8
10
  };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Traces section: root-session list (subagents folded in) that opens the
3
+ * flamegraph trace viewer for a selected session.
4
+ */
5
+ export interface TracesRouteProps {
6
+ active: boolean;
7
+ session: string | null;
8
+ onOpenSession: (file: string | null) => void;
9
+ refreshTrigger: number;
10
+ }
11
+ export declare function TracesRoute({ active, session, onOpenSession, refreshTrigger }: TracesRouteProps): import("react").JSX.Element;
@@ -8,3 +8,4 @@ export * from "./ProjectsRoute.js";
8
8
  export * from "./ProvidersRoute.js";
9
9
  export * from "./RequestsRoute.js";
10
10
  export * from "./ToolsRoute.js";
11
+ export * from "./TracesRoute.js";
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Collapsible per-tool duration aggregates for one trace, sorted by total
3
+ * time descending (as produced by the server).
4
+ */
5
+ import type { TraceToolStat } from "../types.js";
6
+ export interface AggregatesPanelProps {
7
+ toolStats: TraceToolStat[];
8
+ }
9
+ export declare function AggregatesPanel({ toolStats }: AggregatesPanelProps): import("react").JSX.Element | null;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Timeline overview strip: per-category density over the full virtual domain
3
+ * plus a draggable/resizable viewport brush, mirroring DevTools' overview.
4
+ */
5
+ import type { TraceTrack } from "../types.js";
6
+ import type { TimelineViewport } from "./TimelineCanvas.js";
7
+ import type { TraceScale } from "./time-scale.js";
8
+ export interface MinimapProps {
9
+ tracks: TraceTrack[];
10
+ scale: TraceScale;
11
+ viewport: TimelineViewport;
12
+ onViewportChange: (viewport: TimelineViewport) => void;
13
+ }
14
+ export declare function Minimap({ tracks, scale, viewport, onViewportChange }: MinimapProps): import("react").JSX.Element;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Detail drawer for a selected trace span. Fetches the full journal entry on
3
+ * demand (`/api/session/entry`) and renders per-kind detail: model usage grid
4
+ * + text blocks, tool args/result, user text, subagent task text.
5
+ */
6
+ import type { TraceSpan, TraceTrack } from "../types.js";
7
+ export interface SpanDrawerProps {
8
+ span: TraceSpan | null;
9
+ track: TraceTrack | null;
10
+ onClose: () => void;
11
+ /** Selects the first span of the given child track ("open child track"). */
12
+ onOpenChildTrack?: (childTrackId: string) => void;
13
+ }
14
+ export declare function SpanDrawer({ span, track, onClose, onOpenChildTrack }: SpanDrawerProps): import("react").JSX.Element | null;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Headline chips for one trace: wall/model/tool/idle time, turns, requests,
3
+ * tool calls, agents, tokens, cost.
4
+ */
5
+ import type { TraceSummary } from "../types.js";
6
+ export interface SummaryStripProps {
7
+ summary: TraceSummary;
8
+ }
9
+ export declare function SummaryStrip({ summary }: SummaryStripProps): import("react").JSX.Element;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The trace flamegraph: one DPR-scaled canvas with a DOM gutter (track/lane
3
+ * labels, collapse chevrons) and a DOM tooltip. Implements the Chrome
4
+ * DevTools interaction contract: cursor-anchored wheel zoom, drag pan, WASD,
5
+ * fit/focus keys, hover tooltips, click-to-select, double-click-to-zoom.
6
+ */
7
+ import type { TraceTrack } from "../types.js";
8
+ import { type TraceScale } from "./time-scale.js";
9
+ export interface TimelineViewport {
10
+ u0: number;
11
+ u1: number;
12
+ }
13
+ export interface TimelineCanvasProps {
14
+ tracks: TraceTrack[];
15
+ scale: TraceScale;
16
+ viewport: TimelineViewport;
17
+ onViewportChange: (viewport: TimelineViewport) => void;
18
+ selection: string | null;
19
+ onSelect: (spanId: string | null) => void;
20
+ search: string;
21
+ collapsed: ReadonlySet<string>;
22
+ onToggleCollapse: (trackId: string) => void;
23
+ traceStart: number;
24
+ }
25
+ export declare function TimelineCanvas({ tracks, scale, viewport, onViewportChange, selection, onSelect, search, collapsed, onToggleCollapse, traceStart, }: TimelineCanvasProps): import("react").JSX.Element;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Single-session trace viewer: summary strip, axis-mode toolbar, minimap,
3
+ * flamegraph canvas, transcript list, tool aggregates, and the span drawer.
4
+ * Owns the shared viewport/selection state so all pieces stay in sync.
5
+ */
6
+ export interface TraceViewProps {
7
+ file: string;
8
+ active: boolean;
9
+ onBack: () => void;
10
+ }
11
+ export declare function TraceView({ file, active, onBack }: TraceViewProps): import("react").JSX.Element;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Windowed transcript list under the timeline: all spans + markers flattened
3
+ * chronologically across tracks, bidirectionally synced with the canvas
4
+ * selection. Hand-rolled fixed-row virtualization (32px rows, spacer divs).
5
+ */
6
+ import type { TraceMarker, TraceSpan, TraceTrack } from "../types.js";
7
+ export interface TranscriptRow {
8
+ key: string;
9
+ time: number;
10
+ span?: TraceSpan;
11
+ marker?: TraceMarker;
12
+ track: TraceTrack;
13
+ depth: number;
14
+ }
15
+ export interface TranscriptListProps {
16
+ tracks: TraceTrack[];
17
+ selection: string | null;
18
+ onSelect: (spanId: string) => void;
19
+ search: string;
20
+ traceStart: number;
21
+ }
22
+ /** Flatten all spans and markers across tracks into chronological rows. */
23
+ export declare function buildTranscriptRows(tracks: TraceTrack[]): TranscriptRow[];
24
+ export declare function TranscriptList({ tracks, selection, onSelect, search, traceStart }: TranscriptListProps): import("react").JSX.Element;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Virtual time axis for the trace flamegraph.
3
+ *
4
+ * All three axis modes are piecewise-linear monotonic maps over global wall
5
+ * time, so cross-track alignment is preserved in every mode:
6
+ * - `time`: identity, or idle-compressed (long gaps collapse to fixed bridges)
7
+ * - `turns`: each main-track turn interval gets equal virtual width
8
+ * - `calls`: each interval between consecutive span boundaries gets equal width
9
+ */
10
+ import type { TraceTrack } from "../types.js";
11
+ export type AxisMode = "time" | "turns" | "calls";
12
+ export interface TraceScale {
13
+ /** ms epoch → virtual axis; monotonic non-decreasing. */
14
+ toU(t: number): number;
15
+ /** Inverse (clamped to domain). */
16
+ toT(u: number): number;
17
+ /** Virtual axis domain. */
18
+ domain: [number, number];
19
+ /** Idle bridges (time mode + compression): real gap [t0,t1] at virtual uMid. */
20
+ gaps: Array<{
21
+ t0: number;
22
+ t1: number;
23
+ uMid: number;
24
+ }>;
25
+ }
26
+ /** Build the axis map for the given mode over all tracks. */
27
+ export declare function buildScale(tracks: TraceTrack[], mode: AxisMode, compressIdle: boolean): TraceScale;
28
+ export interface Tick {
29
+ u: number;
30
+ label: string;
31
+ major: boolean;
32
+ }
33
+ /** Offset label from trace start: `+mm:ss.mmm`, hours prepended when needed. */
34
+ export declare function formatOffset(deltaMs: number): string;
35
+ /**
36
+ * Ruler ticks inside `[u0, u1]`. Ticks are placed at nice wall-time steps in
37
+ * the underlying t-space (per linear segment in compressed/sequence modes),
38
+ * with major ticks labelled as local wall clock and minors as offsets.
39
+ */
40
+ export declare function buildTicks(scale: TraceScale, u0: number, u1: number, widthPx: number): Tick[];
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Category palette + canvas chrome tokens for the trace flamegraph, keyed by
3
+ * resolved theme. Hues align with the dashboard chip palette; chrome tokens
4
+ * mirror `CHART_THEMES` so the canvas matches the chart.js surfaces.
5
+ */
6
+ import type { TraceSpanKind } from "../types.js";
7
+ export interface TraceTheme {
8
+ /** Span fill per category. */
9
+ category: Record<TraceSpanKind, string>;
10
+ /** Error fill tint + left-edge accent. */
11
+ error: string;
12
+ /** Marker diamond fill. */
13
+ marker: string;
14
+ /** Alternating turn-band fill. */
15
+ turnBand: string;
16
+ /** Canvas background. */
17
+ surface: string;
18
+ /** Ruler/lane hairlines. */
19
+ grid: string;
20
+ /** Ruler tick labels. */
21
+ tick: string;
22
+ /** Span label text drawn inside blocks. */
23
+ spanText: string;
24
+ /** Selection outline (brand cyan focus ring). */
25
+ selection: string;
26
+ tooltipBackground: string;
27
+ tooltipTitle: string;
28
+ tooltipBody: string;
29
+ tooltipBorder: string;
30
+ }
31
+ export declare const TRACE_THEMES: Record<"dark" | "light", TraceTheme>;
@@ -1,5 +1,5 @@
1
1
  import { Database } from "bun:sqlite";
2
- import type { AgentTypeStats, AggregatedStats, BehaviorModelStats, BehaviorOverallStats, BehaviorTimeSeriesPoint, CostTimeSeriesPoint, FolderStats, MessageStats, ModelPerformancePoint, ModelStats, ModelTimeSeriesPoint, ProviderAggregate, ProviderHourlyPoint, ProviderTimeSeriesPoint, TimeSeriesPoint, ToolCallStats, ToolModelStats, ToolResultLink, ToolTimeSeriesPoint, ToolUsageStats, UserMessageLink, UserMessageStats } from "./types.js";
2
+ import type { AgentTypeStats, AggregatedStats, BehaviorModelStats, BehaviorOverallStats, BehaviorTimeSeriesPoint, CostTimeSeriesPoint, DailyActivityPoint, FolderStats, MessageStats, ModelPerformancePoint, ModelStats, ModelTimeSeriesPoint, ProviderAggregate, ProviderHourlyPoint, ProviderTimeSeriesPoint, TimeSeriesPoint, ToolCallStats, ToolModelStats, ToolResultLink, ToolTimeSeriesPoint, ToolUsageStats, UserMessageLink, UserMessageStats } from "./types.js";
3
3
  /**
4
4
  * Initialize the database and create tables.
5
5
  */
@@ -90,10 +90,33 @@ export declare function closeDb(): void;
90
90
  export declare function getRecentRequests(limit?: number): MessageStats[];
91
91
  export declare function getRecentErrors(limit?: number, cutoff?: number | null): MessageStats[];
92
92
  export declare function getMessageById(id: number): MessageStats | null;
93
+ /** Per-transcript-file rollup for the Traces session list. */
94
+ export interface SessionRollupRow {
95
+ sessionFile: string;
96
+ requests: number;
97
+ startedAt: number;
98
+ endedAt: number;
99
+ totalTokens: number;
100
+ costTotal: number;
101
+ /** Comma-joined DISTINCT models. */
102
+ models: string;
103
+ }
104
+ /** Aggregate every synced transcript file into one row (subagents unfolded). */
105
+ export declare function getSessionRollups(): SessionRollupRow[];
106
+ /** Tool-call counts keyed by transcript file, for the Traces session list. */
107
+ export declare function getToolCallCountsBySession(): Map<string, number>;
93
108
  /**
94
109
  * Get daily cost time series data for the last N days, broken down by model.
95
110
  */
96
111
  export declare function getCostTimeSeries(days?: number, cutoff?: number | null): CostTimeSeriesPoint[];
112
+ /**
113
+ * Per-local-day activity aggregates for the last `days` days, oldest first.
114
+ * Self-initializing (opens the stats DB on first use) so the coding-agent TUI
115
+ * can query without the dashboard server's init flow. Days use the machine's
116
+ * timezone — this is a localhost tool, same rationale as
117
+ * {@link getProviderHourlyBurn}.
118
+ */
119
+ export declare function getDailyActivity(days?: number): Promise<DailyActivityPoint[]>;
97
120
  /**
98
121
  * Settle every full-session backfill after a successful sync pass.
99
122
  */
@@ -3,7 +3,7 @@ export { getDashboardStats, getToolDashboardStats, getTotalMessageCount, type Sy
3
3
  export { closeDb } from "./db.js";
4
4
  export { getGainDashboardStats } from "./gain-aggregator.js";
5
5
  export { formatStatsDashboardUrl, startServer } from "./server.js";
6
- export type { GainDashboardStats, GainSource, GainSourceTotals, GainTimeSeriesPoint, } from "./shared-types.js";
6
+ export type { GainDashboardStats, GainSource, GainSourceTotals, GainTimeSeriesPoint } from "./shared-types.js";
7
7
  export type { AggregatedStats, DashboardStats, FolderStats, MessageStats, ModelPerformancePoint, ModelStats, ModelTimeSeriesPoint, TimeSeriesPoint, ToolDashboardStats, ToolModelStats, ToolTimeSeriesPoint, ToolUsageStats, } from "./types.js";
8
8
  /** Parsed arguments for the standalone `omp-stats` entry point. */
9
9
  export interface StandaloneStatsArgs {
@@ -10,6 +10,14 @@ import type { AgentType, MessageStats, SessionEntry, ToolCallStats, ToolResultLi
10
10
  * is a task `subagent`.
11
11
  */
12
12
  export declare function classifyAgentType(sessionPath: string): AgentType;
13
+ /**
14
+ * Extract folder name from session filename.
15
+ * Session files are named like: --work--pi--/timestamp_uuid.jsonl
16
+ * The folder part uses -- as path separator.
17
+ */
18
+ export declare function extractFolderFromPath(sessionPath: string): string;
19
+ /** Parse every well-formed entry in a transcript buffer (malformed lines skipped). */
20
+ export declare function parseAllSessionEntries(bytes: Uint8Array): SessionEntry[];
13
21
  /**
14
22
  * Parse a session file and extract all assistant message stats.
15
23
  * Uses incremental reading with offset tracking.
@@ -7,8 +7,9 @@ export declare function formatStatsDashboardUrl(hostname: string, port: number):
7
7
  /**
8
8
  * Start the HTTP server, reusing a live dashboard or reclaiming a stale omp listener.
9
9
  */
10
- export declare function startServer(port?: number, hostname?: string): Promise<{
10
+ export interface StatsServerHandle {
11
11
  hostname: string;
12
12
  port: number;
13
13
  stop: () => void;
14
- }>;
14
+ }
15
+ export declare function startServer(port?: number, hostname?: string): Promise<StatsServerHandle>;