claude-scope 0.6.1 → 0.6.9
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/dist/claude-scope.cjs +2487 -1028
- package/package.json +3 -3
package/dist/claude-scope.cjs
CHANGED
|
@@ -35,73 +35,14 @@ __export(index_exports, {
|
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(index_exports);
|
|
37
37
|
|
|
38
|
-
// src/
|
|
39
|
-
var
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
* Register a widget
|
|
43
|
-
*/
|
|
44
|
-
async register(widget, context) {
|
|
45
|
-
if (this.widgets.has(widget.id)) {
|
|
46
|
-
throw new Error(`Widget with id '${widget.id}' already registered`);
|
|
47
|
-
}
|
|
48
|
-
if (context) {
|
|
49
|
-
await widget.initialize(context);
|
|
50
|
-
}
|
|
51
|
-
this.widgets.set(widget.id, widget);
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Unregister a widget
|
|
55
|
-
*/
|
|
56
|
-
async unregister(id) {
|
|
57
|
-
const widget = this.widgets.get(id);
|
|
58
|
-
if (!widget) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
try {
|
|
62
|
-
if (widget.cleanup) {
|
|
63
|
-
await widget.cleanup();
|
|
64
|
-
}
|
|
65
|
-
} finally {
|
|
66
|
-
this.widgets.delete(id);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Get a widget by id
|
|
71
|
-
*/
|
|
72
|
-
get(id) {
|
|
73
|
-
return this.widgets.get(id);
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Check if widget is registered
|
|
77
|
-
*/
|
|
78
|
-
has(id) {
|
|
79
|
-
return this.widgets.has(id);
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Get all registered widgets
|
|
83
|
-
*/
|
|
84
|
-
getAll() {
|
|
85
|
-
return Array.from(this.widgets.values());
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Get only enabled widgets
|
|
89
|
-
*/
|
|
90
|
-
getEnabledWidgets() {
|
|
91
|
-
return this.getAll().filter((w) => w.isEnabled());
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Clear all widgets
|
|
95
|
-
*/
|
|
96
|
-
async clear() {
|
|
97
|
-
for (const widget of this.widgets.values()) {
|
|
98
|
-
if (widget.cleanup) {
|
|
99
|
-
await widget.cleanup();
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
this.widgets.clear();
|
|
103
|
-
}
|
|
38
|
+
// src/config/widget-flags.ts
|
|
39
|
+
var WIDGET_FLAGS = {
|
|
40
|
+
activeTools: true,
|
|
41
|
+
cacheMetrics: true
|
|
104
42
|
};
|
|
43
|
+
function isWidgetEnabled(name) {
|
|
44
|
+
return WIDGET_FLAGS[name] ?? true;
|
|
45
|
+
}
|
|
105
46
|
|
|
106
47
|
// src/constants.ts
|
|
107
48
|
var TIME = {
|
|
@@ -207,553 +148,2114 @@ var Renderer = class {
|
|
|
207
148
|
}
|
|
208
149
|
};
|
|
209
150
|
|
|
210
|
-
// src/core/widget-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
var import_node_child_process = require("node:child_process");
|
|
223
|
-
var import_node_util = require("node:util");
|
|
224
|
-
var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
225
|
-
var NativeGit = class {
|
|
226
|
-
cwd;
|
|
227
|
-
constructor(cwd) {
|
|
228
|
-
this.cwd = cwd;
|
|
229
|
-
}
|
|
230
|
-
async status() {
|
|
231
|
-
try {
|
|
232
|
-
const { stdout } = await execFileAsync("git", ["status", "--branch", "--short"], {
|
|
233
|
-
cwd: this.cwd
|
|
234
|
-
});
|
|
235
|
-
const match = stdout.match(/^##\s+(\S+)/m);
|
|
236
|
-
const current = match ? match[1] : null;
|
|
237
|
-
return { current };
|
|
238
|
-
} catch {
|
|
239
|
-
return { current: null };
|
|
151
|
+
// src/core/widget-registry.ts
|
|
152
|
+
var WidgetRegistry = class {
|
|
153
|
+
widgets = /* @__PURE__ */ new Map();
|
|
154
|
+
/**
|
|
155
|
+
* Register a widget
|
|
156
|
+
*/
|
|
157
|
+
async register(widget, context) {
|
|
158
|
+
if (this.widgets.has(widget.id)) {
|
|
159
|
+
throw new Error(`Widget with id '${widget.id}' already registered`);
|
|
160
|
+
}
|
|
161
|
+
if (context) {
|
|
162
|
+
await widget.initialize(context);
|
|
240
163
|
}
|
|
164
|
+
this.widgets.set(widget.id, widget);
|
|
241
165
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
166
|
+
/**
|
|
167
|
+
* Unregister a widget
|
|
168
|
+
*/
|
|
169
|
+
async unregister(id) {
|
|
170
|
+
const widget = this.widgets.get(id);
|
|
171
|
+
if (!widget) {
|
|
172
|
+
return;
|
|
246
173
|
}
|
|
247
174
|
try {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
const deletionMatch = stdout.match(/(\d+)\s+deletion/);
|
|
254
|
-
const fileCount = fileMatch ? parseInt(fileMatch[1], 10) : 0;
|
|
255
|
-
const insertions = insertionMatch ? parseInt(insertionMatch[1], 10) : 0;
|
|
256
|
-
const deletions = deletionMatch ? parseInt(deletionMatch[1], 10) : 0;
|
|
257
|
-
const files = insertions > 0 || deletions > 0 ? [{ file: "(total)", insertions, deletions }] : [];
|
|
258
|
-
return { fileCount, files };
|
|
259
|
-
} catch {
|
|
260
|
-
return { fileCount: 0, files: [] };
|
|
175
|
+
if (widget.cleanup) {
|
|
176
|
+
await widget.cleanup();
|
|
177
|
+
}
|
|
178
|
+
} finally {
|
|
179
|
+
this.widgets.delete(id);
|
|
261
180
|
}
|
|
262
181
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
return stdout.trim();
|
|
269
|
-
} catch {
|
|
270
|
-
return null;
|
|
271
|
-
}
|
|
182
|
+
/**
|
|
183
|
+
* Get a widget by id
|
|
184
|
+
*/
|
|
185
|
+
get(id) {
|
|
186
|
+
return this.widgets.get(id);
|
|
272
187
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
semantic: {
|
|
300
|
-
success: gray,
|
|
301
|
-
warning: gray,
|
|
302
|
-
error: gray,
|
|
303
|
-
info: gray
|
|
304
|
-
},
|
|
305
|
-
git: {
|
|
306
|
-
branch: gray,
|
|
307
|
-
changes: gray
|
|
308
|
-
},
|
|
309
|
-
context: {
|
|
310
|
-
low: gray,
|
|
311
|
-
medium: gray,
|
|
312
|
-
high: gray,
|
|
313
|
-
bar: gray
|
|
314
|
-
},
|
|
315
|
-
lines: {
|
|
316
|
-
added: gray,
|
|
317
|
-
removed: gray
|
|
318
|
-
},
|
|
319
|
-
cost: {
|
|
320
|
-
amount: gray,
|
|
321
|
-
currency: gray
|
|
322
|
-
},
|
|
323
|
-
duration: {
|
|
324
|
-
value: gray,
|
|
325
|
-
unit: gray
|
|
326
|
-
},
|
|
327
|
-
model: {
|
|
328
|
-
name: gray,
|
|
329
|
-
version: gray
|
|
330
|
-
},
|
|
331
|
-
poker: {
|
|
332
|
-
participating: lightGray,
|
|
333
|
-
nonParticipating: gray,
|
|
334
|
-
result: gray
|
|
188
|
+
/**
|
|
189
|
+
* Check if widget is registered
|
|
190
|
+
*/
|
|
191
|
+
has(id) {
|
|
192
|
+
return this.widgets.has(id);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get all registered widgets
|
|
196
|
+
*/
|
|
197
|
+
getAll() {
|
|
198
|
+
return Array.from(this.widgets.values());
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Get only enabled widgets
|
|
202
|
+
*/
|
|
203
|
+
getEnabledWidgets() {
|
|
204
|
+
return this.getAll().filter((w) => w.isEnabled());
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Clear all widgets
|
|
208
|
+
*/
|
|
209
|
+
async clear() {
|
|
210
|
+
for (const widget of this.widgets.values()) {
|
|
211
|
+
if (widget.cleanup) {
|
|
212
|
+
await widget.cleanup();
|
|
213
|
+
}
|
|
335
214
|
}
|
|
215
|
+
this.widgets.clear();
|
|
336
216
|
}
|
|
337
217
|
};
|
|
338
218
|
|
|
339
|
-
// src/
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
// src/ui/utils/style-utils.ts
|
|
343
|
-
function withLabel(prefix, value) {
|
|
344
|
-
if (prefix === "") return value;
|
|
345
|
-
return `${prefix}: ${value}`;
|
|
219
|
+
// src/validation/result.ts
|
|
220
|
+
function success(data) {
|
|
221
|
+
return { success: true, data };
|
|
346
222
|
}
|
|
347
|
-
function
|
|
348
|
-
return
|
|
223
|
+
function failure(path2, message, value) {
|
|
224
|
+
return { success: false, error: { path: path2, message, value } };
|
|
349
225
|
}
|
|
350
|
-
function
|
|
351
|
-
const
|
|
352
|
-
|
|
353
|
-
const empty = width - filled;
|
|
354
|
-
return "\u2588".repeat(filled) + "\u2591".repeat(empty);
|
|
226
|
+
function formatError(error) {
|
|
227
|
+
const path2 = error.path.length > 0 ? error.path.join(".") : "root";
|
|
228
|
+
return `${path2}: ${error.message}`;
|
|
355
229
|
}
|
|
356
230
|
|
|
357
|
-
// src/
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
balanced: (data, colors) => {
|
|
364
|
-
if (data.changes && data.changes.files > 0) {
|
|
365
|
-
const parts = [];
|
|
366
|
-
if (data.changes.insertions > 0) parts.push(`+${data.changes.insertions}`);
|
|
367
|
-
if (data.changes.deletions > 0) parts.push(`-${data.changes.deletions}`);
|
|
368
|
-
if (parts.length > 0) {
|
|
369
|
-
const branch = colors ? colorize(data.branch, colors.branch) : data.branch;
|
|
370
|
-
const changes = colors ? colorize(`[${parts.join(" ")}]`, colors.changes) : `[${parts.join(" ")}]`;
|
|
371
|
-
return `${branch} ${changes}`;
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
return colors ? colorize(data.branch, colors.branch) : data.branch;
|
|
375
|
-
},
|
|
376
|
-
compact: (data, colors) => {
|
|
377
|
-
if (data.changes && data.changes.files > 0) {
|
|
378
|
-
const parts = [];
|
|
379
|
-
if (data.changes.insertions > 0) parts.push(`+${data.changes.insertions}`);
|
|
380
|
-
if (data.changes.deletions > 0) parts.push(`-${data.changes.deletions}`);
|
|
381
|
-
if (parts.length > 0) {
|
|
382
|
-
const branch = colors ? colorize(data.branch, colors.branch) : data.branch;
|
|
383
|
-
const changesStr = parts.join("/");
|
|
384
|
-
return `${branch} ${changesStr}`;
|
|
231
|
+
// src/validation/combinators.ts
|
|
232
|
+
function object(shape) {
|
|
233
|
+
return {
|
|
234
|
+
validate(value) {
|
|
235
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
236
|
+
return failure([], "Expected object", value);
|
|
385
237
|
}
|
|
238
|
+
const result = {};
|
|
239
|
+
for (const [key, validator] of Object.entries(shape)) {
|
|
240
|
+
const fieldValue = value[key];
|
|
241
|
+
const validationResult = validator.validate(fieldValue);
|
|
242
|
+
if (!validationResult.success) {
|
|
243
|
+
return {
|
|
244
|
+
success: false,
|
|
245
|
+
error: { ...validationResult.error, path: [key, ...validationResult.error.path] }
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
result[key] = validationResult.data;
|
|
249
|
+
}
|
|
250
|
+
return success(result);
|
|
386
251
|
}
|
|
387
|
-
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
function optional(validator) {
|
|
255
|
+
return {
|
|
256
|
+
validate(value) {
|
|
257
|
+
if (value === void 0) return success(void 0);
|
|
258
|
+
return validator.validate(value);
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
function nullable(validator) {
|
|
263
|
+
return {
|
|
264
|
+
validate(value) {
|
|
265
|
+
if (value === null) return success(null);
|
|
266
|
+
return validator.validate(value);
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// src/validation/validators.ts
|
|
272
|
+
function string() {
|
|
273
|
+
return {
|
|
274
|
+
validate(value) {
|
|
275
|
+
if (typeof value === "string") return success(value);
|
|
276
|
+
return failure([], "Expected string", value);
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function number() {
|
|
281
|
+
return {
|
|
282
|
+
validate(value) {
|
|
283
|
+
if (typeof value === "number" && !Number.isNaN(value)) return success(value);
|
|
284
|
+
return failure([], "Expected number", value);
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
function literal(expected) {
|
|
289
|
+
return {
|
|
290
|
+
validate(value) {
|
|
291
|
+
if (value === expected) return success(expected);
|
|
292
|
+
return failure([], `Expected '${expected}'`, value);
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// src/schemas/stdin-schema.ts
|
|
298
|
+
var ContextUsageSchema = object({
|
|
299
|
+
input_tokens: number(),
|
|
300
|
+
output_tokens: number(),
|
|
301
|
+
cache_creation_input_tokens: number(),
|
|
302
|
+
cache_read_input_tokens: number()
|
|
303
|
+
});
|
|
304
|
+
var CostInfoSchema = object({
|
|
305
|
+
total_cost_usd: optional(number()),
|
|
306
|
+
total_duration_ms: optional(number()),
|
|
307
|
+
total_api_duration_ms: optional(number()),
|
|
308
|
+
total_lines_added: optional(number()),
|
|
309
|
+
total_lines_removed: optional(number())
|
|
310
|
+
});
|
|
311
|
+
var ContextWindowSchema = object({
|
|
312
|
+
total_input_tokens: number(),
|
|
313
|
+
total_output_tokens: number(),
|
|
314
|
+
context_window_size: number(),
|
|
315
|
+
current_usage: nullable(ContextUsageSchema)
|
|
316
|
+
});
|
|
317
|
+
var ModelInfoSchema = object({
|
|
318
|
+
id: string(),
|
|
319
|
+
display_name: string()
|
|
320
|
+
});
|
|
321
|
+
var WorkspaceSchema = object({
|
|
322
|
+
current_dir: string(),
|
|
323
|
+
project_dir: string()
|
|
324
|
+
});
|
|
325
|
+
var OutputStyleSchema = object({
|
|
326
|
+
name: string()
|
|
327
|
+
});
|
|
328
|
+
var StdinDataSchema = object({
|
|
329
|
+
hook_event_name: optional(literal("Status")),
|
|
330
|
+
session_id: string(),
|
|
331
|
+
transcript_path: string(),
|
|
332
|
+
cwd: string(),
|
|
333
|
+
model: ModelInfoSchema,
|
|
334
|
+
workspace: WorkspaceSchema,
|
|
335
|
+
version: string(),
|
|
336
|
+
output_style: OutputStyleSchema,
|
|
337
|
+
cost: optional(CostInfoSchema),
|
|
338
|
+
context_window: ContextWindowSchema
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
// src/data/stdin-provider.ts
|
|
342
|
+
var StdinParseError = class extends Error {
|
|
343
|
+
constructor(message) {
|
|
344
|
+
super(message);
|
|
345
|
+
this.name = "StdinParseError";
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
var StdinValidationError = class extends Error {
|
|
349
|
+
constructor(message) {
|
|
350
|
+
super(message);
|
|
351
|
+
this.name = "StdinValidationError";
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
var StdinProvider = class {
|
|
355
|
+
/**
|
|
356
|
+
* Parse and validate JSON string from stdin
|
|
357
|
+
* @param input JSON string to parse
|
|
358
|
+
* @returns Validated StdinData object
|
|
359
|
+
* @throws StdinParseError if JSON is malformed
|
|
360
|
+
* @throws StdinValidationError if data doesn't match schema
|
|
361
|
+
*/
|
|
362
|
+
async parse(input) {
|
|
363
|
+
if (!input || input.trim().length === 0) {
|
|
364
|
+
throw new StdinParseError("stdin data is empty");
|
|
365
|
+
}
|
|
366
|
+
let data;
|
|
367
|
+
try {
|
|
368
|
+
data = JSON.parse(input);
|
|
369
|
+
} catch (error) {
|
|
370
|
+
throw new StdinParseError(`Invalid JSON: ${error.message}`);
|
|
371
|
+
}
|
|
372
|
+
const result = StdinDataSchema.validate(data);
|
|
373
|
+
if (!result.success) {
|
|
374
|
+
throw new StdinValidationError(`Validation failed: ${formatError(result.error)}`);
|
|
375
|
+
}
|
|
376
|
+
return result.data;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Safe parse that returns result instead of throwing
|
|
380
|
+
* Useful for testing and optional validation
|
|
381
|
+
* @param input JSON string to parse
|
|
382
|
+
* @returns Result object with success flag
|
|
383
|
+
*/
|
|
384
|
+
async safeParse(input) {
|
|
385
|
+
try {
|
|
386
|
+
const data = await this.parse(input);
|
|
387
|
+
return { success: true, data };
|
|
388
|
+
} catch (error) {
|
|
389
|
+
return { success: false, error: error.message };
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
// src/providers/transcript-provider.ts
|
|
395
|
+
var import_fs = require("fs");
|
|
396
|
+
var import_readline = require("readline");
|
|
397
|
+
var TranscriptProvider = class {
|
|
398
|
+
MAX_TOOLS = 20;
|
|
399
|
+
/**
|
|
400
|
+
* Parse tools from a JSONL transcript file
|
|
401
|
+
* @param transcriptPath Path to the transcript file
|
|
402
|
+
* @returns Array of tool entries, limited to last 20
|
|
403
|
+
*/
|
|
404
|
+
async parseTools(transcriptPath) {
|
|
405
|
+
if (!(0, import_fs.existsSync)(transcriptPath)) {
|
|
406
|
+
return [];
|
|
407
|
+
}
|
|
408
|
+
const toolMap = /* @__PURE__ */ new Map();
|
|
409
|
+
try {
|
|
410
|
+
const fileStream = (0, import_fs.createReadStream)(transcriptPath, { encoding: "utf-8" });
|
|
411
|
+
const rl = (0, import_readline.createInterface)({
|
|
412
|
+
input: fileStream,
|
|
413
|
+
crlfDelay: Infinity
|
|
414
|
+
});
|
|
415
|
+
for await (const line of rl) {
|
|
416
|
+
if (!line.trim()) continue;
|
|
417
|
+
try {
|
|
418
|
+
const entry = JSON.parse(line);
|
|
419
|
+
this.processLine(entry, toolMap);
|
|
420
|
+
} catch {
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
const tools = Array.from(toolMap.values());
|
|
424
|
+
return tools.slice(-this.MAX_TOOLS);
|
|
425
|
+
} catch {
|
|
426
|
+
return [];
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Process a single transcript line and update tool map
|
|
431
|
+
*/
|
|
432
|
+
processLine(line, toolMap) {
|
|
433
|
+
const blocks = line.message?.content ?? [];
|
|
434
|
+
const timestamp = /* @__PURE__ */ new Date();
|
|
435
|
+
for (const block of blocks) {
|
|
436
|
+
if (block.type === "tool_use" && block.id && block.name) {
|
|
437
|
+
const tool = {
|
|
438
|
+
id: block.id,
|
|
439
|
+
name: block.name,
|
|
440
|
+
target: this.extractTarget(block.name, block.input),
|
|
441
|
+
status: "running",
|
|
442
|
+
startTime: timestamp
|
|
443
|
+
};
|
|
444
|
+
toolMap.set(block.id, tool);
|
|
445
|
+
}
|
|
446
|
+
if (block.type === "tool_result" && block.tool_use_id) {
|
|
447
|
+
const existing = toolMap.get(block.tool_use_id);
|
|
448
|
+
if (existing) {
|
|
449
|
+
existing.status = block.is_error ? "error" : "completed";
|
|
450
|
+
existing.endTime = timestamp;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Extract target from tool input based on tool type
|
|
457
|
+
*/
|
|
458
|
+
extractTarget(toolName, input) {
|
|
459
|
+
if (!input) return void 0;
|
|
460
|
+
switch (toolName) {
|
|
461
|
+
case "Read":
|
|
462
|
+
case "Write":
|
|
463
|
+
case "Edit":
|
|
464
|
+
return this.asString(input.file_path ?? input.path);
|
|
465
|
+
case "Glob":
|
|
466
|
+
return this.asString(input.pattern);
|
|
467
|
+
case "Grep":
|
|
468
|
+
return this.asString(input.pattern);
|
|
469
|
+
case "Bash": {
|
|
470
|
+
const cmd = this.asString(input.command);
|
|
471
|
+
return cmd ? this.truncateCommand(cmd) : void 0;
|
|
472
|
+
}
|
|
473
|
+
default:
|
|
474
|
+
return void 0;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Safely convert value to string
|
|
479
|
+
*/
|
|
480
|
+
asString(value) {
|
|
481
|
+
if (typeof value === "string") return value;
|
|
482
|
+
if (typeof value === "number") return String(value);
|
|
483
|
+
return void 0;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Truncate long commands to 30 chars
|
|
487
|
+
*/
|
|
488
|
+
truncateCommand(cmd) {
|
|
489
|
+
if (cmd.length <= 30) return cmd;
|
|
490
|
+
return cmd.slice(0, 30) + "...";
|
|
491
|
+
}
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
// src/ui/utils/colors.ts
|
|
495
|
+
var reset = "\x1B[0m";
|
|
496
|
+
var red = "\x1B[31m";
|
|
497
|
+
var gray = "\x1B[90m";
|
|
498
|
+
var lightGray = "\x1B[37m";
|
|
499
|
+
var bold = "\x1B[1m";
|
|
500
|
+
function colorize(text, color) {
|
|
501
|
+
return `${color}${text}${reset}`;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// src/ui/theme/helpers.ts
|
|
505
|
+
function rgb(r, g, b) {
|
|
506
|
+
return `\x1B[38;2;${r};${g};${b}m`;
|
|
507
|
+
}
|
|
508
|
+
function createBaseColors(params) {
|
|
509
|
+
return {
|
|
510
|
+
text: params.modelColor,
|
|
511
|
+
muted: params.durationColor,
|
|
512
|
+
accent: params.accentColor,
|
|
513
|
+
border: params.durationColor
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
function createSemanticColors(params) {
|
|
517
|
+
return {
|
|
518
|
+
success: params.contextLow,
|
|
519
|
+
warning: params.contextMedium,
|
|
520
|
+
error: params.contextHigh,
|
|
521
|
+
info: params.branchColor
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
function createThemeColors(params) {
|
|
525
|
+
const base = createBaseColors({
|
|
526
|
+
modelColor: params.model,
|
|
527
|
+
durationColor: params.duration,
|
|
528
|
+
accentColor: params.accent
|
|
529
|
+
});
|
|
530
|
+
const semantic = createSemanticColors({
|
|
531
|
+
contextLow: params.contextLow,
|
|
532
|
+
contextMedium: params.contextMedium,
|
|
533
|
+
contextHigh: params.contextHigh,
|
|
534
|
+
branchColor: params.branch
|
|
535
|
+
});
|
|
536
|
+
return {
|
|
537
|
+
base,
|
|
538
|
+
semantic,
|
|
539
|
+
git: {
|
|
540
|
+
branch: params.branch,
|
|
541
|
+
changes: params.changes
|
|
542
|
+
},
|
|
543
|
+
context: {
|
|
544
|
+
low: params.contextLow,
|
|
545
|
+
medium: params.contextMedium,
|
|
546
|
+
high: params.contextHigh,
|
|
547
|
+
bar: params.contextLow
|
|
548
|
+
},
|
|
549
|
+
lines: {
|
|
550
|
+
added: params.linesAdded,
|
|
551
|
+
removed: params.linesRemoved
|
|
552
|
+
},
|
|
553
|
+
cost: {
|
|
554
|
+
amount: params.cost,
|
|
555
|
+
currency: params.cost
|
|
556
|
+
},
|
|
557
|
+
duration: {
|
|
558
|
+
value: params.duration,
|
|
559
|
+
unit: params.duration
|
|
560
|
+
},
|
|
561
|
+
model: {
|
|
562
|
+
name: params.model,
|
|
563
|
+
version: params.model
|
|
564
|
+
},
|
|
565
|
+
poker: {
|
|
566
|
+
participating: params.model,
|
|
567
|
+
nonParticipating: params.duration,
|
|
568
|
+
result: params.accent
|
|
569
|
+
},
|
|
570
|
+
cache: {
|
|
571
|
+
high: params.cacheHigh,
|
|
572
|
+
medium: params.cacheMedium,
|
|
573
|
+
low: params.cacheLow,
|
|
574
|
+
read: params.cacheRead,
|
|
575
|
+
write: params.cacheWrite
|
|
576
|
+
},
|
|
577
|
+
tools: {
|
|
578
|
+
running: params.toolsRunning,
|
|
579
|
+
completed: params.toolsCompleted,
|
|
580
|
+
error: params.toolsError,
|
|
581
|
+
name: params.toolsName,
|
|
582
|
+
target: params.toolsTarget,
|
|
583
|
+
count: params.toolsCount
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// src/ui/theme/gray-theme.ts
|
|
589
|
+
var GRAY_THEME = {
|
|
590
|
+
name: "gray",
|
|
591
|
+
description: "Neutral gray theme for minimal color distraction",
|
|
592
|
+
colors: createThemeColors({
|
|
593
|
+
branch: gray,
|
|
594
|
+
changes: gray,
|
|
595
|
+
contextLow: gray,
|
|
596
|
+
contextMedium: gray,
|
|
597
|
+
contextHigh: gray,
|
|
598
|
+
linesAdded: gray,
|
|
599
|
+
linesRemoved: gray,
|
|
600
|
+
cost: gray,
|
|
601
|
+
model: gray,
|
|
602
|
+
duration: gray,
|
|
603
|
+
accent: gray,
|
|
604
|
+
cacheHigh: gray,
|
|
605
|
+
cacheMedium: gray,
|
|
606
|
+
cacheLow: gray,
|
|
607
|
+
cacheRead: gray,
|
|
608
|
+
cacheWrite: gray,
|
|
609
|
+
toolsRunning: gray,
|
|
610
|
+
toolsCompleted: gray,
|
|
611
|
+
toolsError: gray,
|
|
612
|
+
toolsName: gray,
|
|
613
|
+
toolsTarget: gray,
|
|
614
|
+
toolsCount: gray
|
|
615
|
+
})
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
// src/ui/theme/themes/catppuccin-mocha-theme.ts
|
|
619
|
+
var CATPPUCCIN_MOCHA_THEME = {
|
|
620
|
+
name: "catppuccin-mocha",
|
|
621
|
+
description: "Soothing pastel theme",
|
|
622
|
+
colors: createThemeColors({
|
|
623
|
+
branch: rgb(137, 180, 250),
|
|
624
|
+
// Blue
|
|
625
|
+
changes: rgb(166, 227, 161),
|
|
626
|
+
// Green
|
|
627
|
+
contextLow: rgb(166, 227, 161),
|
|
628
|
+
// Green
|
|
629
|
+
contextMedium: rgb(238, 212, 159),
|
|
630
|
+
// Yellow
|
|
631
|
+
contextHigh: rgb(243, 139, 168),
|
|
632
|
+
// Red
|
|
633
|
+
linesAdded: rgb(166, 227, 161),
|
|
634
|
+
// Green
|
|
635
|
+
linesRemoved: rgb(243, 139, 168),
|
|
636
|
+
// Red
|
|
637
|
+
cost: rgb(245, 224, 220),
|
|
638
|
+
// Rosewater
|
|
639
|
+
model: rgb(203, 166, 247),
|
|
640
|
+
// Mauve
|
|
641
|
+
duration: rgb(147, 153, 178),
|
|
642
|
+
// Text gray
|
|
643
|
+
accent: rgb(243, 139, 168),
|
|
644
|
+
// Pink
|
|
645
|
+
cacheHigh: rgb(166, 227, 161),
|
|
646
|
+
// Green
|
|
647
|
+
cacheMedium: rgb(238, 212, 159),
|
|
648
|
+
// Yellow
|
|
649
|
+
cacheLow: rgb(243, 139, 168),
|
|
650
|
+
// Red
|
|
651
|
+
cacheRead: rgb(137, 180, 250),
|
|
652
|
+
// Blue
|
|
653
|
+
cacheWrite: rgb(203, 166, 247),
|
|
654
|
+
// Mauve
|
|
655
|
+
toolsRunning: rgb(238, 212, 159),
|
|
656
|
+
// Yellow
|
|
657
|
+
toolsCompleted: rgb(166, 227, 161),
|
|
658
|
+
// Green
|
|
659
|
+
toolsError: rgb(243, 139, 168),
|
|
660
|
+
// Red
|
|
661
|
+
toolsName: rgb(137, 180, 250),
|
|
662
|
+
// Blue
|
|
663
|
+
toolsTarget: rgb(147, 153, 178),
|
|
664
|
+
// Gray
|
|
665
|
+
toolsCount: rgb(203, 166, 247)
|
|
666
|
+
// Mauve
|
|
667
|
+
})
|
|
668
|
+
};
|
|
669
|
+
|
|
670
|
+
// src/ui/theme/themes/cyberpunk-neon-theme.ts
|
|
671
|
+
var CYBERPUNK_NEON_THEME = {
|
|
672
|
+
name: "cyberpunk-neon",
|
|
673
|
+
description: "High-contrast neon cyberpunk aesthetic",
|
|
674
|
+
colors: createThemeColors({
|
|
675
|
+
branch: rgb(0, 191, 255),
|
|
676
|
+
// Cyan neon
|
|
677
|
+
changes: rgb(255, 0, 122),
|
|
678
|
+
// Magenta neon
|
|
679
|
+
contextLow: rgb(0, 255, 122),
|
|
680
|
+
// Green neon
|
|
681
|
+
contextMedium: rgb(255, 214, 0),
|
|
682
|
+
// Yellow neon
|
|
683
|
+
contextHigh: rgb(255, 0, 122),
|
|
684
|
+
// Magenta neon
|
|
685
|
+
linesAdded: rgb(0, 255, 122),
|
|
686
|
+
// Green neon
|
|
687
|
+
linesRemoved: rgb(255, 0, 122),
|
|
688
|
+
// Magenta neon
|
|
689
|
+
cost: rgb(255, 111, 97),
|
|
690
|
+
// Orange neon
|
|
691
|
+
model: rgb(140, 27, 255),
|
|
692
|
+
// Purple neon
|
|
693
|
+
duration: rgb(0, 191, 255),
|
|
694
|
+
// Cyan neon
|
|
695
|
+
accent: rgb(255, 0, 122),
|
|
696
|
+
// Magenta neon
|
|
697
|
+
cacheHigh: rgb(0, 255, 122),
|
|
698
|
+
// Green neon
|
|
699
|
+
cacheMedium: rgb(255, 214, 0),
|
|
700
|
+
// Yellow neon
|
|
701
|
+
cacheLow: rgb(255, 0, 122),
|
|
702
|
+
// Magenta neon
|
|
703
|
+
cacheRead: rgb(0, 191, 255),
|
|
704
|
+
// Cyan neon
|
|
705
|
+
cacheWrite: rgb(140, 27, 255),
|
|
706
|
+
// Purple neon
|
|
707
|
+
toolsRunning: rgb(255, 214, 0),
|
|
708
|
+
// Yellow neon
|
|
709
|
+
toolsCompleted: rgb(0, 255, 122),
|
|
710
|
+
// Green neon
|
|
711
|
+
toolsError: rgb(255, 0, 122),
|
|
712
|
+
// Magenta neon
|
|
713
|
+
toolsName: rgb(0, 191, 255),
|
|
714
|
+
// Cyan neon
|
|
715
|
+
toolsTarget: rgb(140, 27, 255),
|
|
716
|
+
// Purple neon
|
|
717
|
+
toolsCount: rgb(255, 111, 97)
|
|
718
|
+
// Orange neon
|
|
719
|
+
})
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
// src/ui/theme/themes/dracula-theme.ts
|
|
723
|
+
var DRACULA_THEME = {
|
|
724
|
+
name: "dracula",
|
|
725
|
+
description: "Purple/pink accent theme",
|
|
726
|
+
colors: createThemeColors({
|
|
727
|
+
branch: rgb(189, 147, 249),
|
|
728
|
+
// Purple
|
|
729
|
+
changes: rgb(139, 233, 253),
|
|
730
|
+
// Cyan
|
|
731
|
+
contextLow: rgb(80, 250, 123),
|
|
732
|
+
// Green
|
|
733
|
+
contextMedium: rgb(241, 250, 140),
|
|
734
|
+
// Yellow
|
|
735
|
+
contextHigh: rgb(255, 85, 85),
|
|
736
|
+
// Red
|
|
737
|
+
linesAdded: rgb(80, 250, 123),
|
|
738
|
+
// Green
|
|
739
|
+
linesRemoved: rgb(255, 85, 85),
|
|
740
|
+
// Red
|
|
741
|
+
cost: rgb(255, 184, 108),
|
|
742
|
+
// Orange
|
|
743
|
+
model: rgb(98, 114, 164),
|
|
744
|
+
// Comment gray
|
|
745
|
+
duration: rgb(68, 71, 90),
|
|
746
|
+
// Selection gray
|
|
747
|
+
accent: rgb(189, 147, 249),
|
|
748
|
+
// Purple
|
|
749
|
+
cacheHigh: rgb(80, 250, 123),
|
|
750
|
+
// Green
|
|
751
|
+
cacheMedium: rgb(241, 250, 140),
|
|
752
|
+
// Yellow
|
|
753
|
+
cacheLow: rgb(255, 85, 85),
|
|
754
|
+
// Red
|
|
755
|
+
cacheRead: rgb(139, 233, 253),
|
|
756
|
+
// Cyan
|
|
757
|
+
cacheWrite: rgb(189, 147, 249),
|
|
758
|
+
// Purple
|
|
759
|
+
toolsRunning: rgb(241, 250, 140),
|
|
760
|
+
// Yellow
|
|
761
|
+
toolsCompleted: rgb(80, 250, 123),
|
|
762
|
+
// Green
|
|
763
|
+
toolsError: rgb(255, 85, 85),
|
|
764
|
+
// Red
|
|
765
|
+
toolsName: rgb(139, 233, 253),
|
|
766
|
+
// Cyan
|
|
767
|
+
toolsTarget: rgb(98, 114, 164),
|
|
768
|
+
// Gray
|
|
769
|
+
toolsCount: rgb(189, 147, 249)
|
|
770
|
+
// Purple
|
|
771
|
+
})
|
|
772
|
+
};
|
|
773
|
+
|
|
774
|
+
// src/ui/theme/themes/dusty-sage-theme.ts
|
|
775
|
+
var DUSTY_SAGE_THEME = {
|
|
776
|
+
name: "dusty-sage",
|
|
777
|
+
description: "Earthy muted greens with peaceful forest fog aesthetic",
|
|
778
|
+
colors: createThemeColors({
|
|
779
|
+
branch: rgb(120, 140, 130),
|
|
780
|
+
// Dusty green
|
|
781
|
+
changes: rgb(135, 145, 140),
|
|
782
|
+
// Sage gray
|
|
783
|
+
contextLow: rgb(135, 145, 140),
|
|
784
|
+
// Subtle sage (low)
|
|
785
|
+
contextMedium: rgb(150, 160, 145),
|
|
786
|
+
// Medium sage
|
|
787
|
+
contextHigh: rgb(165, 175, 160),
|
|
788
|
+
// Light sage (high)
|
|
789
|
+
linesAdded: rgb(135, 145, 140),
|
|
790
|
+
linesRemoved: rgb(135, 145, 140),
|
|
791
|
+
cost: rgb(156, 163, 175),
|
|
792
|
+
model: rgb(148, 163, 184),
|
|
793
|
+
duration: rgb(120, 130, 140),
|
|
794
|
+
accent: rgb(120, 140, 130),
|
|
795
|
+
cacheHigh: rgb(135, 145, 140),
|
|
796
|
+
cacheMedium: rgb(150, 160, 145),
|
|
797
|
+
cacheLow: rgb(165, 175, 160),
|
|
798
|
+
cacheRead: rgb(120, 140, 130),
|
|
799
|
+
cacheWrite: rgb(148, 163, 184),
|
|
800
|
+
toolsRunning: rgb(150, 160, 145),
|
|
801
|
+
// Medium sage
|
|
802
|
+
toolsCompleted: rgb(135, 145, 140),
|
|
803
|
+
// Subtle sage
|
|
804
|
+
toolsError: rgb(165, 175, 160),
|
|
805
|
+
// Light sage
|
|
806
|
+
toolsName: rgb(120, 140, 130),
|
|
807
|
+
// Dusty green
|
|
808
|
+
toolsTarget: rgb(148, 163, 184),
|
|
809
|
+
// Gray
|
|
810
|
+
toolsCount: rgb(156, 163, 175)
|
|
811
|
+
// Light gray
|
|
812
|
+
})
|
|
813
|
+
};
|
|
814
|
+
|
|
815
|
+
// src/ui/theme/themes/github-dark-dimmed-theme.ts
|
|
816
|
+
var GITHUB_DARK_DIMMED_THEME = {
|
|
817
|
+
name: "github-dark-dimmed",
|
|
818
|
+
description: "GitHub's official dark theme (dimmed)",
|
|
819
|
+
colors: createThemeColors({
|
|
820
|
+
branch: rgb(88, 166, 255),
|
|
821
|
+
// GitHub blue
|
|
822
|
+
changes: rgb(156, 220, 254),
|
|
823
|
+
// Light blue
|
|
824
|
+
contextLow: rgb(35, 134, 54),
|
|
825
|
+
// GitHub green
|
|
826
|
+
contextMedium: rgb(210, 153, 34),
|
|
827
|
+
// GitHub orange
|
|
828
|
+
contextHigh: rgb(248, 81, 73),
|
|
829
|
+
// GitHub red
|
|
830
|
+
linesAdded: rgb(35, 134, 54),
|
|
831
|
+
// GitHub green
|
|
832
|
+
linesRemoved: rgb(248, 81, 73),
|
|
833
|
+
// GitHub red
|
|
834
|
+
cost: rgb(163, 113, 247),
|
|
835
|
+
// Purple
|
|
836
|
+
model: rgb(201, 209, 217),
|
|
837
|
+
// Gray
|
|
838
|
+
duration: rgb(110, 118, 129),
|
|
839
|
+
// Dark gray
|
|
840
|
+
accent: rgb(88, 166, 255),
|
|
841
|
+
// GitHub blue
|
|
842
|
+
cacheHigh: rgb(35, 134, 54),
|
|
843
|
+
// GitHub green
|
|
844
|
+
cacheMedium: rgb(210, 153, 34),
|
|
845
|
+
// GitHub orange
|
|
846
|
+
cacheLow: rgb(248, 81, 73),
|
|
847
|
+
// GitHub red
|
|
848
|
+
cacheRead: rgb(88, 166, 255),
|
|
849
|
+
// GitHub blue
|
|
850
|
+
cacheWrite: rgb(163, 113, 247),
|
|
851
|
+
// Purple
|
|
852
|
+
toolsRunning: rgb(210, 153, 34),
|
|
853
|
+
// GitHub orange
|
|
854
|
+
toolsCompleted: rgb(35, 134, 54),
|
|
855
|
+
// GitHub green
|
|
856
|
+
toolsError: rgb(248, 81, 73),
|
|
857
|
+
// GitHub red
|
|
858
|
+
toolsName: rgb(88, 166, 255),
|
|
859
|
+
// GitHub blue
|
|
860
|
+
toolsTarget: rgb(201, 209, 217),
|
|
861
|
+
// Gray
|
|
862
|
+
toolsCount: rgb(163, 113, 247)
|
|
863
|
+
// Purple
|
|
864
|
+
})
|
|
865
|
+
};
|
|
866
|
+
|
|
867
|
+
// src/ui/theme/themes/monokai-theme.ts
|
|
868
|
+
var MONOKAI_THEME = {
|
|
869
|
+
name: "monokai",
|
|
870
|
+
description: "Vibrant, high-contrast",
|
|
871
|
+
colors: createThemeColors({
|
|
872
|
+
branch: rgb(102, 217, 239),
|
|
873
|
+
// Cyan
|
|
874
|
+
changes: rgb(249, 26, 114),
|
|
875
|
+
// Pink
|
|
876
|
+
contextLow: rgb(166, 226, 46),
|
|
877
|
+
// Green
|
|
878
|
+
contextMedium: rgb(253, 151, 31),
|
|
879
|
+
// Orange
|
|
880
|
+
contextHigh: rgb(249, 26, 114),
|
|
881
|
+
// Pink
|
|
882
|
+
linesAdded: rgb(166, 226, 46),
|
|
883
|
+
// Green
|
|
884
|
+
linesRemoved: rgb(249, 26, 114),
|
|
885
|
+
// Pink
|
|
886
|
+
cost: rgb(254, 128, 25),
|
|
887
|
+
// Bright orange
|
|
888
|
+
model: rgb(174, 129, 255),
|
|
889
|
+
// Purple
|
|
890
|
+
duration: rgb(102, 217, 239),
|
|
891
|
+
// Cyan
|
|
892
|
+
accent: rgb(249, 26, 114),
|
|
893
|
+
// Pink
|
|
894
|
+
cacheHigh: rgb(166, 226, 46),
|
|
895
|
+
// Green
|
|
896
|
+
cacheMedium: rgb(253, 151, 31),
|
|
897
|
+
// Orange
|
|
898
|
+
cacheLow: rgb(249, 26, 114),
|
|
899
|
+
// Pink
|
|
900
|
+
cacheRead: rgb(102, 217, 239),
|
|
901
|
+
// Cyan
|
|
902
|
+
cacheWrite: rgb(174, 129, 255),
|
|
903
|
+
// Purple
|
|
904
|
+
toolsRunning: rgb(253, 151, 31),
|
|
905
|
+
// Orange
|
|
906
|
+
toolsCompleted: rgb(166, 226, 46),
|
|
907
|
+
// Green
|
|
908
|
+
toolsError: rgb(249, 26, 114),
|
|
909
|
+
// Pink
|
|
910
|
+
toolsName: rgb(102, 217, 239),
|
|
911
|
+
// Cyan
|
|
912
|
+
toolsTarget: rgb(174, 129, 255),
|
|
913
|
+
// Purple
|
|
914
|
+
toolsCount: rgb(254, 128, 25)
|
|
915
|
+
// Bright orange
|
|
916
|
+
})
|
|
917
|
+
};
|
|
918
|
+
|
|
919
|
+
// src/ui/theme/themes/muted-gray-theme.ts
|
|
920
|
+
var MUTED_GRAY_THEME = {
|
|
921
|
+
name: "muted-gray",
|
|
922
|
+
description: "Very subtle grays with almost invisible progress bar",
|
|
923
|
+
colors: createThemeColors({
|
|
924
|
+
branch: rgb(156, 163, 175),
|
|
925
|
+
// Slate gray
|
|
926
|
+
changes: rgb(148, 163, 184),
|
|
927
|
+
// Lighter slate
|
|
928
|
+
contextLow: rgb(148, 163, 184),
|
|
929
|
+
// Subtle gray (low)
|
|
930
|
+
contextMedium: rgb(160, 174, 192),
|
|
931
|
+
// Medium gray
|
|
932
|
+
contextHigh: rgb(175, 188, 201),
|
|
933
|
+
// Light gray (high)
|
|
934
|
+
linesAdded: rgb(148, 163, 184),
|
|
935
|
+
linesRemoved: rgb(148, 163, 184),
|
|
936
|
+
cost: rgb(156, 163, 175),
|
|
937
|
+
model: rgb(148, 163, 184),
|
|
938
|
+
duration: rgb(107, 114, 128),
|
|
939
|
+
accent: rgb(156, 163, 175),
|
|
940
|
+
cacheHigh: rgb(148, 163, 184),
|
|
941
|
+
cacheMedium: rgb(160, 174, 192),
|
|
942
|
+
cacheLow: rgb(175, 188, 201),
|
|
943
|
+
cacheRead: rgb(156, 163, 175),
|
|
944
|
+
cacheWrite: rgb(148, 163, 184),
|
|
945
|
+
toolsRunning: rgb(160, 174, 192),
|
|
946
|
+
// Medium gray
|
|
947
|
+
toolsCompleted: rgb(148, 163, 184),
|
|
948
|
+
// Subtle gray
|
|
949
|
+
toolsError: rgb(175, 188, 201),
|
|
950
|
+
// Light gray
|
|
951
|
+
toolsName: rgb(156, 163, 175),
|
|
952
|
+
// Slate gray
|
|
953
|
+
toolsTarget: rgb(148, 163, 184),
|
|
954
|
+
// Lighter slate
|
|
955
|
+
toolsCount: rgb(156, 163, 175)
|
|
956
|
+
// Slate gray
|
|
957
|
+
})
|
|
958
|
+
};
|
|
959
|
+
|
|
960
|
+
// src/ui/theme/themes/nord-theme.ts
|
|
961
|
+
var NORD_THEME = {
|
|
962
|
+
name: "nord",
|
|
963
|
+
description: "Arctic, north-bluish color palette",
|
|
964
|
+
colors: createThemeColors({
|
|
965
|
+
branch: rgb(136, 192, 208),
|
|
966
|
+
// Nordic cyan
|
|
967
|
+
changes: rgb(143, 188, 187),
|
|
968
|
+
// Nordic blue-gray
|
|
969
|
+
contextLow: rgb(163, 190, 140),
|
|
970
|
+
// Nordic green
|
|
971
|
+
contextMedium: rgb(235, 203, 139),
|
|
972
|
+
// Nordic yellow
|
|
973
|
+
contextHigh: rgb(191, 97, 106),
|
|
974
|
+
// Nordic red
|
|
975
|
+
linesAdded: rgb(163, 190, 140),
|
|
976
|
+
// Nordic green
|
|
977
|
+
linesRemoved: rgb(191, 97, 106),
|
|
978
|
+
// Nordic red
|
|
979
|
+
cost: rgb(216, 222, 233),
|
|
980
|
+
// Nordic white
|
|
981
|
+
model: rgb(129, 161, 193),
|
|
982
|
+
// Nordic blue
|
|
983
|
+
duration: rgb(94, 129, 172),
|
|
984
|
+
// Nordic dark blue
|
|
985
|
+
accent: rgb(136, 192, 208),
|
|
986
|
+
// Nordic cyan
|
|
987
|
+
cacheHigh: rgb(163, 190, 140),
|
|
988
|
+
// Nordic green
|
|
989
|
+
cacheMedium: rgb(235, 203, 139),
|
|
990
|
+
// Nordic yellow
|
|
991
|
+
cacheLow: rgb(191, 97, 106),
|
|
992
|
+
// Nordic red
|
|
993
|
+
cacheRead: rgb(136, 192, 208),
|
|
994
|
+
// Nordic cyan
|
|
995
|
+
cacheWrite: rgb(129, 161, 193),
|
|
996
|
+
// Nordic blue
|
|
997
|
+
toolsRunning: rgb(235, 203, 139),
|
|
998
|
+
// Nordic yellow
|
|
999
|
+
toolsCompleted: rgb(163, 190, 140),
|
|
1000
|
+
// Nordic green
|
|
1001
|
+
toolsError: rgb(191, 97, 106),
|
|
1002
|
+
// Nordic red
|
|
1003
|
+
toolsName: rgb(136, 192, 208),
|
|
1004
|
+
// Nordic cyan
|
|
1005
|
+
toolsTarget: rgb(129, 161, 193),
|
|
1006
|
+
// Nordic blue
|
|
1007
|
+
toolsCount: rgb(216, 222, 233)
|
|
1008
|
+
// Nordic white
|
|
1009
|
+
})
|
|
1010
|
+
};
|
|
1011
|
+
|
|
1012
|
+
// src/ui/theme/themes/one-dark-pro-theme.ts
|
|
1013
|
+
var ONE_DARK_PRO_THEME = {
|
|
1014
|
+
name: "one-dark-pro",
|
|
1015
|
+
description: "Atom's iconic theme",
|
|
1016
|
+
colors: createThemeColors({
|
|
1017
|
+
branch: rgb(97, 175, 239),
|
|
1018
|
+
// Blue
|
|
1019
|
+
changes: rgb(152, 195, 121),
|
|
1020
|
+
// Green
|
|
1021
|
+
contextLow: rgb(152, 195, 121),
|
|
1022
|
+
// Green
|
|
1023
|
+
contextMedium: rgb(229, 192, 123),
|
|
1024
|
+
// Yellow
|
|
1025
|
+
contextHigh: rgb(224, 108, 117),
|
|
1026
|
+
// Red
|
|
1027
|
+
linesAdded: rgb(152, 195, 121),
|
|
1028
|
+
// Green
|
|
1029
|
+
linesRemoved: rgb(224, 108, 117),
|
|
1030
|
+
// Red
|
|
1031
|
+
cost: rgb(209, 154, 102),
|
|
1032
|
+
// Orange
|
|
1033
|
+
model: rgb(171, 178, 191),
|
|
1034
|
+
// Gray
|
|
1035
|
+
duration: rgb(125, 148, 173),
|
|
1036
|
+
// Dark gray
|
|
1037
|
+
accent: rgb(97, 175, 239),
|
|
1038
|
+
// Blue
|
|
1039
|
+
cacheHigh: rgb(152, 195, 121),
|
|
1040
|
+
// Green
|
|
1041
|
+
cacheMedium: rgb(229, 192, 123),
|
|
1042
|
+
// Yellow
|
|
1043
|
+
cacheLow: rgb(224, 108, 117),
|
|
1044
|
+
// Red
|
|
1045
|
+
cacheRead: rgb(97, 175, 239),
|
|
1046
|
+
// Blue
|
|
1047
|
+
cacheWrite: rgb(171, 178, 191),
|
|
1048
|
+
// Gray
|
|
1049
|
+
toolsRunning: rgb(229, 192, 123),
|
|
1050
|
+
// Yellow
|
|
1051
|
+
toolsCompleted: rgb(152, 195, 121),
|
|
1052
|
+
// Green
|
|
1053
|
+
toolsError: rgb(224, 108, 117),
|
|
1054
|
+
// Red
|
|
1055
|
+
toolsName: rgb(97, 175, 239),
|
|
1056
|
+
// Blue
|
|
1057
|
+
toolsTarget: rgb(171, 178, 191),
|
|
1058
|
+
// Gray
|
|
1059
|
+
toolsCount: rgb(209, 154, 102)
|
|
1060
|
+
// Orange
|
|
1061
|
+
})
|
|
1062
|
+
};
|
|
1063
|
+
|
|
1064
|
+
// src/ui/theme/themes/professional-blue-theme.ts
|
|
1065
|
+
var PROFESSIONAL_BLUE_THEME = {
|
|
1066
|
+
name: "professional-blue",
|
|
1067
|
+
description: "Clean, business-oriented blue color scheme",
|
|
1068
|
+
colors: createThemeColors({
|
|
1069
|
+
branch: rgb(37, 99, 235),
|
|
1070
|
+
// Royal blue
|
|
1071
|
+
changes: rgb(148, 163, 184),
|
|
1072
|
+
// Slate gray
|
|
1073
|
+
contextLow: rgb(96, 165, 250),
|
|
1074
|
+
// Light blue
|
|
1075
|
+
contextMedium: rgb(251, 191, 36),
|
|
1076
|
+
// Amber
|
|
1077
|
+
contextHigh: rgb(248, 113, 113),
|
|
1078
|
+
// Red
|
|
1079
|
+
linesAdded: rgb(74, 222, 128),
|
|
1080
|
+
// Green
|
|
1081
|
+
linesRemoved: rgb(248, 113, 113),
|
|
1082
|
+
// Red
|
|
1083
|
+
cost: rgb(251, 146, 60),
|
|
1084
|
+
// Orange
|
|
1085
|
+
model: rgb(167, 139, 250),
|
|
1086
|
+
// Purple
|
|
1087
|
+
duration: rgb(203, 213, 225),
|
|
1088
|
+
// Light gray
|
|
1089
|
+
accent: rgb(37, 99, 235),
|
|
1090
|
+
// Royal blue
|
|
1091
|
+
cacheHigh: rgb(74, 222, 128),
|
|
1092
|
+
// Green
|
|
1093
|
+
cacheMedium: rgb(251, 191, 36),
|
|
1094
|
+
// Amber
|
|
1095
|
+
cacheLow: rgb(248, 113, 113),
|
|
1096
|
+
// Red
|
|
1097
|
+
cacheRead: rgb(96, 165, 250),
|
|
1098
|
+
// Light blue
|
|
1099
|
+
cacheWrite: rgb(167, 139, 250),
|
|
1100
|
+
// Purple
|
|
1101
|
+
toolsRunning: rgb(251, 191, 36),
|
|
1102
|
+
// Amber
|
|
1103
|
+
toolsCompleted: rgb(74, 222, 128),
|
|
1104
|
+
// Green
|
|
1105
|
+
toolsError: rgb(248, 113, 113),
|
|
1106
|
+
// Red
|
|
1107
|
+
toolsName: rgb(37, 99, 235),
|
|
1108
|
+
// Royal blue
|
|
1109
|
+
toolsTarget: rgb(148, 163, 184),
|
|
1110
|
+
// Slate gray
|
|
1111
|
+
toolsCount: rgb(167, 139, 250)
|
|
1112
|
+
// Purple
|
|
1113
|
+
})
|
|
1114
|
+
};
|
|
1115
|
+
|
|
1116
|
+
// src/ui/theme/themes/rose-pine-theme.ts
|
|
1117
|
+
var ROSE_PINE_THEME = {
|
|
1118
|
+
name: "rose-pine",
|
|
1119
|
+
description: "Rose/violet themed",
|
|
1120
|
+
colors: createThemeColors({
|
|
1121
|
+
branch: rgb(156, 207, 216),
|
|
1122
|
+
// Pine cyan
|
|
1123
|
+
changes: rgb(235, 188, 186),
|
|
1124
|
+
// Rose
|
|
1125
|
+
contextLow: rgb(156, 207, 216),
|
|
1126
|
+
// Pine cyan
|
|
1127
|
+
contextMedium: rgb(233, 201, 176),
|
|
1128
|
+
// Pine beige
|
|
1129
|
+
contextHigh: rgb(235, 111, 146),
|
|
1130
|
+
// Pine red
|
|
1131
|
+
linesAdded: rgb(156, 207, 216),
|
|
1132
|
+
// Pine cyan
|
|
1133
|
+
linesRemoved: rgb(235, 111, 146),
|
|
1134
|
+
// Pine red
|
|
1135
|
+
cost: rgb(226, 185, 218),
|
|
1136
|
+
// Pine pink
|
|
1137
|
+
model: rgb(224, 208, 245),
|
|
1138
|
+
// Pine violet
|
|
1139
|
+
duration: rgb(148, 137, 176),
|
|
1140
|
+
// Pine mute
|
|
1141
|
+
accent: rgb(235, 111, 146),
|
|
1142
|
+
// Pine red
|
|
1143
|
+
cacheHigh: rgb(156, 207, 216),
|
|
1144
|
+
// Pine cyan
|
|
1145
|
+
cacheMedium: rgb(233, 201, 176),
|
|
1146
|
+
// Pine beige
|
|
1147
|
+
cacheLow: rgb(235, 111, 146),
|
|
1148
|
+
// Pine red
|
|
1149
|
+
cacheRead: rgb(156, 207, 216),
|
|
1150
|
+
// Pine cyan
|
|
1151
|
+
cacheWrite: rgb(224, 208, 245),
|
|
1152
|
+
// Pine violet
|
|
1153
|
+
toolsRunning: rgb(233, 201, 176),
|
|
1154
|
+
// Pine beige
|
|
1155
|
+
toolsCompleted: rgb(156, 207, 216),
|
|
1156
|
+
// Pine cyan
|
|
1157
|
+
toolsError: rgb(235, 111, 146),
|
|
1158
|
+
// Pine red
|
|
1159
|
+
toolsName: rgb(156, 207, 216),
|
|
1160
|
+
// Pine cyan
|
|
1161
|
+
toolsTarget: rgb(224, 208, 245),
|
|
1162
|
+
// Pine violet
|
|
1163
|
+
toolsCount: rgb(226, 185, 218)
|
|
1164
|
+
// Pine pink
|
|
1165
|
+
})
|
|
1166
|
+
};
|
|
1167
|
+
|
|
1168
|
+
// src/ui/theme/themes/semantic-classic-theme.ts
|
|
1169
|
+
var SEMANTIC_CLASSIC_THEME = {
|
|
1170
|
+
name: "semantic-classic",
|
|
1171
|
+
description: "Industry-standard semantic colors for maximum clarity",
|
|
1172
|
+
colors: createThemeColors({
|
|
1173
|
+
branch: rgb(59, 130, 246),
|
|
1174
|
+
// Blue
|
|
1175
|
+
changes: rgb(107, 114, 128),
|
|
1176
|
+
// Gray
|
|
1177
|
+
contextLow: rgb(34, 197, 94),
|
|
1178
|
+
// Green
|
|
1179
|
+
contextMedium: rgb(234, 179, 8),
|
|
1180
|
+
// Yellow
|
|
1181
|
+
contextHigh: rgb(239, 68, 68),
|
|
1182
|
+
// Red
|
|
1183
|
+
linesAdded: rgb(34, 197, 94),
|
|
1184
|
+
// Green
|
|
1185
|
+
linesRemoved: rgb(239, 68, 68),
|
|
1186
|
+
// Red
|
|
1187
|
+
cost: rgb(249, 115, 22),
|
|
1188
|
+
// Orange
|
|
1189
|
+
model: rgb(99, 102, 241),
|
|
1190
|
+
// Indigo
|
|
1191
|
+
duration: rgb(107, 114, 128),
|
|
1192
|
+
// Gray
|
|
1193
|
+
accent: rgb(59, 130, 246),
|
|
1194
|
+
// Blue
|
|
1195
|
+
cacheHigh: rgb(34, 197, 94),
|
|
1196
|
+
// Green
|
|
1197
|
+
cacheMedium: rgb(234, 179, 8),
|
|
1198
|
+
// Yellow
|
|
1199
|
+
cacheLow: rgb(239, 68, 68),
|
|
1200
|
+
// Red
|
|
1201
|
+
cacheRead: rgb(59, 130, 246),
|
|
1202
|
+
// Blue
|
|
1203
|
+
cacheWrite: rgb(99, 102, 241),
|
|
1204
|
+
// Indigo
|
|
1205
|
+
toolsRunning: rgb(234, 179, 8),
|
|
1206
|
+
// Yellow
|
|
1207
|
+
toolsCompleted: rgb(34, 197, 94),
|
|
1208
|
+
// Green
|
|
1209
|
+
toolsError: rgb(239, 68, 68),
|
|
1210
|
+
// Red
|
|
1211
|
+
toolsName: rgb(59, 130, 246),
|
|
1212
|
+
// Blue
|
|
1213
|
+
toolsTarget: rgb(107, 114, 128),
|
|
1214
|
+
// Gray
|
|
1215
|
+
toolsCount: rgb(99, 102, 241)
|
|
1216
|
+
// Indigo
|
|
1217
|
+
})
|
|
1218
|
+
};
|
|
1219
|
+
|
|
1220
|
+
// src/ui/theme/themes/slate-blue-theme.ts
|
|
1221
|
+
var SLATE_BLUE_THEME = {
|
|
1222
|
+
name: "slate-blue",
|
|
1223
|
+
description: "Calm blue-grays with gentle ocean tones",
|
|
1224
|
+
colors: createThemeColors({
|
|
1225
|
+
branch: rgb(100, 116, 139),
|
|
1226
|
+
// Cool slate
|
|
1227
|
+
changes: rgb(148, 163, 184),
|
|
1228
|
+
// Neutral slate
|
|
1229
|
+
contextLow: rgb(148, 163, 184),
|
|
1230
|
+
// Subtle slate-blue (low)
|
|
1231
|
+
contextMedium: rgb(160, 174, 192),
|
|
1232
|
+
// Medium slate
|
|
1233
|
+
contextHigh: rgb(175, 188, 201),
|
|
1234
|
+
// Light slate (high)
|
|
1235
|
+
linesAdded: rgb(148, 163, 184),
|
|
1236
|
+
linesRemoved: rgb(148, 163, 184),
|
|
1237
|
+
cost: rgb(156, 163, 175),
|
|
1238
|
+
model: rgb(148, 163, 184),
|
|
1239
|
+
duration: rgb(100, 116, 139),
|
|
1240
|
+
accent: rgb(100, 116, 139),
|
|
1241
|
+
cacheHigh: rgb(148, 163, 184),
|
|
1242
|
+
cacheMedium: rgb(160, 174, 192),
|
|
1243
|
+
cacheLow: rgb(175, 188, 201),
|
|
1244
|
+
cacheRead: rgb(100, 116, 139),
|
|
1245
|
+
cacheWrite: rgb(148, 163, 184),
|
|
1246
|
+
toolsRunning: rgb(160, 174, 192),
|
|
1247
|
+
// Medium slate
|
|
1248
|
+
toolsCompleted: rgb(148, 163, 184),
|
|
1249
|
+
// Subtle slate-blue
|
|
1250
|
+
toolsError: rgb(175, 188, 201),
|
|
1251
|
+
// Light slate
|
|
1252
|
+
toolsName: rgb(100, 116, 139),
|
|
1253
|
+
// Cool slate
|
|
1254
|
+
toolsTarget: rgb(148, 163, 184),
|
|
1255
|
+
// Neutral slate
|
|
1256
|
+
toolsCount: rgb(156, 163, 175)
|
|
1257
|
+
// Light slate
|
|
1258
|
+
})
|
|
1259
|
+
};
|
|
1260
|
+
|
|
1261
|
+
// src/ui/theme/themes/solarized-dark-theme.ts
|
|
1262
|
+
var SOLARIZED_DARK_THEME = {
|
|
1263
|
+
name: "solarized-dark",
|
|
1264
|
+
description: "Precise CIELAB lightness",
|
|
1265
|
+
colors: createThemeColors({
|
|
1266
|
+
branch: rgb(38, 139, 210),
|
|
1267
|
+
// Blue
|
|
1268
|
+
changes: rgb(133, 153, 0),
|
|
1269
|
+
// Olive
|
|
1270
|
+
contextLow: rgb(133, 153, 0),
|
|
1271
|
+
// Olive
|
|
1272
|
+
contextMedium: rgb(181, 137, 0),
|
|
1273
|
+
// Yellow
|
|
1274
|
+
contextHigh: rgb(220, 50, 47),
|
|
1275
|
+
// Red
|
|
1276
|
+
linesAdded: rgb(133, 153, 0),
|
|
1277
|
+
// Olive
|
|
1278
|
+
linesRemoved: rgb(220, 50, 47),
|
|
1279
|
+
// Red
|
|
1280
|
+
cost: rgb(203, 75, 22),
|
|
1281
|
+
// Orange
|
|
1282
|
+
model: rgb(131, 148, 150),
|
|
1283
|
+
// Base0
|
|
1284
|
+
duration: rgb(88, 110, 117),
|
|
1285
|
+
// Base01
|
|
1286
|
+
accent: rgb(38, 139, 210),
|
|
1287
|
+
// Blue
|
|
1288
|
+
cacheHigh: rgb(133, 153, 0),
|
|
1289
|
+
// Olive
|
|
1290
|
+
cacheMedium: rgb(181, 137, 0),
|
|
1291
|
+
// Yellow
|
|
1292
|
+
cacheLow: rgb(220, 50, 47),
|
|
1293
|
+
// Red
|
|
1294
|
+
cacheRead: rgb(38, 139, 210),
|
|
1295
|
+
// Blue
|
|
1296
|
+
cacheWrite: rgb(147, 161, 161),
|
|
1297
|
+
// Base1
|
|
1298
|
+
toolsRunning: rgb(181, 137, 0),
|
|
1299
|
+
// Yellow
|
|
1300
|
+
toolsCompleted: rgb(133, 153, 0),
|
|
1301
|
+
// Olive
|
|
1302
|
+
toolsError: rgb(220, 50, 47),
|
|
1303
|
+
// Red
|
|
1304
|
+
toolsName: rgb(38, 139, 210),
|
|
1305
|
+
// Blue
|
|
1306
|
+
toolsTarget: rgb(131, 148, 150),
|
|
1307
|
+
// Base0
|
|
1308
|
+
toolsCount: rgb(203, 75, 22)
|
|
1309
|
+
// Orange
|
|
1310
|
+
})
|
|
1311
|
+
};
|
|
1312
|
+
|
|
1313
|
+
// src/ui/theme/themes/tokyo-night-theme.ts
|
|
1314
|
+
var TOKYO_NIGHT_THEME = {
|
|
1315
|
+
name: "tokyo-night",
|
|
1316
|
+
description: "Clean, dark Tokyo-inspired",
|
|
1317
|
+
colors: createThemeColors({
|
|
1318
|
+
branch: rgb(122, 132, 173),
|
|
1319
|
+
// Blue
|
|
1320
|
+
changes: rgb(122, 162, 247),
|
|
1321
|
+
// Dark blue
|
|
1322
|
+
contextLow: rgb(146, 180, 203),
|
|
1323
|
+
// Cyan
|
|
1324
|
+
contextMedium: rgb(232, 166, 162),
|
|
1325
|
+
// Pink-red
|
|
1326
|
+
contextHigh: rgb(249, 86, 119),
|
|
1327
|
+
// Red
|
|
1328
|
+
linesAdded: rgb(146, 180, 203),
|
|
1329
|
+
// Cyan
|
|
1330
|
+
linesRemoved: rgb(249, 86, 119),
|
|
1331
|
+
// Red
|
|
1332
|
+
cost: rgb(158, 206, 209),
|
|
1333
|
+
// Teal
|
|
1334
|
+
model: rgb(169, 177, 214),
|
|
1335
|
+
// White-ish
|
|
1336
|
+
duration: rgb(113, 119, 161),
|
|
1337
|
+
// Dark blue-gray
|
|
1338
|
+
accent: rgb(122, 132, 173),
|
|
1339
|
+
// Blue
|
|
1340
|
+
cacheHigh: rgb(146, 180, 203),
|
|
1341
|
+
// Cyan
|
|
1342
|
+
cacheMedium: rgb(232, 166, 162),
|
|
1343
|
+
// Pink-red
|
|
1344
|
+
cacheLow: rgb(249, 86, 119),
|
|
1345
|
+
// Red
|
|
1346
|
+
cacheRead: rgb(122, 132, 173),
|
|
1347
|
+
// Blue
|
|
1348
|
+
cacheWrite: rgb(169, 177, 214),
|
|
1349
|
+
// White-ish
|
|
1350
|
+
toolsRunning: rgb(232, 166, 162),
|
|
1351
|
+
// Pink-red
|
|
1352
|
+
toolsCompleted: rgb(146, 180, 203),
|
|
1353
|
+
// Cyan
|
|
1354
|
+
toolsError: rgb(249, 86, 119),
|
|
1355
|
+
// Red
|
|
1356
|
+
toolsName: rgb(122, 132, 173),
|
|
1357
|
+
// Blue
|
|
1358
|
+
toolsTarget: rgb(169, 177, 214),
|
|
1359
|
+
// White-ish
|
|
1360
|
+
toolsCount: rgb(158, 206, 209)
|
|
1361
|
+
// Teal
|
|
1362
|
+
})
|
|
1363
|
+
};
|
|
1364
|
+
|
|
1365
|
+
// src/ui/theme/themes/vscode-dark-plus-theme.ts
|
|
1366
|
+
var VSCODE_DARK_PLUS_THEME = {
|
|
1367
|
+
name: "vscode-dark-plus",
|
|
1368
|
+
description: "Visual Studio Code's default dark theme (claude-scope default)",
|
|
1369
|
+
colors: createThemeColors({
|
|
1370
|
+
branch: rgb(0, 122, 204),
|
|
1371
|
+
// VSCode blue
|
|
1372
|
+
changes: rgb(78, 201, 176),
|
|
1373
|
+
// Teal
|
|
1374
|
+
contextLow: rgb(78, 201, 176),
|
|
1375
|
+
// Teal
|
|
1376
|
+
contextMedium: rgb(220, 220, 170),
|
|
1377
|
+
// Yellow
|
|
1378
|
+
contextHigh: rgb(244, 71, 71),
|
|
1379
|
+
// Red
|
|
1380
|
+
linesAdded: rgb(78, 201, 176),
|
|
1381
|
+
// Teal
|
|
1382
|
+
linesRemoved: rgb(244, 71, 71),
|
|
1383
|
+
// Red
|
|
1384
|
+
cost: rgb(206, 145, 120),
|
|
1385
|
+
// Orange
|
|
1386
|
+
model: rgb(171, 178, 191),
|
|
1387
|
+
// Gray
|
|
1388
|
+
duration: rgb(125, 148, 173),
|
|
1389
|
+
// Dark gray
|
|
1390
|
+
accent: rgb(0, 122, 204),
|
|
1391
|
+
// VSCode blue
|
|
1392
|
+
cacheHigh: rgb(78, 201, 176),
|
|
1393
|
+
// Teal
|
|
1394
|
+
cacheMedium: rgb(220, 220, 170),
|
|
1395
|
+
// Yellow
|
|
1396
|
+
cacheLow: rgb(244, 71, 71),
|
|
1397
|
+
// Red
|
|
1398
|
+
cacheRead: rgb(0, 122, 204),
|
|
1399
|
+
// VSCode blue
|
|
1400
|
+
cacheWrite: rgb(171, 178, 191),
|
|
1401
|
+
// Gray
|
|
1402
|
+
toolsRunning: rgb(251, 191, 36),
|
|
1403
|
+
// Yellow
|
|
1404
|
+
toolsCompleted: rgb(74, 222, 128),
|
|
1405
|
+
// Green
|
|
1406
|
+
toolsError: rgb(248, 113, 113),
|
|
1407
|
+
// Red
|
|
1408
|
+
toolsName: rgb(96, 165, 250),
|
|
1409
|
+
// Blue
|
|
1410
|
+
toolsTarget: rgb(156, 163, 175),
|
|
1411
|
+
// Gray
|
|
1412
|
+
toolsCount: rgb(167, 139, 250)
|
|
1413
|
+
// Purple
|
|
1414
|
+
})
|
|
1415
|
+
};
|
|
1416
|
+
|
|
1417
|
+
// src/ui/theme/index.ts
|
|
1418
|
+
var DEFAULT_THEME = VSCODE_DARK_PLUS_THEME.colors;
|
|
1419
|
+
|
|
1420
|
+
// src/widgets/core/stdin-data-widget.ts
|
|
1421
|
+
var StdinDataWidget = class {
|
|
1422
|
+
/**
|
|
1423
|
+
* Stored stdin data from last update
|
|
1424
|
+
*/
|
|
1425
|
+
data = null;
|
|
1426
|
+
/**
|
|
1427
|
+
* Widget enabled state
|
|
1428
|
+
*/
|
|
1429
|
+
enabled = true;
|
|
1430
|
+
/**
|
|
1431
|
+
* Initialize widget with context
|
|
1432
|
+
* @param context - Widget initialization context
|
|
1433
|
+
*/
|
|
1434
|
+
async initialize(context) {
|
|
1435
|
+
this.enabled = context.config?.enabled !== false;
|
|
1436
|
+
}
|
|
1437
|
+
/**
|
|
1438
|
+
* Update widget with new stdin data
|
|
1439
|
+
* @param data - Stdin data from Claude Code
|
|
1440
|
+
*/
|
|
1441
|
+
async update(data) {
|
|
1442
|
+
this.data = data;
|
|
1443
|
+
}
|
|
1444
|
+
/**
|
|
1445
|
+
* Get stored stdin data
|
|
1446
|
+
* @returns Stored stdin data
|
|
1447
|
+
* @throws Error if data has not been initialized (update not called)
|
|
1448
|
+
*/
|
|
1449
|
+
getData() {
|
|
1450
|
+
if (!this.data) {
|
|
1451
|
+
throw new Error(`Widget ${this.id} data not initialized. Call update() first.`);
|
|
1452
|
+
}
|
|
1453
|
+
return this.data;
|
|
1454
|
+
}
|
|
1455
|
+
/**
|
|
1456
|
+
* Check if widget is enabled
|
|
1457
|
+
* @returns true if widget should render
|
|
1458
|
+
*/
|
|
1459
|
+
isEnabled() {
|
|
1460
|
+
return this.enabled;
|
|
1461
|
+
}
|
|
1462
|
+
/**
|
|
1463
|
+
* Template method - final, subclasses implement renderWithData()
|
|
1464
|
+
*
|
|
1465
|
+
* Handles null data checks and calls renderWithData() hook.
|
|
1466
|
+
*
|
|
1467
|
+
* @param context - Render context
|
|
1468
|
+
* @returns Rendered string, or null if widget should not display
|
|
1469
|
+
*/
|
|
1470
|
+
async render(context) {
|
|
1471
|
+
if (!this.data || !this.enabled) {
|
|
1472
|
+
return null;
|
|
1473
|
+
}
|
|
1474
|
+
return this.renderWithData(this.data, context);
|
|
1475
|
+
}
|
|
1476
|
+
};
|
|
1477
|
+
|
|
1478
|
+
// src/widgets/active-tools/styles.ts
|
|
1479
|
+
function truncatePath(path2) {
|
|
1480
|
+
if (path2.length <= 30) {
|
|
1481
|
+
return path2;
|
|
1482
|
+
}
|
|
1483
|
+
const parts = path2.split("/");
|
|
1484
|
+
return `.../${parts[parts.length - 1]}`;
|
|
1485
|
+
}
|
|
1486
|
+
function formatTool(name, target, colors) {
|
|
1487
|
+
const nameStr = colorize(name, colors.tools.name);
|
|
1488
|
+
if (target) {
|
|
1489
|
+
const targetStr = colorize(`: ${truncatePath(target)}`, colors.tools.target);
|
|
1490
|
+
return `${nameStr}${targetStr}`;
|
|
1491
|
+
}
|
|
1492
|
+
return nameStr;
|
|
1493
|
+
}
|
|
1494
|
+
var activeToolsStyles = {
|
|
1495
|
+
/**
|
|
1496
|
+
* balanced: Running tools with ◐ spinner, completed aggregated with ✓ ×count
|
|
1497
|
+
*/
|
|
1498
|
+
balanced: (data, colors) => {
|
|
1499
|
+
const parts = [];
|
|
1500
|
+
for (const tool of data.running.slice(-2)) {
|
|
1501
|
+
const indicator = colors ? colorize("\u25D0", colors.tools.running) : "\u25D0";
|
|
1502
|
+
parts.push(
|
|
1503
|
+
`${indicator} ${formatTool(tool.name, tool.target, colors ?? getDefaultColors())}`
|
|
1504
|
+
);
|
|
1505
|
+
}
|
|
1506
|
+
const sorted = Array.from(data.completed.entries()).sort((a, b) => b[1] - a[1]).slice(0, 4);
|
|
1507
|
+
for (const [name, count] of sorted) {
|
|
1508
|
+
const check = colors ? colorize("\u2713", colors.tools.completed) : "\u2713";
|
|
1509
|
+
const countStr = colors ? colorize(`\xD7${count}`, colors.tools.count) : `\xD7${count}`;
|
|
1510
|
+
parts.push(`${check} ${name} ${countStr}`);
|
|
1511
|
+
}
|
|
1512
|
+
if (parts.length === 0) {
|
|
1513
|
+
return "";
|
|
1514
|
+
}
|
|
1515
|
+
return parts.join(" | ");
|
|
388
1516
|
},
|
|
1517
|
+
/**
|
|
1518
|
+
* compact: [ToolName] format for all tools
|
|
1519
|
+
*/
|
|
1520
|
+
compact: (data, colors) => {
|
|
1521
|
+
const parts = [];
|
|
1522
|
+
const c = colors ?? getDefaultColors();
|
|
1523
|
+
for (const tool of data.running) {
|
|
1524
|
+
parts.push(`[${colorize(tool.name, c.tools.name)}]`);
|
|
1525
|
+
}
|
|
1526
|
+
for (const [name] of Array.from(data.completed.entries()).slice(0, 3)) {
|
|
1527
|
+
parts.push(`[${colorize(name, c.tools.completed)}]`);
|
|
1528
|
+
}
|
|
1529
|
+
if (parts.length === 0) {
|
|
1530
|
+
return "";
|
|
1531
|
+
}
|
|
1532
|
+
return parts.join(" ");
|
|
1533
|
+
},
|
|
1534
|
+
/**
|
|
1535
|
+
* minimal: Same as compact
|
|
1536
|
+
*/
|
|
1537
|
+
minimal: (data, colors) => {
|
|
1538
|
+
const compactStyle = activeToolsStyles.compact;
|
|
1539
|
+
if (!compactStyle) return "";
|
|
1540
|
+
return compactStyle(data, colors);
|
|
1541
|
+
},
|
|
1542
|
+
/**
|
|
1543
|
+
* playful: Emojis (📖✏️✨🔄🔍📁) with tool names
|
|
1544
|
+
*/
|
|
389
1545
|
playful: (data, colors) => {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
}
|
|
1546
|
+
const parts = [];
|
|
1547
|
+
const emojis = {
|
|
1548
|
+
Read: "\u{1F4D6}",
|
|
1549
|
+
Write: "\u270F\uFE0F",
|
|
1550
|
+
Edit: "\u2728",
|
|
1551
|
+
Bash: "\u{1F504}",
|
|
1552
|
+
Grep: "\u{1F50D}",
|
|
1553
|
+
Glob: "\u{1F4C1}"
|
|
1554
|
+
};
|
|
1555
|
+
for (const tool of data.running.slice(-3)) {
|
|
1556
|
+
const emoji = emojis[tool.name] ?? "\u{1F527}";
|
|
1557
|
+
const nameStr = colors ? colorize(tool.name, colors.tools.name) : tool.name;
|
|
1558
|
+
parts.push(`${emoji} ${nameStr}`);
|
|
398
1559
|
}
|
|
399
|
-
|
|
400
|
-
|
|
1560
|
+
if (parts.length === 0) {
|
|
1561
|
+
return "";
|
|
1562
|
+
}
|
|
1563
|
+
return parts.join(", ");
|
|
401
1564
|
},
|
|
1565
|
+
/**
|
|
1566
|
+
* verbose: Full text labels "Running:" and "Completed:"
|
|
1567
|
+
*/
|
|
402
1568
|
verbose: (data, colors) => {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
const branch2 = colors ? colorize(data.branch, colors.branch) : data.branch;
|
|
409
|
-
const changes = colors ? colorize(`[${parts.join(", ")}]`, colors.changes) : `[${parts.join(", ")}]`;
|
|
410
|
-
return `branch: ${branch2} ${changes}`;
|
|
411
|
-
}
|
|
1569
|
+
const parts = [];
|
|
1570
|
+
const c = colors ?? getDefaultColors();
|
|
1571
|
+
for (const tool of data.running) {
|
|
1572
|
+
const label = colorize("Running:", c.tools.running);
|
|
1573
|
+
parts.push(`${label} ${formatTool(tool.name, tool.target, c)}`);
|
|
412
1574
|
}
|
|
413
|
-
const
|
|
414
|
-
|
|
1575
|
+
const sorted = Array.from(data.completed.entries()).sort((a, b) => b[1] - a[1]).slice(0, 3);
|
|
1576
|
+
for (const [name, count] of sorted) {
|
|
1577
|
+
const label = colorize("Completed:", c.tools.completed);
|
|
1578
|
+
const countStr = colorize(`(${count}x)`, c.tools.count);
|
|
1579
|
+
parts.push(`${label} ${name} ${countStr}`);
|
|
1580
|
+
}
|
|
1581
|
+
if (parts.length === 0) {
|
|
1582
|
+
return "";
|
|
1583
|
+
}
|
|
1584
|
+
return parts.join(" | ");
|
|
415
1585
|
},
|
|
1586
|
+
/**
|
|
1587
|
+
* labeled: "Tools:" prefix with all tools
|
|
1588
|
+
*/
|
|
416
1589
|
labeled: (data, colors) => {
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
1590
|
+
const c = colors ?? getDefaultColors();
|
|
1591
|
+
const allTools = [
|
|
1592
|
+
...data.running.map((t) => {
|
|
1593
|
+
const indicator = colorize("\u25D0", c.tools.running);
|
|
1594
|
+
return `${indicator} ${formatTool(t.name, t.target, c)}`;
|
|
1595
|
+
}),
|
|
1596
|
+
...Array.from(data.completed.entries()).slice(0, 3).map(([name, count]) => {
|
|
1597
|
+
const indicator = colorize("\u2713", c.tools.completed);
|
|
1598
|
+
const countStr = colorize(`\xD7${count}`, c.tools.count);
|
|
1599
|
+
return `${indicator} ${name} ${countStr}`;
|
|
1600
|
+
})
|
|
1601
|
+
];
|
|
1602
|
+
if (allTools.length === 0) {
|
|
1603
|
+
return "";
|
|
1604
|
+
}
|
|
1605
|
+
const prefix = colors ? colorize("Tools:", c.semantic.info) : "Tools:";
|
|
1606
|
+
return `${prefix}: ${allTools.join(" | ")}`;
|
|
429
1607
|
},
|
|
1608
|
+
/**
|
|
1609
|
+
* indicator: ● bullet indicators
|
|
1610
|
+
*/
|
|
430
1611
|
indicator: (data, colors) => {
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
const branch = colors ? colorize(data.branch, colors.branch) : data.branch;
|
|
437
|
-
const changes = colors ? colorize(`[${parts.join(" ")}]`, colors.changes) : `[${parts.join(" ")}]`;
|
|
438
|
-
return `\u25CF ${branch} ${changes}`;
|
|
439
|
-
}
|
|
1612
|
+
const parts = [];
|
|
1613
|
+
const c = colors ?? getDefaultColors();
|
|
1614
|
+
for (const tool of data.running) {
|
|
1615
|
+
const bullet = colorize("\u25CF", c.semantic.info);
|
|
1616
|
+
parts.push(`${bullet} ${formatTool(tool.name, tool.target, c)}`);
|
|
440
1617
|
}
|
|
441
|
-
|
|
1618
|
+
for (const [name] of Array.from(data.completed.entries()).slice(0, 3)) {
|
|
1619
|
+
const bullet = colorize("\u25CF", c.tools.completed);
|
|
1620
|
+
parts.push(`${bullet} ${name}`);
|
|
1621
|
+
}
|
|
1622
|
+
if (parts.length === 0) {
|
|
1623
|
+
return "";
|
|
1624
|
+
}
|
|
1625
|
+
return parts.join(" | ");
|
|
442
1626
|
}
|
|
443
1627
|
};
|
|
1628
|
+
function getDefaultColors() {
|
|
1629
|
+
return {
|
|
1630
|
+
base: {
|
|
1631
|
+
text: "\x1B[37m",
|
|
1632
|
+
muted: "\x1B[90m",
|
|
1633
|
+
accent: "\x1B[36m",
|
|
1634
|
+
border: "\x1B[90m"
|
|
1635
|
+
},
|
|
1636
|
+
semantic: {
|
|
1637
|
+
success: "\x1B[32m",
|
|
1638
|
+
warning: "\x1B[33m",
|
|
1639
|
+
error: "\x1B[31m",
|
|
1640
|
+
info: "\x1B[36m"
|
|
1641
|
+
},
|
|
1642
|
+
git: {
|
|
1643
|
+
branch: "\x1B[36m",
|
|
1644
|
+
changes: "\x1B[33m"
|
|
1645
|
+
},
|
|
1646
|
+
context: {
|
|
1647
|
+
low: "\x1B[32m",
|
|
1648
|
+
medium: "\x1B[33m",
|
|
1649
|
+
high: "\x1B[31m",
|
|
1650
|
+
bar: "\x1B[37m"
|
|
1651
|
+
},
|
|
1652
|
+
lines: {
|
|
1653
|
+
added: "\x1B[32m",
|
|
1654
|
+
removed: "\x1B[31m"
|
|
1655
|
+
},
|
|
1656
|
+
cost: {
|
|
1657
|
+
amount: "\x1B[37m",
|
|
1658
|
+
currency: "\x1B[90m"
|
|
1659
|
+
},
|
|
1660
|
+
duration: {
|
|
1661
|
+
value: "\x1B[37m",
|
|
1662
|
+
unit: "\x1B[90m"
|
|
1663
|
+
},
|
|
1664
|
+
model: {
|
|
1665
|
+
name: "\x1B[36m",
|
|
1666
|
+
version: "\x1B[90m"
|
|
1667
|
+
},
|
|
1668
|
+
poker: {
|
|
1669
|
+
participating: "\x1B[37m",
|
|
1670
|
+
nonParticipating: "\x1B[90m",
|
|
1671
|
+
result: "\x1B[36m"
|
|
1672
|
+
},
|
|
1673
|
+
cache: {
|
|
1674
|
+
high: "\x1B[32m",
|
|
1675
|
+
medium: "\x1B[33m",
|
|
1676
|
+
low: "\x1B[31m",
|
|
1677
|
+
read: "\x1B[34m",
|
|
1678
|
+
write: "\x1B[35m"
|
|
1679
|
+
},
|
|
1680
|
+
tools: {
|
|
1681
|
+
running: "\x1B[33m",
|
|
1682
|
+
completed: "\x1B[32m",
|
|
1683
|
+
error: "\x1B[31m",
|
|
1684
|
+
name: "\x1B[34m",
|
|
1685
|
+
target: "\x1B[90m",
|
|
1686
|
+
count: "\x1B[35m"
|
|
1687
|
+
}
|
|
1688
|
+
};
|
|
1689
|
+
}
|
|
444
1690
|
|
|
445
|
-
// src/widgets/
|
|
446
|
-
var
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
1691
|
+
// src/widgets/active-tools/active-tools-widget.ts
|
|
1692
|
+
var ActiveToolsWidget = class extends StdinDataWidget {
|
|
1693
|
+
constructor(theme, transcriptProvider) {
|
|
1694
|
+
super();
|
|
1695
|
+
this.theme = theme;
|
|
1696
|
+
this.transcriptProvider = transcriptProvider;
|
|
1697
|
+
}
|
|
1698
|
+
id = "active-tools";
|
|
1699
|
+
metadata = {
|
|
1700
|
+
name: "Active Tools",
|
|
1701
|
+
description: "Active tools display from transcript",
|
|
1702
|
+
version: "1.0.0",
|
|
1703
|
+
author: "claude-scope",
|
|
1704
|
+
line: 2
|
|
1705
|
+
// Display on third line (0-indexed)
|
|
1706
|
+
};
|
|
1707
|
+
style = "balanced";
|
|
1708
|
+
tools = [];
|
|
1709
|
+
renderData;
|
|
1710
|
+
/**
|
|
1711
|
+
* Set display style
|
|
1712
|
+
* @param style - Style to use for rendering
|
|
1713
|
+
*/
|
|
1714
|
+
setStyle(style) {
|
|
1715
|
+
this.style = style;
|
|
1716
|
+
}
|
|
1717
|
+
/**
|
|
1718
|
+
* Aggregate completed tools by name
|
|
1719
|
+
* @param tools - Array of tool entries
|
|
1720
|
+
* @returns Map of tool name to count
|
|
1721
|
+
*/
|
|
1722
|
+
aggregateCompleted(tools) {
|
|
1723
|
+
const counts = /* @__PURE__ */ new Map();
|
|
1724
|
+
for (const tool of tools) {
|
|
1725
|
+
if (tool.status === "completed" || tool.status === "error") {
|
|
1726
|
+
const current = counts.get(tool.name) ?? 0;
|
|
1727
|
+
counts.set(tool.name, current + 1);
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
return counts;
|
|
1731
|
+
}
|
|
462
1732
|
/**
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
* Tests can inject MockGit factory here
|
|
466
|
-
* @param colors - Optional theme colors
|
|
1733
|
+
* Prepare render data from tools
|
|
1734
|
+
* @returns Render data with running, completed, and error tools
|
|
467
1735
|
*/
|
|
468
|
-
|
|
469
|
-
this.
|
|
470
|
-
|
|
1736
|
+
prepareRenderData() {
|
|
1737
|
+
const running = this.tools.filter((t) => t.status === "running");
|
|
1738
|
+
const completed = this.aggregateCompleted(this.tools);
|
|
1739
|
+
const errors = this.tools.filter((t) => t.status === "error");
|
|
1740
|
+
return { running, completed, errors };
|
|
471
1741
|
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
1742
|
+
/**
|
|
1743
|
+
* Update widget with new stdin data
|
|
1744
|
+
* @param data - Stdin data from Claude Code
|
|
1745
|
+
*/
|
|
1746
|
+
async update(data) {
|
|
1747
|
+
await super.update(data);
|
|
1748
|
+
if (data.transcript_path) {
|
|
1749
|
+
this.tools = await this.transcriptProvider.parseTools(data.transcript_path);
|
|
1750
|
+
this.renderData = this.prepareRenderData();
|
|
1751
|
+
} else {
|
|
1752
|
+
this.tools = [];
|
|
1753
|
+
this.renderData = void 0;
|
|
476
1754
|
}
|
|
477
1755
|
}
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
1756
|
+
/**
|
|
1757
|
+
* Render widget output
|
|
1758
|
+
* @param context - Render context
|
|
1759
|
+
* @returns Rendered string or null if no tools
|
|
1760
|
+
*/
|
|
1761
|
+
renderWithData(data, context) {
|
|
1762
|
+
if (!this.renderData || this.tools.length === 0) {
|
|
483
1763
|
return null;
|
|
484
1764
|
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
const branch = status.current || null;
|
|
488
|
-
if (!branch) {
|
|
489
|
-
return null;
|
|
490
|
-
}
|
|
491
|
-
let changes;
|
|
492
|
-
try {
|
|
493
|
-
const diffSummary = await this.git.diffSummary();
|
|
494
|
-
if (diffSummary.fileCount > 0) {
|
|
495
|
-
let insertions = 0;
|
|
496
|
-
let deletions = 0;
|
|
497
|
-
for (const file of diffSummary.files) {
|
|
498
|
-
insertions += file.insertions || 0;
|
|
499
|
-
deletions += file.deletions || 0;
|
|
500
|
-
}
|
|
501
|
-
if (insertions > 0 || deletions > 0) {
|
|
502
|
-
changes = { files: diffSummary.fileCount, insertions, deletions };
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
} catch {
|
|
506
|
-
}
|
|
507
|
-
const renderData = { branch, changes };
|
|
508
|
-
return this.styleFn(renderData, this.colors.git);
|
|
509
|
-
} catch {
|
|
1765
|
+
const styleFn = activeToolsStyles[this.style] ?? activeToolsStyles.balanced;
|
|
1766
|
+
if (!styleFn) {
|
|
510
1767
|
return null;
|
|
511
1768
|
}
|
|
1769
|
+
return styleFn(this.renderData, this.theme);
|
|
512
1770
|
}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
}
|
|
518
|
-
}
|
|
1771
|
+
/**
|
|
1772
|
+
* Check if widget should render
|
|
1773
|
+
* @returns true if there are tools to display
|
|
1774
|
+
*/
|
|
519
1775
|
isEnabled() {
|
|
520
|
-
return this.
|
|
521
|
-
}
|
|
522
|
-
async cleanup() {
|
|
1776
|
+
return super.isEnabled() && this.tools.length > 0;
|
|
523
1777
|
}
|
|
524
1778
|
};
|
|
525
1779
|
|
|
526
|
-
// src/
|
|
527
|
-
|
|
1780
|
+
// src/core/widget-types.ts
|
|
1781
|
+
function createWidgetMetadata(name, description, version = "1.0.0", author = "claude-scope", line = 0) {
|
|
1782
|
+
return {
|
|
1783
|
+
name,
|
|
1784
|
+
description,
|
|
1785
|
+
version,
|
|
1786
|
+
author,
|
|
1787
|
+
line
|
|
1788
|
+
};
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
// src/widgets/cache-metrics/styles.ts
|
|
1792
|
+
function formatK(n) {
|
|
1793
|
+
if (n < 1e3) {
|
|
1794
|
+
return n.toString();
|
|
1795
|
+
}
|
|
1796
|
+
const k = n / 1e3;
|
|
1797
|
+
return k < 10 ? `${k.toFixed(1)}k` : `${Math.round(k)}k`;
|
|
1798
|
+
}
|
|
1799
|
+
function formatCurrency(usd) {
|
|
1800
|
+
if (usd < 5e-3 && usd > 0) {
|
|
1801
|
+
return "<$0.01";
|
|
1802
|
+
}
|
|
1803
|
+
return `$${usd.toFixed(2)}`;
|
|
1804
|
+
}
|
|
1805
|
+
function createProgressBar(percentage, width) {
|
|
1806
|
+
const filled = Math.round(percentage / 100 * width);
|
|
1807
|
+
const empty = width - filled;
|
|
1808
|
+
return "\u2588".repeat(filled) + "\u2591".repeat(empty);
|
|
1809
|
+
}
|
|
1810
|
+
function getCacheColor(hitRate, colors) {
|
|
1811
|
+
if (hitRate > 70) {
|
|
1812
|
+
return colors.cache.high;
|
|
1813
|
+
} else if (hitRate >= 40) {
|
|
1814
|
+
return colors.cache.medium;
|
|
1815
|
+
} else {
|
|
1816
|
+
return colors.cache.low;
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
var cacheMetricsStyles = {
|
|
1820
|
+
/**
|
|
1821
|
+
* balanced: 💾 70% cached (35.0k tokens) with color coding
|
|
1822
|
+
*/
|
|
528
1823
|
balanced: (data, colors) => {
|
|
529
|
-
const
|
|
530
|
-
|
|
531
|
-
|
|
1824
|
+
const { hitRate, cacheRead } = data;
|
|
1825
|
+
const color = colors ? getCacheColor(hitRate, colors) : "";
|
|
1826
|
+
const percentage = color ? `${color}${hitRate.toFixed(0)}%` : `${hitRate.toFixed(0)}%`;
|
|
1827
|
+
const tokens = colors ? `${colors.cache.read}${formatK(cacheRead)} tokens` : `${formatK(cacheRead)} tokens`;
|
|
1828
|
+
return `\u{1F4BE} ${percentage} cached (${tokens})`;
|
|
532
1829
|
},
|
|
1830
|
+
/**
|
|
1831
|
+
* compact: Cache: 70%
|
|
1832
|
+
*/
|
|
533
1833
|
compact: (data, colors) => {
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
1834
|
+
const hitRate = data.hitRate.toFixed(0);
|
|
1835
|
+
if (colors) {
|
|
1836
|
+
return `${colors.cache.read}Cache: ${hitRate}%`;
|
|
1837
|
+
}
|
|
1838
|
+
return `Cache: ${hitRate}%`;
|
|
538
1839
|
},
|
|
1840
|
+
/**
|
|
1841
|
+
* playful: 💾 [███████░] 70% with progress bar
|
|
1842
|
+
*/
|
|
539
1843
|
playful: (data, colors) => {
|
|
540
|
-
const
|
|
541
|
-
|
|
542
|
-
|
|
1844
|
+
const { hitRate } = data;
|
|
1845
|
+
const bar = createProgressBar(hitRate, 7);
|
|
1846
|
+
const color = colors ? getCacheColor(hitRate, colors) : "";
|
|
1847
|
+
const barAndPercent = color ? `${color}[${bar}] ${hitRate.toFixed(0)}%` : `[${bar}] ${hitRate.toFixed(0)}%`;
|
|
1848
|
+
return `\u{1F4BE} ${barAndPercent}`;
|
|
543
1849
|
},
|
|
1850
|
+
/**
|
|
1851
|
+
* verbose: Cache: 35.0k tokens (70%) | $0.03 saved
|
|
1852
|
+
*/
|
|
544
1853
|
verbose: (data, colors) => {
|
|
545
|
-
|
|
546
|
-
const
|
|
547
|
-
|
|
548
|
-
|
|
1854
|
+
const { cacheRead, hitRate, savings } = data;
|
|
1855
|
+
const tokens = colors ? `${colors.cache.read}${formatK(cacheRead)} tokens` : `${formatK(cacheRead)} tokens`;
|
|
1856
|
+
const percent = `${hitRate.toFixed(0)}%`;
|
|
1857
|
+
const saved = colors ? `${colors.cache.write}${formatCurrency(savings)} saved` : `${formatCurrency(savings)} saved`;
|
|
1858
|
+
return `Cache: ${tokens} (${percent}) | ${saved}`;
|
|
549
1859
|
},
|
|
1860
|
+
/**
|
|
1861
|
+
* labeled: Cache Hit: 70% | $0.03 saved
|
|
1862
|
+
*/
|
|
550
1863
|
labeled: (data, colors) => {
|
|
551
|
-
const
|
|
552
|
-
|
|
553
|
-
|
|
1864
|
+
const { hitRate, savings } = data;
|
|
1865
|
+
const percent = colors ? `${colors.cache.read}${hitRate.toFixed(0)}%` : `${hitRate.toFixed(0)}%`;
|
|
1866
|
+
const saved = colors ? `${colors.cache.write}${formatCurrency(savings)} saved` : `${formatCurrency(savings)} saved`;
|
|
1867
|
+
return `Cache Hit: ${percent} | ${saved}`;
|
|
554
1868
|
},
|
|
1869
|
+
/**
|
|
1870
|
+
* indicator: ● 70% cached
|
|
1871
|
+
*/
|
|
555
1872
|
indicator: (data, colors) => {
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
|
|
1873
|
+
const { hitRate } = data;
|
|
1874
|
+
const color = colors ? getCacheColor(hitRate, colors) : "";
|
|
1875
|
+
const percentage = color ? `${color}${hitRate.toFixed(0)}%` : `${hitRate.toFixed(0)}%`;
|
|
1876
|
+
return `\u25CF ${percentage} cached`;
|
|
1877
|
+
},
|
|
1878
|
+
/**
|
|
1879
|
+
* breakdown: Multi-line with ├─ Read: and └─ Write: breakdown
|
|
1880
|
+
*/
|
|
1881
|
+
breakdown: (data, colors) => {
|
|
1882
|
+
const { cacheRead, cacheWrite, hitRate, savings } = data;
|
|
1883
|
+
const color = colors ? getCacheColor(hitRate, colors) : "";
|
|
1884
|
+
const percent = color ? `${color}${hitRate.toFixed(0)}%` : `${hitRate.toFixed(0)}%`;
|
|
1885
|
+
const saved = colors ? `${colors.cache.write}${formatCurrency(savings)} saved` : `${formatCurrency(savings)} saved`;
|
|
1886
|
+
const read = colors ? `${colors.cache.read}${formatK(cacheRead)}` : formatK(cacheRead);
|
|
1887
|
+
const write = colors ? `${colors.cache.write}${formatK(cacheWrite)}` : formatK(cacheWrite);
|
|
1888
|
+
return [`\u{1F4BE} ${percent} cached | ${saved}`, `\u251C\u2500 Read: ${read}`, `\u2514\u2500 Write: ${write}`].join("\n");
|
|
559
1889
|
}
|
|
560
1890
|
};
|
|
561
1891
|
|
|
562
|
-
// src/widgets/
|
|
563
|
-
var
|
|
564
|
-
id = "
|
|
1892
|
+
// src/widgets/cache-metrics/cache-metrics-widget.ts
|
|
1893
|
+
var CacheMetricsWidget = class extends StdinDataWidget {
|
|
1894
|
+
id = "cache-metrics";
|
|
565
1895
|
metadata = createWidgetMetadata(
|
|
566
|
-
"
|
|
567
|
-
"
|
|
1896
|
+
"Cache Metrics",
|
|
1897
|
+
"Cache hit rate and savings display",
|
|
568
1898
|
"1.0.0",
|
|
569
1899
|
"claude-scope",
|
|
570
|
-
|
|
571
|
-
//
|
|
1900
|
+
2
|
|
1901
|
+
// Third line
|
|
572
1902
|
);
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
1903
|
+
theme;
|
|
1904
|
+
style = "balanced";
|
|
1905
|
+
renderData;
|
|
1906
|
+
constructor(theme) {
|
|
1907
|
+
super();
|
|
1908
|
+
this.theme = theme ?? DEFAULT_THEME;
|
|
1909
|
+
}
|
|
579
1910
|
/**
|
|
580
|
-
*
|
|
581
|
-
* If not provided, uses default createGit (production)
|
|
582
|
-
* Tests can inject MockGit factory here
|
|
583
|
-
* @param colors - Optional theme colors
|
|
1911
|
+
* Set display style
|
|
584
1912
|
*/
|
|
585
|
-
|
|
586
|
-
this.
|
|
587
|
-
this.colors = colors ?? DEFAULT_THEME;
|
|
1913
|
+
setStyle(style) {
|
|
1914
|
+
this.style = style;
|
|
588
1915
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
1916
|
+
/**
|
|
1917
|
+
* Calculate cache metrics from context usage data
|
|
1918
|
+
* Returns null if no usage data is available
|
|
1919
|
+
*/
|
|
1920
|
+
calculateMetrics(data) {
|
|
1921
|
+
const usage = data.context_window?.current_usage;
|
|
1922
|
+
if (!usage) {
|
|
1923
|
+
return null;
|
|
1924
|
+
}
|
|
1925
|
+
const cacheRead = usage.cache_read_input_tokens ?? 0;
|
|
1926
|
+
const cacheWrite = usage.cache_creation_input_tokens ?? 0;
|
|
1927
|
+
const inputTokens = usage.input_tokens ?? 0;
|
|
1928
|
+
const outputTokens = usage.output_tokens ?? 0;
|
|
1929
|
+
const totalTokens = inputTokens + outputTokens;
|
|
1930
|
+
const hitRate = inputTokens > 0 ? Math.round(cacheRead / inputTokens * 100) : 0;
|
|
1931
|
+
const costPerToken = 3e-6;
|
|
1932
|
+
const savings = cacheRead * 0.9 * costPerToken;
|
|
1933
|
+
return {
|
|
1934
|
+
cacheRead,
|
|
1935
|
+
cacheWrite,
|
|
1936
|
+
totalTokens,
|
|
1937
|
+
hitRate,
|
|
1938
|
+
savings
|
|
1939
|
+
};
|
|
1940
|
+
}
|
|
1941
|
+
/**
|
|
1942
|
+
* Update widget with new data and calculate metrics
|
|
1943
|
+
*/
|
|
1944
|
+
async update(data) {
|
|
1945
|
+
await super.update(data);
|
|
1946
|
+
const metrics = this.calculateMetrics(data);
|
|
1947
|
+
this.renderData = metrics ?? void 0;
|
|
1948
|
+
}
|
|
1949
|
+
/**
|
|
1950
|
+
* Render the cache metrics display
|
|
1951
|
+
*/
|
|
1952
|
+
renderWithData(_data, _context) {
|
|
1953
|
+
if (!this.renderData) {
|
|
1954
|
+
return null;
|
|
1955
|
+
}
|
|
1956
|
+
const styleFn = cacheMetricsStyles[this.style] ?? cacheMetricsStyles.balanced;
|
|
1957
|
+
if (!styleFn) {
|
|
1958
|
+
return null;
|
|
1959
|
+
}
|
|
1960
|
+
return styleFn(this.renderData, this.theme);
|
|
1961
|
+
}
|
|
1962
|
+
/**
|
|
1963
|
+
* Widget is enabled when we have cache metrics data
|
|
1964
|
+
*/
|
|
1965
|
+
isEnabled() {
|
|
1966
|
+
return this.renderData !== void 0;
|
|
1967
|
+
}
|
|
1968
|
+
};
|
|
1969
|
+
|
|
1970
|
+
// src/core/style-types.ts
|
|
1971
|
+
var DEFAULT_WIDGET_STYLE = "balanced";
|
|
1972
|
+
|
|
1973
|
+
// src/providers/config-provider.ts
|
|
1974
|
+
var fs = __toESM(require("fs/promises"), 1);
|
|
1975
|
+
var os = __toESM(require("os"), 1);
|
|
1976
|
+
var path = __toESM(require("path"), 1);
|
|
1977
|
+
var ConfigProvider = class {
|
|
1978
|
+
cachedCounts;
|
|
1979
|
+
lastScan = 0;
|
|
1980
|
+
cacheInterval = 5e3;
|
|
1981
|
+
// 5 seconds
|
|
1982
|
+
/**
|
|
1983
|
+
* Get config counts with hybrid caching
|
|
1984
|
+
* Scans filesystem if cache is stale (>5 seconds)
|
|
1985
|
+
*/
|
|
1986
|
+
async getConfigs(options = {}) {
|
|
1987
|
+
const now = Date.now();
|
|
1988
|
+
if (this.cachedCounts && now - this.lastScan < this.cacheInterval) {
|
|
1989
|
+
return this.cachedCounts;
|
|
1990
|
+
}
|
|
1991
|
+
this.cachedCounts = await this.scanConfigs(options);
|
|
1992
|
+
this.lastScan = now;
|
|
1993
|
+
return this.cachedCounts;
|
|
1994
|
+
}
|
|
1995
|
+
/**
|
|
1996
|
+
* Scan filesystem for Claude Code configurations
|
|
1997
|
+
*/
|
|
1998
|
+
async scanConfigs(options) {
|
|
1999
|
+
let claudeMdCount = 0;
|
|
2000
|
+
let rulesCount = 0;
|
|
2001
|
+
let mcpCount = 0;
|
|
2002
|
+
let hooksCount = 0;
|
|
2003
|
+
const homeDir = os.homedir();
|
|
2004
|
+
const claudeDir = path.join(homeDir, ".claude");
|
|
2005
|
+
const cwd = options.cwd;
|
|
2006
|
+
if (await this.fileExists(path.join(claudeDir, "CLAUDE.md"))) {
|
|
2007
|
+
claudeMdCount++;
|
|
2008
|
+
}
|
|
2009
|
+
rulesCount += await this.countRulesInDir(path.join(claudeDir, "rules"));
|
|
2010
|
+
const userSettings = path.join(claudeDir, "settings.json");
|
|
2011
|
+
const userSettingsData = await this.readJsonFile(userSettings);
|
|
2012
|
+
if (userSettingsData) {
|
|
2013
|
+
mcpCount += this.countMcpServers(userSettingsData);
|
|
2014
|
+
hooksCount += this.countHooks(userSettingsData);
|
|
2015
|
+
}
|
|
2016
|
+
const userClaudeJson = path.join(homeDir, ".claude.json");
|
|
2017
|
+
const userClaudeData = await this.readJsonFile(userClaudeJson);
|
|
2018
|
+
if (userClaudeData) {
|
|
2019
|
+
const userMcpCount = this.countMcpServers(userClaudeData);
|
|
2020
|
+
mcpCount += Math.max(0, userMcpCount - this.countMcpServers(userSettingsData || {}));
|
|
2021
|
+
}
|
|
2022
|
+
if (cwd) {
|
|
2023
|
+
if (await this.fileExists(path.join(cwd, "CLAUDE.md"))) {
|
|
2024
|
+
claudeMdCount++;
|
|
2025
|
+
}
|
|
2026
|
+
if (await this.fileExists(path.join(cwd, "CLAUDE.local.md"))) {
|
|
2027
|
+
claudeMdCount++;
|
|
2028
|
+
}
|
|
2029
|
+
if (await this.fileExists(path.join(cwd, ".claude", "CLAUDE.md"))) {
|
|
2030
|
+
claudeMdCount++;
|
|
2031
|
+
}
|
|
2032
|
+
if (await this.fileExists(path.join(cwd, ".claude", "CLAUDE.local.md"))) {
|
|
2033
|
+
claudeMdCount++;
|
|
2034
|
+
}
|
|
2035
|
+
rulesCount += await this.countRulesInDir(path.join(cwd, ".claude", "rules"));
|
|
2036
|
+
const mcpJson = path.join(cwd, ".mcp.json");
|
|
2037
|
+
const mcpData = await this.readJsonFile(mcpJson);
|
|
2038
|
+
if (mcpData) {
|
|
2039
|
+
mcpCount += this.countMcpServers(mcpData);
|
|
2040
|
+
}
|
|
2041
|
+
const projectSettings = path.join(cwd, ".claude", "settings.json");
|
|
2042
|
+
const projectSettingsData = await this.readJsonFile(projectSettings);
|
|
2043
|
+
if (projectSettingsData) {
|
|
2044
|
+
mcpCount += this.countMcpServers(projectSettingsData);
|
|
2045
|
+
hooksCount += this.countHooks(projectSettingsData);
|
|
2046
|
+
}
|
|
2047
|
+
const localSettings = path.join(cwd, ".claude", "settings.local.json");
|
|
2048
|
+
const localSettingsData = await this.readJsonFile(localSettings);
|
|
2049
|
+
if (localSettingsData) {
|
|
2050
|
+
mcpCount += this.countMcpServers(localSettingsData);
|
|
2051
|
+
hooksCount += this.countHooks(localSettingsData);
|
|
2052
|
+
}
|
|
593
2053
|
}
|
|
2054
|
+
return { claudeMdCount, rulesCount, mcpCount, hooksCount };
|
|
594
2055
|
}
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
async
|
|
599
|
-
if (!this.enabled || !this.git || !this.cwd) {
|
|
600
|
-
return null;
|
|
601
|
-
}
|
|
2056
|
+
/**
|
|
2057
|
+
* Check if file exists
|
|
2058
|
+
*/
|
|
2059
|
+
async fileExists(filePath) {
|
|
602
2060
|
try {
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
return this.styleFn(renderData, this.colors.git);
|
|
2061
|
+
await fs.access(filePath);
|
|
2062
|
+
return true;
|
|
606
2063
|
} catch {
|
|
607
|
-
return
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
async update(data) {
|
|
611
|
-
if (data.cwd !== this.cwd) {
|
|
612
|
-
this.cwd = data.cwd;
|
|
613
|
-
this.git = this.gitFactory(data.cwd);
|
|
2064
|
+
return false;
|
|
614
2065
|
}
|
|
615
2066
|
}
|
|
616
|
-
isEnabled() {
|
|
617
|
-
return this.enabled;
|
|
618
|
-
}
|
|
619
|
-
async cleanup() {
|
|
620
|
-
}
|
|
621
|
-
};
|
|
622
|
-
|
|
623
|
-
// src/widgets/core/stdin-data-widget.ts
|
|
624
|
-
var StdinDataWidget = class {
|
|
625
|
-
/**
|
|
626
|
-
* Stored stdin data from last update
|
|
627
|
-
*/
|
|
628
|
-
data = null;
|
|
629
|
-
/**
|
|
630
|
-
* Widget enabled state
|
|
631
|
-
*/
|
|
632
|
-
enabled = true;
|
|
633
|
-
/**
|
|
634
|
-
* Initialize widget with context
|
|
635
|
-
* @param context - Widget initialization context
|
|
636
|
-
*/
|
|
637
|
-
async initialize(context) {
|
|
638
|
-
this.enabled = context.config?.enabled !== false;
|
|
639
|
-
}
|
|
640
2067
|
/**
|
|
641
|
-
*
|
|
642
|
-
* @param data - Stdin data from Claude Code
|
|
2068
|
+
* Read and parse JSON file
|
|
643
2069
|
*/
|
|
644
|
-
async
|
|
645
|
-
|
|
2070
|
+
async readJsonFile(filePath) {
|
|
2071
|
+
try {
|
|
2072
|
+
const content = await fs.readFile(filePath, "utf8");
|
|
2073
|
+
return JSON.parse(content);
|
|
2074
|
+
} catch {
|
|
2075
|
+
return null;
|
|
2076
|
+
}
|
|
646
2077
|
}
|
|
647
2078
|
/**
|
|
648
|
-
*
|
|
649
|
-
* @returns Stored stdin data
|
|
650
|
-
* @throws Error if data has not been initialized (update not called)
|
|
2079
|
+
* Count MCP servers in config object
|
|
651
2080
|
*/
|
|
652
|
-
|
|
653
|
-
if (!
|
|
654
|
-
|
|
2081
|
+
countMcpServers(config) {
|
|
2082
|
+
if (!config || !config.mcpServers || typeof config.mcpServers !== "object") {
|
|
2083
|
+
return 0;
|
|
655
2084
|
}
|
|
656
|
-
return
|
|
2085
|
+
return Object.keys(config.mcpServers).length;
|
|
657
2086
|
}
|
|
658
2087
|
/**
|
|
659
|
-
*
|
|
660
|
-
* @returns true if widget should render
|
|
2088
|
+
* Count hooks in config object
|
|
661
2089
|
*/
|
|
662
|
-
|
|
663
|
-
|
|
2090
|
+
countHooks(config) {
|
|
2091
|
+
if (!config || !config.hooks || typeof config.hooks !== "object") {
|
|
2092
|
+
return 0;
|
|
2093
|
+
}
|
|
2094
|
+
return Object.keys(config.hooks).length;
|
|
664
2095
|
}
|
|
665
2096
|
/**
|
|
666
|
-
*
|
|
667
|
-
*
|
|
668
|
-
* Handles null data checks and calls renderWithData() hook.
|
|
669
|
-
*
|
|
670
|
-
* @param context - Render context
|
|
671
|
-
* @returns Rendered string, or null if widget should not display
|
|
2097
|
+
* Recursively count .md files in directory
|
|
672
2098
|
*/
|
|
673
|
-
async
|
|
674
|
-
|
|
675
|
-
|
|
2099
|
+
async countRulesInDir(rulesDir) {
|
|
2100
|
+
const exists = await this.fileExists(rulesDir);
|
|
2101
|
+
if (!exists) return 0;
|
|
2102
|
+
try {
|
|
2103
|
+
let count = 0;
|
|
2104
|
+
const entries = await fs.readdir(rulesDir, { withFileTypes: true });
|
|
2105
|
+
for (const entry of entries) {
|
|
2106
|
+
const fullPath = path.join(rulesDir, entry.name);
|
|
2107
|
+
if (entry.isDirectory()) {
|
|
2108
|
+
count += await this.countRulesInDir(fullPath);
|
|
2109
|
+
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
2110
|
+
count++;
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
return count;
|
|
2114
|
+
} catch {
|
|
2115
|
+
return 0;
|
|
676
2116
|
}
|
|
677
|
-
return this.renderWithData(this.data, context);
|
|
678
2117
|
}
|
|
679
2118
|
};
|
|
680
2119
|
|
|
681
|
-
// src/widgets/
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
return colorize(data.displayName, colors.name);
|
|
689
|
-
},
|
|
690
|
-
compact: (data, colors) => {
|
|
691
|
-
const shortName = getShortName(data.displayName);
|
|
692
|
-
if (!colors) return shortName;
|
|
693
|
-
return colorize(shortName, colors.name);
|
|
694
|
-
},
|
|
695
|
-
playful: (data, colors) => {
|
|
696
|
-
const shortName = getShortName(data.displayName);
|
|
697
|
-
if (!colors) return `\u{1F916} ${shortName}`;
|
|
698
|
-
return `\u{1F916} ${colorize(shortName, colors.name)}`;
|
|
699
|
-
},
|
|
700
|
-
technical: (data, colors) => {
|
|
701
|
-
if (!colors) return data.id;
|
|
702
|
-
const match = data.id.match(/^(.+?)-(\d[\d.]*)$/);
|
|
703
|
-
if (match) {
|
|
704
|
-
return colorize(match[1], colors.name) + colorize(`-${match[2]}`, colors.version);
|
|
2120
|
+
// src/widgets/config-count/styles.ts
|
|
2121
|
+
var configCountStyles = {
|
|
2122
|
+
balanced: (data) => {
|
|
2123
|
+
const { claudeMdCount, rulesCount, mcpCount, hooksCount } = data;
|
|
2124
|
+
const parts = [];
|
|
2125
|
+
if (claudeMdCount > 0) {
|
|
2126
|
+
parts.push(`CLAUDE.md:${claudeMdCount}`);
|
|
705
2127
|
}
|
|
706
|
-
|
|
2128
|
+
if (rulesCount > 0) {
|
|
2129
|
+
parts.push(`rules:${rulesCount}`);
|
|
2130
|
+
}
|
|
2131
|
+
if (mcpCount > 0) {
|
|
2132
|
+
parts.push(`MCPs:${mcpCount}`);
|
|
2133
|
+
}
|
|
2134
|
+
if (hooksCount > 0) {
|
|
2135
|
+
parts.push(`hooks:${hooksCount}`);
|
|
2136
|
+
}
|
|
2137
|
+
return parts.join(" \u2502 ");
|
|
707
2138
|
},
|
|
708
|
-
|
|
709
|
-
const
|
|
710
|
-
|
|
711
|
-
|
|
2139
|
+
compact: (data) => {
|
|
2140
|
+
const { claudeMdCount, rulesCount, mcpCount, hooksCount } = data;
|
|
2141
|
+
const parts = [];
|
|
2142
|
+
if (claudeMdCount > 0) {
|
|
2143
|
+
parts.push(`${claudeMdCount} docs`);
|
|
2144
|
+
}
|
|
2145
|
+
if (rulesCount > 0) {
|
|
2146
|
+
parts.push(`${rulesCount} rules`);
|
|
2147
|
+
}
|
|
2148
|
+
if (mcpCount > 0) {
|
|
2149
|
+
parts.push(`${mcpCount} MCPs`);
|
|
2150
|
+
}
|
|
2151
|
+
if (hooksCount > 0) {
|
|
2152
|
+
const hookLabel = hooksCount === 1 ? "hook" : "hooks";
|
|
2153
|
+
parts.push(`${hooksCount} ${hookLabel}`);
|
|
2154
|
+
}
|
|
2155
|
+
return parts.join(" \u2502 ");
|
|
712
2156
|
},
|
|
713
|
-
|
|
714
|
-
const
|
|
715
|
-
|
|
716
|
-
|
|
2157
|
+
playful: (data) => {
|
|
2158
|
+
const { claudeMdCount, rulesCount, mcpCount, hooksCount } = data;
|
|
2159
|
+
const parts = [];
|
|
2160
|
+
if (claudeMdCount > 0) {
|
|
2161
|
+
parts.push(`\u{1F4C4} CLAUDE.md:${claudeMdCount}`);
|
|
2162
|
+
}
|
|
2163
|
+
if (rulesCount > 0) {
|
|
2164
|
+
parts.push(`\u{1F4DC} rules:${rulesCount}`);
|
|
2165
|
+
}
|
|
2166
|
+
if (mcpCount > 0) {
|
|
2167
|
+
parts.push(`\u{1F50C} MCPs:${mcpCount}`);
|
|
2168
|
+
}
|
|
2169
|
+
if (hooksCount > 0) {
|
|
2170
|
+
parts.push(`\u{1FA9D} hooks:${hooksCount}`);
|
|
2171
|
+
}
|
|
2172
|
+
return parts.join(" \u2502 ");
|
|
717
2173
|
},
|
|
718
|
-
|
|
719
|
-
const
|
|
720
|
-
|
|
721
|
-
|
|
2174
|
+
verbose: (data) => {
|
|
2175
|
+
const { claudeMdCount, rulesCount, mcpCount, hooksCount } = data;
|
|
2176
|
+
const parts = [];
|
|
2177
|
+
if (claudeMdCount > 0) {
|
|
2178
|
+
parts.push(`${claudeMdCount} CLAUDE.md`);
|
|
2179
|
+
}
|
|
2180
|
+
if (rulesCount > 0) {
|
|
2181
|
+
parts.push(`${rulesCount} rules`);
|
|
2182
|
+
}
|
|
2183
|
+
if (mcpCount > 0) {
|
|
2184
|
+
parts.push(`${mcpCount} MCP servers`);
|
|
2185
|
+
}
|
|
2186
|
+
if (hooksCount > 0) {
|
|
2187
|
+
parts.push(`${hooksCount} hook`);
|
|
2188
|
+
}
|
|
2189
|
+
return parts.join(" \u2502 ");
|
|
722
2190
|
}
|
|
723
2191
|
};
|
|
724
2192
|
|
|
725
|
-
// src/widgets/
|
|
726
|
-
var
|
|
727
|
-
id = "
|
|
2193
|
+
// src/widgets/config-count-widget.ts
|
|
2194
|
+
var ConfigCountWidget = class {
|
|
2195
|
+
id = "config-count";
|
|
728
2196
|
metadata = createWidgetMetadata(
|
|
729
|
-
"
|
|
730
|
-
"Displays
|
|
2197
|
+
"Config Count",
|
|
2198
|
+
"Displays Claude Code configuration counts",
|
|
731
2199
|
"1.0.0",
|
|
732
2200
|
"claude-scope",
|
|
733
|
-
|
|
734
|
-
//
|
|
2201
|
+
1
|
|
2202
|
+
// Second line
|
|
735
2203
|
);
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
setStyle(style = "balanced") {
|
|
743
|
-
const fn = modelStyles[style];
|
|
2204
|
+
configProvider = new ConfigProvider();
|
|
2205
|
+
configs;
|
|
2206
|
+
cwd;
|
|
2207
|
+
styleFn = configCountStyles.balanced;
|
|
2208
|
+
setStyle(style = DEFAULT_WIDGET_STYLE) {
|
|
2209
|
+
const fn = configCountStyles[style];
|
|
744
2210
|
if (fn) {
|
|
745
2211
|
this.styleFn = fn;
|
|
746
2212
|
}
|
|
747
2213
|
}
|
|
748
|
-
|
|
2214
|
+
async initialize() {
|
|
2215
|
+
}
|
|
2216
|
+
async update(data) {
|
|
2217
|
+
this.cwd = data.cwd;
|
|
2218
|
+
this.configs = await this.configProvider.getConfigs({ cwd: data.cwd });
|
|
2219
|
+
}
|
|
2220
|
+
isEnabled() {
|
|
2221
|
+
if (!this.configs) {
|
|
2222
|
+
return false;
|
|
2223
|
+
}
|
|
2224
|
+
const { claudeMdCount, rulesCount, mcpCount, hooksCount } = this.configs;
|
|
2225
|
+
return claudeMdCount > 0 || rulesCount > 0 || mcpCount > 0 || hooksCount > 0;
|
|
2226
|
+
}
|
|
2227
|
+
async render(context) {
|
|
2228
|
+
if (!this.configs) {
|
|
2229
|
+
return null;
|
|
2230
|
+
}
|
|
2231
|
+
const { claudeMdCount, rulesCount, mcpCount, hooksCount } = this.configs;
|
|
749
2232
|
const renderData = {
|
|
750
|
-
|
|
751
|
-
|
|
2233
|
+
claudeMdCount,
|
|
2234
|
+
rulesCount,
|
|
2235
|
+
mcpCount,
|
|
2236
|
+
hooksCount
|
|
752
2237
|
};
|
|
753
|
-
return this.styleFn(renderData
|
|
2238
|
+
return this.styleFn(renderData);
|
|
2239
|
+
}
|
|
2240
|
+
async cleanup() {
|
|
754
2241
|
}
|
|
755
2242
|
};
|
|
756
2243
|
|
|
2244
|
+
// src/ui/utils/style-utils.ts
|
|
2245
|
+
function withLabel(prefix, value) {
|
|
2246
|
+
if (prefix === "") return value;
|
|
2247
|
+
return `${prefix}: ${value}`;
|
|
2248
|
+
}
|
|
2249
|
+
function withIndicator(value) {
|
|
2250
|
+
return `\u25CF ${value}`;
|
|
2251
|
+
}
|
|
2252
|
+
function progressBar(percent, width = 10) {
|
|
2253
|
+
const clamped = Math.max(0, Math.min(100, percent));
|
|
2254
|
+
const filled = Math.round(clamped / 100 * width);
|
|
2255
|
+
const empty = width - filled;
|
|
2256
|
+
return "\u2588".repeat(filled) + "\u2591".repeat(empty);
|
|
2257
|
+
}
|
|
2258
|
+
|
|
757
2259
|
// src/widgets/context/styles.ts
|
|
758
2260
|
function getContextColor(percent, colors) {
|
|
759
2261
|
const clampedPercent = Math.max(0, Math.min(100, percent));
|
|
@@ -941,83 +2443,6 @@ var CostWidget = class extends StdinDataWidget {
|
|
|
941
2443
|
}
|
|
942
2444
|
};
|
|
943
2445
|
|
|
944
|
-
// src/widgets/lines/styles.ts
|
|
945
|
-
var linesStyles = {
|
|
946
|
-
balanced: (data, colors) => {
|
|
947
|
-
if (!colors) return `+${data.added}/-${data.removed}`;
|
|
948
|
-
const addedStr = colorize(`+${data.added}`, colors.added);
|
|
949
|
-
const removedStr = colorize(`-${data.removed}`, colors.removed);
|
|
950
|
-
return `${addedStr}/${removedStr}`;
|
|
951
|
-
},
|
|
952
|
-
compact: (data, colors) => {
|
|
953
|
-
if (!colors) return `+${data.added}-${data.removed}`;
|
|
954
|
-
const addedStr = colorize(`+${data.added}`, colors.added);
|
|
955
|
-
const removedStr = colorize(`-${data.removed}`, colors.removed);
|
|
956
|
-
return `${addedStr}${removedStr}`;
|
|
957
|
-
},
|
|
958
|
-
playful: (data, colors) => {
|
|
959
|
-
if (!colors) return `\u2795${data.added} \u2796${data.removed}`;
|
|
960
|
-
const addedStr = colorize(`\u2795${data.added}`, colors.added);
|
|
961
|
-
const removedStr = colorize(`\u2796${data.removed}`, colors.removed);
|
|
962
|
-
return `${addedStr} ${removedStr}`;
|
|
963
|
-
},
|
|
964
|
-
verbose: (data, colors) => {
|
|
965
|
-
const parts = [];
|
|
966
|
-
if (data.added > 0) {
|
|
967
|
-
const text = `+${data.added} added`;
|
|
968
|
-
parts.push(colors ? colorize(text, colors.added) : text);
|
|
969
|
-
}
|
|
970
|
-
if (data.removed > 0) {
|
|
971
|
-
const text = `-${data.removed} removed`;
|
|
972
|
-
parts.push(colors ? colorize(text, colors.removed) : text);
|
|
973
|
-
}
|
|
974
|
-
return parts.join(", ");
|
|
975
|
-
},
|
|
976
|
-
labeled: (data, colors) => {
|
|
977
|
-
const addedStr = colors ? colorize(`+${data.added}`, colors.added) : `+${data.added}`;
|
|
978
|
-
const removedStr = colors ? colorize(`-${data.removed}`, colors.removed) : `-${data.removed}`;
|
|
979
|
-
const lines = `${addedStr}/${removedStr}`;
|
|
980
|
-
return withLabel("Lines", lines);
|
|
981
|
-
},
|
|
982
|
-
indicator: (data, colors) => {
|
|
983
|
-
const addedStr = colors ? colorize(`+${data.added}`, colors.added) : `+${data.added}`;
|
|
984
|
-
const removedStr = colors ? colorize(`-${data.removed}`, colors.removed) : `-${data.removed}`;
|
|
985
|
-
const lines = `${addedStr}/${removedStr}`;
|
|
986
|
-
return withIndicator(lines);
|
|
987
|
-
}
|
|
988
|
-
};
|
|
989
|
-
|
|
990
|
-
// src/widgets/lines-widget.ts
|
|
991
|
-
var LinesWidget = class extends StdinDataWidget {
|
|
992
|
-
id = "lines";
|
|
993
|
-
metadata = createWidgetMetadata(
|
|
994
|
-
"Lines",
|
|
995
|
-
"Displays lines added/removed in session",
|
|
996
|
-
"1.0.0",
|
|
997
|
-
"claude-scope",
|
|
998
|
-
0
|
|
999
|
-
// First line
|
|
1000
|
-
);
|
|
1001
|
-
colors;
|
|
1002
|
-
styleFn = linesStyles.balanced;
|
|
1003
|
-
constructor(colors) {
|
|
1004
|
-
super();
|
|
1005
|
-
this.colors = colors ?? DEFAULT_THEME;
|
|
1006
|
-
}
|
|
1007
|
-
setStyle(style = "balanced") {
|
|
1008
|
-
const fn = linesStyles[style];
|
|
1009
|
-
if (fn) {
|
|
1010
|
-
this.styleFn = fn;
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
|
-
renderWithData(data, _context) {
|
|
1014
|
-
const added = data.cost?.total_lines_added ?? 0;
|
|
1015
|
-
const removed = data.cost?.total_lines_removed ?? 0;
|
|
1016
|
-
const renderData = { added, removed };
|
|
1017
|
-
return this.styleFn(renderData, this.colors.lines);
|
|
1018
|
-
}
|
|
1019
|
-
};
|
|
1020
|
-
|
|
1021
2446
|
// src/widgets/duration/styles.ts
|
|
1022
2447
|
var durationStyles = {
|
|
1023
2448
|
balanced: (data, colors) => {
|
|
@@ -1102,305 +2527,533 @@ function formatDurationWithColors(ms, colors) {
|
|
|
1102
2527
|
var DurationWidget = class extends StdinDataWidget {
|
|
1103
2528
|
id = "duration";
|
|
1104
2529
|
metadata = createWidgetMetadata(
|
|
1105
|
-
"Duration",
|
|
1106
|
-
"Displays elapsed session time",
|
|
2530
|
+
"Duration",
|
|
2531
|
+
"Displays elapsed session time",
|
|
2532
|
+
"1.0.0",
|
|
2533
|
+
"claude-scope",
|
|
2534
|
+
0
|
|
2535
|
+
// First line
|
|
2536
|
+
);
|
|
2537
|
+
colors;
|
|
2538
|
+
styleFn = durationStyles.balanced;
|
|
2539
|
+
constructor(colors) {
|
|
2540
|
+
super();
|
|
2541
|
+
this.colors = colors ?? DEFAULT_THEME;
|
|
2542
|
+
}
|
|
2543
|
+
setStyle(style = "balanced") {
|
|
2544
|
+
const fn = durationStyles[style];
|
|
2545
|
+
if (fn) {
|
|
2546
|
+
this.styleFn = fn;
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
renderWithData(data, _context) {
|
|
2550
|
+
if (!data.cost || data.cost.total_duration_ms === void 0) return null;
|
|
2551
|
+
const renderData = {
|
|
2552
|
+
durationMs: data.cost.total_duration_ms
|
|
2553
|
+
};
|
|
2554
|
+
return this.styleFn(renderData, this.colors.duration);
|
|
2555
|
+
}
|
|
2556
|
+
};
|
|
2557
|
+
|
|
2558
|
+
// src/widgets/empty-line-widget.ts
|
|
2559
|
+
var EmptyLineWidget = class extends StdinDataWidget {
|
|
2560
|
+
id = "empty-line";
|
|
2561
|
+
metadata = createWidgetMetadata(
|
|
2562
|
+
"Empty Line",
|
|
2563
|
+
"Empty line separator",
|
|
2564
|
+
"1.0.0",
|
|
2565
|
+
"claude-scope",
|
|
2566
|
+
5
|
|
2567
|
+
// Sixth line (0-indexed)
|
|
2568
|
+
);
|
|
2569
|
+
/**
|
|
2570
|
+
* All styles return the same value (Braille Pattern Blank).
|
|
2571
|
+
* This method exists for API consistency with other widgets.
|
|
2572
|
+
*/
|
|
2573
|
+
setStyle(_style) {
|
|
2574
|
+
}
|
|
2575
|
+
/**
|
|
2576
|
+
* Return Braille Pattern Blank to create a visible empty separator line.
|
|
2577
|
+
* U+2800 occupies cell width but appears blank, ensuring the line renders.
|
|
2578
|
+
*/
|
|
2579
|
+
renderWithData(_data, _context) {
|
|
2580
|
+
return "\u2800";
|
|
2581
|
+
}
|
|
2582
|
+
};
|
|
2583
|
+
|
|
2584
|
+
// src/providers/git-provider.ts
|
|
2585
|
+
var import_node_child_process = require("node:child_process");
|
|
2586
|
+
var import_node_util = require("node:util");
|
|
2587
|
+
var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
2588
|
+
var NativeGit = class {
|
|
2589
|
+
cwd;
|
|
2590
|
+
constructor(cwd) {
|
|
2591
|
+
this.cwd = cwd;
|
|
2592
|
+
}
|
|
2593
|
+
async status() {
|
|
2594
|
+
try {
|
|
2595
|
+
const { stdout } = await execFileAsync("git", ["status", "--branch", "--short"], {
|
|
2596
|
+
cwd: this.cwd
|
|
2597
|
+
});
|
|
2598
|
+
const match = stdout.match(/^##\s+(\S+)/m);
|
|
2599
|
+
const current = match ? match[1] : null;
|
|
2600
|
+
return { current };
|
|
2601
|
+
} catch {
|
|
2602
|
+
return { current: null };
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
async diffSummary(options) {
|
|
2606
|
+
const args = ["diff", "--shortstat"];
|
|
2607
|
+
if (options) {
|
|
2608
|
+
args.push(...options);
|
|
2609
|
+
}
|
|
2610
|
+
try {
|
|
2611
|
+
const { stdout } = await execFileAsync("git", args, {
|
|
2612
|
+
cwd: this.cwd
|
|
2613
|
+
});
|
|
2614
|
+
const fileMatch = stdout.match(/(\d+)\s+file(s?)\s+changed/);
|
|
2615
|
+
const insertionMatch = stdout.match(/(\d+)\s+insertion/);
|
|
2616
|
+
const deletionMatch = stdout.match(/(\d+)\s+deletion/);
|
|
2617
|
+
const fileCount = fileMatch ? parseInt(fileMatch[1], 10) : 0;
|
|
2618
|
+
const insertions = insertionMatch ? parseInt(insertionMatch[1], 10) : 0;
|
|
2619
|
+
const deletions = deletionMatch ? parseInt(deletionMatch[1], 10) : 0;
|
|
2620
|
+
const files = insertions > 0 || deletions > 0 ? [{ file: "(total)", insertions, deletions }] : [];
|
|
2621
|
+
return { fileCount, files };
|
|
2622
|
+
} catch {
|
|
2623
|
+
return { fileCount: 0, files: [] };
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
async latestTag() {
|
|
2627
|
+
try {
|
|
2628
|
+
const { stdout } = await execFileAsync("git", ["describe", "--tags", "--abbrev=0"], {
|
|
2629
|
+
cwd: this.cwd
|
|
2630
|
+
});
|
|
2631
|
+
return stdout.trim();
|
|
2632
|
+
} catch {
|
|
2633
|
+
return null;
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2636
|
+
};
|
|
2637
|
+
function createGit(cwd) {
|
|
2638
|
+
return new NativeGit(cwd);
|
|
2639
|
+
}
|
|
2640
|
+
|
|
2641
|
+
// src/widgets/git-tag/styles.ts
|
|
2642
|
+
var gitTagStyles = {
|
|
2643
|
+
balanced: (data, colors) => {
|
|
2644
|
+
const tag = data.tag || "\u2014";
|
|
2645
|
+
if (!colors) return tag;
|
|
2646
|
+
return colorize(tag, colors.branch);
|
|
2647
|
+
},
|
|
2648
|
+
compact: (data, colors) => {
|
|
2649
|
+
if (!data.tag) return "\u2014";
|
|
2650
|
+
const tag = data.tag.replace(/^v/, "");
|
|
2651
|
+
if (!colors) return tag;
|
|
2652
|
+
return colorize(tag, colors.branch);
|
|
2653
|
+
},
|
|
2654
|
+
playful: (data, colors) => {
|
|
2655
|
+
const tag = data.tag || "\u2014";
|
|
2656
|
+
if (!colors) return `\u{1F3F7}\uFE0F ${tag}`;
|
|
2657
|
+
return `\u{1F3F7}\uFE0F ${colorize(tag, colors.branch)}`;
|
|
2658
|
+
},
|
|
2659
|
+
verbose: (data, colors) => {
|
|
2660
|
+
if (!data.tag) return "version: none";
|
|
2661
|
+
const tag = `version ${data.tag}`;
|
|
2662
|
+
if (!colors) return tag;
|
|
2663
|
+
return `version ${colorize(data.tag, colors.branch)}`;
|
|
2664
|
+
},
|
|
2665
|
+
labeled: (data, colors) => {
|
|
2666
|
+
const tag = data.tag || "none";
|
|
2667
|
+
if (!colors) return withLabel("Tag", tag);
|
|
2668
|
+
return withLabel("Tag", colorize(tag, colors.branch));
|
|
2669
|
+
},
|
|
2670
|
+
indicator: (data, colors) => {
|
|
2671
|
+
const tag = data.tag || "\u2014";
|
|
2672
|
+
if (!colors) return withIndicator(tag);
|
|
2673
|
+
return withIndicator(colorize(tag, colors.branch));
|
|
2674
|
+
}
|
|
2675
|
+
};
|
|
2676
|
+
|
|
2677
|
+
// src/widgets/git/git-tag-widget.ts
|
|
2678
|
+
var GitTagWidget = class {
|
|
2679
|
+
id = "git-tag";
|
|
2680
|
+
metadata = createWidgetMetadata(
|
|
2681
|
+
"Git Tag Widget",
|
|
2682
|
+
"Displays the latest git tag",
|
|
1107
2683
|
"1.0.0",
|
|
1108
2684
|
"claude-scope",
|
|
1109
|
-
|
|
1110
|
-
//
|
|
2685
|
+
1
|
|
2686
|
+
// Second line
|
|
1111
2687
|
);
|
|
2688
|
+
gitFactory;
|
|
2689
|
+
git = null;
|
|
2690
|
+
enabled = true;
|
|
2691
|
+
cwd = null;
|
|
1112
2692
|
colors;
|
|
1113
|
-
styleFn =
|
|
1114
|
-
|
|
1115
|
-
|
|
2693
|
+
styleFn = gitTagStyles.balanced;
|
|
2694
|
+
/**
|
|
2695
|
+
* @param gitFactory - Optional factory function for creating IGit instances
|
|
2696
|
+
* If not provided, uses default createGit (production)
|
|
2697
|
+
* Tests can inject MockGit factory here
|
|
2698
|
+
* @param colors - Optional theme colors
|
|
2699
|
+
*/
|
|
2700
|
+
constructor(gitFactory, colors) {
|
|
2701
|
+
this.gitFactory = gitFactory || createGit;
|
|
1116
2702
|
this.colors = colors ?? DEFAULT_THEME;
|
|
1117
2703
|
}
|
|
1118
2704
|
setStyle(style = "balanced") {
|
|
1119
|
-
const fn =
|
|
2705
|
+
const fn = gitTagStyles[style];
|
|
1120
2706
|
if (fn) {
|
|
1121
2707
|
this.styleFn = fn;
|
|
1122
2708
|
}
|
|
1123
2709
|
}
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
const renderData = {
|
|
1127
|
-
durationMs: data.cost.total_duration_ms
|
|
1128
|
-
};
|
|
1129
|
-
return this.styleFn(renderData, this.colors.duration);
|
|
1130
|
-
}
|
|
1131
|
-
};
|
|
1132
|
-
|
|
1133
|
-
// src/providers/config-provider.ts
|
|
1134
|
-
var fs = __toESM(require("fs/promises"), 1);
|
|
1135
|
-
var path = __toESM(require("path"), 1);
|
|
1136
|
-
var os = __toESM(require("os"), 1);
|
|
1137
|
-
var ConfigProvider = class {
|
|
1138
|
-
cachedCounts;
|
|
1139
|
-
lastScan = 0;
|
|
1140
|
-
cacheInterval = 5e3;
|
|
1141
|
-
// 5 seconds
|
|
1142
|
-
/**
|
|
1143
|
-
* Get config counts with hybrid caching
|
|
1144
|
-
* Scans filesystem if cache is stale (>5 seconds)
|
|
1145
|
-
*/
|
|
1146
|
-
async getConfigs(options = {}) {
|
|
1147
|
-
const now = Date.now();
|
|
1148
|
-
if (this.cachedCounts && now - this.lastScan < this.cacheInterval) {
|
|
1149
|
-
return this.cachedCounts;
|
|
1150
|
-
}
|
|
1151
|
-
this.cachedCounts = await this.scanConfigs(options);
|
|
1152
|
-
this.lastScan = now;
|
|
1153
|
-
return this.cachedCounts;
|
|
2710
|
+
async initialize(context) {
|
|
2711
|
+
this.enabled = context.config?.enabled !== false;
|
|
1154
2712
|
}
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
async scanConfigs(options) {
|
|
1159
|
-
let claudeMdCount = 0;
|
|
1160
|
-
let rulesCount = 0;
|
|
1161
|
-
let mcpCount = 0;
|
|
1162
|
-
let hooksCount = 0;
|
|
1163
|
-
const homeDir = os.homedir();
|
|
1164
|
-
const claudeDir = path.join(homeDir, ".claude");
|
|
1165
|
-
const cwd = options.cwd;
|
|
1166
|
-
if (await this.fileExists(path.join(claudeDir, "CLAUDE.md"))) {
|
|
1167
|
-
claudeMdCount++;
|
|
2713
|
+
async render(context) {
|
|
2714
|
+
if (!this.enabled || !this.git || !this.cwd) {
|
|
2715
|
+
return null;
|
|
1168
2716
|
}
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
2717
|
+
try {
|
|
2718
|
+
const latestTag = await (this.git.latestTag?.() ?? Promise.resolve(null));
|
|
2719
|
+
const renderData = { tag: latestTag };
|
|
2720
|
+
return this.styleFn(renderData, this.colors.git);
|
|
2721
|
+
} catch {
|
|
2722
|
+
return null;
|
|
1175
2723
|
}
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
if (
|
|
1179
|
-
|
|
1180
|
-
|
|
2724
|
+
}
|
|
2725
|
+
async update(data) {
|
|
2726
|
+
if (data.cwd !== this.cwd) {
|
|
2727
|
+
this.cwd = data.cwd;
|
|
2728
|
+
this.git = this.gitFactory(data.cwd);
|
|
1181
2729
|
}
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
2730
|
+
}
|
|
2731
|
+
isEnabled() {
|
|
2732
|
+
return this.enabled;
|
|
2733
|
+
}
|
|
2734
|
+
async cleanup() {
|
|
2735
|
+
}
|
|
2736
|
+
};
|
|
2737
|
+
|
|
2738
|
+
// src/widgets/git/styles.ts
|
|
2739
|
+
var gitStyles = {
|
|
2740
|
+
minimal: (data, colors) => {
|
|
2741
|
+
if (!colors) return data.branch;
|
|
2742
|
+
return colorize(data.branch, colors.branch);
|
|
2743
|
+
},
|
|
2744
|
+
balanced: (data, colors) => {
|
|
2745
|
+
if (data.changes && data.changes.files > 0) {
|
|
2746
|
+
const parts = [];
|
|
2747
|
+
if (data.changes.insertions > 0) parts.push(`+${data.changes.insertions}`);
|
|
2748
|
+
if (data.changes.deletions > 0) parts.push(`-${data.changes.deletions}`);
|
|
2749
|
+
if (parts.length > 0) {
|
|
2750
|
+
const branch = colors ? colorize(data.branch, colors.branch) : data.branch;
|
|
2751
|
+
const changes = colors ? colorize(`[${parts.join(" ")}]`, colors.changes) : `[${parts.join(" ")}]`;
|
|
2752
|
+
return `${branch} ${changes}`;
|
|
1200
2753
|
}
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
2754
|
+
}
|
|
2755
|
+
return colors ? colorize(data.branch, colors.branch) : data.branch;
|
|
2756
|
+
},
|
|
2757
|
+
compact: (data, colors) => {
|
|
2758
|
+
if (data.changes && data.changes.files > 0) {
|
|
2759
|
+
const parts = [];
|
|
2760
|
+
if (data.changes.insertions > 0) parts.push(`+${data.changes.insertions}`);
|
|
2761
|
+
if (data.changes.deletions > 0) parts.push(`-${data.changes.deletions}`);
|
|
2762
|
+
if (parts.length > 0) {
|
|
2763
|
+
const branch = colors ? colorize(data.branch, colors.branch) : data.branch;
|
|
2764
|
+
const changesStr = parts.join("/");
|
|
2765
|
+
return `${branch} ${changesStr}`;
|
|
1206
2766
|
}
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
2767
|
+
}
|
|
2768
|
+
return colors ? colorize(data.branch, colors.branch) : data.branch;
|
|
2769
|
+
},
|
|
2770
|
+
playful: (data, colors) => {
|
|
2771
|
+
if (data.changes && data.changes.files > 0) {
|
|
2772
|
+
const parts = [];
|
|
2773
|
+
if (data.changes.insertions > 0) parts.push(`\u2B06${data.changes.insertions}`);
|
|
2774
|
+
if (data.changes.deletions > 0) parts.push(`\u2B07${data.changes.deletions}`);
|
|
2775
|
+
if (parts.length > 0) {
|
|
2776
|
+
const branch2 = colors ? colorize(data.branch, colors.branch) : data.branch;
|
|
2777
|
+
return `\u{1F500} ${branch2} ${parts.join(" ")}`;
|
|
1212
2778
|
}
|
|
1213
2779
|
}
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
2780
|
+
const branch = colors ? colorize(data.branch, colors.branch) : data.branch;
|
|
2781
|
+
return `\u{1F500} ${branch}`;
|
|
2782
|
+
},
|
|
2783
|
+
verbose: (data, colors) => {
|
|
2784
|
+
if (data.changes && data.changes.files > 0) {
|
|
2785
|
+
const parts = [];
|
|
2786
|
+
if (data.changes.insertions > 0) parts.push(`+${data.changes.insertions} insertions`);
|
|
2787
|
+
if (data.changes.deletions > 0) parts.push(`-${data.changes.deletions} deletions`);
|
|
2788
|
+
if (parts.length > 0) {
|
|
2789
|
+
const branch2 = colors ? colorize(data.branch, colors.branch) : data.branch;
|
|
2790
|
+
const changes = colors ? colorize(`[${parts.join(", ")}]`, colors.changes) : `[${parts.join(", ")}]`;
|
|
2791
|
+
return `branch: ${branch2} ${changes}`;
|
|
2792
|
+
}
|
|
1225
2793
|
}
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
2794
|
+
const branch = colors ? colorize(data.branch, colors.branch) : data.branch;
|
|
2795
|
+
return `branch: ${branch} (HEAD)`;
|
|
2796
|
+
},
|
|
2797
|
+
labeled: (data, colors) => {
|
|
2798
|
+
if (data.changes && data.changes.files > 0) {
|
|
2799
|
+
const parts = [];
|
|
2800
|
+
if (data.changes.insertions > 0) parts.push(`+${data.changes.insertions}`);
|
|
2801
|
+
if (data.changes.deletions > 0) parts.push(`-${data.changes.deletions}`);
|
|
2802
|
+
if (parts.length > 0) {
|
|
2803
|
+
const branch2 = colors ? colorize(data.branch, colors.branch) : data.branch;
|
|
2804
|
+
const changes = `${data.changes.files} files: ${parts.join("/")}`;
|
|
2805
|
+
return `Git: ${branch2} [${changes}]`;
|
|
2806
|
+
}
|
|
1236
2807
|
}
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
2808
|
+
const branch = colors ? colorize(data.branch, colors.branch) : data.branch;
|
|
2809
|
+
return `Git: ${branch}`;
|
|
2810
|
+
},
|
|
2811
|
+
indicator: (data, colors) => {
|
|
2812
|
+
if (data.changes && data.changes.files > 0) {
|
|
2813
|
+
const parts = [];
|
|
2814
|
+
if (data.changes.insertions > 0) parts.push(`+${data.changes.insertions}`);
|
|
2815
|
+
if (data.changes.deletions > 0) parts.push(`-${data.changes.deletions}`);
|
|
2816
|
+
if (parts.length > 0) {
|
|
2817
|
+
const branch = colors ? colorize(data.branch, colors.branch) : data.branch;
|
|
2818
|
+
const changes = colors ? colorize(`[${parts.join(" ")}]`, colors.changes) : `[${parts.join(" ")}]`;
|
|
2819
|
+
return `\u25CF ${branch} ${changes}`;
|
|
2820
|
+
}
|
|
1244
2821
|
}
|
|
1245
|
-
return
|
|
2822
|
+
return withIndicator(colors ? colorize(data.branch, colors.branch) : data.branch);
|
|
1246
2823
|
}
|
|
2824
|
+
};
|
|
2825
|
+
|
|
2826
|
+
// src/widgets/git/git-widget.ts
|
|
2827
|
+
var GitWidget = class {
|
|
2828
|
+
id = "git";
|
|
2829
|
+
metadata = createWidgetMetadata(
|
|
2830
|
+
"Git Widget",
|
|
2831
|
+
"Displays current git branch",
|
|
2832
|
+
"1.0.0",
|
|
2833
|
+
"claude-scope",
|
|
2834
|
+
0
|
|
2835
|
+
// First line
|
|
2836
|
+
);
|
|
2837
|
+
gitFactory;
|
|
2838
|
+
git = null;
|
|
2839
|
+
enabled = true;
|
|
2840
|
+
cwd = null;
|
|
2841
|
+
colors;
|
|
2842
|
+
styleFn = gitStyles.balanced;
|
|
1247
2843
|
/**
|
|
1248
|
-
*
|
|
2844
|
+
* @param gitFactory - Optional factory function for creating IGit instances
|
|
2845
|
+
* If not provided, uses default createGit (production)
|
|
2846
|
+
* Tests can inject MockGit factory here
|
|
2847
|
+
* @param colors - Optional theme colors
|
|
1249
2848
|
*/
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
2849
|
+
constructor(gitFactory, colors) {
|
|
2850
|
+
this.gitFactory = gitFactory || createGit;
|
|
2851
|
+
this.colors = colors ?? DEFAULT_THEME;
|
|
2852
|
+
}
|
|
2853
|
+
setStyle(style = "balanced") {
|
|
2854
|
+
const fn = gitStyles[style];
|
|
2855
|
+
if (fn) {
|
|
2856
|
+
this.styleFn = fn;
|
|
1253
2857
|
}
|
|
1254
|
-
return Object.keys(config.hooks).length;
|
|
1255
2858
|
}
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
async
|
|
1260
|
-
|
|
1261
|
-
|
|
2859
|
+
async initialize(context) {
|
|
2860
|
+
this.enabled = context.config?.enabled !== false;
|
|
2861
|
+
}
|
|
2862
|
+
async render(context) {
|
|
2863
|
+
if (!this.enabled || !this.git || !this.cwd) {
|
|
2864
|
+
return null;
|
|
2865
|
+
}
|
|
1262
2866
|
try {
|
|
1263
|
-
|
|
1264
|
-
const
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
2867
|
+
const status = await this.git.status();
|
|
2868
|
+
const branch = status.current || null;
|
|
2869
|
+
if (!branch) {
|
|
2870
|
+
return null;
|
|
2871
|
+
}
|
|
2872
|
+
let changes;
|
|
2873
|
+
try {
|
|
2874
|
+
const diffSummary = await this.git.diffSummary();
|
|
2875
|
+
if (diffSummary.fileCount > 0) {
|
|
2876
|
+
let insertions = 0;
|
|
2877
|
+
let deletions = 0;
|
|
2878
|
+
for (const file of diffSummary.files) {
|
|
2879
|
+
insertions += file.insertions || 0;
|
|
2880
|
+
deletions += file.deletions || 0;
|
|
2881
|
+
}
|
|
2882
|
+
if (insertions > 0 || deletions > 0) {
|
|
2883
|
+
changes = { files: diffSummary.fileCount, insertions, deletions };
|
|
2884
|
+
}
|
|
1271
2885
|
}
|
|
2886
|
+
} catch {
|
|
1272
2887
|
}
|
|
1273
|
-
|
|
2888
|
+
const renderData = { branch, changes };
|
|
2889
|
+
return this.styleFn(renderData, this.colors.git);
|
|
1274
2890
|
} catch {
|
|
1275
|
-
return
|
|
2891
|
+
return null;
|
|
2892
|
+
}
|
|
2893
|
+
}
|
|
2894
|
+
async update(data) {
|
|
2895
|
+
if (data.cwd !== this.cwd) {
|
|
2896
|
+
this.cwd = data.cwd;
|
|
2897
|
+
this.git = this.gitFactory(data.cwd);
|
|
1276
2898
|
}
|
|
1277
2899
|
}
|
|
2900
|
+
isEnabled() {
|
|
2901
|
+
return this.enabled;
|
|
2902
|
+
}
|
|
2903
|
+
async cleanup() {
|
|
2904
|
+
}
|
|
1278
2905
|
};
|
|
1279
2906
|
|
|
1280
|
-
// src/widgets/
|
|
1281
|
-
var
|
|
1282
|
-
balanced: (data) => {
|
|
1283
|
-
|
|
1284
|
-
const
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
}
|
|
1288
|
-
if (rulesCount > 0) {
|
|
1289
|
-
parts.push(`rules:${rulesCount}`);
|
|
1290
|
-
}
|
|
1291
|
-
if (mcpCount > 0) {
|
|
1292
|
-
parts.push(`MCPs:${mcpCount}`);
|
|
1293
|
-
}
|
|
1294
|
-
if (hooksCount > 0) {
|
|
1295
|
-
parts.push(`hooks:${hooksCount}`);
|
|
1296
|
-
}
|
|
1297
|
-
return parts.join(" \u2502 ");
|
|
2907
|
+
// src/widgets/lines/styles.ts
|
|
2908
|
+
var linesStyles = {
|
|
2909
|
+
balanced: (data, colors) => {
|
|
2910
|
+
if (!colors) return `+${data.added}/-${data.removed}`;
|
|
2911
|
+
const addedStr = colorize(`+${data.added}`, colors.added);
|
|
2912
|
+
const removedStr = colorize(`-${data.removed}`, colors.removed);
|
|
2913
|
+
return `${addedStr}/${removedStr}`;
|
|
1298
2914
|
},
|
|
1299
|
-
compact: (data) => {
|
|
1300
|
-
|
|
1301
|
-
const
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
}
|
|
1305
|
-
if (rulesCount > 0) {
|
|
1306
|
-
parts.push(`${rulesCount} rules`);
|
|
1307
|
-
}
|
|
1308
|
-
if (mcpCount > 0) {
|
|
1309
|
-
parts.push(`${mcpCount} MCPs`);
|
|
1310
|
-
}
|
|
1311
|
-
if (hooksCount > 0) {
|
|
1312
|
-
const hookLabel = hooksCount === 1 ? "hook" : "hooks";
|
|
1313
|
-
parts.push(`${hooksCount} ${hookLabel}`);
|
|
1314
|
-
}
|
|
1315
|
-
return parts.join(" \u2502 ");
|
|
2915
|
+
compact: (data, colors) => {
|
|
2916
|
+
if (!colors) return `+${data.added}-${data.removed}`;
|
|
2917
|
+
const addedStr = colorize(`+${data.added}`, colors.added);
|
|
2918
|
+
const removedStr = colorize(`-${data.removed}`, colors.removed);
|
|
2919
|
+
return `${addedStr}${removedStr}`;
|
|
1316
2920
|
},
|
|
1317
|
-
playful: (data) => {
|
|
1318
|
-
|
|
1319
|
-
const
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
}
|
|
1323
|
-
if (rulesCount > 0) {
|
|
1324
|
-
parts.push(`\u{1F4DC} rules:${rulesCount}`);
|
|
1325
|
-
}
|
|
1326
|
-
if (mcpCount > 0) {
|
|
1327
|
-
parts.push(`\u{1F50C} MCPs:${mcpCount}`);
|
|
1328
|
-
}
|
|
1329
|
-
if (hooksCount > 0) {
|
|
1330
|
-
parts.push(`\u{1FA9D} hooks:${hooksCount}`);
|
|
1331
|
-
}
|
|
1332
|
-
return parts.join(" \u2502 ");
|
|
2921
|
+
playful: (data, colors) => {
|
|
2922
|
+
if (!colors) return `\u2795${data.added} \u2796${data.removed}`;
|
|
2923
|
+
const addedStr = colorize(`\u2795${data.added}`, colors.added);
|
|
2924
|
+
const removedStr = colorize(`\u2796${data.removed}`, colors.removed);
|
|
2925
|
+
return `${addedStr} ${removedStr}`;
|
|
1333
2926
|
},
|
|
1334
|
-
verbose: (data) => {
|
|
1335
|
-
const { claudeMdCount, rulesCount, mcpCount, hooksCount } = data;
|
|
2927
|
+
verbose: (data, colors) => {
|
|
1336
2928
|
const parts = [];
|
|
1337
|
-
if (
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
if (rulesCount > 0) {
|
|
1341
|
-
parts.push(`${rulesCount} rules`);
|
|
2929
|
+
if (data.added > 0) {
|
|
2930
|
+
const text = `+${data.added} added`;
|
|
2931
|
+
parts.push(colors ? colorize(text, colors.added) : text);
|
|
1342
2932
|
}
|
|
1343
|
-
if (
|
|
1344
|
-
|
|
2933
|
+
if (data.removed > 0) {
|
|
2934
|
+
const text = `-${data.removed} removed`;
|
|
2935
|
+
parts.push(colors ? colorize(text, colors.removed) : text);
|
|
1345
2936
|
}
|
|
1346
|
-
|
|
1347
|
-
|
|
2937
|
+
return parts.join(", ");
|
|
2938
|
+
},
|
|
2939
|
+
labeled: (data, colors) => {
|
|
2940
|
+
const addedStr = colors ? colorize(`+${data.added}`, colors.added) : `+${data.added}`;
|
|
2941
|
+
const removedStr = colors ? colorize(`-${data.removed}`, colors.removed) : `-${data.removed}`;
|
|
2942
|
+
const lines = `${addedStr}/${removedStr}`;
|
|
2943
|
+
return withLabel("Lines", lines);
|
|
2944
|
+
},
|
|
2945
|
+
indicator: (data, colors) => {
|
|
2946
|
+
const addedStr = colors ? colorize(`+${data.added}`, colors.added) : `+${data.added}`;
|
|
2947
|
+
const removedStr = colors ? colorize(`-${data.removed}`, colors.removed) : `-${data.removed}`;
|
|
2948
|
+
const lines = `${addedStr}/${removedStr}`;
|
|
2949
|
+
return withIndicator(lines);
|
|
2950
|
+
}
|
|
2951
|
+
};
|
|
2952
|
+
|
|
2953
|
+
// src/widgets/lines-widget.ts
|
|
2954
|
+
var LinesWidget = class extends StdinDataWidget {
|
|
2955
|
+
id = "lines";
|
|
2956
|
+
metadata = createWidgetMetadata(
|
|
2957
|
+
"Lines",
|
|
2958
|
+
"Displays lines added/removed in session",
|
|
2959
|
+
"1.0.0",
|
|
2960
|
+
"claude-scope",
|
|
2961
|
+
0
|
|
2962
|
+
// First line
|
|
2963
|
+
);
|
|
2964
|
+
colors;
|
|
2965
|
+
styleFn = linesStyles.balanced;
|
|
2966
|
+
constructor(colors) {
|
|
2967
|
+
super();
|
|
2968
|
+
this.colors = colors ?? DEFAULT_THEME;
|
|
2969
|
+
}
|
|
2970
|
+
setStyle(style = "balanced") {
|
|
2971
|
+
const fn = linesStyles[style];
|
|
2972
|
+
if (fn) {
|
|
2973
|
+
this.styleFn = fn;
|
|
1348
2974
|
}
|
|
1349
|
-
|
|
2975
|
+
}
|
|
2976
|
+
renderWithData(data, _context) {
|
|
2977
|
+
const added = data.cost?.total_lines_added ?? 0;
|
|
2978
|
+
const removed = data.cost?.total_lines_removed ?? 0;
|
|
2979
|
+
const renderData = { added, removed };
|
|
2980
|
+
return this.styleFn(renderData, this.colors.lines);
|
|
1350
2981
|
}
|
|
1351
2982
|
};
|
|
1352
2983
|
|
|
1353
|
-
// src/
|
|
1354
|
-
|
|
2984
|
+
// src/widgets/model/styles.ts
|
|
2985
|
+
function getShortName(displayName) {
|
|
2986
|
+
return displayName.replace(/^Claude\s+/, "");
|
|
2987
|
+
}
|
|
2988
|
+
var modelStyles = {
|
|
2989
|
+
balanced: (data, colors) => {
|
|
2990
|
+
if (!colors) return data.displayName;
|
|
2991
|
+
return colorize(data.displayName, colors.name);
|
|
2992
|
+
},
|
|
2993
|
+
compact: (data, colors) => {
|
|
2994
|
+
const shortName = getShortName(data.displayName);
|
|
2995
|
+
if (!colors) return shortName;
|
|
2996
|
+
return colorize(shortName, colors.name);
|
|
2997
|
+
},
|
|
2998
|
+
playful: (data, colors) => {
|
|
2999
|
+
const shortName = getShortName(data.displayName);
|
|
3000
|
+
if (!colors) return `\u{1F916} ${shortName}`;
|
|
3001
|
+
return `\u{1F916} ${colorize(shortName, colors.name)}`;
|
|
3002
|
+
},
|
|
3003
|
+
technical: (data, colors) => {
|
|
3004
|
+
if (!colors) return data.id;
|
|
3005
|
+
const match = data.id.match(/^(.+?)-(\d[\d.]*)$/);
|
|
3006
|
+
if (match) {
|
|
3007
|
+
return colorize(match[1], colors.name) + colorize(`-${match[2]}`, colors.version);
|
|
3008
|
+
}
|
|
3009
|
+
return colorize(data.id, colors.name);
|
|
3010
|
+
},
|
|
3011
|
+
symbolic: (data, colors) => {
|
|
3012
|
+
const shortName = getShortName(data.displayName);
|
|
3013
|
+
if (!colors) return `\u25C6 ${shortName}`;
|
|
3014
|
+
return `\u25C6 ${colorize(shortName, colors.name)}`;
|
|
3015
|
+
},
|
|
3016
|
+
labeled: (data, colors) => {
|
|
3017
|
+
const shortName = getShortName(data.displayName);
|
|
3018
|
+
if (!colors) return withLabel("Model", shortName);
|
|
3019
|
+
return withLabel("Model", colorize(shortName, colors.name));
|
|
3020
|
+
},
|
|
3021
|
+
indicator: (data, colors) => {
|
|
3022
|
+
const shortName = getShortName(data.displayName);
|
|
3023
|
+
if (!colors) return withIndicator(shortName);
|
|
3024
|
+
return withIndicator(colorize(shortName, colors.name));
|
|
3025
|
+
}
|
|
3026
|
+
};
|
|
1355
3027
|
|
|
1356
|
-
// src/widgets/
|
|
1357
|
-
var
|
|
1358
|
-
id = "
|
|
3028
|
+
// src/widgets/model-widget.ts
|
|
3029
|
+
var ModelWidget = class extends StdinDataWidget {
|
|
3030
|
+
id = "model";
|
|
1359
3031
|
metadata = createWidgetMetadata(
|
|
1360
|
-
"
|
|
1361
|
-
"Displays Claude
|
|
3032
|
+
"Model",
|
|
3033
|
+
"Displays the current Claude model name",
|
|
1362
3034
|
"1.0.0",
|
|
1363
3035
|
"claude-scope",
|
|
1364
|
-
|
|
1365
|
-
//
|
|
3036
|
+
0
|
|
3037
|
+
// First line
|
|
1366
3038
|
);
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
3039
|
+
colors;
|
|
3040
|
+
styleFn = modelStyles.balanced;
|
|
3041
|
+
constructor(colors) {
|
|
3042
|
+
super();
|
|
3043
|
+
this.colors = colors ?? DEFAULT_THEME;
|
|
3044
|
+
}
|
|
3045
|
+
setStyle(style = "balanced") {
|
|
3046
|
+
const fn = modelStyles[style];
|
|
1373
3047
|
if (fn) {
|
|
1374
3048
|
this.styleFn = fn;
|
|
1375
3049
|
}
|
|
1376
3050
|
}
|
|
1377
|
-
|
|
1378
|
-
}
|
|
1379
|
-
async update(data) {
|
|
1380
|
-
this.cwd = data.cwd;
|
|
1381
|
-
this.configs = await this.configProvider.getConfigs({ cwd: data.cwd });
|
|
1382
|
-
}
|
|
1383
|
-
isEnabled() {
|
|
1384
|
-
if (!this.configs) {
|
|
1385
|
-
return false;
|
|
1386
|
-
}
|
|
1387
|
-
const { claudeMdCount, rulesCount, mcpCount, hooksCount } = this.configs;
|
|
1388
|
-
return claudeMdCount > 0 || rulesCount > 0 || mcpCount > 0 || hooksCount > 0;
|
|
1389
|
-
}
|
|
1390
|
-
async render(context) {
|
|
1391
|
-
if (!this.configs) {
|
|
1392
|
-
return null;
|
|
1393
|
-
}
|
|
1394
|
-
const { claudeMdCount, rulesCount, mcpCount, hooksCount } = this.configs;
|
|
3051
|
+
renderWithData(data, _context) {
|
|
1395
3052
|
const renderData = {
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
mcpCount,
|
|
1399
|
-
hooksCount
|
|
3053
|
+
displayName: data.model.display_name,
|
|
3054
|
+
id: data.model.id
|
|
1400
3055
|
};
|
|
1401
|
-
return this.styleFn(renderData);
|
|
1402
|
-
}
|
|
1403
|
-
async cleanup() {
|
|
3056
|
+
return this.styleFn(renderData, this.colors.model);
|
|
1404
3057
|
}
|
|
1405
3058
|
};
|
|
1406
3059
|
|
|
@@ -1952,8 +3605,8 @@ var PokerWidget = class extends StdinDataWidget {
|
|
|
1952
3605
|
"Displays random Texas Hold'em hands for entertainment",
|
|
1953
3606
|
"1.0.0",
|
|
1954
3607
|
"claude-scope",
|
|
1955
|
-
|
|
1956
|
-
//
|
|
3608
|
+
4
|
|
3609
|
+
// Fifth line (0-indexed)
|
|
1957
3610
|
);
|
|
1958
3611
|
holeCards = [];
|
|
1959
3612
|
boardCards = [];
|
|
@@ -2046,207 +3699,6 @@ var PokerWidget = class extends StdinDataWidget {
|
|
|
2046
3699
|
}
|
|
2047
3700
|
};
|
|
2048
3701
|
|
|
2049
|
-
// src/widgets/empty-line-widget.ts
|
|
2050
|
-
var EmptyLineWidget = class extends StdinDataWidget {
|
|
2051
|
-
id = "empty-line";
|
|
2052
|
-
metadata = createWidgetMetadata(
|
|
2053
|
-
"Empty Line",
|
|
2054
|
-
"Empty line separator",
|
|
2055
|
-
"1.0.0",
|
|
2056
|
-
"claude-scope",
|
|
2057
|
-
3
|
|
2058
|
-
// Fourth line (0-indexed)
|
|
2059
|
-
);
|
|
2060
|
-
/**
|
|
2061
|
-
* All styles return the same value (Braille Pattern Blank).
|
|
2062
|
-
* This method exists for API consistency with other widgets.
|
|
2063
|
-
*/
|
|
2064
|
-
setStyle(_style) {
|
|
2065
|
-
}
|
|
2066
|
-
/**
|
|
2067
|
-
* Return Braille Pattern Blank to create a visible empty separator line.
|
|
2068
|
-
* U+2800 occupies cell width but appears blank, ensuring the line renders.
|
|
2069
|
-
*/
|
|
2070
|
-
renderWithData(_data, _context) {
|
|
2071
|
-
return "\u2800";
|
|
2072
|
-
}
|
|
2073
|
-
};
|
|
2074
|
-
|
|
2075
|
-
// src/validation/result.ts
|
|
2076
|
-
function success(data) {
|
|
2077
|
-
return { success: true, data };
|
|
2078
|
-
}
|
|
2079
|
-
function failure(path2, message, value) {
|
|
2080
|
-
return { success: false, error: { path: path2, message, value } };
|
|
2081
|
-
}
|
|
2082
|
-
function formatError(error) {
|
|
2083
|
-
const path2 = error.path.length > 0 ? error.path.join(".") : "root";
|
|
2084
|
-
return `${path2}: ${error.message}`;
|
|
2085
|
-
}
|
|
2086
|
-
|
|
2087
|
-
// src/validation/validators.ts
|
|
2088
|
-
function string() {
|
|
2089
|
-
return {
|
|
2090
|
-
validate(value) {
|
|
2091
|
-
if (typeof value === "string") return success(value);
|
|
2092
|
-
return failure([], "Expected string", value);
|
|
2093
|
-
}
|
|
2094
|
-
};
|
|
2095
|
-
}
|
|
2096
|
-
function number() {
|
|
2097
|
-
return {
|
|
2098
|
-
validate(value) {
|
|
2099
|
-
if (typeof value === "number" && !Number.isNaN(value)) return success(value);
|
|
2100
|
-
return failure([], "Expected number", value);
|
|
2101
|
-
}
|
|
2102
|
-
};
|
|
2103
|
-
}
|
|
2104
|
-
function literal(expected) {
|
|
2105
|
-
return {
|
|
2106
|
-
validate(value) {
|
|
2107
|
-
if (value === expected) return success(expected);
|
|
2108
|
-
return failure([], `Expected '${expected}'`, value);
|
|
2109
|
-
}
|
|
2110
|
-
};
|
|
2111
|
-
}
|
|
2112
|
-
|
|
2113
|
-
// src/validation/combinators.ts
|
|
2114
|
-
function object(shape) {
|
|
2115
|
-
return {
|
|
2116
|
-
validate(value) {
|
|
2117
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
2118
|
-
return failure([], "Expected object", value);
|
|
2119
|
-
}
|
|
2120
|
-
const result = {};
|
|
2121
|
-
for (const [key, validator] of Object.entries(shape)) {
|
|
2122
|
-
const fieldValue = value[key];
|
|
2123
|
-
const validationResult = validator.validate(fieldValue);
|
|
2124
|
-
if (!validationResult.success) {
|
|
2125
|
-
return {
|
|
2126
|
-
success: false,
|
|
2127
|
-
error: { ...validationResult.error, path: [key, ...validationResult.error.path] }
|
|
2128
|
-
};
|
|
2129
|
-
}
|
|
2130
|
-
result[key] = validationResult.data;
|
|
2131
|
-
}
|
|
2132
|
-
return success(result);
|
|
2133
|
-
}
|
|
2134
|
-
};
|
|
2135
|
-
}
|
|
2136
|
-
function optional(validator) {
|
|
2137
|
-
return {
|
|
2138
|
-
validate(value) {
|
|
2139
|
-
if (value === void 0) return success(void 0);
|
|
2140
|
-
return validator.validate(value);
|
|
2141
|
-
}
|
|
2142
|
-
};
|
|
2143
|
-
}
|
|
2144
|
-
function nullable(validator) {
|
|
2145
|
-
return {
|
|
2146
|
-
validate(value) {
|
|
2147
|
-
if (value === null) return success(null);
|
|
2148
|
-
return validator.validate(value);
|
|
2149
|
-
}
|
|
2150
|
-
};
|
|
2151
|
-
}
|
|
2152
|
-
|
|
2153
|
-
// src/schemas/stdin-schema.ts
|
|
2154
|
-
var ContextUsageSchema = object({
|
|
2155
|
-
input_tokens: number(),
|
|
2156
|
-
output_tokens: number(),
|
|
2157
|
-
cache_creation_input_tokens: number(),
|
|
2158
|
-
cache_read_input_tokens: number()
|
|
2159
|
-
});
|
|
2160
|
-
var CostInfoSchema = object({
|
|
2161
|
-
total_cost_usd: optional(number()),
|
|
2162
|
-
total_duration_ms: optional(number()),
|
|
2163
|
-
total_api_duration_ms: optional(number()),
|
|
2164
|
-
total_lines_added: optional(number()),
|
|
2165
|
-
total_lines_removed: optional(number())
|
|
2166
|
-
});
|
|
2167
|
-
var ContextWindowSchema = object({
|
|
2168
|
-
total_input_tokens: number(),
|
|
2169
|
-
total_output_tokens: number(),
|
|
2170
|
-
context_window_size: number(),
|
|
2171
|
-
current_usage: nullable(ContextUsageSchema)
|
|
2172
|
-
});
|
|
2173
|
-
var ModelInfoSchema = object({
|
|
2174
|
-
id: string(),
|
|
2175
|
-
display_name: string()
|
|
2176
|
-
});
|
|
2177
|
-
var WorkspaceSchema = object({
|
|
2178
|
-
current_dir: string(),
|
|
2179
|
-
project_dir: string()
|
|
2180
|
-
});
|
|
2181
|
-
var OutputStyleSchema = object({
|
|
2182
|
-
name: string()
|
|
2183
|
-
});
|
|
2184
|
-
var StdinDataSchema = object({
|
|
2185
|
-
hook_event_name: optional(literal("Status")),
|
|
2186
|
-
session_id: string(),
|
|
2187
|
-
transcript_path: string(),
|
|
2188
|
-
cwd: string(),
|
|
2189
|
-
model: ModelInfoSchema,
|
|
2190
|
-
workspace: WorkspaceSchema,
|
|
2191
|
-
version: string(),
|
|
2192
|
-
output_style: OutputStyleSchema,
|
|
2193
|
-
cost: optional(CostInfoSchema),
|
|
2194
|
-
context_window: ContextWindowSchema
|
|
2195
|
-
});
|
|
2196
|
-
|
|
2197
|
-
// src/data/stdin-provider.ts
|
|
2198
|
-
var StdinParseError = class extends Error {
|
|
2199
|
-
constructor(message) {
|
|
2200
|
-
super(message);
|
|
2201
|
-
this.name = "StdinParseError";
|
|
2202
|
-
}
|
|
2203
|
-
};
|
|
2204
|
-
var StdinValidationError = class extends Error {
|
|
2205
|
-
constructor(message) {
|
|
2206
|
-
super(message);
|
|
2207
|
-
this.name = "StdinValidationError";
|
|
2208
|
-
}
|
|
2209
|
-
};
|
|
2210
|
-
var StdinProvider = class {
|
|
2211
|
-
/**
|
|
2212
|
-
* Parse and validate JSON string from stdin
|
|
2213
|
-
* @param input JSON string to parse
|
|
2214
|
-
* @returns Validated StdinData object
|
|
2215
|
-
* @throws StdinParseError if JSON is malformed
|
|
2216
|
-
* @throws StdinValidationError if data doesn't match schema
|
|
2217
|
-
*/
|
|
2218
|
-
async parse(input) {
|
|
2219
|
-
if (!input || input.trim().length === 0) {
|
|
2220
|
-
throw new StdinParseError("stdin data is empty");
|
|
2221
|
-
}
|
|
2222
|
-
let data;
|
|
2223
|
-
try {
|
|
2224
|
-
data = JSON.parse(input);
|
|
2225
|
-
} catch (error) {
|
|
2226
|
-
throw new StdinParseError(`Invalid JSON: ${error.message}`);
|
|
2227
|
-
}
|
|
2228
|
-
const result = StdinDataSchema.validate(data);
|
|
2229
|
-
if (!result.success) {
|
|
2230
|
-
throw new StdinValidationError(`Validation failed: ${formatError(result.error)}`);
|
|
2231
|
-
}
|
|
2232
|
-
return result.data;
|
|
2233
|
-
}
|
|
2234
|
-
/**
|
|
2235
|
-
* Safe parse that returns result instead of throwing
|
|
2236
|
-
* Useful for testing and optional validation
|
|
2237
|
-
* @param input JSON string to parse
|
|
2238
|
-
* @returns Result object with success flag
|
|
2239
|
-
*/
|
|
2240
|
-
async safeParse(input) {
|
|
2241
|
-
try {
|
|
2242
|
-
const data = await this.parse(input);
|
|
2243
|
-
return { success: true, data };
|
|
2244
|
-
} catch (error) {
|
|
2245
|
-
return { success: false, error: error.message };
|
|
2246
|
-
}
|
|
2247
|
-
}
|
|
2248
|
-
};
|
|
2249
|
-
|
|
2250
3702
|
// src/index.ts
|
|
2251
3703
|
async function readStdin() {
|
|
2252
3704
|
const chunks = [];
|
|
@@ -2265,6 +3717,7 @@ async function main() {
|
|
|
2265
3717
|
const provider = new StdinProvider();
|
|
2266
3718
|
const stdinData = await provider.parse(stdin);
|
|
2267
3719
|
const registry = new WidgetRegistry();
|
|
3720
|
+
const transcriptProvider = new TranscriptProvider();
|
|
2268
3721
|
await registry.register(new ModelWidget());
|
|
2269
3722
|
await registry.register(new ContextWidget());
|
|
2270
3723
|
await registry.register(new CostWidget());
|
|
@@ -2273,6 +3726,12 @@ async function main() {
|
|
|
2273
3726
|
await registry.register(new GitWidget());
|
|
2274
3727
|
await registry.register(new GitTagWidget());
|
|
2275
3728
|
await registry.register(new ConfigCountWidget());
|
|
3729
|
+
if (isWidgetEnabled("cacheMetrics")) {
|
|
3730
|
+
await registry.register(new CacheMetricsWidget(DEFAULT_THEME));
|
|
3731
|
+
}
|
|
3732
|
+
if (isWidgetEnabled("activeTools")) {
|
|
3733
|
+
await registry.register(new ActiveToolsWidget(DEFAULT_THEME, transcriptProvider));
|
|
3734
|
+
}
|
|
2276
3735
|
await registry.register(new PokerWidget());
|
|
2277
3736
|
await registry.register(new EmptyLineWidget());
|
|
2278
3737
|
const renderer = new Renderer({
|