claude-scope 0.8.44 → 0.8.46

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.
Files changed (2) hide show
  1. package/dist/claude-scope.cjs +270 -327
  2. package/package.json +1 -1
@@ -148,6 +148,10 @@ function createThemeColors(params) {
148
148
  disk: params.sysmonDisk,
149
149
  network: params.sysmonNetwork,
150
150
  separator: params.sysmonSeparator
151
+ },
152
+ configCount: {
153
+ label: params.configCountLabel ?? semantic.info,
154
+ separator: params.configCountSeparator ?? base.muted
151
155
  }
152
156
  };
153
157
  }
@@ -1553,7 +1557,7 @@ var init_theme = __esm({
1553
1557
  });
1554
1558
 
1555
1559
  // src/constants.ts
1556
- var TIME, DEFAULTS, ANSI_COLORS, DEMO_DATA, DEFAULT_PROGRESS_BAR_WIDTH;
1560
+ var TIME, DEFAULTS, DEMO_DATA;
1557
1561
  var init_constants = __esm({
1558
1562
  "src/constants.ts"() {
1559
1563
  "use strict";
@@ -1567,19 +1571,7 @@ var init_constants = __esm({
1567
1571
  };
1568
1572
  DEFAULTS = {
1569
1573
  /** Default separator between widgets */
1570
- SEPARATOR: " ",
1571
- /** Default width for progress bars in characters */
1572
- PROGRESS_BAR_WIDTH: 20
1573
- };
1574
- ANSI_COLORS = {
1575
- /** Green color */
1576
- GREEN: "\x1B[32m",
1577
- /** Yellow color */
1578
- YELLOW: "\x1B[33m",
1579
- /** Red color */
1580
- RED: "\x1B[31m",
1581
- /** Reset color */
1582
- RESET: "\x1B[0m"
1574
+ SEPARATOR: " "
1583
1575
  };
1584
1576
  DEMO_DATA = {
1585
1577
  /** Demo session cost in USD */
@@ -1607,7 +1599,6 @@ var init_constants = __esm({
1607
1599
  /** Demo cache read tokens */
1608
1600
  CACHE_READ_TOKENS: 15e3
1609
1601
  };
1610
- DEFAULT_PROGRESS_BAR_WIDTH = DEFAULTS.PROGRESS_BAR_WIDTH;
1611
1602
  }
1612
1603
  });
1613
1604
 
@@ -1902,6 +1893,22 @@ var init_mock_transcript_provider = __esm({
1902
1893
  }
1903
1894
  });
1904
1895
 
1896
+ // src/core/widget-types.ts
1897
+ function createWidgetMetadata(name, description, version = "1.0.0", author = "claude-scope", line = 0) {
1898
+ return {
1899
+ name,
1900
+ description,
1901
+ version,
1902
+ author,
1903
+ line
1904
+ };
1905
+ }
1906
+ var init_widget_types = __esm({
1907
+ "src/core/widget-types.ts"() {
1908
+ "use strict";
1909
+ }
1910
+ });
1911
+
1905
1912
  // src/widgets/core/stdin-data-widget.ts
1906
1913
  var StdinDataWidget;
1907
1914
  var init_stdin_data_widget = __esm({
@@ -1916,6 +1923,10 @@ var init_stdin_data_widget = __esm({
1916
1923
  * Widget enabled state
1917
1924
  */
1918
1925
  enabled = true;
1926
+ /**
1927
+ * Line override for dynamic positioning
1928
+ */
1929
+ _lineOverride;
1919
1930
  /**
1920
1931
  * Initialize widget with context
1921
1932
  * @param context - Widget initialization context
@@ -1962,6 +1973,20 @@ var init_stdin_data_widget = __esm({
1962
1973
  }
1963
1974
  return this.renderWithData(this.data, context);
1964
1975
  }
1976
+ /**
1977
+ * Set line override for dynamic positioning
1978
+ * @param line - Line number to position widget on
1979
+ */
1980
+ setLine(line) {
1981
+ this._lineOverride = line;
1982
+ }
1983
+ /**
1984
+ * Get effective line number (override or metadata default)
1985
+ * @returns Line number for widget positioning
1986
+ */
1987
+ getLine() {
1988
+ return this._lineOverride ?? this.metadata.line ?? 0;
1989
+ }
1965
1990
  };
1966
1991
  }
1967
1992
  });
@@ -2071,6 +2096,10 @@ function getDefaultColors() {
2071
2096
  disk: "\x1B[33m",
2072
2097
  network: "\x1B[32m",
2073
2098
  separator: "\x1B[90m"
2099
+ },
2100
+ configCount: {
2101
+ label: "\x1B[36m",
2102
+ separator: "\x1B[90m"
2074
2103
  }
2075
2104
  };
2076
2105
  }
