@sooneocean/claude-hud 0.7.0 → 0.9.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/.claude-plugin/plugin.json +5 -1
- package/commands/diff.md +42 -0
- package/commands/preset.md +44 -0
- package/commands/report.md +6 -0
- package/commands/shortcuts.md +35 -0
- package/commands/tag.md +29 -0
- package/dist/alert.d.ts +1 -0
- package/dist/alert.d.ts.map +1 -1
- package/dist/alert.js +24 -0
- package/dist/alert.js.map +1 -1
- package/dist/config.d.ts +2 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +33 -13
- package/dist/config.js.map +1 -1
- package/dist/i18n.d.ts +6 -0
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +18 -0
- package/dist/i18n.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -8
- package/dist/index.js.map +1 -1
- package/dist/perf-guard.d.ts +3 -0
- package/dist/perf-guard.d.ts.map +1 -0
- package/dist/perf-guard.js +33 -0
- package/dist/perf-guard.js.map +1 -0
- package/dist/presets.d.ts +14 -0
- package/dist/presets.d.ts.map +1 -0
- package/dist/presets.js +47 -0
- package/dist/presets.js.map +1 -0
- package/dist/render/lines/identity.d.ts.map +1 -1
- package/dist/render/lines/identity.js +3 -0
- package/dist/render/lines/identity.js.map +1 -1
- package/dist/render/lines/usage.js +6 -6
- package/dist/render/lines/usage.js.map +1 -1
- package/dist/render/todos-line.d.ts.map +1 -1
- package/dist/render/todos-line.js +3 -1
- package/dist/render/todos-line.js.map +1 -1
- package/dist/render/tools-line.d.ts.map +1 -1
- package/dist/render/tools-line.js +3 -1
- package/dist/render/tools-line.js.map +1 -1
- package/dist/session-history.d.ts +3 -0
- package/dist/session-history.d.ts.map +1 -1
- package/dist/session-history.js +16 -0
- package/dist/session-history.js.map +1 -1
- package/dist/session-stats.d.ts +7 -0
- package/dist/session-stats.d.ts.map +1 -1
- package/dist/session-stats.js +17 -0
- package/dist/session-stats.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
- package/src/alert.ts +23 -0
- package/src/config.ts +35 -15
- package/src/i18n.ts +24 -0
- package/src/index.ts +31 -9
- package/src/perf-guard.ts +43 -0
- package/src/presets.ts +56 -0
- package/src/render/lines/identity.ts +4 -0
- package/src/render/lines/usage.ts +6 -6
- package/src/render/todos-line.ts +3 -1
- package/src/render/tools-line.ts +3 -1
- package/src/session-history.ts +19 -0
- package/src/session-stats.ts +27 -0
- package/src/types.ts +2 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-stats.js","sourceRoot":"","sources":["../src/session-stats.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"session-stats.js","sourceRoot":"","sources":["../src/session-stats.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type { McpServerInfo } from './mcp-monitor.js';
|
|
|
5
5
|
import type { Locale } from './i18n.js';
|
|
6
6
|
import type { CustomWidget } from './custom-widgets.js';
|
|
7
7
|
import type { Suggestion } from './suggestions.js';
|
|
8
|
+
import type { ResumeInfo } from './session-stats.js';
|
|
8
9
|
export interface StdinData {
|
|
9
10
|
transcript_path?: string;
|
|
10
11
|
cwd?: string;
|
|
@@ -130,5 +131,6 @@ export interface RenderContext {
|
|
|
130
131
|
customWidgets: CustomWidget[];
|
|
131
132
|
suggestions: Suggestion[];
|
|
132
133
|
rateLimitEta: string | null;
|
|
134
|
+
resumeInfo: ResumeInfo | null;
|
|
133
135
|
}
|
|
134
136
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAsEA,8DAA8D;AAC9D,MAAM,UAAU,cAAc,CAAC,IAAe;IAC5C,OAAO,IAAI,CAAC,QAAQ,KAAK,GAAG,IAAI,IAAI,CAAC,QAAQ,KAAK,GAAG,CAAC;AACxD,CAAC"}
|
package/package.json
CHANGED
package/src/alert.ts
CHANGED
|
@@ -129,6 +129,29 @@ export function predictRateLimitHit(
|
|
|
129
129
|
return `~${hours}h ${mins}m`;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
export function sendWebhook(url: string, alert: Alert): void {
|
|
133
|
+
try {
|
|
134
|
+
const payload = JSON.stringify({
|
|
135
|
+
type: alert.type,
|
|
136
|
+
message: alert.message,
|
|
137
|
+
timestamp: new Date().toISOString(),
|
|
138
|
+
source: 'claude-hud',
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// Fire and forget — don't block HUD rendering
|
|
142
|
+
fetch(url, {
|
|
143
|
+
method: 'POST',
|
|
144
|
+
headers: { 'Content-Type': 'application/json' },
|
|
145
|
+
body: payload,
|
|
146
|
+
signal: AbortSignal.timeout(3000),
|
|
147
|
+
}).catch(() => {
|
|
148
|
+
if (DEBUG) console.error('[claude-hud:alert] webhook failed');
|
|
149
|
+
});
|
|
150
|
+
} catch {
|
|
151
|
+
if (DEBUG) console.error('[claude-hud:alert] webhook error');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
132
155
|
export function runAlertHook(hook: string, alert: Alert): void {
|
|
133
156
|
try {
|
|
134
157
|
const env = {
|
package/src/config.ts
CHANGED
|
@@ -94,7 +94,8 @@ export interface HudConfig {
|
|
|
94
94
|
context: { warningThreshold: number; criticalThreshold: number; actions: AlertAction };
|
|
95
95
|
usage5h: { warningThreshold: number; criticalThreshold: number; actions: AlertAction };
|
|
96
96
|
usage7d: { warningThreshold: number; actions: AlertAction };
|
|
97
|
-
hook?: string;
|
|
97
|
+
hook?: string; // shell command to run on any alert trigger
|
|
98
|
+
webhook?: string; // URL to POST alert data as JSON
|
|
98
99
|
};
|
|
99
100
|
locale: Locale;
|
|
100
101
|
schemaVersion: number;
|
|
@@ -501,6 +502,7 @@ export function mergeConfig(userConfig: Partial<HudConfig>): HudConfig {
|
|
|
501
502
|
actions: mergeAlertActions(migrated.alerts?.usage7d?.actions, DEFAULT_CONFIG.alerts.usage7d.actions),
|
|
502
503
|
},
|
|
503
504
|
hook: typeof migrated.alerts?.hook === 'string' ? migrated.alerts.hook : undefined,
|
|
505
|
+
webhook: typeof migrated.alerts?.webhook === 'string' ? migrated.alerts.webhook : undefined,
|
|
504
506
|
};
|
|
505
507
|
|
|
506
508
|
const locale = (migrated.locale === 'en' || migrated.locale === 'zh' || migrated.locale === 'ja')
|
|
@@ -557,27 +559,45 @@ export function validateConfigWithWarnings(userConfig: Record<string, unknown>):
|
|
|
557
559
|
return warnings;
|
|
558
560
|
}
|
|
559
561
|
|
|
560
|
-
export async function loadConfig(): Promise<HudConfig> {
|
|
562
|
+
export async function loadConfig(cwd?: string): Promise<HudConfig> {
|
|
561
563
|
const configPath = getConfigPath();
|
|
562
564
|
const DEBUG = process.env.DEBUG?.includes('claude-hud') || process.env.DEBUG === '*';
|
|
563
565
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
return DEFAULT_CONFIG;
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
const content = fs.readFileSync(configPath, 'utf-8');
|
|
570
|
-
const userConfig = JSON.parse(content) as Partial<HudConfig>;
|
|
566
|
+
let projectConfig: Partial<HudConfig> = {};
|
|
567
|
+
let userConfig: Partial<HudConfig> = {};
|
|
571
568
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
569
|
+
// 1. Read project-level config (.claude-hud.json in project root)
|
|
570
|
+
if (cwd) {
|
|
571
|
+
try {
|
|
572
|
+
const projectPath = path.join(cwd, '.claude-hud.json');
|
|
573
|
+
if (fs.existsSync(projectPath)) {
|
|
574
|
+
projectConfig = JSON.parse(fs.readFileSync(projectPath, 'utf-8'));
|
|
575
|
+
if (DEBUG) console.error('[claude-hud:config] loaded project config from .claude-hud.json');
|
|
576
576
|
}
|
|
577
|
+
} catch {
|
|
578
|
+
if (DEBUG) console.error('[claude-hud:config] error reading .claude-hud.json');
|
|
577
579
|
}
|
|
580
|
+
}
|
|
578
581
|
|
|
579
|
-
|
|
582
|
+
// 2. Read user config (existing logic)
|
|
583
|
+
try {
|
|
584
|
+
if (fs.existsSync(configPath)) {
|
|
585
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
586
|
+
userConfig = JSON.parse(content) as Partial<HudConfig>;
|
|
587
|
+
}
|
|
580
588
|
} catch {
|
|
581
|
-
|
|
589
|
+
// ignore
|
|
582
590
|
}
|
|
591
|
+
|
|
592
|
+
// 3. Merge: defaults <- project <- user (user overrides project)
|
|
593
|
+
const merged = { ...projectConfig, ...userConfig };
|
|
594
|
+
|
|
595
|
+
const warnings = validateConfigWithWarnings(merged as Record<string, unknown>);
|
|
596
|
+
if (DEBUG && warnings.length > 0) {
|
|
597
|
+
for (const w of warnings) {
|
|
598
|
+
console.error(`[claude-hud:config] ⚠ ${w}`);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
return mergeConfig(merged);
|
|
583
603
|
}
|
package/src/i18n.ts
CHANGED
|
@@ -11,6 +11,12 @@ interface Labels {
|
|
|
11
11
|
resets: string;
|
|
12
12
|
compact: string;
|
|
13
13
|
tokPerMin: string;
|
|
14
|
+
resetsIn: string;
|
|
15
|
+
syncing: string;
|
|
16
|
+
err: string;
|
|
17
|
+
total: string;
|
|
18
|
+
limit: string;
|
|
19
|
+
warn: string;
|
|
14
20
|
}
|
|
15
21
|
|
|
16
22
|
const LABELS: Record<Locale, Labels> = {
|
|
@@ -25,6 +31,12 @@ const LABELS: Record<Locale, Labels> = {
|
|
|
25
31
|
resets: 'resets in',
|
|
26
32
|
compact: 'compact',
|
|
27
33
|
tokPerMin: 'tok/m',
|
|
34
|
+
resetsIn: 'resets in',
|
|
35
|
+
syncing: 'syncing...',
|
|
36
|
+
err: 'err',
|
|
37
|
+
total: 'total',
|
|
38
|
+
limit: 'limit',
|
|
39
|
+
warn: 'Warning',
|
|
28
40
|
},
|
|
29
41
|
zh: {
|
|
30
42
|
context: '上下文',
|
|
@@ -37,6 +49,12 @@ const LABELS: Record<Locale, Labels> = {
|
|
|
37
49
|
resets: '重置於',
|
|
38
50
|
compact: '壓縮',
|
|
39
51
|
tokPerMin: 'tok/m',
|
|
52
|
+
resetsIn: '重置於',
|
|
53
|
+
syncing: '同步中...',
|
|
54
|
+
err: '錯誤',
|
|
55
|
+
total: '總計',
|
|
56
|
+
limit: '上限',
|
|
57
|
+
warn: '警告',
|
|
40
58
|
},
|
|
41
59
|
ja: {
|
|
42
60
|
context: 'コンテキスト',
|
|
@@ -49,6 +67,12 @@ const LABELS: Record<Locale, Labels> = {
|
|
|
49
67
|
resets: 'リセット',
|
|
50
68
|
compact: 'コンパクト',
|
|
51
69
|
tokPerMin: 'tok/m',
|
|
70
|
+
resetsIn: 'リセット',
|
|
71
|
+
syncing: '同期中...',
|
|
72
|
+
err: 'エラー',
|
|
73
|
+
total: '合計',
|
|
74
|
+
limit: '制限',
|
|
75
|
+
warn: '警告',
|
|
52
76
|
},
|
|
53
77
|
};
|
|
54
78
|
|
package/src/index.ts
CHANGED
|
@@ -5,15 +5,16 @@ import { countConfigs } from './config-reader.js';
|
|
|
5
5
|
import { getGitStatus } from './git.js';
|
|
6
6
|
import { getUsage } from './usage-api.js';
|
|
7
7
|
import { loadConfig } from './config.js';
|
|
8
|
+
import type { HudConfig } from './config.js';
|
|
8
9
|
import { parseExtraCmdArg, runExtraCmd } from './extra-cmd.js';
|
|
9
10
|
import type { RenderContext } from './types.js';
|
|
10
11
|
import { fileURLToPath } from 'node:url';
|
|
11
12
|
import { realpathSync } from 'node:fs';
|
|
12
13
|
import { getDefaultCacheDir, readCache, writeCache, readLatency, writeLatency } from './cache.js';
|
|
13
14
|
import { loadProviders, fetchAllProviders } from './providers/index.js';
|
|
14
|
-
import { evaluateAlerts, shouldBell, sendNotification, recordAlertHistory, runAlertHook, predictRateLimitHit } from './alert.js';
|
|
15
|
+
import { evaluateAlerts, shouldBell, sendNotification, recordAlertHistory, runAlertHook, predictRateLimitHit, sendWebhook } from './alert.js';
|
|
15
16
|
import { calculateBurnRate, recordTokenSnapshot } from './burn-rate.js';
|
|
16
|
-
import { updateSessionStats, getSessionStats, getSparkline, updatePromptStats, updateAgentStats } from './session-stats.js';
|
|
17
|
+
import { updateSessionStats, getSessionStats, getSparkline, updatePromptStats, updateAgentStats, detectResume, getResumeInfo } from './session-stats.js';
|
|
17
18
|
import { getTerminalWidth } from './utils/terminal.js';
|
|
18
19
|
import { estimateCost } from './cost-tracker.js';
|
|
19
20
|
import { saveCurrentSession, getLastSession, formatSessionSummary } from './session-history.js';
|
|
@@ -25,6 +26,7 @@ import { loadCustomWidgets } from './custom-widgets.js';
|
|
|
25
26
|
import { updateTokenAnalytics } from './token-analytics.js';
|
|
26
27
|
import { getSuggestions } from './suggestions.js';
|
|
27
28
|
import { autoTuneConfig } from './auto-tune.js';
|
|
29
|
+
import { shouldDegrade, recordExecutionTime } from './perf-guard.js';
|
|
28
30
|
|
|
29
31
|
export type MainDeps = {
|
|
30
32
|
readStdin: typeof readStdin;
|
|
@@ -32,7 +34,7 @@ export type MainDeps = {
|
|
|
32
34
|
countConfigs: typeof countConfigs;
|
|
33
35
|
getGitStatus: typeof getGitStatus;
|
|
34
36
|
getUsage: typeof getUsage;
|
|
35
|
-
loadConfig:
|
|
37
|
+
loadConfig: (cwd?: string) => Promise<HudConfig>;
|
|
36
38
|
parseExtraCmdArg: typeof parseExtraCmdArg;
|
|
37
39
|
runExtraCmd: typeof runExtraCmd;
|
|
38
40
|
render: typeof render;
|
|
@@ -48,6 +50,7 @@ function timer() {
|
|
|
48
50
|
export async function main(overrides: Partial<MainDeps> = {}): Promise<void> {
|
|
49
51
|
const DEBUG = process.env.DEBUG?.includes('claude-hud') || process.env.DEBUG === '*';
|
|
50
52
|
const tTotal = timer();
|
|
53
|
+
const perfStart = Date.now();
|
|
51
54
|
|
|
52
55
|
const deps: MainDeps = {
|
|
53
56
|
readStdin,
|
|
@@ -55,7 +58,7 @@ export async function main(overrides: Partial<MainDeps> = {}): Promise<void> {
|
|
|
55
58
|
countConfigs,
|
|
56
59
|
getGitStatus,
|
|
57
60
|
getUsage,
|
|
58
|
-
loadConfig,
|
|
61
|
+
loadConfig: (cwd?: string) => loadConfig(cwd),
|
|
59
62
|
parseExtraCmdArg,
|
|
60
63
|
runExtraCmd,
|
|
61
64
|
render,
|
|
@@ -89,8 +92,11 @@ export async function main(overrides: Partial<MainDeps> = {}): Promise<void> {
|
|
|
89
92
|
|
|
90
93
|
const cacheDir = getDefaultCacheDir();
|
|
91
94
|
|
|
95
|
+
const degradeMode = shouldDegrade(cacheDir);
|
|
96
|
+
if (DEBUG && degradeMode) console.error('[claude-hud:perf] running in degrade mode');
|
|
97
|
+
|
|
92
98
|
const t3 = timer();
|
|
93
|
-
let config = await deps.loadConfig();
|
|
99
|
+
let config = await deps.loadConfig(stdin.cwd);
|
|
94
100
|
if (DEBUG) console.error(`[claude-hud:timing] loadConfig: ${t3()}ms`);
|
|
95
101
|
config = autoTuneConfig(config, getTerminalWidth(), cacheDir);
|
|
96
102
|
const t4 = timer();
|
|
@@ -121,16 +127,16 @@ export async function main(overrides: Partial<MainDeps> = {}): Promise<void> {
|
|
|
121
127
|
|
|
122
128
|
const sessionDuration = formatSessionDuration(transcript.sessionStart, deps.now);
|
|
123
129
|
|
|
124
|
-
// Framework providers
|
|
130
|
+
// Framework providers — skip if degrading
|
|
125
131
|
let frameworkStatus: RenderContext['frameworkStatus'] = [];
|
|
126
|
-
if (config.display.showFrameworks) {
|
|
132
|
+
if (config.display.showFrameworks && !degradeMode) {
|
|
127
133
|
const providers = loadProviders(config.frameworks, cacheDir);
|
|
128
134
|
frameworkStatus = await fetchAllProviders(providers);
|
|
129
135
|
}
|
|
130
136
|
|
|
131
|
-
// Token analytics (data collection only, no HUD display)
|
|
137
|
+
// Token analytics (data collection only, no HUD display) — skip if degrading
|
|
132
138
|
const inputTokens = stdin.context_window?.current_usage?.input_tokens;
|
|
133
|
-
if (inputTokens) {
|
|
139
|
+
if (inputTokens && !degradeMode) {
|
|
134
140
|
updateTokenAnalytics(inputTokens, transcript.tools, cacheDir);
|
|
135
141
|
}
|
|
136
142
|
|
|
@@ -155,6 +161,13 @@ export async function main(overrides: Partial<MainDeps> = {}): Promise<void> {
|
|
|
155
161
|
// Context percent
|
|
156
162
|
const contextPercent = getContextPercent(stdin);
|
|
157
163
|
|
|
164
|
+
// Session resume detection — detect autocompact by large context drop
|
|
165
|
+
const prevContextPercent = readCache<number>('prev-context-percent', 86400000, cacheDir);
|
|
166
|
+
const contextSizeForResume = stdin.context_window?.context_window_size ?? 0;
|
|
167
|
+
detectResume(contextPercent, prevContextPercent, contextSizeForResume, cacheDir);
|
|
168
|
+
writeCache('prev-context-percent', contextPercent, cacheDir);
|
|
169
|
+
const resumeInfo = getResumeInfo(cacheDir);
|
|
170
|
+
|
|
158
171
|
// Agent efficiency tracking
|
|
159
172
|
if (transcript.agents.length > 0) {
|
|
160
173
|
updateAgentStats(transcript.agents, cacheDir);
|
|
@@ -203,6 +216,12 @@ export async function main(overrides: Partial<MainDeps> = {}): Promise<void> {
|
|
|
203
216
|
runAlertHook(config.alerts.hook as string, alert);
|
|
204
217
|
}
|
|
205
218
|
}
|
|
219
|
+
|
|
220
|
+
if (config.alerts.webhook) {
|
|
221
|
+
for (const alert of alerts.filter(a => a.type.includes('critical'))) {
|
|
222
|
+
sendWebhook(config.alerts.webhook, alert);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
206
225
|
}
|
|
207
226
|
|
|
208
227
|
// Rate limit prediction
|
|
@@ -272,6 +291,7 @@ export async function main(overrides: Partial<MainDeps> = {}): Promise<void> {
|
|
|
272
291
|
locale: config.locale ?? detectLocale(),
|
|
273
292
|
customWidgets,
|
|
274
293
|
rateLimitEta,
|
|
294
|
+
resumeInfo,
|
|
275
295
|
};
|
|
276
296
|
const suggestions = config.display.showAlerts
|
|
277
297
|
? getSuggestions(suggestionInput as RenderContext)
|
|
@@ -286,6 +306,8 @@ export async function main(overrides: Partial<MainDeps> = {}): Promise<void> {
|
|
|
286
306
|
deps.render(ctx);
|
|
287
307
|
if (DEBUG) console.error(`[claude-hud:timing] render: ${t6()}ms`);
|
|
288
308
|
if (DEBUG) console.error(`[claude-hud:timing] total: ${tTotal()}ms`);
|
|
309
|
+
|
|
310
|
+
recordExecutionTime(Date.now() - perfStart, cacheDir);
|
|
289
311
|
} catch (error) {
|
|
290
312
|
deps.log('[claude-hud] Error:', error instanceof Error ? error.message : 'Unknown error');
|
|
291
313
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { readCache, writeCache } from './cache.js';
|
|
2
|
+
|
|
3
|
+
const DEBUG = process.env.DEBUG?.includes('claude-hud') || process.env.DEBUG === '*';
|
|
4
|
+
const PERF_KEY = 'perf-history';
|
|
5
|
+
const TTL = 24 * 60 * 60 * 1000;
|
|
6
|
+
const BUDGET_MS = 250; // Leave 50ms margin from 300ms
|
|
7
|
+
|
|
8
|
+
interface PerfHistory {
|
|
9
|
+
recentTimes: number[]; // last 10 execution times
|
|
10
|
+
degradeMode: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function shouldDegrade(cacheDir: string): boolean {
|
|
14
|
+
const history = readCache<PerfHistory>(PERF_KEY, TTL, cacheDir);
|
|
15
|
+
return history?.degradeMode ?? false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function recordExecutionTime(ms: number, cacheDir: string): void {
|
|
19
|
+
const history = readCache<PerfHistory>(PERF_KEY, TTL, cacheDir) ?? {
|
|
20
|
+
recentTimes: [],
|
|
21
|
+
degradeMode: false,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
history.recentTimes.push(ms);
|
|
25
|
+
if (history.recentTimes.length > 10) history.recentTimes.shift();
|
|
26
|
+
|
|
27
|
+
// Check if average of last 5 exceeds budget
|
|
28
|
+
const recent5 = history.recentTimes.slice(-5);
|
|
29
|
+
if (recent5.length >= 5) {
|
|
30
|
+
const avg = recent5.reduce((a, b) => a + b, 0) / recent5.length;
|
|
31
|
+
const wasDegrade = history.degradeMode;
|
|
32
|
+
history.degradeMode = avg > BUDGET_MS;
|
|
33
|
+
|
|
34
|
+
if (history.degradeMode && !wasDegrade && DEBUG) {
|
|
35
|
+
console.error(`[claude-hud:perf] degrading — avg ${Math.round(avg)}ms > ${BUDGET_MS}ms budget`);
|
|
36
|
+
}
|
|
37
|
+
if (!history.degradeMode && wasDegrade && DEBUG) {
|
|
38
|
+
console.error(`[claude-hud:perf] recovered — avg ${Math.round(avg)}ms`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
writeCache(PERF_KEY, history, cacheDir);
|
|
43
|
+
}
|
package/src/presets.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import type { HudConfig } from './config.js';
|
|
4
|
+
|
|
5
|
+
const DEBUG = process.env.DEBUG?.includes('claude-hud') || process.env.DEBUG === '*';
|
|
6
|
+
|
|
7
|
+
interface Preset {
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
config: Partial<HudConfig>;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function getPresetsPath(): string {
|
|
15
|
+
const configDir = process.env.CLAUDE_CONFIG_DIR || path.join(process.env.HOME || '', '.claude');
|
|
16
|
+
return path.join(configDir, 'plugins', 'claude-hud', 'presets.json');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function loadPresets(): Preset[] {
|
|
20
|
+
try {
|
|
21
|
+
return JSON.parse(fs.readFileSync(getPresetsPath(), 'utf-8'));
|
|
22
|
+
} catch {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function savePreset(name: string, description: string, config: Partial<HudConfig>): void {
|
|
28
|
+
const presets = loadPresets();
|
|
29
|
+
const existing = presets.findIndex(p => p.name === name);
|
|
30
|
+
const preset: Preset = { name, description, config, createdAt: new Date().toISOString() };
|
|
31
|
+
if (existing >= 0) presets[existing] = preset;
|
|
32
|
+
else presets.push(preset);
|
|
33
|
+
|
|
34
|
+
const dir = path.dirname(getPresetsPath());
|
|
35
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
36
|
+
fs.writeFileSync(getPresetsPath(), JSON.stringify(presets, null, 2));
|
|
37
|
+
if (DEBUG) console.error(`[claude-hud:presets] saved preset "${name}"`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function getPreset(name: string): Preset | undefined {
|
|
41
|
+
return loadPresets().find(p => p.name === name);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function deletePreset(name: string): boolean {
|
|
45
|
+
const presets = loadPresets();
|
|
46
|
+
const idx = presets.findIndex(p => p.name === name);
|
|
47
|
+
if (idx < 0) return false;
|
|
48
|
+
presets.splice(idx, 1);
|
|
49
|
+
fs.writeFileSync(getPresetsPath(), JSON.stringify(presets, null, 2));
|
|
50
|
+
if (DEBUG) console.error(`[claude-hud:presets] deleted preset "${name}"`);
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function exportPresetAsJson(preset: Preset): string {
|
|
55
|
+
return JSON.stringify(preset, null, 2);
|
|
56
|
+
}
|
|
@@ -117,6 +117,10 @@ export function renderIdentityLine(ctx: RenderContext): string {
|
|
|
117
117
|
line += dim(` (${ordinal(ctx.sessionStats.autocompactCount)} compact)`);
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
if (ctx.resumeInfo) {
|
|
121
|
+
line += ` ${dim(`↓${ctx.resumeInfo.preCompactPercent}→${ctx.resumeInfo.postCompactPercent}%`)}`;
|
|
122
|
+
}
|
|
123
|
+
|
|
120
124
|
if (!isNarrow && ctx.sparkline && ctx.sparkline.length >= 3) {
|
|
121
125
|
line += ` ${renderHeatmap(ctx.sparkline)}`;
|
|
122
126
|
}
|
|
@@ -34,7 +34,7 @@ export function renderUsageLine(ctx: RenderContext): string | null {
|
|
|
34
34
|
const resetTime = ctx.usageData.fiveHour === 100
|
|
35
35
|
? formatResetTime(ctx.usageData.fiveHourResetAt)
|
|
36
36
|
: formatResetTime(ctx.usageData.sevenDayResetAt);
|
|
37
|
-
return `${label} ${critical(`⚠
|
|
37
|
+
return `${label} ${critical(`⚠ ${labels.limitReached}${resetTime ? ` (${labels.resetsIn} ${resetTime})` : ''}`, colors)}`;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
const threshold = display?.usageThreshold ?? 0;
|
|
@@ -53,25 +53,25 @@ export function renderUsageLine(ctx: RenderContext): string | null {
|
|
|
53
53
|
const barStyle = display?.barStyle ?? 'classic';
|
|
54
54
|
const fiveHourPart = usageBarEnabled
|
|
55
55
|
? (fiveHourReset
|
|
56
|
-
? `${quotaBar(fiveHour ?? 0, getAdaptiveBarWidth(), colors, barStyle)} ${fiveHourDisplay} (
|
|
56
|
+
? `${quotaBar(fiveHour ?? 0, getAdaptiveBarWidth(), colors, barStyle)} ${fiveHourDisplay} (${labels.resetsIn} ${fiveHourReset})`
|
|
57
57
|
: `${quotaBar(fiveHour ?? 0, getAdaptiveBarWidth(), colors, barStyle)} ${fiveHourDisplay}`)
|
|
58
58
|
: (fiveHourReset
|
|
59
|
-
? `5h: ${fiveHourDisplay} (
|
|
59
|
+
? `5h: ${fiveHourDisplay} (${labels.resetsIn} ${fiveHourReset})`
|
|
60
60
|
: `5h: ${fiveHourDisplay}`);
|
|
61
61
|
|
|
62
62
|
const sevenDayThreshold = display?.sevenDayThreshold ?? 80;
|
|
63
63
|
const syncingSuffix = ctx.usageData.apiError === 'rate-limited'
|
|
64
|
-
? ` ${dim(
|
|
64
|
+
? ` ${dim(`(${labels.syncing})`)}`
|
|
65
65
|
: '';
|
|
66
66
|
if (sevenDay !== null && sevenDay >= sevenDayThreshold) {
|
|
67
67
|
const sevenDayDisplay = formatUsagePercent(sevenDay, colors);
|
|
68
68
|
const sevenDayReset = formatResetTime(ctx.usageData.sevenDayResetAt);
|
|
69
69
|
const sevenDayPart = usageBarEnabled
|
|
70
70
|
? (sevenDayReset
|
|
71
|
-
? `${quotaBar(sevenDay, getAdaptiveBarWidth(), colors, barStyle)} ${sevenDayDisplay} (
|
|
71
|
+
? `${quotaBar(sevenDay, getAdaptiveBarWidth(), colors, barStyle)} ${sevenDayDisplay} (${labels.resetsIn} ${sevenDayReset})`
|
|
72
72
|
: `${quotaBar(sevenDay, getAdaptiveBarWidth(), colors, barStyle)} ${sevenDayDisplay}`)
|
|
73
73
|
: (sevenDayReset
|
|
74
|
-
? `7d: ${sevenDayDisplay} (
|
|
74
|
+
? `7d: ${sevenDayDisplay} (${labels.resetsIn} ${sevenDayReset})`
|
|
75
75
|
: `7d: ${sevenDayDisplay}`);
|
|
76
76
|
let result = `${label} ${fiveHourPart} ${dim('│')} ${sevenDayPart}${syncingSuffix}`;
|
|
77
77
|
if (ctx.rateLimitEta) {
|
package/src/render/todos-line.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { RenderContext } from '../types.js';
|
|
2
2
|
import { yellow, green, dim, claudeOrange } from './colors.js';
|
|
3
3
|
import { truncateString } from '../utils/format.js';
|
|
4
|
+
import { getLabels } from '../i18n.js';
|
|
4
5
|
|
|
5
6
|
export function renderTodosLine(ctx: RenderContext): string | null {
|
|
7
|
+
const labels = getLabels(ctx.locale || 'en');
|
|
6
8
|
const { todos } = ctx.transcript;
|
|
7
9
|
|
|
8
10
|
if (!todos || todos.length === 0) {
|
|
@@ -15,7 +17,7 @@ export function renderTodosLine(ctx: RenderContext): string | null {
|
|
|
15
17
|
|
|
16
18
|
if (!inProgress) {
|
|
17
19
|
if (completed === total && total > 0) {
|
|
18
|
-
return `${green('✓')}
|
|
20
|
+
return `${green('✓')} ${labels.allComplete} ${dim(`(${completed}/${total})`)}`;
|
|
19
21
|
}
|
|
20
22
|
return null;
|
|
21
23
|
}
|
package/src/render/tools-line.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { RenderContext } from '../types.js';
|
|
2
2
|
import { yellow, green, cyan, dim, magenta, red } from './colors.js';
|
|
3
3
|
import { truncatePath } from '../utils/format.js';
|
|
4
|
+
import { getLabels } from '../i18n.js';
|
|
4
5
|
|
|
5
6
|
export function renderToolsLine(ctx: RenderContext): string | null {
|
|
7
|
+
const labels = getLabels(ctx.locale || 'en');
|
|
6
8
|
const { tools } = ctx.transcript;
|
|
7
9
|
|
|
8
10
|
if (tools.length === 0) {
|
|
@@ -36,7 +38,7 @@ export function renderToolsLine(ctx: RenderContext): string | null {
|
|
|
36
38
|
// Show error count if any tools failed
|
|
37
39
|
const errorCount = ctx.transcript.tools.filter(t => t.status === 'error').length;
|
|
38
40
|
if (errorCount > 0) {
|
|
39
|
-
parts.push(`${red('✘')} ${errorCount} err`);
|
|
41
|
+
parts.push(`${red('✘')} ${errorCount} ${labels.err}`);
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
if (ctx.config.display.mergeToolsAgents && ctx.transcript.agents.length > 0) {
|
package/src/session-history.ts
CHANGED
|
@@ -12,6 +12,7 @@ export interface SessionRecord {
|
|
|
12
12
|
autocompactCount: number;
|
|
13
13
|
totalToolCalls: number;
|
|
14
14
|
totalAgentRuns: number;
|
|
15
|
+
tags?: string[];
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
function getHistoryPath(): string {
|
|
@@ -57,6 +58,24 @@ export function getLastSession(): SessionRecord | null {
|
|
|
57
58
|
return history.length >= 2 ? history[history.length - 2] : null;
|
|
58
59
|
}
|
|
59
60
|
|
|
61
|
+
export function tagCurrentSession(tags: string[], _cacheDir: string): void {
|
|
62
|
+
const history = loadHistory();
|
|
63
|
+
if (history.length === 0) return;
|
|
64
|
+
|
|
65
|
+
// Tag the most recent session
|
|
66
|
+
const last = history[history.length - 1];
|
|
67
|
+
last.tags = [...new Set([...(last.tags || []), ...tags])];
|
|
68
|
+
|
|
69
|
+
const dir = path.dirname(getHistoryPath());
|
|
70
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
71
|
+
fs.writeFileSync(getHistoryPath(), JSON.stringify(history, null, 2));
|
|
72
|
+
if (DEBUG) console.error(`[claude-hud:session-history] tagged session with: ${tags.join(', ')}`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function getSessionsByTag(tag: string): SessionRecord[] {
|
|
76
|
+
return loadHistory().filter(s => s.tags?.includes(tag));
|
|
77
|
+
}
|
|
78
|
+
|
|
60
79
|
export function formatSessionSummary(record: SessionRecord): string {
|
|
61
80
|
return `Last: ${record.model} ${record.duration} | ${record.peakContextPercent}% peak | ${record.totalToolCalls} tools | ${record.autocompactCount} compacts`;
|
|
62
81
|
}
|
package/src/session-stats.ts
CHANGED
|
@@ -1,6 +1,33 @@
|
|
|
1
1
|
import { readCache, writeCache } from './cache.js';
|
|
2
2
|
import type { SessionStats } from './types.js';
|
|
3
3
|
|
|
4
|
+
export interface ResumeInfo {
|
|
5
|
+
preCompactPercent: number;
|
|
6
|
+
postCompactPercent: number;
|
|
7
|
+
tokensRecovered: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const RESUME_KEY = 'resume-info';
|
|
11
|
+
|
|
12
|
+
export function detectResume(contextPercent: number, prevPercent: number | null, contextSize: number, cacheDir: string): ResumeInfo | null {
|
|
13
|
+
if (prevPercent === null || prevPercent - contextPercent < 20) return null;
|
|
14
|
+
|
|
15
|
+
const tokensRecovered = Math.round((prevPercent - contextPercent) / 100 * contextSize);
|
|
16
|
+
const info: ResumeInfo = {
|
|
17
|
+
preCompactPercent: prevPercent,
|
|
18
|
+
postCompactPercent: contextPercent,
|
|
19
|
+
tokensRecovered,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// Store for display (expires after 60s — only show briefly after compact)
|
|
23
|
+
writeCache(RESUME_KEY, info, cacheDir);
|
|
24
|
+
return info;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function getResumeInfo(cacheDir: string): ResumeInfo | null {
|
|
28
|
+
return readCache<ResumeInfo>(RESUME_KEY, 60000, cacheDir);
|
|
29
|
+
}
|
|
30
|
+
|
|
4
31
|
export interface PromptStats {
|
|
5
32
|
count: number;
|
|
6
33
|
avgTokens: number;
|
package/src/types.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type { McpServerInfo } from './mcp-monitor.js';
|
|
|
5
5
|
import type { Locale } from './i18n.js';
|
|
6
6
|
import type { CustomWidget } from './custom-widgets.js';
|
|
7
7
|
import type { Suggestion } from './suggestions.js';
|
|
8
|
+
import type { ResumeInfo } from './session-stats.js';
|
|
8
9
|
|
|
9
10
|
export interface StdinData {
|
|
10
11
|
transcript_path?: string;
|
|
@@ -153,4 +154,5 @@ export interface RenderContext {
|
|
|
153
154
|
customWidgets: CustomWidget[];
|
|
154
155
|
suggestions: Suggestion[];
|
|
155
156
|
rateLimitEta: string | null;
|
|
157
|
+
resumeInfo: ResumeInfo | null;
|
|
156
158
|
}
|