@tokentop/ttop 0.2.2 → 0.3.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 (158) 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 +32 -32
  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 +29 -23
  19. package/src/plugins/notifications/visual-flash.ts +21 -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 +66 -57
  34. package/src/plugins/registry.ts +47 -43
  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/repos/agentSessions.ts +33 -23
  73. package/src/storage/repos/providerSnapshots.ts +5 -5
  74. package/src/storage/repos/usageEvents.ts +40 -28
  75. package/src/storage/types.ts +5 -5
  76. package/src/tui/App.tsx +180 -137
  77. package/src/tui/components/CommandPalette.tsx +46 -34
  78. package/src/tui/components/DebugConsole.tsx +39 -33
  79. package/src/tui/components/DebugPanel.tsx +295 -177
  80. package/src/tui/components/FooterHints.tsx +2 -2
  81. package/src/tui/components/GhostProviderCard.tsx +37 -35
  82. package/src/tui/components/Header.tsx +68 -35
  83. package/src/tui/components/HelpOverlay.tsx +99 -29
  84. package/src/tui/components/InlineGauge.tsx +10 -7
  85. package/src/tui/components/InlineSparkline.tsx +17 -11
  86. package/src/tui/components/KpiStrip.tsx +128 -98
  87. package/src/tui/components/LimitGauge.tsx +96 -59
  88. package/src/tui/components/ModalBackdrop.tsx +4 -4
  89. package/src/tui/components/ProviderAggregateStrip.tsx +69 -38
  90. package/src/tui/components/ProviderCard.tsx +232 -226
  91. package/src/tui/components/ProviderDetailPanel.tsx +133 -58
  92. package/src/tui/components/ProviderLimitsPanel.tsx +126 -89
  93. package/src/tui/components/ProvidersList.tsx +215 -126
  94. package/src/tui/components/SessionDetailsDrawer.tsx +191 -94
  95. package/src/tui/components/SessionsTable.tsx +313 -166
  96. package/src/tui/components/SettingsModal.tsx +231 -214
  97. package/src/tui/components/SidebarBreakdown.tsx +30 -16
  98. package/src/tui/components/Skeleton.tsx +24 -17
  99. package/src/tui/components/SmartSidebar.tsx +360 -258
  100. package/src/tui/components/Sparkline.tsx +64 -52
  101. package/src/tui/components/Spinner.tsx +3 -3
  102. package/src/tui/components/StatusBar.tsx +27 -27
  103. package/src/tui/components/ThemePicker.tsx +67 -66
  104. package/src/tui/components/Toast.tsx +9 -6
  105. package/src/tui/components/UsageGauge.tsx +10 -13
  106. package/src/tui/components/index.ts +5 -5
  107. package/src/tui/contexts/AgentSessionContext.tsx +193 -144
  108. package/src/tui/contexts/ConfigContext.tsx +15 -13
  109. package/src/tui/contexts/DashboardRuntimeContext.tsx +26 -26
  110. package/src/tui/contexts/DemoModeContext.tsx +22 -15
  111. package/src/tui/contexts/DrawerContext.tsx +11 -9
  112. package/src/tui/contexts/InputContext.tsx +2 -2
  113. package/src/tui/contexts/LogContext.tsx +62 -47
  114. package/src/tui/contexts/PluginContext.tsx +232 -183
  115. package/src/tui/contexts/RealTimeActivityContext.tsx +70 -36
  116. package/src/tui/contexts/StorageContext.tsx +151 -117
  117. package/src/tui/contexts/ThemeContext.tsx +21 -16
  118. package/src/tui/contexts/TimeWindowContext.tsx +72 -61
  119. package/src/tui/contexts/ToastContext.tsx +10 -7
  120. package/src/tui/contexts/index.ts +9 -5
  121. package/src/tui/createApp.tsx +8 -12
  122. package/src/tui/debug/captureFrame.ts +25 -28
  123. package/src/tui/debug/snapshot.tsx +179 -162
  124. package/src/tui/driver/assertions.ts +30 -22
  125. package/src/tui/driver/cli.ts +231 -221
  126. package/src/tui/driver/coverage.ts +27 -44
  127. package/src/tui/driver/demo-snapshot.ts +33 -33
  128. package/src/tui/driver/diff.ts +26 -32
  129. package/src/tui/driver/driver.ts +43 -48
  130. package/src/tui/driver/index.ts +36 -40
  131. package/src/tui/driver/recorder.ts +37 -48
  132. package/src/tui/driver/test-workflow.ts +51 -51
  133. package/src/tui/driver/test.ts +25 -25
  134. package/src/tui/hooks/index.ts +24 -20
  135. package/src/tui/hooks/useAnimatedValue.ts +13 -18
  136. package/src/tui/hooks/useDashboardKeyboard.ts +118 -98
  137. package/src/tui/hooks/useDashboardState.ts +26 -24
  138. package/src/tui/hooks/useEmaActivity.ts +82 -74
  139. package/src/tui/hooks/useEntranceAnimation.ts +11 -11
  140. package/src/tui/hooks/useExitAnimation.ts +3 -3
  141. package/src/tui/hooks/usePulse.ts +4 -4
  142. package/src/tui/hooks/useSafeRenderer.ts +5 -5
  143. package/src/tui/hooks/useSessionEnrichedProviders.ts +150 -0
  144. package/src/tui/hooks/useValueFlash.ts +10 -14
  145. package/src/tui/index.tsx +29 -6
  146. package/src/tui/shutdown.ts +19 -0
  147. package/src/tui/utils/providerColor.ts +1 -1
  148. package/src/tui/views/Dashboard.tsx +127 -102
  149. package/src/tui/views/HistoricalTrendsView.tsx +579 -250
  150. package/src/tui/views/ProjectsView.tsx +466 -237
  151. package/src/tui/views/RealTimeDashboard.tsx +150 -111
  152. package/src/tui/views/SettingsView.tsx +222 -191
  153. package/src/tui/views/index.ts +2 -2
  154. package/src/types/opentui-test-utils.d.ts +7 -7
  155. package/src/utils/clipboard.ts +29 -29
  156. package/src/utils/currency.test.ts +53 -53
  157. package/src/utils/currency.ts +35 -32
  158. 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
  );