@@ -2276,25 +2305,25 @@ var ActiveToolsWidget;
2276
2305
  var init_active_tools_widget = __esm({
2277
2306
  "src/widgets/active-tools/active-tools-widget.ts"() {
2278
2307
  "use strict";
2308
+ init_widget_types();
2279
2309
  init_stdin_data_widget();
2280
2310
  init_styles();
2281
2311
  ActiveToolsWidget = class extends StdinDataWidget {
2282
- constructor(theme, transcriptProvider) {
2312
+ constructor(colors2, transcriptProvider) {
2283
2313
  super();
2284
- this.theme = theme;
2314
+ this.colors = colors2;
2285
2315
  this.transcriptProvider = transcriptProvider;
2286
2316
  }
2287
2317
  id = "active-tools";
2288
- metadata = {
2289
- name: "Active Tools",
2290
- description: "Active tools display from transcript",
2291
- version: "1.0.0",
2292
- author: "claude-scope",
2293
- line: 2
2318
+ metadata = createWidgetMetadata(
2319
+ "Active Tools",
2320
+ "Active tools display from transcript",
2321
+ "1.0.0",
2322
+ "claude-scope",
2323
+ 2
2294
2324
  // Display on third line (0-indexed)
2295
- };
2296
- style = "balanced";
2297
- _lineOverride;
2325
+ );
2326
+ styleFn = activeToolsStyles.balanced;
2298
2327
  tools = [];
2299
2328
  renderData;
2300
2329
  /**
@@ -2302,13 +2331,10 @@ var init_active_tools_widget = __esm({
2302
2331
  * @param style - Style to use for rendering
2303
2332
  */
2304
2333
  setStyle(style) {
2305
- this.style = style;
2306
- }
2307
- setLine(line) {
2308
- this._lineOverride = line;
2309
- }
2310
- getLine() {
2311
- return this._lineOverride ?? this.metadata.line ?? 0;
2334
+ const fn = activeToolsStyles[style];
2335
+ if (fn) {
2336
+ this.styleFn = fn;
2337
+ }
2312
2338
  }
2313
2339
  /**
2314
2340
  * Aggregate completed tools by name and sort by count (descending)
@@ -2363,11 +2389,7 @@ var init_active_tools_widget = __esm({
2363
2389
  if (!this.renderData || this.tools.length === 0) {
2364
2390
  return null;
2365
2391
  }
2366
- const styleFn = activeToolsStyles[this.style] ?? activeToolsStyles.balanced;
2367
- if (!styleFn) {
2368
- return null;
2369
- }
2370
- return styleFn(this.renderData, this.theme);
2392
+ return this.styleFn(this.renderData, this.colors);
2371
2393
  }
2372
2394
  /**
2373
2395
  * Check if widget should render
@@ -2397,29 +2419,53 @@ var init_active_tools = __esm({
2397
2419
  }
2398
2420
  });
2399
2421
 
2400
- // src/core/widget-types.ts
2401
- function createWidgetMetadata(name, description, version = "1.0.0", author = "claude-scope", line = 0) {
2402
- return {
2403
- name,
2404
- description,
2405
- version,
2406
- author,
2407
- line
2408
- };
2422
+ // src/providers/jsonl-reader.ts
2423
+ async function readJsonlLines(filePath, options = {}) {
2424
+ if (!(0, import_node_fs.existsSync)(filePath)) {
2425
+ return [];
2426
+ }
2427
+ const lines = [];
2428
+ const fileStream = (0, import_node_fs.createReadStream)(filePath, {
2429
+ encoding: options.encoding ?? "utf-8"
2430
+ });
2431
+ const rl = (0, import_node_readline.createInterface)({
2432
+ input: fileStream,
2433
+ crlfDelay: Infinity
2434
+ });
2435
+ try {
2436
+ for await (const line of rl) {
2437
+ const trimmed = line.trim();
2438
+ if (trimmed) {
2439
+ lines.push(trimmed);
2440
+ }
2441
+ }
2442
+ return lines;
2443
+ } catch {
2444
+ return [];
2445
+ } finally {
2446
+ rl.close();
2447
+ fileStream.destroy();
2448
+ }
2409
2449
  }
2410
- var init_widget_types = __esm({
2411
- "src/core/widget-types.ts"() {
2450
+ var import_node_fs, import_node_readline;
2451
+ var init_jsonl_reader = __esm({
2452
+ "src/providers/jsonl-reader.ts"() {
2412
2453
  "use strict";
2454
+ import_node_fs = require("node:fs");
2455
+ import_node_readline = require("node:readline");
2413
2456
  }
2414
2457
  });
2415
2458
 
2416
2459
  // src/providers/usage-parser.ts
2417
- var import_fs, import_readline, UsageParser;
2460
+ function hasRealUsage(usage) {
2461
+ if (!usage) return false;
2462
+ return (usage.input_tokens ?? 0) > 0 || (usage.output_tokens ?? 0) > 0 || (usage.cache_read_input_tokens ?? 0) > 0 || (usage.cache_creation_input_tokens ?? 0) > 0;
2463
+ }
2464
+ var UsageParser;
2418
2465
  var init_usage_parser = __esm({
2419
2466
  "src/providers/usage-parser.ts"() {
2420
2467
  "use strict";
2421
- import_fs = require("fs");
2422
- import_readline = require("readline");
2468
+ init_jsonl_reader();
2423
2469
  UsageParser = class {
2424
2470
  /**
2425
2471
  * Parse the last assistant message with usage data from transcript
@@ -2429,11 +2475,11 @@ var init_usage_parser = __esm({
2429
2475
  * @returns ContextUsage or null if not found
2430
2476
  */
2431
2477
  async parseLastUsage(transcriptPath) {
2432
- if (!(0, import_fs.existsSync)(transcriptPath)) {
2433
- return null;
2434
- }
2435
2478
  try {
2436
- const lines = await this.readAllLines(transcriptPath);
2479
+ const lines = await readJsonlLines(transcriptPath);
2480
+ if (lines.length === 0) {
2481
+ return null;
2482
+ }
2437
2483
  let mostRecentUsage = null;
2438
2484
  let mostRecentTimestamp = null;
2439
2485
  let hasAnyTimestamp = false;
@@ -2470,27 +2516,6 @@ var init_usage_parser = __esm({
2470
2516
  }
2471
2517
  return null;
2472
2518
  }
2473
- /**
2474
- * Read all lines from transcript file
2475
- */
2476
- async readAllLines(transcriptPath) {
2477
- const lines = [];
2478
- try {
2479
- const fileStream = (0, import_fs.createReadStream)(transcriptPath, { encoding: "utf-8" });
2480
- const rl = (0, import_readline.createInterface)({
2481
- input: fileStream,
2482
- crlfDelay: Infinity
2483
- });
2484
- for await (const line of rl) {
2485
- if (line.trim()) {
2486
- lines.push(line);
2487
- }
2488
- }
2489
- } catch {
2490
- return [];
2491
- }
2492
- return lines;
2493
- }
2494
2519
  /**
2495
2520
  * Parse cumulative cache tokens from all assistant messages in transcript
2496
2521
  *
@@ -2502,11 +2527,11 @@ var init_usage_parser = __esm({
2502
2527
  * @returns Object with cumulative cacheRead and cacheCreation, or null if not found
2503
2528
  */
2504
2529
  async parseCumulativeCache(transcriptPath) {
2505
- if (!(0, import_fs.existsSync)(transcriptPath)) {
2506
- return null;
2507
- }
2508
2530
  try {
2509
- const lines = await this.readAllLines(transcriptPath);
2531
+ const lines = await readJsonlLines(transcriptPath);
2532
+ if (lines.length === 0) {
2533
+ return null;
2534
+ }
2510
2535
  const cacheEntries = [];
2511
2536
  for (const line of lines) {
2512
2537
  const entry = this.parseLineForCache(line);
@@ -2621,11 +2646,11 @@ var init_usage_parser = __esm({
2621
2646
  });
2622
2647
 
2623
2648
  // src/storage/cache-manager.ts
2624
- var import_node_fs, import_node_os2, import_node_path2, DEFAULT_CACHE_PATH, DEFAULT_EXPIRY_MS, CacheManager;
2649
+ var import_node_fs2, import_node_os2, import_node_path2, DEFAULT_CACHE_PATH, DEFAULT_EXPIRY_MS, CacheManager;
2625
2650
  var init_cache_manager = __esm({
2626
2651
  "src/storage/cache-manager.ts"() {
2627
2652
  "use strict";
2628
- import_node_fs = require("node:fs");
2653
+ import_node_fs2 = require("node:fs");
2629
2654
  import_node_os2 = require("node:os");
2630
2655
  import_node_path2 = require("node:path");
2631
2656
  DEFAULT_CACHE_PATH = `${(0, import_node_os2.homedir)()}/.config/claude-scope/cache.json`;
@@ -2698,11 +2723,11 @@ var init_cache_manager = __esm({
2698
2723
  * Load cache from file
2699
2724
  */
2700
2725
  loadCache() {
2701
- if (!(0, import_node_fs.existsSync)(this.cachePath)) {
2726
+ if (!(0, import_node_fs2.existsSync)(this.cachePath)) {
2702
2727
  return { sessions: {}, version: 1 };
2703
2728
  }
2704
2729
  try {
2705
- const content = (0, import_node_fs.readFileSync)(this.cachePath, "utf-8");
2730
+ const content = (0, import_node_fs2.readFileSync)(this.cachePath, "utf-8");
2706
2731
  return JSON.parse(content);
2707
2732
  } catch {
2708
2733
  return { sessions: {}, version: 1 };
@@ -2713,7 +2738,7 @@ var init_cache_manager = __esm({
2713
2738
  */
2714
2739
  saveCache(cache) {
2715
2740
  try {
2716
- (0, import_node_fs.writeFileSync)(this.cachePath, JSON.stringify(cache, null, 2), "utf-8");
2741
+ (0, import_node_fs2.writeFileSync)(this.cachePath, JSON.stringify(cache, null, 2), "utf-8");
2717
2742
  } catch {
2718
2743
  }
2719
2744
  }
@@ -2723,8 +2748,8 @@ var init_cache_manager = __esm({
2723
2748
  ensureCacheDir() {
2724
2749
  try {
2725
2750
  const dir = (0, import_node_path2.dirname)(this.cachePath);
2726
- if (!(0, import_node_fs.existsSync)(dir)) {
2727
- (0, import_node_fs.mkdirSync)(dir, { recursive: true });
2751
+ if (!(0, import_node_fs2.existsSync)(dir)) {
2752
+ (0, import_node_fs2.mkdirSync)(dir, { recursive: true });
2728
2753
  }
2729
2754
  } catch {
2730
2755
  }
@@ -2756,9 +2781,6 @@ function formatDuration(ms) {
2756
2781
  function formatCostUSD(usd) {
2757
2782
  return `$${usd.toFixed(2)}`;
2758
2783
  }
2759
- function colorize2(text, color) {
2760
- return `${color}${text}${ANSI_COLORS.RESET}`;
2761
- }
2762
2784
  function formatK(n) {
2763
2785
  const absN = Math.abs(n);
2764
2786
  if (absN < 1e3) {
@@ -2887,9 +2909,8 @@ var init_cache_metrics_widget = __esm({
2887
2909
  2
2888
2910
  // Third line
2889
2911
  );
2890
- theme;
2891
- _lineOverride;
2892
- style = "balanced";
2912
+ colors;
2913
+ styleFn = cacheMetricsStyles.balanced;
2893
2914
  renderData;
2894
2915
  cacheManager;
2895
2916
  usageParser;
@@ -2898,9 +2919,9 @@ var init_cache_metrics_widget = __esm({
2898
2919
  // Cache parsed usage within render cycle
2899
2920
  cachedCumulativeCache;
2900
2921
  // Cumulative cache for session
2901
- constructor(theme) {
2922
+ constructor(colors2) {
2902
2923
  super();
2903
- this.theme = theme ?? DEFAULT_THEME;
2924
+ this.colors = colors2 ?? DEFAULT_THEME;
2904
2925
  this.cacheManager = new CacheManager();
2905
2926
  this.usageParser = new UsageParser();
2906
2927
  }
@@ -2908,13 +2929,10 @@ var init_cache_metrics_widget = __esm({
2908
2929
  * Set display style
2909
2930
  */
2910
2931
  setStyle(style) {
2911
- this.style = style;
2912
- }
2913
- setLine(line) {
2914
- this._lineOverride = line;
2915
- }
2916
- getLine() {
2917
- return this._lineOverride ?? this.metadata.line ?? 0;
2932
+ const fn = cacheMetricsStyles[style];
2933
+ if (fn) {
2934
+ this.styleFn = fn;
2935
+ }
2918
2936
  }
2919
2937
  /**
2920
2938
  * Calculate cache metrics from context usage data
@@ -2964,8 +2982,7 @@ var init_cache_metrics_widget = __esm({
2964
2982
  this.lastSessionId = sessionId;
2965
2983
  const usage = data.context_window?.current_usage;
2966
2984
  if (usage && !sessionChanged && sessionId) {
2967
- const hasAnyTokens = (usage.input_tokens ?? 0) > 0 || (usage.output_tokens ?? 0) > 0 || (usage.cache_creation_input_tokens ?? 0) > 0 || (usage.cache_read_input_tokens ?? 0) > 0;
2968
- if (hasAnyTokens) {
2985
+ if (hasRealUsage(usage)) {
2969
2986
  this.cacheManager.setCachedUsage(sessionId, {
2970
2987
  input_tokens: usage.input_tokens,
2971
2988
  output_tokens: usage.output_tokens,
@@ -2974,9 +2991,8 @@ var init_cache_metrics_widget = __esm({
2974
2991
  });
2975
2992
  }
2976
2993
  }
2977
- const hasRealUsage = usage && ((usage.input_tokens ?? 0) > 0 || (usage.output_tokens ?? 0) > 0 || (usage.cache_read_input_tokens ?? 0) > 0 || (usage.cache_creation_input_tokens ?? 0) > 0);
2978
2994
  const transcriptPath = data.transcript_path;
2979
- if (!usage || !hasRealUsage) {
2995
+ if (!hasRealUsage(usage)) {
2980
2996
  if (transcriptPath) {
2981
2997
  this.cachedUsage = await this.usageParser.parseLastUsage(transcriptPath);
2982
2998
  }
@@ -2992,8 +3008,7 @@ var init_cache_metrics_widget = __esm({
2992
3008
  */
2993
3009
  renderWithData(data, _context) {
2994
3010
  let usage = data.context_window?.current_usage;
2995
- const hasRealUsage = usage && ((usage.input_tokens ?? 0) > 0 || (usage.output_tokens ?? 0) > 0 || (usage.cache_read_input_tokens ?? 0) > 0 || (usage.cache_creation_input_tokens ?? 0) > 0);
2996
- if ((!usage || !hasRealUsage) && this.cachedUsage) {
3011
+ if (!hasRealUsage(usage) && this.cachedUsage) {
2997
3012
  usage = this.cachedUsage;
2998
3013
  }
2999
3014
  if (!usage && data.session_id) {
@@ -3008,11 +3023,7 @@ var init_cache_metrics_widget = __esm({
3008
3023
  return null;
3009
3024
  }
3010
3025
  this.renderData = metrics;
3011
- const styleFn = cacheMetricsStyles[this.style] ?? cacheMetricsStyles.balanced;
3012
- if (!styleFn) {
3013
- return null;
3014
- }
3015
- return styleFn(this.renderData, this.theme);
3026
+ return this.styleFn(this.renderData, this.colors);
3016
3027
  }
3017
3028
  /**
3018
3029
  * Widget is always enabled (shows zeros when no data)
@@ -3230,98 +3241,90 @@ var init_styles3 = __esm({
3230
3241
  balanced: (data, colors2) => {
3231
3242
  const { claudeMdCount, rulesCount, mcpCount, hooksCount } = data;
3232
3243
  const parts = [];
3233
- const info = colors2?.semantic.info ?? "";
3234
- const muted = colors2?.base.muted ?? "";
3235
3244
  if (claudeMdCount > 0) {
3236
- const label = info ? colorize("CLAUDE.md", info) : "CLAUDE.md";
3245
+ const label = colors2 ? colorize("CLAUDE.md", colors2.label) : "CLAUDE.md";
3237
3246
  parts.push(`${label}:${claudeMdCount}`);
3238
3247
  }
3239
3248
  if (rulesCount > 0) {
3240
- const label = info ? colorize("rules", info) : "rules";
3249
+ const label = colors2 ? colorize("rules", colors2.label) : "rules";
3241
3250
  parts.push(`${label}:${rulesCount}`);
3242
3251
  }
3243
3252
  if (mcpCount > 0) {
3244
- const label = info ? colorize("MCPs", info) : "MCPs";
3253
+ const label = colors2 ? colorize("MCPs", colors2.label) : "MCPs";
3245
3254
  parts.push(`${label}:${mcpCount}`);
3246
3255
  }
3247
3256
  if (hooksCount > 0) {
3248
- const label = info ? colorize("hooks", info) : "hooks";
3257
+ const label = colors2 ? colorize("hooks", colors2.label) : "hooks";
3249
3258
  parts.push(`${label}:${hooksCount}`);
3250
3259
  }
3251
- const sep = muted ? colorize(" \u2502 ", muted) : " \u2502 ";
3260
+ const sep = colors2 ? colorize(" \u2502 ", colors2.separator) : " \u2502 ";
3252
3261
  return parts.join(sep);
3253
3262
  },
3254
3263
  compact: (data, colors2) => {
3255
3264
  const { claudeMdCount, rulesCount, mcpCount, hooksCount } = data;
3256
3265
  const parts = [];
3257
- const info = colors2?.semantic.info ?? "";
3258
- const muted = colors2?.base.muted ?? "";
3259
3266
  if (claudeMdCount > 0) {
3260
- const text = info ? colorize(`${claudeMdCount} docs`, info) : `${claudeMdCount} docs`;
3267
+ const text = colors2 ? colorize(`${claudeMdCount} docs`, colors2.label) : `${claudeMdCount} docs`;
3261
3268
  parts.push(text);
3262
3269
  }
3263
3270
  if (rulesCount > 0) {
3264
- const text = info ? colorize(`${rulesCount} rules`, info) : `${rulesCount} rules`;
3271
+ const text = colors2 ? colorize(`${rulesCount} rules`, colors2.label) : `${rulesCount} rules`;
3265
3272
  parts.push(text);
3266
3273
  }
3267
3274
  if (mcpCount > 0) {
3268
- const text = info ? colorize(`${mcpCount} MCPs`, info) : `${mcpCount} MCPs`;
3275
+ const text = colors2 ? colorize(`${mcpCount} MCPs`, colors2.label) : `${mcpCount} MCPs`;
3269
3276
  parts.push(text);
3270
3277
  }
3271
3278
  if (hooksCount > 0) {
3272
3279
  const hookLabel = hooksCount === 1 ? "hook" : "hooks";
3273
- const text = info ? colorize(`${hooksCount} ${hookLabel}`, info) : `${hooksCount} ${hookLabel}`;
3280
+ const text = colors2 ? colorize(`${hooksCount} ${hookLabel}`, colors2.label) : `${hooksCount} ${hookLabel}`;
3274
3281
  parts.push(text);
3275
3282
  }
3276
- const sep = muted ? colorize(" \u2502 ", muted) : " \u2502 ";
3283
+ const sep = colors2 ? colorize(" \u2502 ", colors2.separator) : " \u2502 ";
3277
3284
  return parts.join(sep);
3278
3285
  },
3279
3286
  playful: (data, colors2) => {
3280
3287
  const { claudeMdCount, rulesCount, mcpCount, hooksCount } = data;
3281
3288
  const parts = [];
3282
- const info = colors2?.semantic.info ?? "";
3283
- const muted = colors2?.base.muted ?? "";
3284
3289
  if (claudeMdCount > 0) {
3285
- const text = info ? colorize(`CLAUDE.md:${claudeMdCount}`, info) : `CLAUDE.md:${claudeMdCount}`;
3290
+ const text = colors2 ? colorize(`CLAUDE.md:${claudeMdCount}`, colors2.label) : `CLAUDE.md:${claudeMdCount}`;
3286
3291
  parts.push(`\u{1F4C4} ${text}`);
3287
3292
  }
3288
3293
  if (rulesCount > 0) {
3289
- const text = info ? colorize(`rules:${rulesCount}`, info) : `rules:${rulesCount}`;
3294
+ const text = colors2 ? colorize(`rules:${rulesCount}`, colors2.label) : `rules:${rulesCount}`;
3290
3295
  parts.push(`\u{1F4DC} ${text}`);
3291
3296
  }
3292
3297
  if (mcpCount > 0) {
3293
- const text = info ? colorize(`MCPs:${mcpCount}`, info) : `MCPs:${mcpCount}`;
3298
+ const text = colors2 ? colorize(`MCPs:${mcpCount}`, colors2.label) : `MCPs:${mcpCount}`;
3294
3299
  parts.push(`\u{1F50C} ${text}`);
3295
3300
  }
3296
3301
  if (hooksCount > 0) {
3297
- const text = info ? colorize(`hooks:${hooksCount}`, info) : `hooks:${hooksCount}`;
3302
+ const text = colors2 ? colorize(`hooks:${hooksCount}`, colors2.label) : `hooks:${hooksCount}`;
3298
3303
  parts.push(`\u{1FA9D} ${text}`);
3299
3304
  }
3300
- const sep = muted ? colorize(" \u2502 ", muted) : " \u2502 ";
3305
+ const sep = colors2 ? colorize(" \u2502 ", colors2.separator) : " \u2502 ";
3301
3306
  return parts.join(sep);
3302
3307
  },
3303
3308
  verbose: (data, colors2) => {
3304
3309
  const { claudeMdCount, rulesCount, mcpCount, hooksCount } = data;
3305
3310
  const parts = [];
3306
- const info = colors2?.semantic.info ?? "";
3307
- const muted = colors2?.base.muted ?? "";
3308
3311
  if (claudeMdCount > 0) {
3309
- const text = info ? colorize(`${claudeMdCount} CLAUDE.md`, info) : `${claudeMdCount} CLAUDE.md`;
3312
+ const text = colors2 ? colorize(`${claudeMdCount} CLAUDE.md`, colors2.label) : `${claudeMdCount} CLAUDE.md`;
3310
3313
  parts.push(text);
3311
3314
  }
3312
3315
  if (rulesCount > 0) {
3313
- const text = info ? colorize(`${rulesCount} rules`, info) : `${rulesCount} rules`;
3316
+ const text = colors2 ? colorize(`${rulesCount} rules`, colors2.label) : `${rulesCount} rules`;
3314
3317
  parts.push(text);
3315
3318
  }
3316
3319
  if (mcpCount > 0) {
3317
- const text = info ? colorize(`${mcpCount} MCP servers`, info) : `${mcpCount} MCP servers`;
3320
+ const text = colors2 ? colorize(`${mcpCount} MCP servers`, colors2.label) : `${mcpCount} MCP servers`;
3318
3321
  parts.push(text);
3319
3322
  }
3320
3323
  if (hooksCount > 0) {
3321
- const text = info ? colorize(`${hooksCount} hooks`, info) : `${hooksCount} hooks`;
3324
+ const text = colors2 ? colorize(`${hooksCount} hooks`, colors2.label) : `${hooksCount} hooks`;
3322
3325
  parts.push(text);
3323
3326
  }
3324
- const sep = muted ? colorize(" \u2502 ", muted) : " \u2502 ";
3327
+ const sep = colors2 ? colorize(" \u2502 ", colors2.separator) : " \u2502 ";
3325
3328
  return parts.join(sep);
3326
3329
  }
3327
3330
  };
@@ -3350,13 +3353,13 @@ var init_config_count_widget = __esm({
3350
3353
  );
3351
3354
  configProvider;
3352
3355
  configs;
3353
- cwd;
3354
- themeColors;
3355
- _lineOverride;
3356
+ colors;
3357
+ enabled = true;
3356
3358
  styleFn = configCountStyles.balanced;
3357
- constructor(configProvider, themeColors) {
3359
+ _lineOverride;
3360
+ constructor(configProvider, colors2) {
3358
3361
  this.configProvider = configProvider ?? new ConfigProvider();
3359
- this.themeColors = themeColors ?? DEFAULT_THEME;
3362
+ this.colors = colors2 ?? DEFAULT_THEME;
3360
3363
  }
3361
3364
  setStyle(style = DEFAULT_WIDGET_STYLE) {
3362
3365
  const fn = configCountStyles[style];
@@ -3364,20 +3367,14 @@ var init_config_count_widget = __esm({
3364
3367
  this.styleFn = fn;
3365
3368
  }
3366
3369
  }
3367
- setLine(line) {
3368
- this._lineOverride = line;
3369
- }
3370
- getLine() {
3371
- return this._lineOverride ?? this.metadata.line ?? 0;
3372
- }
3373
- async initialize() {
3370
+ async initialize(context) {
3371
+ this.enabled = context.config?.enabled !== false;
3374
3372
  }
3375
3373
  async update(data) {
3376
- this.cwd = data.cwd;
3377
3374
  this.configs = await this.configProvider.getConfigs({ cwd: data.cwd });
3378
3375
  }
3379
3376
  isEnabled() {
3380
- if (!this.configs) {
3377
+ if (!this.enabled || !this.configs) {
3381
3378
  return false;
3382
3379
  }
3383
3380
  const { claudeMdCount, rulesCount, mcpCount, hooksCount } = this.configs;
@@ -3392,12 +3389,15 @@ var init_config_count_widget = __esm({
3392
3389
  claudeMdCount,
3393
3390
  rulesCount,
3394
3391
  mcpCount,
3395
- hooksCount,
3396
- colors: this.themeColors
3392
+ hooksCount
3397
3393
  };
3398
- return this.styleFn(renderData, this.themeColors);
3394
+ return this.styleFn(renderData, this.colors.configCount);
3395
+ }
3396
+ setLine(line) {
3397
+ this._lineOverride = line;
3399
3398
  }
3400
- async cleanup() {
3399
+ getLine() {
3400
+ return this._lineOverride ?? this.metadata.line ?? 0;
3401
3401
  }
3402
3402
  };
3403
3403
  }
@@ -3493,6 +3493,7 @@ var ContextWidget;
3493
3493
  var init_context_widget = __esm({
3494
3494
  "src/widgets/context-widget.ts"() {
3495
3495
  "use strict";
3496
+ init_style_types();
3496
3497
  init_widget_types();
3497
3498
  init_usage_parser();
3498
3499
  init_cache_manager();
@@ -3510,7 +3511,6 @@ var init_context_widget = __esm({
3510
3511
  // First line
3511
3512
  );
3512
3513
  colors;
3513
- _lineOverride;
3514
3514
  styleFn = contextStyles.balanced;
3515
3515
  cacheManager;
3516
3516
  usageParser;
@@ -3523,18 +3523,12 @@ var init_context_widget = __esm({
3523
3523
  this.cacheManager = new CacheManager();
3524
3524
  this.usageParser = new UsageParser();
3525
3525
  }
3526
- setStyle(style = "balanced") {
3526
+ setStyle(style = DEFAULT_WIDGET_STYLE) {
3527
3527
  const fn = contextStyles[style];
3528
3528
  if (fn) {
3529
3529
  this.styleFn = fn;
3530
3530
  }
3531
3531
  }
3532
- setLine(line) {
3533
- this._lineOverride = line;
3534
- }
3535
- getLine() {
3536
- return this._lineOverride ?? this.metadata.line ?? 0;
3537
- }
3538
3532
  /**
3539
3533
  * Update widget with new data, storing valid values in cache
3540
3534
  */
@@ -3549,8 +3543,7 @@ var init_context_widget = __esm({
3549
3543
  this.lastSessionId = sessionId;
3550
3544
  const { current_usage } = contextWindow;
3551
3545
  if (current_usage && !sessionChanged && sessionId) {
3552
- const hasAnyTokens = (current_usage.input_tokens ?? 0) > 0 || (current_usage.output_tokens ?? 0) > 0 || (current_usage.cache_creation_input_tokens ?? 0) > 0 || (current_usage.cache_read_input_tokens ?? 0) > 0;
3553
- if (hasAnyTokens) {
3546
+ if (hasRealUsage(current_usage)) {
3554
3547
  this.cacheManager.setCachedUsage(sessionId, {
3555
3548
  input_tokens: current_usage.input_tokens,
3556
3549
  output_tokens: current_usage.output_tokens,
@@ -3559,8 +3552,7 @@ var init_context_widget = __esm({
3559
3552
  });
3560
3553
  }
3561
3554
  }
3562
- const hasRealUsage = current_usage && ((current_usage.input_tokens ?? 0) > 0 || (current_usage.output_tokens ?? 0) > 0 || (current_usage.cache_read_input_tokens ?? 0) > 0 || (current_usage.cache_creation_input_tokens ?? 0) > 0);
3563
- if (!current_usage || !hasRealUsage) {
3555
+ if (!hasRealUsage(current_usage)) {
3564
3556
  const transcriptPath = data.transcript_path;
3565
3557
  if (transcriptPath) {
3566
3558
  this.cachedUsage = await this.usageParser.parseLastUsage(transcriptPath);
@@ -3584,8 +3576,7 @@ var init_context_widget = __esm({
3584
3576
  return this.styleFn(renderData2, this.colors.context);
3585
3577
  }
3586
3578
  let usage = current_usage;
3587
- const hasRealUsage = usage && ((usage.input_tokens ?? 0) > 0 || (usage.output_tokens ?? 0) > 0 || (usage.cache_read_input_tokens ?? 0) > 0 || (usage.cache_creation_input_tokens ?? 0) > 0);
3588
- if ((!usage || !hasRealUsage) && this.cachedUsage) {
3579
+ if (!hasRealUsage(usage) && this.cachedUsage) {
3589
3580
  usage = this.cachedUsage;
3590
3581
  }
3591
3582
  if (!usage && data.session_id) {
@@ -3666,6 +3657,7 @@ var CostWidget;
3666
3657
  var init_cost_widget = __esm({
3667
3658
  "src/widgets/cost-widget.ts"() {
3668
3659
  "use strict";
3660
+ init_style_types();
3669
3661
  init_widget_types();
3670
3662
  init_theme();
3671
3663
  init_stdin_data_widget();
@@ -3681,24 +3673,17 @@ var init_cost_widget = __esm({
3681
3673
  // First line
3682
3674
  );
3683
3675
  colors;
3684
- _lineOverride;
3685
3676
  styleFn = costStyles.balanced;
3686
3677
  constructor(colors2) {
3687
3678
  super();
3688
3679
  this.colors = colors2 ?? DEFAULT_THEME;
3689
3680
  }
3690
- setStyle(style = "balanced") {
3681
+ setStyle(style = DEFAULT_WIDGET_STYLE) {
3691
3682
  const fn = costStyles[style];
3692
3683
  if (fn) {
3693
3684
  this.styleFn = fn;
3694
3685
  }
3695
3686
  }
3696
- setLine(line) {
3697
- this._lineOverride = line;
3698
- }
3699
- getLine() {
3700
- return this._lineOverride ?? this.metadata.line ?? 0;
3701
- }
3702
3687
  renderWithData(data, _context) {
3703
3688
  if (!data.cost || data.cost.total_cost_usd === void 0) return null;
3704
3689
  if (data.cost.total_cost_usd === 0) return null;
@@ -3905,6 +3890,7 @@ var DevServerWidget;
3905
3890
  var init_dev_server_widget = __esm({
3906
3891
  "src/widgets/dev-server/dev-server-widget.ts"() {
3907
3892
  "use strict";
3893
+ init_style_types();
3908
3894
  init_widget_types();
3909
3895
  init_theme();
3910
3896
  init_port_detector();
@@ -3935,7 +3921,7 @@ var init_dev_server_widget = __esm({
3935
3921
  * Set display style
3936
3922
  * @param style - Style to use for rendering
3937
3923
  */
3938
- setStyle(style = "balanced") {
3924
+ setStyle(style = DEFAULT_WIDGET_STYLE) {
3939
3925
  const fn = devServerStyles[style];
3940
3926
  if (fn) {
3941
3927
  this.styleFn = fn;
@@ -3976,11 +3962,6 @@ var init_dev_server_widget = __esm({
3976
3962
  isEnabled() {
3977
3963
  return this.enabled;
3978
3964
  }
3979
- /**
3980
- * Cleanup resources
3981
- */
3982
- async cleanup() {
3983
- }
3984
3965
  /**
3985
3966
  * Render widget output
3986
3967
  * @param context - Render context
@@ -4096,6 +4077,7 @@ var init_docker_widget = __esm({
4096
4077
  "use strict";
4097
4078
  import_node_child_process3 = require("node:child_process");
4098
4079
  import_node_util3 = require("node:util");
4080
+ init_style_types();
4099
4081
  init_widget_types();
4100
4082
  init_theme();
4101
4083
  init_styles7();
@@ -4119,7 +4101,7 @@ var init_docker_widget = __esm({
4119
4101
  constructor(colors2) {
4120
4102
  this.colors = colors2 ?? DEFAULT_THEME;
4121
4103
  }
4122
- setStyle(style = "balanced") {
4104
+ setStyle(style = DEFAULT_WIDGET_STYLE) {
4123
4105
  const fn = dockerStyles[style];
4124
4106
  if (fn) {
4125
4107
  this.styleFn = fn;
@@ -4139,8 +4121,6 @@ var init_docker_widget = __esm({
4139
4121
  isEnabled() {
4140
4122
  return this.enabled;
4141
4123
  }
4142
- async cleanup() {
4143
- }
4144
4124
  async render(_context) {
4145
4125
  if (!this.enabled) {
4146
4126
  return null;
@@ -4279,6 +4259,7 @@ var DurationWidget;
4279
4259
  var init_duration_widget = __esm({
4280
4260
  "src/widgets/duration-widget.ts"() {
4281
4261
  "use strict";
4262
+ init_style_types();
4282
4263
  init_widget_types();
4283
4264
  init_theme();
4284
4265
  init_stdin_data_widget();
@@ -4294,24 +4275,17 @@ var init_duration_widget = __esm({
4294
4275
  // First line
4295
4276
  );
4296
4277
  colors;
4297
- _lineOverride;
4298
4278
  styleFn = durationStyles.balanced;
4299
4279
  constructor(colors2) {
4300
4280
  super();
4301
4281
  this.colors = colors2 ?? DEFAULT_THEME;
4302
4282
  }
4303
- setStyle(style = "balanced") {
4283
+ setStyle(style = DEFAULT_WIDGET_STYLE) {
4304
4284
  const fn = durationStyles[style];
4305
4285
  if (fn) {
4306
4286
  this.styleFn = fn;
4307
4287
  }
4308
4288
  }
4309
- setLine(line) {
4310
- this._lineOverride = line;
4311
- }
4312
- getLine() {
4313
- return this._lineOverride ?? this.metadata.line ?? 0;
4314
- }
4315
4289
  renderWithData(data, _context) {
4316
4290
  if (!data.cost || data.cost.total_duration_ms === void 0) return null;
4317
4291
  if (data.cost.total_duration_ms === 0) return null;
@@ -4396,36 +4370,29 @@ var init_styles9 = __esm({
4396
4370
  init_style_utils();
4397
4371
  gitTagStyles = {
4398
4372
  balanced: (data, colors2) => {
4399
- const tag = data.tag || "\u2014";
4400
- if (!colors2) return tag;
4401
- return colorize(tag, colors2.branch);
4373
+ if (!colors2) return data.tag;
4374
+ return colorize(data.tag, colors2.branch);
4402
4375
  },
4403
4376
  compact: (data, colors2) => {
4404
- if (!data.tag) return "\u2014";
4405
4377
  const tag = data.tag.replace(/^v/, "");
4406
4378
  if (!colors2) return tag;
4407
4379
  return colorize(tag, colors2.branch);
4408
4380
  },
4409
4381
  playful: (data, colors2) => {
4410
- const tag = data.tag || "\u2014";
4411
- if (!colors2) return `\u{1F3F7}\uFE0F ${tag}`;
4412
- return `\u{1F3F7}\uFE0F ${colorize(tag, colors2.branch)}`;
4382
+ if (!colors2) return `\u{1F3F7}\uFE0F ${data.tag}`;
4383
+ return `\u{1F3F7}\uFE0F ${colorize(data.tag, colors2.branch)}`;
4413
4384
  },
4414
4385
  verbose: (data, colors2) => {
4415
- if (!data.tag) return "version: none";
4416
- const tag = `version ${data.tag}`;
4417
- if (!colors2) return tag;
4386
+ if (!colors2) return `version ${data.tag}`;
4418
4387
  return `version ${colorize(data.tag, colors2.branch)}`;
4419
4388
  },
4420
4389
  labeled: (data, colors2) => {
4421
- const tag = data.tag || "none";
4422
- if (!colors2) return withLabel("Tag", tag);
4423
- return withLabel("Tag", colorize(tag, colors2.branch));
4390
+ if (!colors2) return withLabel("Tag", data.tag);
4391
+ return withLabel("Tag", colorize(data.tag, colors2.branch));
4424
4392
  },
4425
4393
  indicator: (data, colors2) => {
4426
- const tag = data.tag || "\u2014";
4427
- if (!colors2) return withIndicator(tag);
4428
- return withIndicator(colorize(tag, colors2.branch));
4394
+ if (!colors2) return withIndicator(data.tag);
4395
+ return withIndicator(colorize(data.tag, colors2.branch));
4429
4396
  }
4430
4397
  };
4431
4398
  }
@@ -4436,6 +4403,7 @@ var GitTagWidget;
4436
4403
  var init_git_tag_widget = __esm({
4437
4404
  "src/widgets/git/git-tag-widget.ts"() {
4438
4405
  "use strict";
4406
+ init_style_types();
4439
4407
  init_widget_types();
4440
4408
  init_git_provider();
4441
4409
  init_theme();
@@ -4467,7 +4435,7 @@ var init_git_tag_widget = __esm({
4467
4435
  this.gitFactory = gitFactory || createGit;
4468
4436
  this.colors = colors2 ?? DEFAULT_THEME;
4469
4437
  }
4470
- setStyle(style = "balanced") {
4438
+ setStyle(style = DEFAULT_WIDGET_STYLE) {
4471
4439
  const fn = gitTagStyles[style];
4472
4440
  if (fn) {
4473
4441
  this.styleFn = fn;
@@ -4488,6 +4456,9 @@ var init_git_tag_widget = __esm({
4488
4456
  }
4489
4457
  try {
4490
4458
  const latestTag = await (this.git.latestTag?.() ?? Promise.resolve(null));
4459
+ if (!latestTag) {
4460
+ return null;
4461
+ }
4491
4462
  const renderData = { tag: latestTag };
4492
4463
  return this.styleFn(renderData, this.colors.git);
4493
4464
  } catch {
@@ -4503,8 +4474,6 @@ var init_git_tag_widget = __esm({
4503
4474
  isEnabled() {
4504
4475
  return this.enabled;
4505
4476
  }
4506
- async cleanup() {
4507
- }
4508
4477
  };
4509
4478
  }
4510
4479
  });
@@ -4610,6 +4579,7 @@ var GitWidget;
4610
4579
  var init_git_widget = __esm({
4611
4580
  "src/widgets/git/git-widget.ts"() {
4612
4581
  "use strict";
4582
+ init_style_types();
4613
4583
  init_widget_types();
4614
4584
  init_git_provider();
4615
4585
  init_theme();
@@ -4641,7 +4611,7 @@ var init_git_widget = __esm({
4641
4611
  this.gitFactory = gitFactory || createGit;
4642
4612
  this.colors = colors2 ?? DEFAULT_THEME;
4643
4613
  }
4644
- setStyle(style = "balanced") {
4614
+ setStyle(style = DEFAULT_WIDGET_STYLE) {
4645
4615
  const fn = gitStyles[style];
4646
4616
  if (fn) {
4647
4617
  this.styleFn = fn;
@@ -4697,8 +4667,6 @@ var init_git_widget = __esm({
4697
4667
  isEnabled() {
4698
4668
  return this.enabled;
4699
4669
  }
4700
- async cleanup() {
4701
- }
4702
4670
  };
4703
4671
  }
4704
4672
  });
@@ -4762,6 +4730,7 @@ var LinesWidget;
4762
4730
  var init_lines_widget = __esm({
4763
4731
  "src/widgets/lines-widget.ts"() {
4764
4732
  "use strict";
4733
+ init_style_types();
4765
4734
  init_widget_types();
4766
4735
  init_theme();
4767
4736
  init_stdin_data_widget();
@@ -4777,24 +4746,17 @@ var init_lines_widget = __esm({
4777
4746
  // First line
4778
4747
  );
4779
4748
  colors;
4780
- _lineOverride;
4781
4749
  styleFn = linesStyles.balanced;
4782
4750
  constructor(colors2) {
4783
4751
  super();
4784
4752
  this.colors = colors2 ?? DEFAULT_THEME;
4785
4753
  }
4786
- setStyle(style = "balanced") {
4754
+ setStyle(style = DEFAULT_WIDGET_STYLE) {
4787
4755
  const fn = linesStyles[style];
4788
4756
  if (fn) {
4789
4757
  this.styleFn = fn;
4790
4758
  }
4791
4759
  }
4792
- setLine(line) {
4793
- this._lineOverride = line;
4794
- }
4795
- getLine() {
4796
- return this._lineOverride ?? this.metadata.line ?? 0;
4797
- }
4798
4760
  renderWithData(data, _context) {
4799
4761
  const added = data.cost?.total_lines_added ?? 0;
4800
4762
  const removed = data.cost?.total_lines_removed ?? 0;
@@ -4863,6 +4825,7 @@ var ModelWidget;
4863
4825
  var init_model_widget = __esm({
4864
4826
  "src/widgets/model-widget.ts"() {
4865
4827
  "use strict";
4828
+ init_style_types();
4866
4829
  init_widget_types();
4867
4830
  init_theme();
4868
4831
  init_stdin_data_widget();
@@ -4878,24 +4841,17 @@ var init_model_widget = __esm({
4878
4841
  // First line
4879
4842
  );
4880
4843
  colors;
4881
- _lineOverride;
4882
4844
  styleFn = modelStyles.balanced;
4883
4845
  constructor(colors2) {
4884
4846
  super();
4885
4847
  this.colors = colors2 ?? DEFAULT_THEME;
4886
4848
  }
4887
- setStyle(style = "balanced") {
4849
+ setStyle(style = DEFAULT_WIDGET_STYLE) {
4888
4850
  const fn = modelStyles[style];
4889
4851
  if (fn) {
4890
4852
  this.styleFn = fn;
4891
4853
  }
4892
4854
  }
4893
- setLine(line) {
4894
- this._lineOverride = line;
4895
- }
4896
- getLine() {
4897
- return this._lineOverride ?? this.metadata.line ?? 0;
4898
- }
4899
4855
  renderWithData(data, _context) {
4900
4856
  if (!data.model) {
4901
4857
  return null;
@@ -26443,8 +26399,7 @@ init_renderer();
26443
26399
  init_widget_registry();
26444
26400
 
26445
26401
  // src/providers/transcript-provider.ts
26446
- var import_node_fs2 = require("node:fs");
26447
- var import_node_readline = require("node:readline");
26402
+ init_jsonl_reader();
26448
26403
  var TranscriptProvider = class {
26449
26404
  MAX_TOOLS = 20;
26450
26405
  /**
@@ -26453,29 +26408,17 @@ var TranscriptProvider = class {
26453
26408
  * @returns Array of tool entries, limited to last 20
26454
26409
  */
26455
26410
  async parseTools(transcriptPath) {
26456
- if (!(0, import_node_fs2.existsSync)(transcriptPath)) {
26457
- return [];
26458
- }
26411
+ const lines = await readJsonlLines(transcriptPath);
26459
26412
  const toolMap = /* @__PURE__ */ new Map();
26460
- try {
26461
- const fileStream = (0, import_node_fs2.createReadStream)(transcriptPath, { encoding: "utf-8" });
26462
- const rl = (0, import_node_readline.createInterface)({
26463
- input: fileStream,
26464
- crlfDelay: Infinity
26465
- });
26466
- for await (const line of rl) {
26467
- if (!line.trim()) continue;
26468
- try {
26469
- const entry = JSON.parse(line);
26470
- this.processLine(entry, toolMap);
26471
- } catch {
26472
- }
26413
+ for (const line of lines) {
26414
+ try {
26415
+ const entry = JSON.parse(line);
26416
+ this.processLine(entry, toolMap);
26417
+ } catch {
26473
26418
  }
26474
- const tools = Array.from(toolMap.values());
26475
- return tools.slice(-this.MAX_TOOLS);
26476
- } catch {
26477
- return [];
26478
26419
  }
26420
+ const tools = Array.from(toolMap.values());
26421
+ return tools.slice(-this.MAX_TOOLS);
26479
26422
  }
26480
26423
  /**
26481
26424
  * Process a single transcript line and update tool map
@@ -26556,6 +26499,7 @@ init_lines_widget();
26556
26499
  init_model_widget();
26557
26500
 
26558
26501
  // src/widgets/sysmon-widget.ts
26502
+ init_style_types();
26559
26503
  init_widget_types();
26560
26504
  init_theme();
26561
26505
 
@@ -26626,9 +26570,9 @@ var SysmonWidget = class {
26626
26570
  );
26627
26571
  colors;
26628
26572
  provider;
26629
- _lineOverride;
26630
26573
  styleFn = sysmonStyles.balanced;
26631
26574
  enabled = true;
26575
+ _lineOverride;
26632
26576
  constructor(colors2, provider) {
26633
26577
  this.colors = colors2 ?? DEFAULT_THEME;
26634
26578
  this.provider = provider ?? null;
@@ -26651,9 +26595,7 @@ var SysmonWidget = class {
26651
26595
  isEnabled() {
26652
26596
  return this.enabled && this.provider !== null;
26653
26597
  }
26654
- async cleanup() {
26655
- }
26656
- setStyle(style = "balanced") {
26598
+ setStyle(style = DEFAULT_WIDGET_STYLE) {
26657
26599
  const fn = sysmonStyles[style];
26658
26600
  if (fn) {
26659
26601
  this.styleFn = fn;
@@ -26663,7 +26605,7 @@ var SysmonWidget = class {
26663
26605
  this._lineOverride = line;
26664
26606
  }
26665
26607
  getLine() {
26666
- return this._lineOverride ?? this.metadata.line ?? 2;
26608
+ return this._lineOverride ?? this.metadata.line ?? 0;
26667
26609
  }
26668
26610
  };
26669
26611
 
@@ -26778,13 +26720,10 @@ async function loadSystemInformation() {
26778
26720
  }
26779
26721
  }
26780
26722
  var NETWORK_STATS_FILE = "/tmp/claude-scope-network-stats.json";
26781
- function loadNetworkStatsSync() {
26723
+ async function loadNetworkStats() {
26782
26724
  try {
26783
- const fs2 = require("node:fs");
26784
- if (!fs2.existsSync(NETWORK_STATS_FILE)) {
26785
- return /* @__PURE__ */ new Map();
26786
- }
26787
- const text = fs2.readFileSync(NETWORK_STATS_FILE, "utf-8");
26725
+ const fs2 = await import("node:fs/promises");
26726
+ const text = await fs2.readFile(NETWORK_STATS_FILE, "utf-8");
26788
26727
  const data = JSON.parse(text);
26789
26728
  if (Date.now() - data.lastUpdate > 5 * 60 * 1e3) {
26790
26729
  return /* @__PURE__ */ new Map();
@@ -26799,34 +26738,50 @@ function loadNetworkStatsSync() {
26799
26738
  return /* @__PURE__ */ new Map();
26800
26739
  }
26801
26740
  }
26802
- function saveNetworkStatsSync(stats) {
26803
- try {
26804
- const fs2 = require("node:fs");
26805
- const data = {
26806
- stats: Object.fromEntries(stats),
26807
- lastUpdate: Date.now()
26808
- };
26809
- fs2.writeFileSync(NETWORK_STATS_FILE, JSON.stringify(data), "utf-8");
26810
- } catch {
26741
+ var pendingSave = null;
26742
+ var pendingSaveData = null;
26743
+ async function saveNetworkStats(stats) {
26744
+ pendingSaveData = stats;
26745
+ if (pendingSave) {
26746
+ return;
26811
26747
  }
26748
+ pendingSave = (async () => {
26749
+ await new Promise((resolve) => setImmediate(resolve));
26750
+ if (!pendingSaveData) {
26751
+ pendingSave = null;
26752
+ return;
26753
+ }
26754
+ try {
26755
+ const fs2 = await import("node:fs/promises");
26756
+ const data = {
26757
+ stats: Object.fromEntries(pendingSaveData),
26758
+ lastUpdate: Date.now()
26759
+ };
26760
+ await fs2.writeFile(NETWORK_STATS_FILE, JSON.stringify(data), "utf-8");
26761
+ } catch {
26762
+ } finally {
26763
+ pendingSave = null;
26764
+ pendingSaveData = null;
26765
+ }
26766
+ })();
26812
26767
  }
26813
26768
  var SystemProvider = class {
26814
26769
  intervalId;
26815
- lastNetworkStats;
26770
+ lastNetworkStats = /* @__PURE__ */ new Map();
26816
26771
  lastErrorTime = 0;
26817
26772
  ERROR_LOG_INTERVAL = 6e4;
26818
26773
  // 1 minute
26819
26774
  initialized = false;
26820
- statsLoaded = false;
26821
- constructor() {
26822
- this.lastNetworkStats = loadNetworkStatsSync();
26823
- this.statsLoaded = true;
26824
- }
26775
+ networkStatsLoaded = false;
26825
26776
  async ensureInitialized() {
26826
26777
  if (!this.initialized) {
26827
26778
  await loadSystemInformation();
26828
26779
  this.initialized = true;
26829
26780
  }
26781
+ if (!this.networkStatsLoaded) {
26782
+ this.lastNetworkStats = await loadNetworkStats();
26783
+ this.networkStatsLoaded = true;
26784
+ }
26830
26785
  }
26831
26786
  async getMetrics() {
26832
26787
  await this.ensureInitialized();
@@ -26851,7 +26806,7 @@ var SystemProvider = class {
26851
26806
  const diskTotalGB = mainFs.size / 1024 / 1024 / 1024;
26852
26807
  const diskPercent = Math.round(mainFs.use);
26853
26808
  const iface = Array.isArray(net) && net.length > 0 ? net[0] : net;
26854
- const networkSpeed = this.calculateNetworkSpeed(iface);
26809
+ const networkSpeed = await this.calculateNetworkSpeed(iface);
26855
26810
  return {
26856
26811
  cpu: { percent: cpuPercent },
26857
26812
  memory: {
@@ -26891,7 +26846,7 @@ var SystemProvider = class {
26891
26846
  this.intervalId = void 0;
26892
26847
  }
26893
26848
  }
26894
- calculateNetworkSpeed(iface) {
26849
+ async calculateNetworkSpeed(iface) {
26895
26850
  if (!iface || iface.iface === void 0) {
26896
26851
  return { rxSec: 0, txSec: 0 };
26897
26852
  }
@@ -26904,7 +26859,7 @@ var SystemProvider = class {
26904
26859
  tx: iface.tx_bytes,
26905
26860
  time: now
26906
26861
  });
26907
- saveNetworkStatsSync(this.lastNetworkStats);
26862
+ saveNetworkStats(this.lastNetworkStats);
26908
26863
  return { rxSec: 0, txSec: 0 };
26909
26864
  }
26910
26865
  const timeDiff = Math.max(0.1, (now - last.time) / 1e3);
@@ -26917,7 +26872,7 @@ var SystemProvider = class {
26917
26872
  tx: iface.tx_bytes,
26918
26873
  time: now
26919
26874
  });
26920
- saveNetworkStatsSync(this.lastNetworkStats);
26875
+ saveNetworkStats(this.lastNetworkStats);
26921
26876
  return {
26922
26877
  rxSec: Math.max(0, Number(rx_sec.toFixed(2))),
26923
26878
  txSec: Math.max(0, Number(tx_sec.toFixed(2)))
@@ -26964,19 +26919,12 @@ var EmptyLineWidget = class extends StdinDataWidget {
26964
26919
  5
26965
26920
  // Sixth line (0-indexed)
26966
26921
  );
26967
- _lineOverride;
26968
26922
  /**
26969
26923
  * All styles return the same value (Braille Pattern Blank).
26970
26924
  * This method exists for API consistency with other widgets.
26971
26925
  */
26972
26926
  setStyle(_style) {
26973
26927
  }
26974
- setLine(line) {
26975
- this._lineOverride = line;
26976
- }
26977
- getLine() {
26978
- return this._lineOverride ?? this.metadata.line ?? 0;
26979
- }
26980
26928
  /**
26981
26929
  * Return Braille Pattern Blank to create a visible empty separator line.
26982
26930
  * U+2800 occupies cell width but appears blank, ensuring the line renders.
@@ -27222,7 +27170,6 @@ function getStraightFlushHighCard(cards, suit) {
27222
27170
  return getStraightHighCard(suitCards);
27223
27171
  }
27224
27172
  function getStraightFlushIndices(cards, highCard, suit) {
27225
- const _suitCards = cards.filter((c) => c.suit === suit);
27226
27173
  const suitCardIndices = [];
27227
27174
  const indexMap = /* @__PURE__ */ new Map();
27228
27175
  for (let i = 0; i < cards.length; i++) {
@@ -27434,7 +27381,6 @@ function evaluateHand(hole, board) {
27434
27381
 
27435
27382
  // src/widgets/poker/styles.ts
27436
27383
  init_colors();
27437
- init_formatters();
27438
27384
  var HAND_ABBREVIATIONS = {
27439
27385
  "Royal Flush": "RF",
27440
27386
  "Straight Flush": "SF",
@@ -27493,7 +27439,7 @@ function formatHandResult(handResult, colors2) {
27493
27439
  const playerParticipates = handResult.participatingIndices.some((idx) => idx < 2);
27494
27440
  const resultText = !playerParticipates ? `Nothing \u{1F0CF}` : `${handResult.name}! ${handResult.emoji}`;
27495
27441
  if (!colors2) return resultText;
27496
- return colorize2(resultText, colors2.result);
27442
+ return colorize(resultText, colors2.result);
27497
27443
  }
27498
27444
  function getHandAbbreviation(handResult) {
27499
27445
  if (!handResult) {
@@ -27508,8 +27454,8 @@ function balancedStyle2(data, colors2) {
27508
27454
  const handStr = holeCards.map((hc, idx) => formatCardByParticipation(hc, participatingSet.has(idx))).join("");
27509
27455
  const boardStr = boardCards.map((bc, idx) => formatCardByParticipation(bc, participatingSet.has(idx + 2))).join("");
27510
27456
  const labelColor = colors2?.participating ?? lightGray;
27511
- const handLabel = colorize2("Hand:", labelColor);
27512
- const boardLabel = colorize2("Board:", labelColor);
27457
+ const handLabel = colorize("Hand:", labelColor);
27458
+ const boardLabel = colorize("Board:", labelColor);
27513
27459
  return `${handLabel} ${handStr}| ${boardLabel} ${boardStr}\u2192 ${formatHandResult(handResult, colors2)}`;
27514
27460
  }
27515
27461
  var pokerStyles = {
@@ -27524,7 +27470,7 @@ var pokerStyles = {
27524
27470
  const abbreviation = getHandAbbreviation(handResult);
27525
27471
  const result2 = `${handStr}| ${boardStr}\u2192 ${abbreviation}`;
27526
27472
  if (!colors2) return result2;
27527
- return colorize2(result2, colors2.result);
27473
+ return colorize(result2, colors2.result);
27528
27474
  },
27529
27475
  emoji: (data, colors2) => {
27530
27476
  const { holeCards, boardCards, handResult } = data;
@@ -27532,8 +27478,8 @@ var pokerStyles = {
27532
27478
  const handStr = holeCards.map((hc, idx) => formatCardEmojiByParticipation(hc, participatingSet.has(idx))).join("");
27533
27479
  const boardStr = boardCards.map((bc, idx) => formatCardEmojiByParticipation(bc, participatingSet.has(idx + 2))).join("");
27534
27480
  const labelColor = colors2?.participating ?? lightGray;
27535
- const handLabel = colorize2("Hand:", labelColor);
27536
- const boardLabel = colorize2("Board:", labelColor);
27481
+ const handLabel = colorize("Hand:", labelColor);
27482
+ const boardLabel = colorize("Board:", labelColor);
27537
27483
  return `${handLabel} ${handStr}| ${boardLabel} ${boardStr}\u2192 ${formatHandResult(handResult, colors2)}`;
27538
27484
  }
27539
27485
  };
@@ -27556,7 +27502,6 @@ var PokerWidget = class extends StdinDataWidget {
27556
27502
  THROTTLE_MS = 5e3;
27557
27503
  // 5 seconds
27558
27504
  colors;
27559
- _lineOverride;
27560
27505
  styleFn = pokerStyles.balanced;
27561
27506
  setStyle(style = DEFAULT_WIDGET_STYLE) {
27562
27507
  const fn = pokerStyles[style];
@@ -27564,12 +27509,6 @@ var PokerWidget = class extends StdinDataWidget {
27564
27509
  this.styleFn = fn;
27565
27510
  }
27566
27511
  }
27567
- setLine(line) {
27568
- this._lineOverride = line;
27569
- }
27570
- getLine() {
27571
- return this._lineOverride ?? this.metadata.line ?? 0;
27572
- }
27573
27512
  constructor(colors2) {
27574
27513
  super();
27575
27514
  this.colors = colors2 ?? DEFAULT_THEME;
@@ -27613,7 +27552,6 @@ var PokerWidget = class extends StdinDataWidget {
27613
27552
  * Format card with appropriate color (red for ♥♦, gray for ♠♣)
27614
27553
  */
27615
27554
  formatCardColor(card) {
27616
- const _color = isRedSuit(card.suit) ? "red" : "gray";
27617
27555
  return formatCard(card);
27618
27556
  }
27619
27557
  renderWithData(_data, _context) {
@@ -27651,9 +27589,14 @@ var PokerWidget = class extends StdinDataWidget {
27651
27589
  var WidgetFactory = class {
27652
27590
  transcriptProvider;
27653
27591
  systemProvider;
27654
- constructor() {
27592
+ theme;
27593
+ /**
27594
+ * @param theme - Optional theme colors. Defaults to DEFAULT_THEME (Monokai).
27595
+ */
27596
+ constructor(theme) {
27655
27597
  this.transcriptProvider = new TranscriptProvider();
27656
27598
  this.systemProvider = new SystemProvider();
27599
+ this.theme = theme ?? DEFAULT_THEME;
27657
27600
  }
27658
27601
  /**
27659
27602
  * Create a widget instance by ID
@@ -27663,33 +27606,33 @@ var WidgetFactory = class {
27663
27606
  createWidget(widgetId) {
27664
27607
  switch (widgetId) {
27665
27608
  case "model":
27666
- return new ModelWidget();
27609
+ return new ModelWidget(this.theme);
27667
27610
  case "context":
27668
- return new ContextWidget();
27611
+ return new ContextWidget(this.theme);
27669
27612
  case "cost":
27670
- return new CostWidget();
27613
+ return new CostWidget(this.theme);
27671
27614
  case "lines":
27672
- return new LinesWidget();
27615
+ return new LinesWidget(this.theme);
27673
27616
  case "duration":
27674
- return new DurationWidget();
27617
+ return new DurationWidget(this.theme);
27675
27618
  case "git":
27676
- return new GitWidget();
27619
+ return new GitWidget(void 0, this.theme);
27677
27620
  case "git-tag":
27678
- return new GitTagWidget();
27621
+ return new GitTagWidget(void 0, this.theme);
27679
27622
  case "config-count":
27680
- return new ConfigCountWidget();
27623
+ return new ConfigCountWidget(void 0, this.theme);
27681
27624
  case "cache-metrics":
27682
- return new CacheMetricsWidget(DEFAULT_THEME);
27625
+ return new CacheMetricsWidget(this.theme);
27683
27626
  case "active-tools":
27684
- return new ActiveToolsWidget(DEFAULT_THEME, this.transcriptProvider);
27627
+ return new ActiveToolsWidget(this.theme, this.transcriptProvider);
27685
27628
  case "dev-server":
27686
- return new DevServerWidget(DEFAULT_THEME);
27629
+ return new DevServerWidget(this.theme);
27687
27630
  case "docker":
27688
- return new DockerWidget(DEFAULT_THEME);
27631
+ return new DockerWidget(this.theme);
27689
27632
  case "poker":
27690
- return new PokerWidget(DEFAULT_THEME);
27633
+ return new PokerWidget(this.theme);
27691
27634
  case "sysmon":
27692
- return new SysmonWidget(DEFAULT_THEME, this.systemProvider);
27635
+ return new SysmonWidget(this.theme, this.systemProvider);
27693
27636
  case "empty-line":
27694
27637
  return new EmptyLineWidget();
27695
27638
  default:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-scope",
3
- "version": "0.8.44",
3
+ "version": "0.8.46",
4
4
  "description": "Claude Code plugin for session status and analytics",
5
5
  "license": "MIT",
6
6
  "type": "module",