@tokentop/ttop 0.2.2 → 0.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 (160) hide show
  1. package/README.md +2 -5
  2. package/package.json +8 -5
  3. package/src/agents/aggregator.ts +39 -19
  4. package/src/agents/costing.ts +11 -9
  5. package/src/agents/index.ts +7 -9
  6. package/src/agents/types.ts +2 -2
  7. package/src/cli.ts +28 -23
  8. package/src/config/schema.test.ts +42 -40
  9. package/src/config/schema.ts +26 -26
  10. package/src/demo/simulator.ts +161 -122
  11. package/src/plugins/agents/index.ts +2 -2
  12. package/src/plugins/auth-sources.ts +42 -38
  13. package/src/plugins/lifecycle.ts +42 -38
  14. package/src/plugins/loader.test.ts +49 -49
  15. package/src/plugins/loader.ts +67 -63
  16. package/src/plugins/notification-bus.ts +21 -16
  17. package/src/plugins/notifications/index.ts +2 -2
  18. package/src/plugins/notifications/terminal-bell.ts +36 -23
  19. package/src/plugins/notifications/visual-flash.ts +31 -19
  20. package/src/plugins/npm-installer.ts +23 -25
  21. package/src/plugins/plugin-context-factory.ts +10 -10
  22. package/src/plugins/plugin-host.ts +12 -5
  23. package/src/plugins/providers/anthropic.ts +64 -57
  24. package/src/plugins/providers/antigravity.ts +81 -69
  25. package/src/plugins/providers/codex.ts +42 -42
  26. package/src/plugins/providers/gemini.ts +106 -87
  27. package/src/plugins/providers/github-copilot.ts +49 -45
  28. package/src/plugins/providers/index.ts +10 -12
  29. package/src/plugins/providers/minimax.ts +50 -44
  30. package/src/plugins/providers/openai-api.ts +82 -62
  31. package/src/plugins/providers/opencode-zen.ts +46 -39
  32. package/src/plugins/providers/perplexity.ts +55 -46
  33. package/src/plugins/providers/zai.ts +68 -57
  34. package/src/plugins/registry.ts +80 -71
  35. package/src/plugins/sandbox-guard.test.ts +45 -48
  36. package/src/plugins/sandbox-guard.ts +20 -25
  37. package/src/plugins/sandbox.ts +26 -48
  38. package/src/plugins/themes/catppuccin-latte.ts +29 -29
  39. package/src/plugins/themes/catppuccin-mocha.ts +29 -29
  40. package/src/plugins/themes/claude-code.ts +29 -29
  41. package/src/plugins/themes/dracula.ts +29 -29
  42. package/src/plugins/themes/github-light.ts +29 -29
  43. package/src/plugins/themes/gruvbox-dark.ts +29 -29
  44. package/src/plugins/themes/gruvbox-light.ts +29 -29
  45. package/src/plugins/themes/index.ts +15 -15
  46. package/src/plugins/themes/kanagawa.ts +29 -29
  47. package/src/plugins/themes/nord.ts +29 -29
  48. package/src/plugins/themes/one-dark.ts +29 -29
  49. package/src/plugins/themes/opencode.ts +31 -31
  50. package/src/plugins/themes/rose-pine-dawn.ts +29 -29
  51. package/src/plugins/themes/rose-pine.ts +29 -29
  52. package/src/plugins/themes/solarized-light.ts +29 -29
  53. package/src/plugins/themes/tokyo-night.ts +29 -29
  54. package/src/plugins/types/agent.ts +5 -5
  55. package/src/plugins/types/base.ts +35 -24
  56. package/src/plugins/types/index.ts +9 -9
  57. package/src/plugins/types/notification.ts +12 -12
  58. package/src/plugins/types/provider.ts +12 -8
  59. package/src/plugins/types/theme.ts +31 -23
  60. package/src/plugins/update-checker.ts +6 -6
  61. package/src/pricing/estimator.test.ts +39 -44
  62. package/src/pricing/estimator.ts +7 -13
  63. package/src/pricing/fallback.test.ts +30 -34
  64. package/src/pricing/fallback.ts +54 -27
  65. package/src/pricing/index.ts +18 -12
  66. package/src/pricing/models-dev.ts +6 -6
  67. package/src/storage/database.ts +56 -46
  68. package/src/storage/db.ts +12 -12
  69. package/src/storage/index.ts +44 -45
  70. package/src/storage/migrations/index.ts +2 -2
  71. package/src/storage/paths.ts +13 -13
  72. package/src/storage/persistence-service.ts +206 -0
  73. package/src/storage/repos/agentSessions.ts +33 -23
  74. package/src/storage/repos/providerSnapshots.ts +5 -5
  75. package/src/storage/repos/usageEvents.ts +40 -28
  76. package/src/storage/retention.ts +146 -0
  77. package/src/storage/types.ts +5 -5
  78. package/src/tui/App.tsx +180 -137
  79. package/src/tui/components/CommandPalette.tsx +46 -34
  80. package/src/tui/components/DebugConsole.tsx +39 -33
  81. package/src/tui/components/DebugPanel.tsx +314 -183
  82. package/src/tui/components/FooterHints.tsx +2 -2
  83. package/src/tui/components/GhostProviderCard.tsx +37 -35
  84. package/src/tui/components/Header.tsx +68 -35
  85. package/src/tui/components/HelpOverlay.tsx +99 -29
  86. package/src/tui/components/InlineGauge.tsx +10 -7
  87. package/src/tui/components/InlineSparkline.tsx +17 -11
  88. package/src/tui/components/KpiStrip.tsx +128 -98
  89. package/src/tui/components/LimitGauge.tsx +96 -59
  90. package/src/tui/components/ModalBackdrop.tsx +4 -4
  91. package/src/tui/components/ProviderAggregateStrip.tsx +69 -38
  92. package/src/tui/components/ProviderCard.tsx +232 -226
  93. package/src/tui/components/ProviderDetailPanel.tsx +133 -58
  94. package/src/tui/components/ProviderLimitsPanel.tsx +126 -89
  95. package/src/tui/components/ProvidersList.tsx +215 -126
  96. package/src/tui/components/SessionDetailsDrawer.tsx +191 -94
  97. package/src/tui/components/SessionsTable.tsx +320 -169
  98. package/src/tui/components/SettingsModal.tsx +593 -269
  99. package/src/tui/components/SidebarBreakdown.tsx +30 -16
  100. package/src/tui/components/Skeleton.tsx +24 -17
  101. package/src/tui/components/SmartSidebar.tsx +360 -258
  102. package/src/tui/components/Sparkline.tsx +64 -52
  103. package/src/tui/components/Spinner.tsx +3 -3
  104. package/src/tui/components/StatusBar.tsx +27 -27
  105. package/src/tui/components/ThemePicker.tsx +67 -66
  106. package/src/tui/components/Toast.tsx +9 -6
  107. package/src/tui/components/UsageGauge.tsx +10 -13
  108. package/src/tui/components/index.ts +5 -5
  109. package/src/tui/contexts/AgentSessionContext.tsx +164 -151
  110. package/src/tui/contexts/ConfigContext.tsx +15 -13
  111. package/src/tui/contexts/DashboardRuntimeContext.tsx +26 -26
  112. package/src/tui/contexts/DemoModeContext.tsx +22 -15
  113. package/src/tui/contexts/DrawerContext.tsx +11 -9
  114. package/src/tui/contexts/InputContext.tsx +2 -2
  115. package/src/tui/contexts/LogContext.tsx +62 -47
  116. package/src/tui/contexts/PluginContext.tsx +238 -183
  117. package/src/tui/contexts/RealTimeActivityContext.tsx +70 -36
  118. package/src/tui/contexts/StorageContext.tsx +95 -149
  119. package/src/tui/contexts/ThemeContext.tsx +21 -16
  120. package/src/tui/contexts/TimeWindowContext.tsx +72 -61
  121. package/src/tui/contexts/ToastContext.tsx +10 -7
  122. package/src/tui/contexts/index.ts +9 -5
  123. package/src/tui/createApp.tsx +8 -12
  124. package/src/tui/debug/captureFrame.ts +25 -28
  125. package/src/tui/debug/snapshot.tsx +179 -162
  126. package/src/tui/driver/assertions.ts +30 -22
  127. package/src/tui/driver/cli.ts +231 -221
  128. package/src/tui/driver/coverage.ts +27 -44
  129. package/src/tui/driver/demo-snapshot.ts +33 -33
  130. package/src/tui/driver/diff.ts +26 -32
  131. package/src/tui/driver/driver.ts +43 -48
  132. package/src/tui/driver/index.ts +36 -40
  133. package/src/tui/driver/recorder.ts +37 -48
  134. package/src/tui/driver/test-workflow.ts +51 -51
  135. package/src/tui/driver/test.ts +25 -25
  136. package/src/tui/hooks/index.ts +24 -20
  137. package/src/tui/hooks/useAnimatedValue.ts +13 -18
  138. package/src/tui/hooks/useDashboardKeyboard.ts +118 -98
  139. package/src/tui/hooks/useDashboardState.ts +26 -24
  140. package/src/tui/hooks/useEmaActivity.ts +82 -74
  141. package/src/tui/hooks/useEntranceAnimation.ts +11 -11
  142. package/src/tui/hooks/useExitAnimation.ts +7 -3
  143. package/src/tui/hooks/usePulse.ts +4 -4
  144. package/src/tui/hooks/useSafeRenderer.ts +5 -5
  145. package/src/tui/hooks/useSessionEnrichedProviders.ts +150 -0
  146. package/src/tui/hooks/useValueFlash.ts +10 -14
  147. package/src/tui/index.tsx +29 -6
  148. package/src/tui/shutdown.ts +19 -0
  149. package/src/tui/utils/providerColor.ts +1 -1
  150. package/src/tui/views/Dashboard.tsx +164 -102
  151. package/src/tui/views/HistoricalTrendsView.tsx +579 -250
  152. package/src/tui/views/ProjectsView.tsx +495 -243
  153. package/src/tui/views/RealTimeDashboard.tsx +176 -116
  154. package/src/tui/views/SettingsView.tsx +225 -189
  155. package/src/tui/views/index.ts +2 -2
  156. package/src/types/opentui-test-utils.d.ts +7 -7
  157. package/src/utils/clipboard.ts +29 -29
  158. package/src/utils/currency.test.ts +53 -53
  159. package/src/utils/currency.ts +35 -32
  160. package/src/version.ts +1 -1
