bashstats 0.1.0 → 0.2.1
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/NUL +10 -0
- package/README.md +186 -0
- package/dist/chunk-4HVDBCTU.js +2119 -0
- package/dist/chunk-4HVDBCTU.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/hooks/{chunk-EFVDQUHM.js → chunk-37VUNTM4.js} +114 -15
- package/dist/hooks/chunk-37VUNTM4.js.map +1 -0
- package/dist/hooks/notification.js +1 -1
- package/dist/hooks/permission-request.js +1 -1
- package/dist/hooks/post-tool-failure.js +1 -1
- package/dist/hooks/post-tool-use.js +1 -1
- package/dist/hooks/pre-compact.js +1 -1
- package/dist/hooks/pre-tool-use.js +1 -1
- package/dist/hooks/session-start.js +1 -1
- package/dist/hooks/setup.js +1 -1
- package/dist/hooks/stop.js +1 -1
- package/dist/hooks/subagent-start.js +1 -1
- package/dist/hooks/subagent-stop.js +1 -1
- package/dist/hooks/user-prompt-submit.js +1 -1
- package/dist/index.d.ts +78 -3
- package/dist/index.js +1 -1
- package/dist/static/index.html +57 -13
- package/package.json +1 -1
- package/debug-hook.cjs +0 -38
- package/dist/chunk-2KXMOTBO.js +0 -1370
- package/dist/chunk-2KXMOTBO.js.map +0 -1
- package/dist/hooks/chunk-EFVDQUHM.js.map +0 -1
- package/nul +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -54,6 +54,12 @@ interface SetupInput extends HookInput {
|
|
|
54
54
|
trigger: 'init' | 'maintenance';
|
|
55
55
|
CLAUDE_ENV_FILE: string;
|
|
56
56
|
}
|
|
57
|
+
interface TokenUsage {
|
|
58
|
+
input_tokens: number;
|
|
59
|
+
output_tokens: number;
|
|
60
|
+
cache_creation_input_tokens: number;
|
|
61
|
+
cache_read_input_tokens: number;
|
|
62
|
+
}
|
|
57
63
|
interface EventRow {
|
|
58
64
|
id: number;
|
|
59
65
|
session_id: string;
|
|
@@ -78,6 +84,10 @@ interface SessionRow {
|
|
|
78
84
|
error_count: number;
|
|
79
85
|
project: string | null;
|
|
80
86
|
duration_seconds: number | null;
|
|
87
|
+
input_tokens: number | null;
|
|
88
|
+
output_tokens: number | null;
|
|
89
|
+
cache_creation_input_tokens: number | null;
|
|
90
|
+
cache_read_input_tokens: number | null;
|
|
81
91
|
}
|
|
82
92
|
interface PromptRow {
|
|
83
93
|
id: number;
|
|
@@ -94,6 +104,10 @@ interface DailyActivityRow {
|
|
|
94
104
|
tool_calls: number;
|
|
95
105
|
errors: number;
|
|
96
106
|
duration_seconds: number;
|
|
107
|
+
input_tokens: number;
|
|
108
|
+
output_tokens: number;
|
|
109
|
+
cache_creation_input_tokens: number;
|
|
110
|
+
cache_read_input_tokens: number;
|
|
97
111
|
}
|
|
98
112
|
interface AchievementUnlockRow {
|
|
99
113
|
badge_id: string;
|
|
@@ -118,6 +132,11 @@ interface LifetimeStats {
|
|
|
118
132
|
totalCompactions: number;
|
|
119
133
|
totalErrors: number;
|
|
120
134
|
totalRateLimits: number;
|
|
135
|
+
totalInputTokens: number;
|
|
136
|
+
totalOutputTokens: number;
|
|
137
|
+
totalCacheCreationTokens: number;
|
|
138
|
+
totalCacheReadTokens: number;
|
|
139
|
+
totalTokens: number;
|
|
121
140
|
}
|
|
122
141
|
interface ToolBreakdown {
|
|
123
142
|
[toolName: string]: number;
|
|
@@ -142,6 +161,8 @@ interface SessionRecords {
|
|
|
142
161
|
avgDurationSeconds: number;
|
|
143
162
|
avgPromptsPerSession: number;
|
|
144
163
|
avgToolsPerSession: number;
|
|
164
|
+
mostTokensInSession: number;
|
|
165
|
+
avgTokensPerSession: number;
|
|
145
166
|
}
|
|
146
167
|
interface ProjectStats {
|
|
147
168
|
uniqueProjects: number;
|
|
@@ -164,9 +185,10 @@ interface BadgeDefinition {
|
|
|
164
185
|
name: string;
|
|
165
186
|
icon: string;
|
|
166
187
|
description: string;
|
|
167
|
-
category: 'volume' | 'tool_mastery' | 'time' | 'behavioral' | 'resilience' | 'shipping' | 'multi_agent' | 'humor' | 'aspirational' | 'secret';
|
|
188
|
+
category: 'volume' | 'tool_mastery' | 'time' | 'behavioral' | 'resilience' | 'shipping' | 'multi_agent' | 'humor' | 'aspirational' | 'secret' | 'session_behavior' | 'prompt_patterns' | 'error_recovery' | 'tool_combos' | 'project_dedication' | 'token_usage';
|
|
168
189
|
stat: string;
|
|
169
190
|
tiers: [number, number, number, number, number];
|
|
191
|
+
trigger: string;
|
|
170
192
|
secret?: boolean;
|
|
171
193
|
humor?: boolean;
|
|
172
194
|
aspirational?: boolean;
|
|
@@ -185,6 +207,7 @@ interface BadgeResult {
|
|
|
185
207
|
nextThreshold: number;
|
|
186
208
|
progress: number;
|
|
187
209
|
maxed: boolean;
|
|
210
|
+
trigger: string;
|
|
188
211
|
secret: boolean;
|
|
189
212
|
unlocked: boolean;
|
|
190
213
|
}
|
|
@@ -221,6 +244,7 @@ declare class BashStatsDB {
|
|
|
221
244
|
}): void;
|
|
222
245
|
getSession(id: string): SessionRow | null;
|
|
223
246
|
updateSession(id: string, updates: Partial<Pick<SessionRow, 'ended_at' | 'stop_reason' | 'duration_seconds'>>): void;
|
|
247
|
+
updateSessionTokens(id: string, tokens: TokenUsage): void;
|
|
224
248
|
incrementSessionCounters(id: string, counters: {
|
|
225
249
|
prompts?: number;
|
|
226
250
|
tools?: number;
|
|
@@ -234,6 +258,10 @@ declare class BashStatsDB {
|
|
|
234
258
|
tool_calls?: number;
|
|
235
259
|
errors?: number;
|
|
236
260
|
duration_seconds?: number;
|
|
261
|
+
input_tokens?: number;
|
|
262
|
+
output_tokens?: number;
|
|
263
|
+
cache_creation_input_tokens?: number;
|
|
264
|
+
cache_read_input_tokens?: number;
|
|
237
265
|
}): void;
|
|
238
266
|
getDailyActivity(date: string): DailyActivityRow | null;
|
|
239
267
|
getAllDailyActivity(days?: number): DailyActivityRow[];
|
|
@@ -255,7 +283,7 @@ declare class BashStatsWriter {
|
|
|
255
283
|
recordSessionStart(sessionId: string, cwd: string, source: string, agent?: string): void;
|
|
256
284
|
recordPrompt(sessionId: string, content: string): void;
|
|
257
285
|
recordToolUse(sessionId: string, hookType: string, toolName: string, toolInput: Record<string, unknown>, toolOutput: Record<string, unknown>, exitCode: number | null, cwd: string): void;
|
|
258
|
-
recordSessionEnd(sessionId: string, stopReason: string): void;
|
|
286
|
+
recordSessionEnd(sessionId: string, stopReason: string, tokens?: TokenUsage | null): void;
|
|
259
287
|
recordNotification(sessionId: string, message: string, notificationType: string): void;
|
|
260
288
|
recordSubagent(sessionId: string, hookType: string, agentId: string, agentType?: string): void;
|
|
261
289
|
recordCompaction(sessionId: string, trigger: string): void;
|
|
@@ -307,6 +335,53 @@ declare class AchievementEngine {
|
|
|
307
335
|
private queryHolidayActivity;
|
|
308
336
|
private querySpeedRunSession;
|
|
309
337
|
private queryAllToolsInSession;
|
|
338
|
+
private queryWitchingHourPrompts;
|
|
339
|
+
private queryLunchBreakDays;
|
|
340
|
+
private queryMondaySessions;
|
|
341
|
+
private queryFridayCommits;
|
|
342
|
+
private queryMaxUniqueHoursInDay;
|
|
343
|
+
private queryUniqueQuarters;
|
|
344
|
+
private queryExtendedSessionCount;
|
|
345
|
+
private queryQuickDrawSessions;
|
|
346
|
+
private queryDiverseToolSessions;
|
|
347
|
+
private queryPermissionRequests;
|
|
348
|
+
private queryReturnerDays;
|
|
349
|
+
private queryShortPromptCount;
|
|
350
|
+
private queryQuestionPromptCount;
|
|
351
|
+
private querySorryPromptCount;
|
|
352
|
+
private queryCapsLockPromptCount;
|
|
353
|
+
private queryEmojiPromptCount;
|
|
354
|
+
private queryCodeDumpPromptCount;
|
|
355
|
+
private queryRubberDuckCount;
|
|
356
|
+
private queryThirdTimeCharmCount;
|
|
357
|
+
private queryUndoEditCount;
|
|
358
|
+
private queryCrashySessions;
|
|
359
|
+
private queryReadEditRunCount;
|
|
360
|
+
private queryMaxFilesCreatedInSession;
|
|
361
|
+
private queryMaxSameFileEditsLifetime;
|
|
362
|
+
private querySearchThenEditCount;
|
|
363
|
+
private queryMaxProjectSessions;
|
|
364
|
+
private queryMaxProjectsInDay;
|
|
365
|
+
private queryFinishedProjects;
|
|
366
|
+
private queryLegacyReturns;
|
|
367
|
+
private queryMaxConcurrentSubagents;
|
|
368
|
+
private queryQuickSubagentStops;
|
|
369
|
+
private queryMaxSubagentsInSession;
|
|
370
|
+
private queryDejaVuCount;
|
|
371
|
+
private queryTrustIssueCount;
|
|
372
|
+
private queryBackseatDriverCount;
|
|
373
|
+
private queryNegotiatorCount;
|
|
374
|
+
private queryMaxConsecutivePermissions;
|
|
375
|
+
private queryBashRetrySuccessCount;
|
|
376
|
+
private queryEasterEggActivity;
|
|
377
|
+
private queryFullMoonSession;
|
|
378
|
+
private queryBirthdaySession;
|
|
379
|
+
private queryGhostSessions;
|
|
380
|
+
private queryBullseyeSessions;
|
|
381
|
+
private queryHeavyTokenSessions;
|
|
382
|
+
private queryLightTokenSessions;
|
|
383
|
+
private queryMaxOutputInSession;
|
|
384
|
+
private queryHasTenMillionSession;
|
|
310
385
|
}
|
|
311
386
|
|
|
312
387
|
/**
|
|
@@ -352,4 +427,4 @@ declare const DATA_DIR = ".bashstats";
|
|
|
352
427
|
declare const DB_FILENAME = "bashstats.db";
|
|
353
428
|
declare const DEFAULT_PORT = 17900;
|
|
354
429
|
|
|
355
|
-
export { AGENT_DISPLAY_NAMES, AchievementEngine, type AchievementUnlockRow, type AchievementsPayload, type AgentType, type AllStats, BADGE_DEFINITIONS, type BadgeDefinition, type BadgeResult, type BadgeTier, BashStatsDB, BashStatsWriter, DATA_DIR, DB_FILENAME, DEFAULT_PORT, type DailyActivityRow, type EventRow, type HookInput, type LifetimeStats, type NotificationInput, type PermissionRequestInput, type PostToolUseInput, type PreCompactInput, type PreToolUseInput, type ProjectStats, type PromptRow, RANK_THRESHOLDS, type SessionRecords, type SessionRow, type SessionStartInput, type SetupInput, StatsEngine, type StopInput, type SubagentStartInput, type SubagentStopInput, TIER_NAMES, TIER_XP, type TimeStats, type ToolBreakdown, type UserPromptInput, type XPResult, detectAgent, handleHookEvent, install, isInstalled, parseHookEvent, uninstall };
|
|
430
|
+
export { AGENT_DISPLAY_NAMES, AchievementEngine, type AchievementUnlockRow, type AchievementsPayload, type AgentType, type AllStats, BADGE_DEFINITIONS, type BadgeDefinition, type BadgeResult, type BadgeTier, BashStatsDB, BashStatsWriter, DATA_DIR, DB_FILENAME, DEFAULT_PORT, type DailyActivityRow, type EventRow, type HookInput, type LifetimeStats, type NotificationInput, type PermissionRequestInput, type PostToolUseInput, type PreCompactInput, type PreToolUseInput, type ProjectStats, type PromptRow, RANK_THRESHOLDS, type SessionRecords, type SessionRow, type SessionStartInput, type SetupInput, StatsEngine, type StopInput, type SubagentStartInput, type SubagentStopInput, TIER_NAMES, TIER_XP, type TimeStats, type TokenUsage, type ToolBreakdown, type UserPromptInput, type XPResult, detectAgent, handleHookEvent, install, isInstalled, parseHookEvent, uninstall };
|
package/dist/index.js
CHANGED
package/dist/static/index.html
CHANGED
|
@@ -608,6 +608,17 @@
|
|
|
608
608
|
line-height: 1.4;
|
|
609
609
|
}
|
|
610
610
|
|
|
611
|
+
.badge-trigger {
|
|
612
|
+
font-size: 11px;
|
|
613
|
+
font-family: 'JetBrains Mono', monospace;
|
|
614
|
+
color: var(--accent);
|
|
615
|
+
line-height: 1.3;
|
|
616
|
+
padding: 3px 6px;
|
|
617
|
+
background: var(--bg-accent);
|
|
618
|
+
border-radius: 2px;
|
|
619
|
+
border-left: 2px solid var(--accent);
|
|
620
|
+
}
|
|
621
|
+
|
|
611
622
|
.badge-progress-row {
|
|
612
623
|
display: flex;
|
|
613
624
|
align-items: center;
|
|
@@ -802,7 +813,7 @@
|
|
|
802
813
|
|
|
803
814
|
.session-item {
|
|
804
815
|
display: grid;
|
|
805
|
-
grid-template-columns: 140px 1fr 100px 100px 100px;
|
|
816
|
+
grid-template-columns: 140px 1fr 100px 100px 100px 100px;
|
|
806
817
|
gap: 12px;
|
|
807
818
|
align-items: center;
|
|
808
819
|
padding: 10px 14px;
|
|
@@ -1246,6 +1257,14 @@
|
|
|
1246
1257
|
return (seconds / 3600).toFixed(1);
|
|
1247
1258
|
}
|
|
1248
1259
|
|
|
1260
|
+
function formatTokens(n) {
|
|
1261
|
+
if (n == null || n === 0) return '0';
|
|
1262
|
+
if (n >= 1000000000) return (n / 1000000000).toFixed(1) + 'B';
|
|
1263
|
+
if (n >= 1000000) return (n / 1000000).toFixed(1) + 'M';
|
|
1264
|
+
if (n >= 1000) return (n / 1000).toFixed(1) + 'K';
|
|
1265
|
+
return n.toLocaleString();
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1249
1268
|
function formatDate(dateStr) {
|
|
1250
1269
|
const d = new Date(dateStr);
|
|
1251
1270
|
return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
|
|
@@ -1407,7 +1426,7 @@
|
|
|
1407
1426
|
{ label: 'Prompts', value: formatNumber(lt.totalPrompts || 0), sub: 'messages sent' },
|
|
1408
1427
|
{ label: 'Tool Calls', value: formatNumber(lt.totalToolCalls || 0), sub: 'total invocations' },
|
|
1409
1428
|
{ label: 'Hours', value: formatHours(lt.totalDurationSeconds || 0), sub: 'coding time' },
|
|
1410
|
-
{ label: '
|
|
1429
|
+
{ label: 'Tokens Used', value: formatTokens(lt.totalTokens || 0), sub: 'all token types' },
|
|
1411
1430
|
{ label: 'Bash Cmds', value: formatNumber(lt.totalBashCommands || lt.totalToolCalls || 0), sub: 'commands run' },
|
|
1412
1431
|
];
|
|
1413
1432
|
|
|
@@ -1440,7 +1459,7 @@
|
|
|
1440
1459
|
<div class="stat-card"><div class="stat-card-label">Prompts</div><div class="stat-card-number mono">0</div></div>
|
|
1441
1460
|
<div class="stat-card"><div class="stat-card-label">Tool Calls</div><div class="stat-card-number mono">0</div></div>
|
|
1442
1461
|
<div class="stat-card"><div class="stat-card-label">Hours</div><div class="stat-card-number mono">0</div></div>
|
|
1443
|
-
<div class="stat-card"><div class="stat-card-label">
|
|
1462
|
+
<div class="stat-card"><div class="stat-card-label">Tokens Used</div><div class="stat-card-number mono">0</div></div>
|
|
1444
1463
|
<div class="stat-card"><div class="stat-card-label">Bash Cmds</div><div class="stat-card-number mono">0</div></div>
|
|
1445
1464
|
`;
|
|
1446
1465
|
}
|
|
@@ -1610,17 +1629,20 @@
|
|
|
1610
1629
|
const recent = sessions.slice(-20).reverse();
|
|
1611
1630
|
el.innerHTML = `
|
|
1612
1631
|
<div class="session-item" style="font-weight:600;background:var(--bg-accent);font-size:12px;">
|
|
1613
|
-
<div>Date</div><div>Project</div><div style="text-align:right">Duration</div><div style="text-align:right">Prompts</div><div style="text-align:right">Tools</div>
|
|
1632
|
+
<div>Date</div><div>Project</div><div style="text-align:right">Duration</div><div style="text-align:right">Prompts</div><div style="text-align:right">Tools</div><div style="text-align:right">Tokens</div>
|
|
1614
1633
|
</div>
|
|
1615
|
-
${recent.map(s =>
|
|
1634
|
+
${recent.map(s => {
|
|
1635
|
+
const sessionTokens = (s.input_tokens || 0) + (s.output_tokens || 0) + (s.cache_creation_input_tokens || 0) + (s.cache_read_input_tokens || 0);
|
|
1636
|
+
return `
|
|
1616
1637
|
<div class="session-item">
|
|
1617
1638
|
<div class="session-date">${escapeHtml(formatDateTime(s.start_time || s.startTime || s.started_at || ''))}</div>
|
|
1618
1639
|
<div class="session-project">${escapeHtml(s.project || s.projectName || 'Unknown')}</div>
|
|
1619
1640
|
<div class="session-stat">${formatDuration(s.duration_seconds || s.durationSeconds || 0)}</div>
|
|
1620
1641
|
<div class="session-stat">${formatNumber(s.prompt_count || s.prompts || s.promptCount || 0)}</div>
|
|
1621
1642
|
<div class="session-stat">${formatNumber(s.tool_count || s.tool_calls || s.toolCalls || 0)}</div>
|
|
1643
|
+
<div class="session-stat">${formatTokens(sessionTokens)}</div>
|
|
1622
1644
|
</div>
|
|
1623
|
-
`).join('')}
|
|
1645
|
+
`}).join('')}
|
|
1624
1646
|
`;
|
|
1625
1647
|
}
|
|
1626
1648
|
|
|
@@ -1658,6 +1680,16 @@
|
|
|
1658
1680
|
['Files Read', formatNumber(lt.totalFilesRead)],
|
|
1659
1681
|
]);
|
|
1660
1682
|
|
|
1683
|
+
// Token Usage
|
|
1684
|
+
html += buildStatsSection('Token Usage', [
|
|
1685
|
+
['Total Tokens', formatTokens(lt.totalTokens || 0)],
|
|
1686
|
+
['Input Tokens', formatTokens(lt.totalInputTokens)],
|
|
1687
|
+
['Output Tokens', formatTokens(lt.totalOutputTokens)],
|
|
1688
|
+
['Cache Read Tokens', formatTokens(lt.totalCacheReadTokens)],
|
|
1689
|
+
['Cache Creation Tokens', formatTokens(lt.totalCacheCreationTokens)],
|
|
1690
|
+
['Avg Tokens / Session', formatTokens(lt.totalSessions ? Math.round((lt.totalTokens || 0) / lt.totalSessions) : 0)],
|
|
1691
|
+
]);
|
|
1692
|
+
|
|
1661
1693
|
// Tool Breakdown
|
|
1662
1694
|
const toolEntries = Object.entries(tools).sort((a, b) => b[1] - a[1]);
|
|
1663
1695
|
if (toolEntries.length > 0) {
|
|
@@ -1736,16 +1768,24 @@
|
|
|
1736
1768
|
});
|
|
1737
1769
|
|
|
1738
1770
|
let html = '';
|
|
1739
|
-
const catOrder = ['volume', '
|
|
1771
|
+
const catOrder = ['volume', 'token_usage', 'tool_mastery', 'time', 'session_behavior', 'behavioral', 'prompt_patterns', 'resilience', 'error_recovery', 'tool_combos', 'shipping', 'project_dedication', 'multi_agent', 'humor', 'aspirational', 'secret'];
|
|
1740
1772
|
const catNames = {
|
|
1741
1773
|
volume: 'Volume',
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
time: 'Time',
|
|
1745
|
-
|
|
1746
|
-
|
|
1774
|
+
token_usage: 'Token Usage',
|
|
1775
|
+
tool_mastery: 'Tool Mastery',
|
|
1776
|
+
time: 'Time & Patterns',
|
|
1777
|
+
session_behavior: 'Session Behavior',
|
|
1778
|
+
behavioral: 'Behavioral',
|
|
1779
|
+
prompt_patterns: 'Prompt Patterns',
|
|
1780
|
+
resilience: 'Resilience',
|
|
1781
|
+
error_recovery: 'Error & Recovery',
|
|
1782
|
+
tool_combos: 'Tool Combos',
|
|
1783
|
+
shipping: 'Shipping & Projects',
|
|
1784
|
+
project_dedication: 'Project Dedication',
|
|
1785
|
+
multi_agent: 'Multi-Agent',
|
|
1786
|
+
humor: 'Humor & Meta',
|
|
1787
|
+
aspirational: 'Aspirational',
|
|
1747
1788
|
secret: 'Secret',
|
|
1748
|
-
general: 'General',
|
|
1749
1789
|
};
|
|
1750
1790
|
|
|
1751
1791
|
// Sort: known categories first, then others
|
|
@@ -1765,6 +1805,7 @@
|
|
|
1765
1805
|
const cardClass = isSecretLocked ? 'badge-card secret-locked' : (isLocked ? 'badge-card locked' : 'badge-card');
|
|
1766
1806
|
const displayName = isSecretLocked ? '???' : b.name;
|
|
1767
1807
|
const displayDesc = isSecretLocked ? 'Unlock this secret badge to reveal it.' : (b.description || '');
|
|
1808
|
+
const displayTrigger = isSecretLocked ? '' : (b.trigger || '');
|
|
1768
1809
|
const pct = b.maxed ? 100 : Math.min(100, (b.progress || 0) * 100);
|
|
1769
1810
|
const fillClass = b.maxed ? 'badge-progress-fill maxed' : 'badge-progress-fill';
|
|
1770
1811
|
|
|
@@ -1778,6 +1819,7 @@
|
|
|
1778
1819
|
<span class="badge-tier-label" style="color:${tierColor(b.tier)};border-color:${tierColor(b.tier)}">${escapeHtml(b.tierName || TIER_NAMES[b.tier] || 'Locked')}</span>
|
|
1779
1820
|
</div>
|
|
1780
1821
|
${displayDesc ? `<div class="badge-description">${escapeHtml(displayDesc)}</div>` : ''}
|
|
1822
|
+
${displayTrigger ? `<div class="badge-trigger">${escapeHtml(displayTrigger)}</div>` : ''}
|
|
1781
1823
|
<div class="badge-progress-row">
|
|
1782
1824
|
<div class="badge-progress-track">
|
|
1783
1825
|
<div class="${fillClass}" style="width:${pct}%"></div>
|
|
@@ -1823,9 +1865,11 @@
|
|
|
1823
1865
|
{ label: 'Longest Session', value: formatDuration(sess.longestSessionSeconds), sub: 'personal best' },
|
|
1824
1866
|
{ label: 'Most Tools (Session)', value: formatNumber(sess.mostToolsInSession), sub: 'single session' },
|
|
1825
1867
|
{ label: 'Most Prompts (Session)', value: formatNumber(sess.mostPromptsInSession), sub: 'single session' },
|
|
1868
|
+
{ label: 'Most Tokens (Session)', value: formatTokens(sess.mostTokensInSession), sub: 'single session' },
|
|
1826
1869
|
{ label: 'Shortest Session', value: formatDuration(sess.shortestSessionSeconds), sub: 'speed run' },
|
|
1827
1870
|
{ label: 'Average Prompts', value: formatNumber(avgPrompts), sub: 'per session' },
|
|
1828
1871
|
{ label: 'Average Tools', value: formatNumber(avgTools), sub: 'per session' },
|
|
1872
|
+
{ label: 'Avg Tokens / Session', value: formatTokens(sess.avgTokensPerSession), sub: 'per session' },
|
|
1829
1873
|
{ label: 'Average Duration', value: formatDuration(avgDuration), sub: 'per session' },
|
|
1830
1874
|
{ label: 'Longest Streak', value: (time.longestStreak || 0) + ' days', sub: 'consecutive days' },
|
|
1831
1875
|
{ label: 'Peak Hour', value: time.peakHour != null ? time.peakHour + ':00' : 'N/A', sub: 'most active hour' },
|
package/package.json
CHANGED
package/debug-hook.cjs
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const fs = require('fs')
|
|
3
|
-
const path = require('path')
|
|
4
|
-
const os = require('os')
|
|
5
|
-
|
|
6
|
-
const logFile = path.join(os.homedir(), '.bashstats', 'hook-debug.log')
|
|
7
|
-
|
|
8
|
-
function log(msg) {
|
|
9
|
-
fs.appendFileSync(logFile, `[${new Date().toISOString()}] ${msg}\n`)
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
log(`--- Hook invoked ---`)
|
|
13
|
-
log(`argv: ${JSON.stringify(process.argv)}`)
|
|
14
|
-
log(`CLAUDE_HOOK_EVENT env: ${process.env.CLAUDE_HOOK_EVENT ? 'SET (' + process.env.CLAUDE_HOOK_EVENT.length + ' chars)' : 'NOT SET'}`)
|
|
15
|
-
|
|
16
|
-
let data = ''
|
|
17
|
-
process.stdin.setEncoding('utf-8')
|
|
18
|
-
process.stdin.on('data', (chunk) => {
|
|
19
|
-
data += chunk
|
|
20
|
-
})
|
|
21
|
-
process.stdin.on('end', () => {
|
|
22
|
-
log(`stdin length: ${data.length}`)
|
|
23
|
-
log(`stdin preview: ${data.substring(0, 500)}`)
|
|
24
|
-
try {
|
|
25
|
-
const parsed = JSON.parse(data)
|
|
26
|
-
log(`parsed hook_event_name: ${parsed.hook_event_name}`)
|
|
27
|
-
log(`parsed session_id: ${parsed.session_id}`)
|
|
28
|
-
if (parsed.prompt) log(`parsed prompt: ${parsed.prompt.substring(0, 100)}`)
|
|
29
|
-
} catch (e) {
|
|
30
|
-
log(`parse error: ${e.message}`)
|
|
31
|
-
}
|
|
32
|
-
log(`--- Done ---\n`)
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
setTimeout(() => {
|
|
36
|
-
log(`TIMEOUT - stdin never ended. data so far: ${data.length} chars`)
|
|
37
|
-
process.exit(0)
|
|
38
|
-
}, 3000)
|