@sooneocean/claude-hud 0.1.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/marketplace.json +20 -0
- package/.claude-plugin/plugin.json +20 -0
- package/LICENSE +21 -0
- package/README.md +379 -0
- package/commands/configure.md +361 -0
- package/commands/export.md +43 -0
- package/commands/health.md +61 -0
- package/commands/setup.md +287 -0
- package/commands/theme.md +31 -0
- package/dist/alert.d.ts +31 -0
- package/dist/alert.d.ts.map +1 -0
- package/dist/alert.js +53 -0
- package/dist/alert.js.map +1 -0
- package/dist/burn-rate.d.ts +4 -0
- package/dist/burn-rate.d.ts.map +1 -0
- package/dist/burn-rate.js +36 -0
- package/dist/burn-rate.js.map +1 -0
- package/dist/cache.d.ts +6 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +47 -0
- package/dist/cache.js.map +1 -0
- package/dist/claude-config-dir.d.ts +4 -0
- package/dist/claude-config-dir.d.ts.map +1 -0
- package/dist/claude-config-dir.js +24 -0
- package/dist/claude-config-dir.js.map +1 -0
- package/dist/config-io.d.ts +6 -0
- package/dist/config-io.d.ts.map +1 -0
- package/dist/config-io.js +27 -0
- package/dist/config-io.js.map +1 -0
- package/dist/config-reader.d.ts +8 -0
- package/dist/config-reader.d.ts.map +1 -0
- package/dist/config-reader.js +204 -0
- package/dist/config-reader.js.map +1 -0
- package/dist/config.d.ts +94 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +358 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +11 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +11 -0
- package/dist/constants.js.map +1 -0
- package/dist/cost-tracker.d.ts +9 -0
- package/dist/cost-tracker.d.ts.map +1 -0
- package/dist/cost-tracker.js +46 -0
- package/dist/cost-tracker.js.map +1 -0
- package/dist/debug.d.ts +6 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +15 -0
- package/dist/debug.js.map +1 -0
- package/dist/extra-cmd.d.ts +20 -0
- package/dist/extra-cmd.d.ts.map +1 -0
- package/dist/extra-cmd.js +112 -0
- package/dist/extra-cmd.js.map +1 -0
- package/dist/git.d.ts +16 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +94 -0
- package/dist/git.js.map +1 -0
- package/dist/health-check.d.ts +12 -0
- package/dist/health-check.d.ts.map +1 -0
- package/dist/health-check.js +37 -0
- package/dist/health-check.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +198 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/agent-teams-provider.d.ts +10 -0
- package/dist/providers/agent-teams-provider.d.ts.map +1 -0
- package/dist/providers/agent-teams-provider.js +57 -0
- package/dist/providers/agent-teams-provider.js.map +1 -0
- package/dist/providers/agw-provider.d.ts +10 -0
- package/dist/providers/agw-provider.d.ts.map +1 -0
- package/dist/providers/agw-provider.js +49 -0
- package/dist/providers/agw-provider.js.map +1 -0
- package/dist/providers/index.d.ts +14 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +25 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/render/agents-line.d.ts +3 -0
- package/dist/render/agents-line.d.ts.map +1 -0
- package/dist/render/agents-line.js +40 -0
- package/dist/render/agents-line.js.map +1 -0
- package/dist/render/alert-line.d.ts +3 -0
- package/dist/render/alert-line.d.ts.map +1 -0
- package/dist/render/alert-line.js +11 -0
- package/dist/render/alert-line.js.map +1 -0
- package/dist/render/colors.d.ts +39 -0
- package/dist/render/colors.d.ts.map +1 -0
- package/dist/render/colors.js +109 -0
- package/dist/render/colors.js.map +1 -0
- package/dist/render/framework-line.d.ts +3 -0
- package/dist/render/framework-line.d.ts.map +1 -0
- package/dist/render/framework-line.js +32 -0
- package/dist/render/framework-line.js.map +1 -0
- package/dist/render/index.d.ts +3 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +435 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/lines/environment.d.ts +3 -0
- package/dist/render/lines/environment.d.ts.map +1 -0
- package/dist/render/lines/environment.js +30 -0
- package/dist/render/lines/environment.js.map +1 -0
- package/dist/render/lines/identity.d.ts +3 -0
- package/dist/render/lines/identity.d.ts.map +1 -0
- package/dist/render/lines/identity.js +93 -0
- package/dist/render/lines/identity.js.map +1 -0
- package/dist/render/lines/index.d.ts +5 -0
- package/dist/render/lines/index.d.ts.map +1 -0
- package/dist/render/lines/index.js +5 -0
- package/dist/render/lines/index.js.map +1 -0
- package/dist/render/lines/project.d.ts +3 -0
- package/dist/render/lines/project.d.ts.map +1 -0
- package/dist/render/lines/project.js +100 -0
- package/dist/render/lines/project.js.map +1 -0
- package/dist/render/lines/usage.d.ts +3 -0
- package/dist/render/lines/usage.d.ts.map +1 -0
- package/dist/render/lines/usage.js +65 -0
- package/dist/render/lines/usage.js.map +1 -0
- package/dist/render/session-line.d.ts +7 -0
- package/dist/render/session-line.d.ts.map +1 -0
- package/dist/render/session-line.js +227 -0
- package/dist/render/session-line.js.map +1 -0
- package/dist/render/todos-line.d.ts +3 -0
- package/dist/render/todos-line.d.ts.map +1 -0
- package/dist/render/todos-line.js +29 -0
- package/dist/render/todos-line.js.map +1 -0
- package/dist/render/tools-line.d.ts +3 -0
- package/dist/render/tools-line.d.ts.map +1 -0
- package/dist/render/tools-line.js +45 -0
- package/dist/render/tools-line.js.map +1 -0
- package/dist/session-history.d.ts +15 -0
- package/dist/session-history.d.ts.map +1 -0
- package/dist/session-history.js +46 -0
- package/dist/session-history.js.map +1 -0
- package/dist/session-stats.d.ts +11 -0
- package/dist/session-stats.d.ts.map +1 -0
- package/dist/session-stats.js +48 -0
- package/dist/session-stats.js.map +1 -0
- package/dist/speed-tracker.d.ts +7 -0
- package/dist/speed-tracker.d.ts.map +1 -0
- package/dist/speed-tracker.js +34 -0
- package/dist/speed-tracker.js.map +1 -0
- package/dist/stdin.d.ts +9 -0
- package/dist/stdin.d.ts.map +1 -0
- package/dist/stdin.js +142 -0
- package/dist/stdin.js.map +1 -0
- package/dist/themes.d.ts +10 -0
- package/dist/themes.d.ts.map +1 -0
- package/dist/themes.js +81 -0
- package/dist/themes.js.map +1 -0
- package/dist/transcript.d.ts +3 -0
- package/dist/transcript.d.ts.map +1 -0
- package/dist/transcript.js +221 -0
- package/dist/transcript.js.map +1 -0
- package/dist/types.d.ts +124 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/usage-api.d.ts +62 -0
- package/dist/usage-api.d.ts.map +1 -0
- package/dist/usage-api.js +908 -0
- package/dist/usage-api.js.map +1 -0
- package/dist/utils/format.d.ts +9 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +75 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/terminal.d.ts +5 -0
- package/dist/utils/terminal.d.ts.map +1 -0
- package/dist/utils/terminal.js +42 -0
- package/dist/utils/terminal.js.map +1 -0
- package/package.json +36 -0
- package/src/alert.ts +75 -0
- package/src/burn-rate.ts +45 -0
- package/src/cache.ts +57 -0
- package/src/claude-config-dir.ts +27 -0
- package/src/config-io.ts +26 -0
- package/src/config-reader.ts +236 -0
- package/src/config.ts +496 -0
- package/src/constants.ts +10 -0
- package/src/cost-tracker.ts +53 -0
- package/src/debug.ts +16 -0
- package/src/extra-cmd.ts +125 -0
- package/src/git.ts +126 -0
- package/src/health-check.ts +50 -0
- package/src/index.ts +234 -0
- package/src/providers/agent-teams-provider.ts +56 -0
- package/src/providers/agw-provider.ts +47 -0
- package/src/providers/index.ts +27 -0
- package/src/render/agents-line.ts +51 -0
- package/src/render/alert-line.ts +11 -0
- package/src/render/colors.ts +145 -0
- package/src/render/framework-line.ts +34 -0
- package/src/render/index.ts +512 -0
- package/src/render/lines/environment.ts +41 -0
- package/src/render/lines/identity.ts +109 -0
- package/src/render/lines/index.ts +4 -0
- package/src/render/lines/project.ts +113 -0
- package/src/render/lines/usage.ts +79 -0
- package/src/render/session-line.ts +253 -0
- package/src/render/todos-line.ts +35 -0
- package/src/render/tools-line.ts +58 -0
- package/src/session-history.ts +62 -0
- package/src/session-stats.ts +65 -0
- package/src/speed-tracker.ts +51 -0
- package/src/stdin.ts +169 -0
- package/src/themes.ts +90 -0
- package/src/transcript.ts +268 -0
- package/src/types.ts +146 -0
- package/src/usage-api.ts +1090 -0
- package/src/utils/format.ts +79 -0
- package/src/utils/terminal.ts +46 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as readline from 'readline';
|
|
3
|
+
import type { TranscriptData, ToolEntry, AgentEntry, TodoItem } from './types.js';
|
|
4
|
+
import { readCache, writeCache, getDefaultCacheDir } from './cache.js';
|
|
5
|
+
|
|
6
|
+
interface TranscriptLine {
|
|
7
|
+
timestamp?: string;
|
|
8
|
+
type?: string;
|
|
9
|
+
slug?: string;
|
|
10
|
+
customTitle?: string;
|
|
11
|
+
message?: {
|
|
12
|
+
content?: ContentBlock[];
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface ContentBlock {
|
|
17
|
+
type: string;
|
|
18
|
+
id?: string;
|
|
19
|
+
name?: string;
|
|
20
|
+
input?: Record<string, unknown>;
|
|
21
|
+
tool_use_id?: string;
|
|
22
|
+
is_error?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function restoreDates(data: TranscriptData): TranscriptData {
|
|
26
|
+
return {
|
|
27
|
+
...data,
|
|
28
|
+
sessionStart: data.sessionStart ? new Date(data.sessionStart) : undefined,
|
|
29
|
+
tools: data.tools.map(t => ({
|
|
30
|
+
...t,
|
|
31
|
+
startTime: new Date(t.startTime),
|
|
32
|
+
endTime: t.endTime ? new Date(t.endTime) : undefined,
|
|
33
|
+
})),
|
|
34
|
+
agents: data.agents.map(a => ({
|
|
35
|
+
...a,
|
|
36
|
+
startTime: new Date(a.startTime),
|
|
37
|
+
endTime: a.endTime ? new Date(a.endTime) : undefined,
|
|
38
|
+
})),
|
|
39
|
+
todos: data.todos,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function parseTranscript(transcriptPath: string): Promise<TranscriptData> {
|
|
44
|
+
const result: TranscriptData = {
|
|
45
|
+
tools: [],
|
|
46
|
+
agents: [],
|
|
47
|
+
todos: [],
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
if (!transcriptPath) {
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const cacheDir = getDefaultCacheDir();
|
|
55
|
+
const stats = fs.statSync(transcriptPath, { throwIfNoEntry: false });
|
|
56
|
+
if (!stats) return result;
|
|
57
|
+
|
|
58
|
+
const mtime = stats.mtimeMs;
|
|
59
|
+
const cacheKey = 'transcript-parsed';
|
|
60
|
+
|
|
61
|
+
const cached = readCache<TranscriptData>(cacheKey, 500, cacheDir, mtime);
|
|
62
|
+
if (cached) {
|
|
63
|
+
return restoreDates(cached);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!fs.existsSync(transcriptPath)) {
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const toolMap = new Map<string, ToolEntry>();
|
|
71
|
+
const agentMap = new Map<string, AgentEntry>();
|
|
72
|
+
let latestTodos: TodoItem[] = [];
|
|
73
|
+
const taskIdToIndex = new Map<string, number>();
|
|
74
|
+
let latestSlug: string | undefined;
|
|
75
|
+
let customTitle: string | undefined;
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
const fileStream = fs.createReadStream(transcriptPath);
|
|
79
|
+
const rl = readline.createInterface({
|
|
80
|
+
input: fileStream,
|
|
81
|
+
crlfDelay: Infinity,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
for await (const line of rl) {
|
|
85
|
+
if (!line.trim()) continue;
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const entry = JSON.parse(line) as TranscriptLine;
|
|
89
|
+
if (entry.type === 'custom-title' && typeof entry.customTitle === 'string') {
|
|
90
|
+
customTitle = entry.customTitle;
|
|
91
|
+
} else if (typeof entry.slug === 'string') {
|
|
92
|
+
latestSlug = entry.slug;
|
|
93
|
+
}
|
|
94
|
+
processEntry(entry, toolMap, agentMap, taskIdToIndex, latestTodos, result);
|
|
95
|
+
} catch {
|
|
96
|
+
// Skip malformed lines
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
} catch {
|
|
100
|
+
// Return partial results on error
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
result.tools = Array.from(toolMap.values()).slice(-20);
|
|
104
|
+
result.agents = Array.from(agentMap.values()).slice(-10);
|
|
105
|
+
result.todos = latestTodos;
|
|
106
|
+
result.sessionName = customTitle ?? latestSlug;
|
|
107
|
+
|
|
108
|
+
writeCache(cacheKey, result, cacheDir, mtime);
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function processEntry(
|
|
113
|
+
entry: TranscriptLine,
|
|
114
|
+
toolMap: Map<string, ToolEntry>,
|
|
115
|
+
agentMap: Map<string, AgentEntry>,
|
|
116
|
+
taskIdToIndex: Map<string, number>,
|
|
117
|
+
latestTodos: TodoItem[],
|
|
118
|
+
result: TranscriptData
|
|
119
|
+
): void {
|
|
120
|
+
const timestamp = entry.timestamp ? new Date(entry.timestamp) : new Date();
|
|
121
|
+
|
|
122
|
+
if (!result.sessionStart && entry.timestamp) {
|
|
123
|
+
result.sessionStart = timestamp;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const content = entry.message?.content;
|
|
127
|
+
if (!content || !Array.isArray(content)) return;
|
|
128
|
+
|
|
129
|
+
for (const block of content) {
|
|
130
|
+
if (block.type === 'tool_use' && block.id && block.name) {
|
|
131
|
+
const toolEntry: ToolEntry = {
|
|
132
|
+
id: block.id,
|
|
133
|
+
name: block.name,
|
|
134
|
+
target: extractTarget(block.name, block.input),
|
|
135
|
+
status: 'running',
|
|
136
|
+
startTime: timestamp,
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
if (block.name === 'Task') {
|
|
140
|
+
const input = block.input as Record<string, unknown>;
|
|
141
|
+
const agentEntry: AgentEntry = {
|
|
142
|
+
id: block.id,
|
|
143
|
+
type: (input?.subagent_type as string) ?? 'unknown',
|
|
144
|
+
model: (input?.model as string) ?? undefined,
|
|
145
|
+
description: (input?.description as string) ?? undefined,
|
|
146
|
+
status: 'running',
|
|
147
|
+
startTime: timestamp,
|
|
148
|
+
};
|
|
149
|
+
agentMap.set(block.id, agentEntry);
|
|
150
|
+
} else if (block.name === 'TodoWrite') {
|
|
151
|
+
const input = block.input as { todos?: TodoItem[] };
|
|
152
|
+
if (input?.todos && Array.isArray(input.todos)) {
|
|
153
|
+
latestTodos.length = 0;
|
|
154
|
+
taskIdToIndex.clear();
|
|
155
|
+
latestTodos.push(...input.todos);
|
|
156
|
+
}
|
|
157
|
+
} else if (block.name === 'TaskCreate') {
|
|
158
|
+
const input = block.input as Record<string, unknown>;
|
|
159
|
+
const subject = typeof input?.subject === 'string' ? input.subject : '';
|
|
160
|
+
const description = typeof input?.description === 'string' ? input.description : '';
|
|
161
|
+
const content = subject || description || 'Untitled task';
|
|
162
|
+
const status = normalizeTaskStatus(input?.status) ?? 'pending';
|
|
163
|
+
latestTodos.push({ content, status });
|
|
164
|
+
|
|
165
|
+
const rawTaskId = input?.taskId;
|
|
166
|
+
const taskId = typeof rawTaskId === 'string' || typeof rawTaskId === 'number'
|
|
167
|
+
? String(rawTaskId)
|
|
168
|
+
: block.id;
|
|
169
|
+
if (taskId) {
|
|
170
|
+
taskIdToIndex.set(taskId, latestTodos.length - 1);
|
|
171
|
+
}
|
|
172
|
+
} else if (block.name === 'TaskUpdate') {
|
|
173
|
+
const input = block.input as Record<string, unknown>;
|
|
174
|
+
const index = resolveTaskIndex(input?.taskId, taskIdToIndex, latestTodos);
|
|
175
|
+
if (index !== null) {
|
|
176
|
+
const status = normalizeTaskStatus(input?.status);
|
|
177
|
+
if (status) {
|
|
178
|
+
latestTodos[index].status = status;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const subject = typeof input?.subject === 'string' ? input.subject : '';
|
|
182
|
+
const description = typeof input?.description === 'string' ? input.description : '';
|
|
183
|
+
const content = subject || description;
|
|
184
|
+
if (content) {
|
|
185
|
+
latestTodos[index].content = content;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
} else {
|
|
189
|
+
toolMap.set(block.id, toolEntry);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (block.type === 'tool_result' && block.tool_use_id) {
|
|
194
|
+
const tool = toolMap.get(block.tool_use_id);
|
|
195
|
+
if (tool) {
|
|
196
|
+
tool.status = block.is_error ? 'error' : 'completed';
|
|
197
|
+
tool.endTime = timestamp;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const agent = agentMap.get(block.tool_use_id);
|
|
201
|
+
if (agent) {
|
|
202
|
+
agent.status = 'completed';
|
|
203
|
+
agent.endTime = timestamp;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function extractTarget(toolName: string, input?: Record<string, unknown>): string | undefined {
|
|
210
|
+
if (!input) return undefined;
|
|
211
|
+
|
|
212
|
+
switch (toolName) {
|
|
213
|
+
case 'Read':
|
|
214
|
+
case 'Write':
|
|
215
|
+
case 'Edit':
|
|
216
|
+
return (input.file_path as string) ?? (input.path as string);
|
|
217
|
+
case 'Glob':
|
|
218
|
+
return input.pattern as string;
|
|
219
|
+
case 'Grep':
|
|
220
|
+
return input.pattern as string;
|
|
221
|
+
case 'Bash':
|
|
222
|
+
const cmd = input.command as string;
|
|
223
|
+
return cmd?.slice(0, 30) + (cmd?.length > 30 ? '...' : '');
|
|
224
|
+
}
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function resolveTaskIndex(
|
|
229
|
+
taskId: unknown,
|
|
230
|
+
taskIdToIndex: Map<string, number>,
|
|
231
|
+
latestTodos: TodoItem[]
|
|
232
|
+
): number | null {
|
|
233
|
+
if (typeof taskId === 'string' || typeof taskId === 'number') {
|
|
234
|
+
const key = String(taskId);
|
|
235
|
+
const mapped = taskIdToIndex.get(key);
|
|
236
|
+
if (typeof mapped === 'number') {
|
|
237
|
+
return mapped;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (/^\d+$/.test(key)) {
|
|
241
|
+
const numericIndex = Number.parseInt(key, 10) - 1;
|
|
242
|
+
if (numericIndex >= 0 && numericIndex < latestTodos.length) {
|
|
243
|
+
return numericIndex;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function normalizeTaskStatus(status: unknown): TodoItem['status'] | null {
|
|
252
|
+
if (typeof status !== 'string') return null;
|
|
253
|
+
|
|
254
|
+
switch (status) {
|
|
255
|
+
case 'pending':
|
|
256
|
+
case 'not_started':
|
|
257
|
+
return 'pending';
|
|
258
|
+
case 'in_progress':
|
|
259
|
+
case 'running':
|
|
260
|
+
return 'in_progress';
|
|
261
|
+
case 'completed':
|
|
262
|
+
case 'complete':
|
|
263
|
+
case 'done':
|
|
264
|
+
return 'completed';
|
|
265
|
+
default:
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import type { HudConfig } from './config.js';
|
|
2
|
+
import type { GitStatus } from './git.js';
|
|
3
|
+
import type { CostEstimate } from './cost-tracker.js';
|
|
4
|
+
|
|
5
|
+
export interface StdinData {
|
|
6
|
+
transcript_path?: string;
|
|
7
|
+
cwd?: string;
|
|
8
|
+
model?: {
|
|
9
|
+
id?: string;
|
|
10
|
+
display_name?: string;
|
|
11
|
+
};
|
|
12
|
+
context_window?: {
|
|
13
|
+
context_window_size?: number;
|
|
14
|
+
current_usage?: {
|
|
15
|
+
input_tokens?: number;
|
|
16
|
+
output_tokens?: number;
|
|
17
|
+
cache_creation_input_tokens?: number;
|
|
18
|
+
cache_read_input_tokens?: number;
|
|
19
|
+
} | null;
|
|
20
|
+
// Native percentage fields (Claude Code v2.1.6+)
|
|
21
|
+
used_percentage?: number | null;
|
|
22
|
+
remaining_percentage?: number | null;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ToolEntry {
|
|
27
|
+
id: string;
|
|
28
|
+
name: string;
|
|
29
|
+
target?: string;
|
|
30
|
+
status: 'running' | 'completed' | 'error';
|
|
31
|
+
startTime: Date;
|
|
32
|
+
endTime?: Date;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface AgentEntry {
|
|
36
|
+
id: string;
|
|
37
|
+
type: string;
|
|
38
|
+
model?: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
status: 'running' | 'completed';
|
|
41
|
+
startTime: Date;
|
|
42
|
+
endTime?: Date;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface TodoItem {
|
|
46
|
+
content: string;
|
|
47
|
+
status: 'pending' | 'in_progress' | 'completed';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Usage window data from the OAuth API */
|
|
51
|
+
export interface UsageWindow {
|
|
52
|
+
utilization: number | null; // 0-100 percentage, null if unavailable
|
|
53
|
+
resetAt: Date | null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface UsageData {
|
|
57
|
+
planName: string | null; // 'Max', 'Pro', or null for API users
|
|
58
|
+
fiveHour: number | null; // 0-100 percentage, null if unavailable
|
|
59
|
+
sevenDay: number | null; // 0-100 percentage, null if unavailable
|
|
60
|
+
fiveHourResetAt: Date | null;
|
|
61
|
+
sevenDayResetAt: Date | null;
|
|
62
|
+
apiUnavailable?: boolean; // true if API call failed (user should check DEBUG logs)
|
|
63
|
+
apiError?: string; // short error reason (e.g., 401, timeout)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Check if usage limit is reached (either window at 100%) */
|
|
67
|
+
export function isLimitReached(data: UsageData): boolean {
|
|
68
|
+
return data.fiveHour === 100 || data.sevenDay === 100;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface TranscriptData {
|
|
72
|
+
tools: ToolEntry[];
|
|
73
|
+
agents: AgentEntry[];
|
|
74
|
+
todos: TodoItem[];
|
|
75
|
+
sessionStart?: Date;
|
|
76
|
+
sessionName?: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Framework provider types
|
|
80
|
+
export interface FrameworkEntry {
|
|
81
|
+
label: string;
|
|
82
|
+
status: 'running' | 'completed' | 'error' | 'waiting';
|
|
83
|
+
progress?: string;
|
|
84
|
+
detail?: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface FrameworkStatus {
|
|
88
|
+
provider: string;
|
|
89
|
+
entries: FrameworkEntry[];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface FrameworkProvider {
|
|
93
|
+
name: string;
|
|
94
|
+
isAvailable(): boolean;
|
|
95
|
+
fetch(): Promise<FrameworkStatus | null>;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Alert types
|
|
99
|
+
export interface AlertAction {
|
|
100
|
+
visual: boolean;
|
|
101
|
+
bell: boolean;
|
|
102
|
+
predict: boolean;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface Alert {
|
|
106
|
+
type: 'context-warning' | 'context-critical' | 'usage-5h-warning' | 'usage-5h-critical' | 'usage-7d-warning';
|
|
107
|
+
message: string;
|
|
108
|
+
actions: AlertAction;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Burn rate
|
|
112
|
+
export interface BurnRate {
|
|
113
|
+
tokensPerMinute: number;
|
|
114
|
+
estimatedCallsRemaining: number;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Session stats
|
|
118
|
+
export interface SessionStats {
|
|
119
|
+
startTime?: Date;
|
|
120
|
+
totalToolCalls: number;
|
|
121
|
+
totalAgentRuns: number;
|
|
122
|
+
peakContextPercent: number;
|
|
123
|
+
autocompactCount: number;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface RenderContext {
|
|
127
|
+
stdin: StdinData;
|
|
128
|
+
transcript: TranscriptData;
|
|
129
|
+
claudeMdCount: number;
|
|
130
|
+
rulesCount: number;
|
|
131
|
+
mcpCount: number;
|
|
132
|
+
hooksCount: number;
|
|
133
|
+
sessionDuration: string;
|
|
134
|
+
gitStatus: GitStatus | null;
|
|
135
|
+
usageData: UsageData | null;
|
|
136
|
+
config: HudConfig;
|
|
137
|
+
extraLabel: string | null;
|
|
138
|
+
frameworkStatus: FrameworkStatus[];
|
|
139
|
+
alerts: Alert[];
|
|
140
|
+
burnRate: BurnRate | null;
|
|
141
|
+
sessionStats: SessionStats;
|
|
142
|
+
sparkline: number[];
|
|
143
|
+
terminalWidth: number | null;
|
|
144
|
+
costEstimate: CostEstimate | null;
|
|
145
|
+
apiLatency: number | null;
|
|
146
|
+
}
|