@@ -1,10 +1,10 @@
1
- import { useMemo } from 'react';
2
- import { useTerminalDimensions } from '@opentui/react';
3
- import { useColors } from '../contexts/ThemeContext.tsx';
4
- import type { ProviderState } from '../contexts/PluginContext.tsx';
1
+ import { useTerminalDimensions } from "@opentui/react";
2
+ import { useMemo } from "react";
3
+ import type { ProviderState } from "../contexts/PluginContext.tsx";
4
+ import { useColors } from "../contexts/ThemeContext.tsx";
5
5
 
6
6
  function pad(str: string, len: number): string {
7
- return str.length >= len ? str.slice(0, len) : str + ' '.repeat(len - str.length);
7
+ return str.length >= len ? str.slice(0, len) : str + " ".repeat(len - str.length);
8
8
  }
9
9
 
10
10
  function formatCost(val: number): string {
@@ -62,10 +62,13 @@ export function computeAggregates(providers: ProviderState[]): ProviderAggregate
62
62
 
63
63
  if (p.usage?.cost) {
64
64
  const cost = p.usage.cost;
65
- const todayTotal = cost.actual?.total ?? cost.estimated?.total ?? 0;
65
+ const todayTotal =
66
+ cost.estimatedDaily?.total ?? cost.actual?.total ?? cost.estimated?.total ?? 0;
67
+ const mtdTotal =
68
+ cost.estimatedMonthly?.total ?? cost.actual?.total ?? cost.estimated?.total ?? 0;
66
69
  costToday += todayTotal;
67
- costMtd += todayTotal;
68
- if (cost.source === 'estimated') {
70
+ costMtd += mtdTotal;
71
+ if (cost.source === "estimated" || cost.estimatedDaily || cost.estimatedMonthly) {
69
72
  costTodayEstimated = true;
70
73
  costMtdEstimated = true;
71
74
  }
@@ -122,48 +125,72 @@ export function ProviderAggregateStrip({ providers }: ProviderAggregateStripProp
122
125
 
123
126
  const agg = useMemo(() => computeAggregates(providers), [providers]);
124
127
 
125
- const costTodayStr = `${agg.costTodayEstimated ? '~' : ''}${formatCost(agg.costToday)}`;
126
- const costMtdStr = `${agg.costMtdEstimated ? '~' : ''}${formatCost(agg.costMtd)}`;
127
- const tokensStr = `${agg.tokens24hEstimated ? '~' : ''}${formatTokens(agg.totalTokens24h)}`;
128
-
129
- const trendStr = agg.trendVsYesterday !== null
130
- ? (agg.trendVsYesterday >= 0 ? `+${agg.trendVsYesterday.toFixed(0)}%` : `${agg.trendVsYesterday.toFixed(0)}%`)
131
- : '—';
132
- const trendColor = agg.trendVsYesterday !== null
133
- ? (agg.trendVsYesterday > 10 ? colors.warning : agg.trendVsYesterday < -10 ? colors.success : colors.textMuted)
134
- : colors.textSubtle;
128
+ const costTodayStr = `${agg.costTodayEstimated ? "~" : ""}${formatCost(agg.costToday)}`;
129
+ const costMtdStr = `${agg.costMtdEstimated ? "~" : ""}${formatCost(agg.costMtd)}`;
130
+ const tokensStr = `${agg.tokens24hEstimated ? "~" : ""}${formatTokens(agg.totalTokens24h)}`;
131
+
132
+ const trendStr =
133
+ agg.trendVsYesterday !== null
134
+ ? agg.trendVsYesterday >= 0
135
+ ? `+${agg.trendVsYesterday.toFixed(0)}%`
136
+ : `${agg.trendVsYesterday.toFixed(0)}%`
137
+ : "—";
138
+ const trendColor =
139
+ agg.trendVsYesterday !== null
140
+ ? agg.trendVsYesterday > 10
141
+ ? colors.warning
142
+ : agg.trendVsYesterday < -10
143
+ ? colors.success
144
+ : colors.textMuted
145
+ : colors.textSubtle;
135
146
 
136
147
  return (
137
148
  <box flexDirection="column" flexShrink={0}>
138
149
  <box flexDirection="row" height={1} gap={2} paddingX={1}>
139
150
  <text height={1}>
140
151
  <span fg={colors.textMuted}>HEALTH </span>
141
- {agg.okCount > 0 && <span fg={colors.success}>{pad(`${agg.okCount} ok`, isCompact ? 5 : 5)}</span>}
142
- {agg.warnCount > 0 && <span fg={colors.warning}> {pad(`${agg.warnCount} warn`, isCompact ? 7 : 7)}</span>}
143
- {agg.errCount > 0 && <span fg={colors.error}> {pad(`${agg.errCount} err`, isCompact ? 6 : 6)}</span>}
152
+ {agg.okCount > 0 && (
153
+ <span fg={colors.success}>{pad(`${agg.okCount} ok`, isCompact ? 5 : 5)}</span>
154
+ )}
155
+ {agg.warnCount > 0 && (
156
+ <span fg={colors.warning}> {pad(`${agg.warnCount} warn`, isCompact ? 7 : 7)}</span>
157
+ )}
158
+ {agg.errCount > 0 && (
159
+ <span fg={colors.error}> {pad(`${agg.errCount} err`, isCompact ? 6 : 6)}</span>
160
+ )}
144
161
  {agg.okCount === 0 && agg.warnCount === 0 && agg.errCount === 0 && (
145
162
  <span fg={colors.textSubtle}>no providers</span>
146
163
  )}
147
164
  </text>
148
165
 
149
- <text fg={colors.textSubtle} height={1}>│</text>
166
+ <text fg={colors.textSubtle} height={1}>
167
+ │
168
+ </text>
150
169
 
151
170
  <text height={1}>
152
171
  <span fg={colors.textMuted}>TODAY </span>
153
- <span fg={agg.costTodayEstimated ? colors.textMuted : colors.success}>{costTodayStr}</span>
172
+ <span fg={agg.costTodayEstimated ? colors.textMuted : colors.success}>
173
+ {costTodayStr}
174
+ </span>
154
175
  </text>
155
176
 
156
177
  {!isCompact && (
157
178
  <>
158
- <text fg={colors.textSubtle} height={1}>│</text>
179
+ <text fg={colors.textSubtle} height={1}>
180
+ │
181
+ </text>
159
182
  <text height={1}>
160
183
  <span fg={colors.textMuted}>MTD </span>
161
- <span fg={agg.costMtdEstimated ? colors.textMuted : colors.success}>{costMtdStr}</span>
184
+ <span fg={agg.costMtdEstimated ? colors.textMuted : colors.success}>
185
+ {costMtdStr}
186
+ </span>
162
187
  </text>
163
188
  </>
164
189
  )}
165
190
 
166
- <text fg={colors.textSubtle} height={1}>│</text>
191
+ <text fg={colors.textSubtle} height={1}>
192
+ │
193
+ </text>
167
194
 
168
195
  <text height={1}>
169
196
  <span fg={colors.textMuted}>TOKENS </span>
@@ -173,18 +200,22 @@ export function ProviderAggregateStrip({ providers }: ProviderAggregateStripProp
173
200
 
174
201
  <box flexDirection="row" height={1} gap={2} paddingX={1}>
175
202
  {agg.hottestProvider && (
176
- <text height={1}>
177
- <span fg={colors.textMuted}>HOTTEST </span>
178
- <span fg={agg.hottestPercent >= 80 ? colors.warning : colors.text}>
179
- {pad(agg.hottestProvider, isCompact ? 10 : 14)}
180
- </span>
181
- <span fg={agg.hottestPercent >= 80 ? colors.warning : colors.textMuted}>
182
- {` ${Math.round(agg.hottestPercent)}%`}
183
- </span>
184
- </text>
185
- )}
203
+ <>
204
+ <text height={1}>
205
+ <span fg={colors.textMuted}>HOTTEST </span>
206
+ <span fg={agg.hottestPercent >= 80 ? colors.warning : colors.text}>
207
+ {pad(agg.hottestProvider, isCompact ? 10 : 14)}
208
+ </span>
209
+ <span fg={agg.hottestPercent >= 80 ? colors.warning : colors.textMuted}>
210
+ {` ${Math.round(agg.hottestPercent)}%`}
211
+ </span>
212
+ </text>
186
213
 
187
- <text fg={colors.textSubtle} height={1}>│</text>
214
+ <text fg={colors.textSubtle} height={1}>
215
+ │
216
+ </text>
217
+ </>
218
+ )}
188
219
 
189
220
  <text height={1}>
190
221
  <span fg={colors.textMuted}>vs YESTERDAY </span>
@@ -193,7 +224,7 @@ export function ProviderAggregateStrip({ providers }: ProviderAggregateStripProp
193
224
  </box>
194
225
 
195
226
  <box height={1} overflow="hidden">
196
- <text fg={colors.border}>{'─'.repeat(300)}</text>
227
+ <text fg={colors.border}>{"─".repeat(300)}</text>
197
228
  </box>
198
229
  </box>
199
230
  );