@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.
- package/README.md +2 -5
- package/package.json +8 -5
- package/src/agents/aggregator.ts +39 -19
- package/src/agents/costing.ts +11 -9
- package/src/agents/index.ts +7 -9
- package/src/agents/types.ts +2 -2
- package/src/cli.ts +28 -23
- package/src/config/schema.test.ts +42 -40
- package/src/config/schema.ts +26 -26
- package/src/demo/simulator.ts +161 -122
- package/src/plugins/agents/index.ts +2 -2
- package/src/plugins/auth-sources.ts +42 -38
- package/src/plugins/lifecycle.ts +32 -32
- package/src/plugins/loader.test.ts +49 -49
- package/src/plugins/loader.ts +67 -63
- package/src/plugins/notification-bus.ts +21 -16
- package/src/plugins/notifications/index.ts +2 -2
- package/src/plugins/notifications/terminal-bell.ts +29 -23
- package/src/plugins/notifications/visual-flash.ts +21 -19
- package/src/plugins/npm-installer.ts +23 -25
- package/src/plugins/plugin-context-factory.ts +10 -10
- package/src/plugins/plugin-host.ts +12 -5
- package/src/plugins/providers/anthropic.ts +64 -57
- package/src/plugins/providers/antigravity.ts +81 -69
- package/src/plugins/providers/codex.ts +42 -42
- package/src/plugins/providers/gemini.ts +106 -87
- package/src/plugins/providers/github-copilot.ts +49 -45
- package/src/plugins/providers/index.ts +10 -12
- package/src/plugins/providers/minimax.ts +50 -44
- package/src/plugins/providers/openai-api.ts +82 -62
- package/src/plugins/providers/opencode-zen.ts +46 -39
- package/src/plugins/providers/perplexity.ts +55 -46
- package/src/plugins/providers/zai.ts +66 -57
- package/src/plugins/registry.ts +47 -43
- package/src/plugins/sandbox-guard.test.ts +45 -48
- package/src/plugins/sandbox-guard.ts +20 -25
- package/src/plugins/sandbox.ts +26 -48
- package/src/plugins/themes/catppuccin-latte.ts +29 -29
- package/src/plugins/themes/catppuccin-mocha.ts +29 -29
- package/src/plugins/themes/claude-code.ts +29 -29
- package/src/plugins/themes/dracula.ts +29 -29
- package/src/plugins/themes/github-light.ts +29 -29
- package/src/plugins/themes/gruvbox-dark.ts +29 -29
- package/src/plugins/themes/gruvbox-light.ts +29 -29
- package/src/plugins/themes/index.ts +15 -15
- package/src/plugins/themes/kanagawa.ts +29 -29
- package/src/plugins/themes/nord.ts +29 -29
- package/src/plugins/themes/one-dark.ts +29 -29
- package/src/plugins/themes/opencode.ts +31 -31
- package/src/plugins/themes/rose-pine-dawn.ts +29 -29
- package/src/plugins/themes/rose-pine.ts +29 -29
- package/src/plugins/themes/solarized-light.ts +29 -29
- package/src/plugins/themes/tokyo-night.ts +29 -29
- package/src/plugins/types/agent.ts +5 -5
- package/src/plugins/types/base.ts +35 -24
- package/src/plugins/types/index.ts +9 -9
- package/src/plugins/types/notification.ts +12 -12
- package/src/plugins/types/provider.ts +12 -8
- package/src/plugins/types/theme.ts +31 -23
- package/src/plugins/update-checker.ts +6 -6
- package/src/pricing/estimator.test.ts +39 -44
- package/src/pricing/estimator.ts +7 -13
- package/src/pricing/fallback.test.ts +30 -34
- package/src/pricing/fallback.ts +54 -27
- package/src/pricing/index.ts +18 -12
- package/src/pricing/models-dev.ts +6 -6
- package/src/storage/database.ts +56 -46
- package/src/storage/db.ts +12 -12
- package/src/storage/index.ts +44 -45
- package/src/storage/migrations/index.ts +2 -2
- package/src/storage/paths.ts +13 -13
- package/src/storage/repos/agentSessions.ts +33 -23
- package/src/storage/repos/providerSnapshots.ts +5 -5
- package/src/storage/repos/usageEvents.ts +40 -28
- package/src/storage/types.ts +5 -5
- package/src/tui/App.tsx +180 -137
- package/src/tui/components/CommandPalette.tsx +46 -34
- package/src/tui/components/DebugConsole.tsx +39 -33
- package/src/tui/components/DebugPanel.tsx +295 -177
- package/src/tui/components/FooterHints.tsx +2 -2
- package/src/tui/components/GhostProviderCard.tsx +37 -35
- package/src/tui/components/Header.tsx +68 -35
- package/src/tui/components/HelpOverlay.tsx +99 -29
- package/src/tui/components/InlineGauge.tsx +10 -7
- package/src/tui/components/InlineSparkline.tsx +17 -11
- package/src/tui/components/KpiStrip.tsx +128 -98
- package/src/tui/components/LimitGauge.tsx +96 -59
- package/src/tui/components/ModalBackdrop.tsx +4 -4
- package/src/tui/components/ProviderAggregateStrip.tsx +69 -38
- package/src/tui/components/ProviderCard.tsx +232 -226
- package/src/tui/components/ProviderDetailPanel.tsx +133 -58
- package/src/tui/components/ProviderLimitsPanel.tsx +126 -89
- package/src/tui/components/ProvidersList.tsx +215 -126
- package/src/tui/components/SessionDetailsDrawer.tsx +191 -94
- package/src/tui/components/SessionsTable.tsx +313 -166
- package/src/tui/components/SettingsModal.tsx +231 -214
- package/src/tui/components/SidebarBreakdown.tsx +30 -16
- package/src/tui/components/Skeleton.tsx +24 -17
- package/src/tui/components/SmartSidebar.tsx +360 -258
- package/src/tui/components/Sparkline.tsx +64 -52
- package/src/tui/components/Spinner.tsx +3 -3
- package/src/tui/components/StatusBar.tsx +27 -27
- package/src/tui/components/ThemePicker.tsx +67 -66
- package/src/tui/components/Toast.tsx +9 -6
- package/src/tui/components/UsageGauge.tsx +10 -13
- package/src/tui/components/index.ts +5 -5
- package/src/tui/contexts/AgentSessionContext.tsx +193 -144
- package/src/tui/contexts/ConfigContext.tsx +15 -13
- package/src/tui/contexts/DashboardRuntimeContext.tsx +26 -26
- package/src/tui/contexts/DemoModeContext.tsx +22 -15
- package/src/tui/contexts/DrawerContext.tsx +11 -9
- package/src/tui/contexts/InputContext.tsx +2 -2
- package/src/tui/contexts/LogContext.tsx +62 -47
- package/src/tui/contexts/PluginContext.tsx +232 -183
- package/src/tui/contexts/RealTimeActivityContext.tsx +70 -36
- package/src/tui/contexts/StorageContext.tsx +151 -117
- package/src/tui/contexts/ThemeContext.tsx +21 -16
- package/src/tui/contexts/TimeWindowContext.tsx +72 -61
- package/src/tui/contexts/ToastContext.tsx +10 -7
- package/src/tui/contexts/index.ts +9 -5
- package/src/tui/createApp.tsx +8 -12
- package/src/tui/debug/captureFrame.ts +25 -28
- package/src/tui/debug/snapshot.tsx +179 -162
- package/src/tui/driver/assertions.ts +30 -22
- package/src/tui/driver/cli.ts +231 -221
- package/src/tui/driver/coverage.ts +27 -44
- package/src/tui/driver/demo-snapshot.ts +33 -33
- package/src/tui/driver/diff.ts +26 -32
- package/src/tui/driver/driver.ts +43 -48
- package/src/tui/driver/index.ts +36 -40
- package/src/tui/driver/recorder.ts +37 -48
- package/src/tui/driver/test-workflow.ts +51 -51
- package/src/tui/driver/test.ts +25 -25
- package/src/tui/hooks/index.ts +24 -20
- package/src/tui/hooks/useAnimatedValue.ts +13 -18
- package/src/tui/hooks/useDashboardKeyboard.ts +118 -98
- package/src/tui/hooks/useDashboardState.ts +26 -24
- package/src/tui/hooks/useEmaActivity.ts +82 -74
- package/src/tui/hooks/useEntranceAnimation.ts +11 -11
- package/src/tui/hooks/useExitAnimation.ts +3 -3
- package/src/tui/hooks/usePulse.ts +4 -4
- package/src/tui/hooks/useSafeRenderer.ts +5 -5
- package/src/tui/hooks/useSessionEnrichedProviders.ts +150 -0
- package/src/tui/hooks/useValueFlash.ts +10 -14
- package/src/tui/index.tsx +29 -6
- package/src/tui/shutdown.ts +19 -0
- package/src/tui/utils/providerColor.ts +1 -1
- package/src/tui/views/Dashboard.tsx +127 -102
- package/src/tui/views/HistoricalTrendsView.tsx +579 -250
- package/src/tui/views/ProjectsView.tsx +466 -237
- package/src/tui/views/RealTimeDashboard.tsx +150 -111
- package/src/tui/views/SettingsView.tsx +222 -191
- package/src/tui/views/index.ts +2 -2
- package/src/types/opentui-test-utils.d.ts +7 -7
- package/src/utils/clipboard.ts +29 -29
- package/src/utils/currency.test.ts +53 -53
- package/src/utils/currency.ts +35 -32
- package/src/version.ts +1 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { getDatabase } from
|
|
1
|
+
import { getDatabase } from "../db.ts";
|
|
2
2
|
import type {
|
|
3
3
|
AgentSessionDim,
|
|
4
|
-
AgentSessionUpsert,
|
|
5
4
|
AgentSessionSnapshotInsert,
|
|
6
5
|
AgentSessionStreamSnapshotRow,
|
|
7
|
-
|
|
6
|
+
AgentSessionUpsert,
|
|
7
|
+
} from "../types.ts";
|
|
8
8
|
|
|
9
9
|
const UPSERT_SESSION_SQL = `
|
|
10
10
|
INSERT INTO agent_sessions (agent_id, session_id, project_path, started_at, first_seen_at, last_seen_at)
|
|
@@ -36,21 +36,23 @@ export function upsertAgentSession(session: AgentSessionUpsert): number {
|
|
|
36
36
|
const db = getDatabase();
|
|
37
37
|
const now = Date.now();
|
|
38
38
|
|
|
39
|
-
const row = db
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
const row = db
|
|
40
|
+
.prepare(UPSERT_SESSION_SQL)
|
|
41
|
+
.get(
|
|
42
|
+
session.agentId,
|
|
43
|
+
session.sessionId,
|
|
44
|
+
session.projectPath ?? null,
|
|
45
|
+
session.startedAt ?? null,
|
|
46
|
+
session.firstSeenAt ?? now,
|
|
47
|
+
session.lastSeenAt,
|
|
48
|
+
) as { id: number };
|
|
47
49
|
|
|
48
50
|
return row.id;
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
export function insertAgentSessionSnapshot(
|
|
52
54
|
snapshot: AgentSessionSnapshotInsert,
|
|
53
|
-
streams: Omit<AgentSessionStreamSnapshotRow,
|
|
55
|
+
streams: Omit<AgentSessionStreamSnapshotRow, "agentSessionSnapshotId">[],
|
|
54
56
|
): number {
|
|
55
57
|
const db = getDatabase();
|
|
56
58
|
|
|
@@ -70,7 +72,7 @@ export function insertAgentSessionSnapshot(
|
|
|
70
72
|
snapshot.totalCacheReadTokens,
|
|
71
73
|
snapshot.totalCacheWriteTokens,
|
|
72
74
|
snapshot.totalCostUsd,
|
|
73
|
-
snapshot.requestCount
|
|
75
|
+
snapshot.requestCount,
|
|
74
76
|
);
|
|
75
77
|
|
|
76
78
|
snapshotId = Number(result.lastInsertRowid);
|
|
@@ -86,7 +88,7 @@ export function insertAgentSessionSnapshot(
|
|
|
86
88
|
stream.cacheWriteTokens,
|
|
87
89
|
stream.costUsd,
|
|
88
90
|
stream.requestCount,
|
|
89
|
-
stream.pricingSource ?? null
|
|
91
|
+
stream.pricingSource ?? null,
|
|
90
92
|
);
|
|
91
93
|
}
|
|
92
94
|
})();
|
|
@@ -97,9 +99,11 @@ export function insertAgentSessionSnapshot(
|
|
|
97
99
|
export function getAgentSession(agentId: string, sessionId: string): AgentSessionDim | null {
|
|
98
100
|
const db = getDatabase();
|
|
99
101
|
|
|
100
|
-
const row = db
|
|
102
|
+
const row = db
|
|
103
|
+
.prepare(`
|
|
101
104
|
SELECT * FROM agent_sessions WHERE agent_id = ? AND session_id = ?
|
|
102
|
-
`)
|
|
105
|
+
`)
|
|
106
|
+
.get(agentId, sessionId) as DbSessionRow | null;
|
|
103
107
|
|
|
104
108
|
return row ? mapSessionRow(row) : null;
|
|
105
109
|
}
|
|
@@ -107,11 +111,13 @@ export function getAgentSession(agentId: string, sessionId: string): AgentSessio
|
|
|
107
111
|
export function getRecentSessions(limit = 50): AgentSessionDim[] {
|
|
108
112
|
const db = getDatabase();
|
|
109
113
|
|
|
110
|
-
const rows = db
|
|
114
|
+
const rows = db
|
|
115
|
+
.prepare(`
|
|
111
116
|
SELECT * FROM agent_sessions
|
|
112
117
|
ORDER BY last_seen_at DESC
|
|
113
118
|
LIMIT ?
|
|
114
|
-
`)
|
|
119
|
+
`)
|
|
120
|
+
.all(limit) as DbSessionRow[];
|
|
115
121
|
|
|
116
122
|
return rows.map(mapSessionRow);
|
|
117
123
|
}
|
|
@@ -119,12 +125,14 @@ export function getRecentSessions(limit = 50): AgentSessionDim[] {
|
|
|
119
125
|
export function getSessionsByProject(projectPath: string, limit = 50): AgentSessionDim[] {
|
|
120
126
|
const db = getDatabase();
|
|
121
127
|
|
|
122
|
-
const rows = db
|
|
128
|
+
const rows = db
|
|
129
|
+
.prepare(`
|
|
123
130
|
SELECT * FROM agent_sessions
|
|
124
131
|
WHERE project_path = ?
|
|
125
132
|
ORDER BY last_seen_at DESC
|
|
126
133
|
LIMIT ?
|
|
127
|
-
`)
|
|
134
|
+
`)
|
|
135
|
+
.all(projectPath, limit) as DbSessionRow[];
|
|
128
136
|
|
|
129
137
|
return rows.map(mapSessionRow);
|
|
130
138
|
}
|
|
@@ -167,7 +175,8 @@ export interface LatestStreamTotals {
|
|
|
167
175
|
export function getLatestStreamTotalsForAllSessions(): LatestStreamTotals[] {
|
|
168
176
|
const db = getDatabase();
|
|
169
177
|
|
|
170
|
-
const rows = db
|
|
178
|
+
const rows = db
|
|
179
|
+
.prepare(`
|
|
171
180
|
SELECT
|
|
172
181
|
s.agent_id, s.session_id,
|
|
173
182
|
ss.provider, ss.model,
|
|
@@ -182,7 +191,8 @@ export function getLatestStreamTotalsForAllSessions(): LatestStreamTotals[] {
|
|
|
182
191
|
FROM agent_session_snapshots snap2
|
|
183
192
|
GROUP BY snap2.agent_session_id
|
|
184
193
|
)
|
|
185
|
-
`)
|
|
194
|
+
`)
|
|
195
|
+
.all() as Array<{
|
|
186
196
|
agent_id: string;
|
|
187
197
|
session_id: string;
|
|
188
198
|
provider: string;
|
|
@@ -195,7 +205,7 @@ export function getLatestStreamTotalsForAllSessions(): LatestStreamTotals[] {
|
|
|
195
205
|
request_count: number;
|
|
196
206
|
}>;
|
|
197
207
|
|
|
198
|
-
return rows.map(r => ({
|
|
208
|
+
return rows.map((r) => ({
|
|
199
209
|
agentId: r.agent_id,
|
|
200
210
|
sessionId: r.session_id,
|
|
201
211
|
provider: r.provider,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getDatabase } from
|
|
2
|
-
import type { ProviderSnapshotInsert, ProviderSnapshotRow
|
|
1
|
+
import { getDatabase } from "../db.ts";
|
|
2
|
+
import type { CostSource, ProviderSnapshotInsert, ProviderSnapshotRow } from "../types.ts";
|
|
3
3
|
|
|
4
4
|
const INSERT_SQL = `
|
|
5
5
|
INSERT INTO provider_snapshots (
|
|
@@ -36,7 +36,7 @@ export function insertProviderSnapshot(snapshot: ProviderSnapshotInsert): number
|
|
|
36
36
|
snapshot.tokensOutput ?? null,
|
|
37
37
|
snapshot.costUsd ?? null,
|
|
38
38
|
snapshot.costSource ?? null,
|
|
39
|
-
snapshot.rawJson ?? null
|
|
39
|
+
snapshot.rawJson ?? null,
|
|
40
40
|
);
|
|
41
41
|
|
|
42
42
|
return Number(result.lastInsertRowid);
|
|
@@ -60,7 +60,7 @@ export function insertProviderSnapshotBatch(snapshots: ProviderSnapshotInsert[])
|
|
|
60
60
|
s.tokensOutput ?? null,
|
|
61
61
|
s.costUsd ?? null,
|
|
62
62
|
s.costSource ?? null,
|
|
63
|
-
s.rawJson ?? null
|
|
63
|
+
s.rawJson ?? null,
|
|
64
64
|
);
|
|
65
65
|
}
|
|
66
66
|
});
|
|
@@ -72,7 +72,7 @@ export function queryProviderSnapshots(
|
|
|
72
72
|
provider: string,
|
|
73
73
|
startMs: number,
|
|
74
74
|
endMs: number,
|
|
75
|
-
limit = 100
|
|
75
|
+
limit = 100,
|
|
76
76
|
): ProviderSnapshotRow[] {
|
|
77
77
|
const db = getDatabase();
|
|
78
78
|
const rows = db.prepare(QUERY_BY_PROVIDER_SQL).all(provider, startMs, endMs, limit) as DbRow[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getDatabase } from
|
|
2
|
-
import type {
|
|
1
|
+
import { getDatabase } from "../db.ts";
|
|
2
|
+
import type { TimeSeriesFilters, TimeSeriesPoint, UsageEventInsert } from "../types.ts";
|
|
3
3
|
|
|
4
4
|
const INSERT_SQL = `
|
|
5
5
|
INSERT INTO usage_events (
|
|
@@ -27,7 +27,7 @@ export function insertUsageEvent(event: UsageEventInsert): number {
|
|
|
27
27
|
event.cacheWriteTokens,
|
|
28
28
|
event.costUsd,
|
|
29
29
|
event.requestCount,
|
|
30
|
-
event.pricingSource ?? null
|
|
30
|
+
event.pricingSource ?? null,
|
|
31
31
|
);
|
|
32
32
|
|
|
33
33
|
return Number(result.lastInsertRowid);
|
|
@@ -55,7 +55,7 @@ export function insertUsageEventBatch(events: UsageEventInsert[]): void {
|
|
|
55
55
|
e.cacheWriteTokens,
|
|
56
56
|
e.costUsd,
|
|
57
57
|
e.requestCount,
|
|
58
|
-
e.pricingSource ?? null
|
|
58
|
+
e.pricingSource ?? null,
|
|
59
59
|
);
|
|
60
60
|
}
|
|
61
61
|
});
|
|
@@ -67,31 +67,31 @@ export function queryUsageTimeSeries(
|
|
|
67
67
|
startMs: number,
|
|
68
68
|
endMs: number,
|
|
69
69
|
bucketMs: number,
|
|
70
|
-
filters: TimeSeriesFilters = {}
|
|
70
|
+
filters: TimeSeriesFilters = {},
|
|
71
71
|
): TimeSeriesPoint[] {
|
|
72
72
|
const db = getDatabase();
|
|
73
73
|
|
|
74
|
-
const conditions: string[] = [
|
|
74
|
+
const conditions: string[] = ["timestamp >= ?", "timestamp <= ?"];
|
|
75
75
|
const params: (string | number)[] = [startMs, endMs];
|
|
76
76
|
|
|
77
77
|
if (filters.provider) {
|
|
78
|
-
conditions.push(
|
|
78
|
+
conditions.push("provider = ?");
|
|
79
79
|
params.push(filters.provider);
|
|
80
80
|
}
|
|
81
81
|
if (filters.model) {
|
|
82
|
-
conditions.push(
|
|
82
|
+
conditions.push("model = ?");
|
|
83
83
|
params.push(filters.model);
|
|
84
84
|
}
|
|
85
85
|
if (filters.agentId) {
|
|
86
|
-
conditions.push(
|
|
86
|
+
conditions.push("agent_id = ?");
|
|
87
87
|
params.push(filters.agentId);
|
|
88
88
|
}
|
|
89
89
|
if (filters.sessionId) {
|
|
90
|
-
conditions.push(
|
|
90
|
+
conditions.push("session_id = ?");
|
|
91
91
|
params.push(filters.sessionId);
|
|
92
92
|
}
|
|
93
93
|
if (filters.projectPath) {
|
|
94
|
-
conditions.push(
|
|
94
|
+
conditions.push("project_path = ?");
|
|
95
95
|
params.push(filters.projectPath);
|
|
96
96
|
}
|
|
97
97
|
|
|
@@ -102,7 +102,7 @@ export function queryUsageTimeSeries(
|
|
|
102
102
|
COALESCE(SUM(cost_usd), 0) AS cost_usd,
|
|
103
103
|
COALESCE(SUM(request_count), 0) AS request_count
|
|
104
104
|
FROM usage_events
|
|
105
|
-
WHERE ${conditions.join(
|
|
105
|
+
WHERE ${conditions.join(" AND ")}
|
|
106
106
|
GROUP BY bucket_start
|
|
107
107
|
ORDER BY bucket_start ASC
|
|
108
108
|
`;
|
|
@@ -114,7 +114,7 @@ export function queryUsageTimeSeries(
|
|
|
114
114
|
request_count: number;
|
|
115
115
|
}>;
|
|
116
116
|
|
|
117
|
-
return rows.map(r => ({
|
|
117
|
+
return rows.map((r) => ({
|
|
118
118
|
bucketStart: r.bucket_start,
|
|
119
119
|
tokens: r.tokens,
|
|
120
120
|
costUsd: r.cost_usd,
|
|
@@ -122,17 +122,22 @@ export function queryUsageTimeSeries(
|
|
|
122
122
|
}));
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
export function calculateBurnRate(
|
|
125
|
+
export function calculateBurnRate(
|
|
126
|
+
windowMs: number,
|
|
127
|
+
nowMs = Date.now(),
|
|
128
|
+
): { costPerHour: number; tokensPerMinute: number } {
|
|
126
129
|
const db = getDatabase();
|
|
127
130
|
const startMs = nowMs - windowMs;
|
|
128
131
|
|
|
129
|
-
const row = db
|
|
132
|
+
const row = db
|
|
133
|
+
.prepare(`
|
|
130
134
|
SELECT
|
|
131
135
|
COALESCE(SUM(cost_usd), 0) AS cost,
|
|
132
136
|
COALESCE(SUM(input_tokens + output_tokens), 0) AS tokens
|
|
133
137
|
FROM usage_events
|
|
134
138
|
WHERE timestamp >= ? AND timestamp <= ?
|
|
135
|
-
`)
|
|
139
|
+
`)
|
|
140
|
+
.get(startMs, nowMs) as { cost: number; tokens: number };
|
|
136
141
|
|
|
137
142
|
const hours = windowMs / (1000 * 60 * 60);
|
|
138
143
|
const minutes = windowMs / (1000 * 60);
|
|
@@ -143,7 +148,10 @@ export function calculateBurnRate(windowMs: number, nowMs = Date.now()): { costP
|
|
|
143
148
|
};
|
|
144
149
|
}
|
|
145
150
|
|
|
146
|
-
export function getTotalUsageInWindow(
|
|
151
|
+
export function getTotalUsageInWindow(
|
|
152
|
+
startMs: number,
|
|
153
|
+
endMs: number,
|
|
154
|
+
): {
|
|
147
155
|
inputTokens: number;
|
|
148
156
|
outputTokens: number;
|
|
149
157
|
costUsd: number;
|
|
@@ -151,7 +159,8 @@ export function getTotalUsageInWindow(startMs: number, endMs: number): {
|
|
|
151
159
|
} {
|
|
152
160
|
const db = getDatabase();
|
|
153
161
|
|
|
154
|
-
const row = db
|
|
162
|
+
const row = db
|
|
163
|
+
.prepare(`
|
|
155
164
|
SELECT
|
|
156
165
|
COALESCE(SUM(input_tokens), 0) AS input_tokens,
|
|
157
166
|
COALESCE(SUM(output_tokens), 0) AS output_tokens,
|
|
@@ -159,7 +168,8 @@ export function getTotalUsageInWindow(startMs: number, endMs: number): {
|
|
|
159
168
|
COALESCE(SUM(request_count), 0) AS request_count
|
|
160
169
|
FROM usage_events
|
|
161
170
|
WHERE timestamp >= ? AND timestamp <= ?
|
|
162
|
-
`)
|
|
171
|
+
`)
|
|
172
|
+
.get(startMs, endMs) as {
|
|
163
173
|
input_tokens: number;
|
|
164
174
|
output_tokens: number;
|
|
165
175
|
cost_usd: number;
|
|
@@ -190,7 +200,7 @@ export interface ProviderDailyCost {
|
|
|
190
200
|
export function queryProviderDailyCosts(
|
|
191
201
|
startMs: number,
|
|
192
202
|
endMs: number,
|
|
193
|
-
bucketMs: number
|
|
203
|
+
bucketMs: number,
|
|
194
204
|
): ProviderDailyCost[] {
|
|
195
205
|
const db = getDatabase();
|
|
196
206
|
|
|
@@ -216,7 +226,7 @@ export function queryProviderDailyCosts(
|
|
|
216
226
|
request_count: number;
|
|
217
227
|
}>;
|
|
218
228
|
|
|
219
|
-
return rows.map(r => ({
|
|
229
|
+
return rows.map((r) => ({
|
|
220
230
|
provider: r.provider,
|
|
221
231
|
bucketStart: r.bucket_start,
|
|
222
232
|
costUsd: r.cost_usd,
|
|
@@ -236,7 +246,7 @@ export interface ModelDailyCost {
|
|
|
236
246
|
export function queryModelDailyCosts(
|
|
237
247
|
startMs: number,
|
|
238
248
|
endMs: number,
|
|
239
|
-
bucketMs: number
|
|
249
|
+
bucketMs: number,
|
|
240
250
|
): ModelDailyCost[] {
|
|
241
251
|
const db = getDatabase();
|
|
242
252
|
|
|
@@ -262,7 +272,7 @@ export function queryModelDailyCosts(
|
|
|
262
272
|
request_count: number;
|
|
263
273
|
}>;
|
|
264
274
|
|
|
265
|
-
return rows.map(r => ({
|
|
275
|
+
return rows.map((r) => ({
|
|
266
276
|
model: r.model,
|
|
267
277
|
bucketStart: r.bucket_start,
|
|
268
278
|
costUsd: r.cost_usd,
|
|
@@ -282,7 +292,7 @@ export interface ProjectDailyCost {
|
|
|
282
292
|
export function queryProjectDailyCosts(
|
|
283
293
|
startMs: number,
|
|
284
294
|
endMs: number,
|
|
285
|
-
bucketMs: number
|
|
295
|
+
bucketMs: number,
|
|
286
296
|
): ProjectDailyCost[] {
|
|
287
297
|
const db = getDatabase();
|
|
288
298
|
|
|
@@ -308,7 +318,7 @@ export function queryProjectDailyCosts(
|
|
|
308
318
|
request_count: number;
|
|
309
319
|
}>;
|
|
310
320
|
|
|
311
|
-
return rows.map(r => ({
|
|
321
|
+
return rows.map((r) => ({
|
|
312
322
|
projectPath: r.project_path,
|
|
313
323
|
bucketStart: r.bucket_start,
|
|
314
324
|
costUsd: r.cost_usd,
|
|
@@ -320,14 +330,16 @@ export function queryProjectDailyCosts(
|
|
|
320
330
|
export function getSessionActivityTimeline(sessionId: string): SessionActivityPoint[] {
|
|
321
331
|
const db = getDatabase();
|
|
322
332
|
|
|
323
|
-
const rows = db
|
|
333
|
+
const rows = db
|
|
334
|
+
.prepare(`
|
|
324
335
|
SELECT timestamp, (input_tokens + output_tokens) AS tokens
|
|
325
336
|
FROM usage_events
|
|
326
337
|
WHERE session_id = ?
|
|
327
338
|
ORDER BY timestamp ASC
|
|
328
|
-
`)
|
|
339
|
+
`)
|
|
340
|
+
.all(sessionId) as Array<{ timestamp: number; tokens: number }>;
|
|
329
341
|
|
|
330
|
-
return rows.map(r => ({
|
|
342
|
+
return rows.map((r) => ({
|
|
331
343
|
timestamp: r.timestamp,
|
|
332
344
|
tokens: r.tokens,
|
|
333
345
|
}));
|
package/src/storage/types.ts
CHANGED
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
// Enums & Literal Types
|
|
8
8
|
// ============================================================================
|
|
9
9
|
|
|
10
|
-
export type UsageEventSource =
|
|
11
|
-
export type SessionStatus =
|
|
12
|
-
export type CostSource =
|
|
13
|
-
export type PricingSource =
|
|
10
|
+
export type UsageEventSource = "agent" | "provider";
|
|
11
|
+
export type SessionStatus = "active" | "idle";
|
|
12
|
+
export type CostSource = "api" | "estimated";
|
|
13
|
+
export type PricingSource = "models.dev" | "fallback" | "unknown";
|
|
14
14
|
|
|
15
15
|
// ============================================================================
|
|
16
16
|
// App Runs Table
|
|
@@ -253,7 +253,7 @@ export interface StreamTotals {
|
|
|
253
253
|
*/
|
|
254
254
|
export function computeStreamDelta(
|
|
255
255
|
current: StreamTotals,
|
|
256
|
-
previous: StreamTotals | undefined
|
|
256
|
+
previous: StreamTotals | undefined,
|
|
257
257
|
): StreamTotals | null {
|
|
258
258
|
if (!previous) {
|
|
259
259
|
// First observation - treat as a delta from zero
|