claude-scope 0.8.4 → 0.8.6

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 +229 -753
  2. package/package.json +7 -7
@@ -38,15 +38,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
38
38
  function colorize(text, color) {
39
39
  return `${color}${text}${reset}`;
40
40
  }
41
- var reset, red, gray, lightGray, bold;
41
+ var reset, gray;
42
42
  var init_colors = __esm({
43
43
  "src/ui/utils/colors.ts"() {
44
44
  "use strict";
45
45
  reset = "\x1B[0m";
46
- red = "\x1B[31m";
47
46
  gray = "\x1B[90m";
48
- lightGray = "\x1B[37m";
49
- bold = "\x1B[1m";
50
47
  }
51
48
  });
52
49
 
@@ -1139,7 +1136,7 @@ var init_theme = __esm({
1139
1136
  });
1140
1137
 
1141
1138
  // src/constants.ts
1142
- var TIME, DEFAULTS, ANSI_COLORS, DEMO_DATA, DEFAULT_PROGRESS_BAR_WIDTH;
1139
+ var TIME, DEFAULTS, DEMO_DATA, DEFAULT_PROGRESS_BAR_WIDTH;
1143
1140
  var init_constants = __esm({
1144
1141
  "src/constants.ts"() {
1145
1142
  "use strict";
@@ -1157,16 +1154,6 @@ var init_constants = __esm({
1157
1154
  /** Default width for progress bars in characters */
1158
1155
  PROGRESS_BAR_WIDTH: 20
1159
1156
  };
1160
- ANSI_COLORS = {
1161
- /** Green color */
1162
- GREEN: "\x1B[32m",
1163
- /** Yellow color */
1164
- YELLOW: "\x1B[33m",
1165
- /** Red color */
1166
- RED: "\x1B[31m",
1167
- /** Reset color */
1168
- RESET: "\x1B[0m"
1169
- };
1170
1157
  DEMO_DATA = {
1171
1158
  /** Demo session cost in USD */
1172
1159
  COST_USD: 0.42,
@@ -1229,7 +1216,7 @@ var init_renderer = __esm({
1229
1216
  if (!widget.isEnabled()) {
1230
1217
  continue;
1231
1218
  }
1232
- const line = widget.metadata.line ?? 0;
1219
+ const line = widget.getLine ? widget.getLine() : widget.metadata.line ?? 0;
1233
1220
  if (!lineMap.has(line)) {
1234
1221
  lineMap.set(line, []);
1235
1222
  }
@@ -1355,6 +1342,28 @@ var init_widget_registry = __esm({
1355
1342
  }
1356
1343
  });
1357
1344
 
1345
+ // src/providers/mock-config-provider.ts
1346
+ var MockConfigProvider;
1347
+ var init_mock_config_provider = __esm({
1348
+ "src/providers/mock-config-provider.ts"() {
1349
+ "use strict";
1350
+ MockConfigProvider = class {
1351
+ /**
1352
+ * Return demo config counts
1353
+ * @returns Demo counts for CLAUDE.md, rules, MCPs, hooks
1354
+ */
1355
+ async getConfigs() {
1356
+ return {
1357
+ claudeMdCount: 1,
1358
+ rulesCount: 3,
1359
+ mcpCount: 2,
1360
+ hooksCount: 4
1361
+ };
1362
+ }
1363
+ };
1364
+ }
1365
+ });
1366
+
1358
1367
  // src/providers/mock-git.ts
1359
1368
  var MockGit;
1360
1369
  var init_mock_git = __esm({
@@ -1801,6 +1810,7 @@ var init_active_tools_widget = __esm({
1801
1810
  // Display on third line (0-indexed)
1802
1811
  };
1803
1812
  style = "balanced";
1813
+ _lineOverride;
1804
1814
  tools = [];
1805
1815
  renderData;
1806
1816
  /**
@@ -1810,6 +1820,12 @@ var init_active_tools_widget = __esm({
1810
1820
  setStyle(style) {
1811
1821
  this.style = style;
1812
1822
  }
1823
+ setLine(line) {
1824
+ this._lineOverride = line;
1825
+ }
1826
+ getLine() {
1827
+ return this._lineOverride ?? this.metadata.line ?? 0;
1828
+ }
1813
1829
  /**
1814
1830
  * Aggregate completed tools by name and sort by count (descending)
1815
1831
  * @param tools - Array of tool entries
@@ -2049,9 +2065,6 @@ function formatDuration(ms) {
2049
2065
  function formatCostUSD(usd) {
2050
2066
  return `$${usd.toFixed(2)}`;
2051
2067
  }
2052
- function colorize2(text, color) {
2053
- return `${color}${text}${ANSI_COLORS.RESET}`;
2054
- }
2055
2068
  function formatK(n) {
2056
2069
  const absN = Math.abs(n);
2057
2070
  if (absN < 1e3) {
@@ -2090,13 +2103,13 @@ var init_styles2 = __esm({
2090
2103
  init_formatters();
2091
2104
  cacheMetricsStyles = {
2092
2105
  /**
2093
- * balanced: 💾 35.0k cache with color coding
2106
+ * balanced: 35.0k cache with color coding
2094
2107
  */
2095
2108
  balanced: (data, colors2) => {
2096
2109
  const { cacheRead, hitRate } = data;
2097
2110
  const color = colors2 ? getCacheColor(hitRate, colors2) : "";
2098
2111
  const amount = color ? `${color}${formatK(cacheRead)} cache` : `${formatK(cacheRead)} cache`;
2099
- return `\u{1F4BE} ${amount}`;
2112
+ return amount;
2100
2113
  },
2101
2114
  /**
2102
2115
  * compact: Cache: 35.0k
@@ -2180,6 +2193,7 @@ var init_cache_metrics_widget = __esm({
2180
2193
  // Third line
2181
2194
  );
2182
2195
  theme;
2196
+ _lineOverride;
2183
2197
  style = "balanced";
2184
2198
  renderData;
2185
2199
  cacheManager;
@@ -2195,6 +2209,12 @@ var init_cache_metrics_widget = __esm({
2195
2209
  setStyle(style) {
2196
2210
  this.style = style;
2197
2211
  }
2212
+ setLine(line) {
2213
+ this._lineOverride = line;
2214
+ }
2215
+ getLine() {
2216
+ return this._lineOverride ?? this.metadata.line ?? 0;
2217
+ }
2198
2218
  /**
2199
2219
  * Calculate cache metrics from context usage data
2200
2220
  * Returns null if no usage data is available (current or cached)
@@ -2474,75 +2494,104 @@ var configCountStyles;
2474
2494
  var init_styles3 = __esm({
2475
2495
  "src/widgets/config-count/styles.ts"() {
2476
2496
  "use strict";
2497
+ init_colors();
2477
2498
  configCountStyles = {
2478
- balanced: (data) => {
2499
+ balanced: (data, colors2) => {
2479
2500
  const { claudeMdCount, rulesCount, mcpCount, hooksCount } = data;
2480
2501
  const parts = [];
2502
+ const info = colors2?.semantic.info ?? "";
2503
+ const muted = colors2?.base.muted ?? "";
2481
2504
  if (claudeMdCount > 0) {
2482
- parts.push(`CLAUDE.md:${claudeMdCount}`);
2505
+ const label = info ? colorize("CLAUDE.md", info) : "CLAUDE.md";
2506
+ parts.push(`${label}:${claudeMdCount}`);
2483
2507
  }
2484
2508
  if (rulesCount > 0) {
2485
- parts.push(`rules:${rulesCount}`);
2509
+ const label = info ? colorize("rules", info) : "rules";
2510
+ parts.push(`${label}:${rulesCount}`);
2486
2511
  }
2487
2512
  if (mcpCount > 0) {
2488
- parts.push(`MCPs:${mcpCount}`);
2513
+ const label = info ? colorize("MCPs", info) : "MCPs";
2514
+ parts.push(`${label}:${mcpCount}`);
2489
2515
  }
2490
2516
  if (hooksCount > 0) {
2491
- parts.push(`hooks:${hooksCount}`);
2517
+ const label = info ? colorize("hooks", info) : "hooks";
2518
+ parts.push(`${label}:${hooksCount}`);
2492
2519
  }
2493
- return parts.join(" \u2502 ");
2520
+ const sep = muted ? colorize(" \u2502 ", muted) : " \u2502 ";
2521
+ return parts.join(sep);
2494
2522
  },
2495
- compact: (data) => {
2523
+ compact: (data, colors2) => {
2496
2524
  const { claudeMdCount, rulesCount, mcpCount, hooksCount } = data;
2497
2525
  const parts = [];
2526
+ const info = colors2?.semantic.info ?? "";
2527
+ const muted = colors2?.base.muted ?? "";
2498
2528
  if (claudeMdCount > 0) {
2499
- parts.push(`${claudeMdCount} docs`);
2529
+ const text = info ? colorize(`${claudeMdCount} docs`, info) : `${claudeMdCount} docs`;
2530
+ parts.push(text);
2500
2531
  }
2501
2532
  if (rulesCount > 0) {
2502
- parts.push(`${rulesCount} rules`);
2533
+ const text = info ? colorize(`${rulesCount} rules`, info) : `${rulesCount} rules`;
2534
+ parts.push(text);
2503
2535
  }
2504
2536
  if (mcpCount > 0) {
2505
- parts.push(`${mcpCount} MCPs`);
2537
+ const text = info ? colorize(`${mcpCount} MCPs`, info) : `${mcpCount} MCPs`;
2538
+ parts.push(text);
2506
2539
  }
2507
2540
  if (hooksCount > 0) {
2508
2541
  const hookLabel = hooksCount === 1 ? "hook" : "hooks";
2509
- parts.push(`${hooksCount} ${hookLabel}`);
2542
+ const text = info ? colorize(`${hooksCount} ${hookLabel}`, info) : `${hooksCount} ${hookLabel}`;
2543
+ parts.push(text);
2510
2544
  }
2511
- return parts.join(" \u2502 ");
2545
+ const sep = muted ? colorize(" \u2502 ", muted) : " \u2502 ";
2546
+ return parts.join(sep);
2512
2547
  },
2513
- playful: (data) => {
2548
+ playful: (data, colors2) => {
2514
2549
  const { claudeMdCount, rulesCount, mcpCount, hooksCount } = data;
2515
2550
  const parts = [];
2551
+ const info = colors2?.semantic.info ?? "";
2552
+ const muted = colors2?.base.muted ?? "";
2516
2553
  if (claudeMdCount > 0) {
2517
- parts.push(`\u{1F4C4} CLAUDE.md:${claudeMdCount}`);
2554
+ const text = info ? colorize(`CLAUDE.md:${claudeMdCount}`, info) : `CLAUDE.md:${claudeMdCount}`;
2555
+ parts.push(`\u{1F4C4} ${text}`);
2518
2556
  }
2519
2557
  if (rulesCount > 0) {
2520
- parts.push(`\u{1F4DC} rules:${rulesCount}`);
2558
+ const text = info ? colorize(`rules:${rulesCount}`, info) : `rules:${rulesCount}`;
2559
+ parts.push(`\u{1F4DC} ${text}`);
2521
2560
  }
2522
2561
  if (mcpCount > 0) {
2523
- parts.push(`\u{1F50C} MCPs:${mcpCount}`);
2562
+ const text = info ? colorize(`MCPs:${mcpCount}`, info) : `MCPs:${mcpCount}`;
2563
+ parts.push(`\u{1F50C} ${text}`);
2524
2564
  }
2525
2565
  if (hooksCount > 0) {
2526
- parts.push(`\u{1FA9D} hooks:${hooksCount}`);
2566
+ const text = info ? colorize(`hooks:${hooksCount}`, info) : `hooks:${hooksCount}`;
2567
+ parts.push(`\u{1FA9D} ${text}`);
2527
2568
  }
2528
- return parts.join(" \u2502 ");
2569
+ const sep = muted ? colorize(" \u2502 ", muted) : " \u2502 ";
2570
+ return parts.join(sep);
2529
2571
  },
2530
- verbose: (data) => {
2572
+ verbose: (data, colors2) => {
2531
2573
  const { claudeMdCount, rulesCount, mcpCount, hooksCount } = data;
2532
2574
  const parts = [];
2575
+ const info = colors2?.semantic.info ?? "";
2576
+ const muted = colors2?.base.muted ?? "";
2533
2577
  if (claudeMdCount > 0) {
2534
- parts.push(`${claudeMdCount} CLAUDE.md`);
2578
+ const text = info ? colorize(`${claudeMdCount} CLAUDE.md`, info) : `${claudeMdCount} CLAUDE.md`;
2579
+ parts.push(text);
2535
2580
  }
2536
2581
  if (rulesCount > 0) {
2537
- parts.push(`${rulesCount} rules`);
2582
+ const text = info ? colorize(`${rulesCount} rules`, info) : `${rulesCount} rules`;
2583
+ parts.push(text);
2538
2584
  }
2539
2585
  if (mcpCount > 0) {
2540
- parts.push(`${mcpCount} MCP servers`);
2586
+ const text = info ? colorize(`${mcpCount} MCP servers`, info) : `${mcpCount} MCP servers`;
2587
+ parts.push(text);
2541
2588
  }
2542
2589
  if (hooksCount > 0) {
2543
- parts.push(`${hooksCount} hook`);
2590
+ const text = info ? colorize(`${hooksCount} hooks`, info) : `${hooksCount} hooks`;
2591
+ parts.push(text);
2544
2592
  }
2545
- return parts.join(" \u2502 ");
2593
+ const sep = muted ? colorize(" \u2502 ", muted) : " \u2502 ";
2594
+ return parts.join(sep);
2546
2595
  }
2547
2596
  };
2548
2597
  }
@@ -2556,6 +2605,7 @@ var init_config_count_widget = __esm({
2556
2605
  init_style_types();
2557
2606
  init_widget_types();
2558
2607
  init_config_provider();
2608
+ init_theme();
2559
2609
  init_styles3();
2560
2610
  ConfigCountWidget = class {
2561
2611
  id = "config-count";
@@ -2567,16 +2617,28 @@ var init_config_count_widget = __esm({
2567
2617
  1
2568
2618
  // Second line
2569
2619
  );
2570
- configProvider = new ConfigProvider();
2620
+ configProvider;
2571
2621
  configs;
2572
2622
  cwd;
2623
+ themeColors;
2624
+ _lineOverride;
2573
2625
  styleFn = configCountStyles.balanced;
2626
+ constructor(configProvider, themeColors) {
2627
+ this.configProvider = configProvider ?? new ConfigProvider();
2628
+ this.themeColors = themeColors ?? DEFAULT_THEME;
2629
+ }
2574
2630
  setStyle(style = DEFAULT_WIDGET_STYLE) {
2575
2631
  const fn = configCountStyles[style];
2576
2632
  if (fn) {
2577
2633
  this.styleFn = fn;
2578
2634
  }
2579
2635
  }
2636
+ setLine(line) {
2637
+ this._lineOverride = line;
2638
+ }
2639
+ getLine() {
2640
+ return this._lineOverride ?? this.metadata.line ?? 0;
2641
+ }
2580
2642
  async initialize() {
2581
2643
  }
2582
2644
  async update(data) {
@@ -2599,9 +2661,10 @@ var init_config_count_widget = __esm({
2599
2661
  claudeMdCount,
2600
2662
  rulesCount,
2601
2663
  mcpCount,
2602
- hooksCount
2664
+ hooksCount,
2665
+ colors: this.themeColors
2603
2666
  };
2604
- return this.styleFn(renderData);
2667
+ return this.styleFn(renderData, this.themeColors);
2605
2668
  }
2606
2669
  async cleanup() {
2607
2670
  }
@@ -2715,6 +2778,7 @@ var init_context_widget = __esm({
2715
2778
  // First line
2716
2779
  );
2717
2780
  colors;
2781
+ _lineOverride;
2718
2782
  styleFn = contextStyles.balanced;
2719
2783
  cacheManager;
2720
2784
  lastSessionId;
@@ -2729,6 +2793,12 @@ var init_context_widget = __esm({
2729
2793
  this.styleFn = fn;
2730
2794
  }
2731
2795
  }
2796
+ setLine(line) {
2797
+ this._lineOverride = line;
2798
+ }
2799
+ getLine() {
2800
+ return this._lineOverride ?? this.metadata.line ?? 0;
2801
+ }
2732
2802
  /**
2733
2803
  * Update widget with new data, storing valid values in cache
2734
2804
  */
@@ -2837,6 +2907,7 @@ var init_cost_widget = __esm({
2837
2907
  // First line
2838
2908
  );
2839
2909
  colors;
2910
+ _lineOverride;
2840
2911
  styleFn = costStyles.balanced;
2841
2912
  constructor(colors2) {
2842
2913
  super();
@@ -2848,6 +2919,12 @@ var init_cost_widget = __esm({
2848
2919
  this.styleFn = fn;
2849
2920
  }
2850
2921
  }
2922
+ setLine(line) {
2923
+ this._lineOverride = line;
2924
+ }
2925
+ getLine() {
2926
+ return this._lineOverride ?? this.metadata.line ?? 0;
2927
+ }
2851
2928
  renderWithData(data, _context) {
2852
2929
  if (!data.cost || data.cost.total_cost_usd === void 0) return null;
2853
2930
  const renderData = {
@@ -2915,17 +2992,25 @@ var init_styles6 = __esm({
2915
2992
  const totalSeconds = Math.floor(data.durationMs / 1e3);
2916
2993
  const hours = Math.floor(totalSeconds / 3600);
2917
2994
  const minutes = Math.floor(totalSeconds % 3600 / 60);
2995
+ const seconds = totalSeconds % 60;
2918
2996
  if (!colors2) {
2919
2997
  if (hours > 0) {
2920
- return `\u231B ${hours}h ${minutes}m`;
2998
+ return `\u231B ${hours}h ${minutes}m ${seconds}s`;
2921
2999
  }
2922
- return `\u231B ${minutes}m`;
3000
+ if (minutes > 0) {
3001
+ return `\u231B ${minutes}m ${seconds}s`;
3002
+ }
3003
+ return `\u231B ${seconds}s`;
2923
3004
  }
2924
3005
  if (hours > 0) {
2925
- const colored = colorize(`${hours}`, colors2.value) + colorize("h", colors2.unit) + colorize(` ${minutes}`, colors2.value) + colorize("m", colors2.unit);
3006
+ const colored = colorize(`${hours}`, colors2.value) + colorize("h", colors2.unit) + colorize(` ${minutes}`, colors2.value) + colorize("m", colors2.unit) + colorize(` ${seconds}`, colors2.value) + colorize("s", colors2.unit);
3007
+ return `\u231B ${colored}`;
3008
+ }
3009
+ if (minutes > 0) {
3010
+ const colored = colorize(`${minutes}`, colors2.value) + colorize("m", colors2.unit) + colorize(` ${seconds}`, colors2.value) + colorize("s", colors2.unit);
2926
3011
  return `\u231B ${colored}`;
2927
3012
  }
2928
- return `\u231B ${colorize(`${minutes}`, colors2.value)}${colorize("m", colors2.unit)}`;
3013
+ return `\u231B ${colorize(`${seconds}`, colors2.value)}${colorize("s", colors2.unit)}`;
2929
3014
  },
2930
3015
  technical: (data, colors2) => {
2931
3016
  const value = `${Math.floor(data.durationMs)}ms`;
@@ -2968,6 +3053,7 @@ var init_duration_widget = __esm({
2968
3053
  // First line
2969
3054
  );
2970
3055
  colors;
3056
+ _lineOverride;
2971
3057
  styleFn = durationStyles.balanced;
2972
3058
  constructor(colors2) {
2973
3059
  super();
@@ -2979,6 +3065,12 @@ var init_duration_widget = __esm({
2979
3065
  this.styleFn = fn;
2980
3066
  }
2981
3067
  }
3068
+ setLine(line) {
3069
+ this._lineOverride = line;
3070
+ }
3071
+ getLine() {
3072
+ return this._lineOverride ?? this.metadata.line ?? 0;
3073
+ }
2982
3074
  renderWithData(data, _context) {
2983
3075
  if (!data.cost || data.cost.total_duration_ms === void 0) return null;
2984
3076
  const renderData = {
@@ -3121,6 +3213,7 @@ var init_git_tag_widget = __esm({
3121
3213
  enabled = true;
3122
3214
  cwd = null;
3123
3215
  colors;
3216
+ _lineOverride;
3124
3217
  styleFn = gitTagStyles.balanced;
3125
3218
  /**
3126
3219
  * @param gitFactory - Optional factory function for creating IGit instances
@@ -3138,6 +3231,12 @@ var init_git_tag_widget = __esm({
3138
3231
  this.styleFn = fn;
3139
3232
  }
3140
3233
  }
3234
+ setLine(line) {
3235
+ this._lineOverride = line;
3236
+ }
3237
+ getLine() {
3238
+ return this._lineOverride ?? this.metadata.line ?? 0;
3239
+ }
3141
3240
  async initialize(context) {
3142
3241
  this.enabled = context.config?.enabled !== false;
3143
3242
  }
@@ -3288,6 +3387,7 @@ var init_git_widget = __esm({
3288
3387
  enabled = true;
3289
3388
  cwd = null;
3290
3389
  colors;
3390
+ _lineOverride;
3291
3391
  styleFn = gitStyles.balanced;
3292
3392
  /**
3293
3393
  * @param gitFactory - Optional factory function for creating IGit instances
@@ -3305,6 +3405,12 @@ var init_git_widget = __esm({
3305
3405
  this.styleFn = fn;
3306
3406
  }
3307
3407
  }
3408
+ setLine(line) {
3409
+ this._lineOverride = line;
3410
+ }
3411
+ getLine() {
3412
+ return this._lineOverride ?? this.metadata.line ?? 0;
3413
+ }
3308
3414
  async initialize(context) {
3309
3415
  this.enabled = context.config?.enabled !== false;
3310
3416
  }
@@ -3429,6 +3535,7 @@ var init_lines_widget = __esm({
3429
3535
  // First line
3430
3536
  );
3431
3537
  colors;
3538
+ _lineOverride;
3432
3539
  styleFn = linesStyles.balanced;
3433
3540
  constructor(colors2) {
3434
3541
  super();
@@ -3440,6 +3547,12 @@ var init_lines_widget = __esm({
3440
3547
  this.styleFn = fn;
3441
3548
  }
3442
3549
  }
3550
+ setLine(line) {
3551
+ this._lineOverride = line;
3552
+ }
3553
+ getLine() {
3554
+ return this._lineOverride ?? this.metadata.line ?? 0;
3555
+ }
3443
3556
  renderWithData(data, _context) {
3444
3557
  const added = data.cost?.total_lines_added ?? 0;
3445
3558
  const removed = data.cost?.total_lines_removed ?? 0;
@@ -3522,6 +3635,7 @@ var init_model_widget = __esm({
3522
3635
  // First line
3523
3636
  );
3524
3637
  colors;
3638
+ _lineOverride;
3525
3639
  styleFn = modelStyles.balanced;
3526
3640
  constructor(colors2) {
3527
3641
  super();
@@ -3533,6 +3647,12 @@ var init_model_widget = __esm({
3533
3647
  this.styleFn = fn;
3534
3648
  }
3535
3649
  }
3650
+ setLine(line) {
3651
+ this._lineOverride = line;
3652
+ }
3653
+ getLine() {
3654
+ return this._lineOverride ?? this.metadata.line ?? 0;
3655
+ }
3536
3656
  renderWithData(data, _context) {
3537
3657
  const renderData = {
3538
3658
  displayName: data.model.display_name,
@@ -3631,7 +3751,8 @@ async function registerWidgetsFromConfig(registry, config, style, themeName) {
3631
3751
  return w;
3632
3752
  },
3633
3753
  "config-count": (s) => {
3634
- const w = new ConfigCountWidget();
3754
+ const mockConfig = new MockConfigProvider();
3755
+ const w = new ConfigCountWidget(mockConfig, themeColors);
3635
3756
  w.setStyle(s);
3636
3757
  return w;
3637
3758
  },
@@ -3682,6 +3803,7 @@ var init_layout_preview = __esm({
3682
3803
  "use strict";
3683
3804
  init_renderer();
3684
3805
  init_widget_registry();
3806
+ init_mock_config_provider();
3685
3807
  init_mock_git();
3686
3808
  init_mock_transcript_provider();
3687
3809
  init_theme();
@@ -6486,14 +6608,22 @@ async function generatePreviews(choices, style, themeName) {
6486
6608
  const previews = [];
6487
6609
  const isStyleSelection = choices.length >= 3 && choices.every((c) => isQuickConfigStyle(c.value));
6488
6610
  const availableThemes = [
6489
- "monokai",
6490
- "nord",
6491
- "dracula",
6492
6611
  "catppuccin-mocha",
6493
- "tokyo-night",
6494
- "vscode-dark-plus",
6612
+ // AVAILABLE_THEMES[0]
6613
+ "cyberpunk-neon",
6614
+ // AVAILABLE_THEMES[1]
6615
+ "dracula",
6616
+ // AVAILABLE_THEMES[2]
6617
+ "dusty-sage",
6618
+ // AVAILABLE_THEMES[3]
6495
6619
  "github-dark-dimmed",
6496
- "dusty-sage"
6620
+ // AVAILABLE_THEMES[4]
6621
+ "gray",
6622
+ // AVAILABLE_THEMES[5] - was missing!
6623
+ "monokai",
6624
+ // AVAILABLE_THEMES[6]
6625
+ "muted-gray"
6626
+ // AVAILABLE_THEMES[7] - was missing!
6497
6627
  ];
6498
6628
  const isThemeSelection = choices.some((c) => isThemeName(c.value, availableThemes));
6499
6629
  for (const choice of choices) {
@@ -6736,6 +6866,11 @@ function generateRichLayout(style, themeName) {
6736
6866
  style,
6737
6867
  colors: { amount: theme.cost.amount, currency: theme.cost.currency }
6738
6868
  },
6869
+ {
6870
+ id: "lines",
6871
+ style,
6872
+ colors: { added: theme.lines.added, removed: theme.lines.removed }
6873
+ },
6739
6874
  {
6740
6875
  id: "duration",
6741
6876
  style,
@@ -6753,11 +6888,6 @@ function generateRichLayout(style, themeName) {
6753
6888
  style,
6754
6889
  colors: { base: theme.base.text }
6755
6890
  },
6756
- {
6757
- id: "lines",
6758
- style,
6759
- colors: { added: theme.lines.added, removed: theme.lines.removed }
6760
- },
6761
6891
  {
6762
6892
  id: "active-tools",
6763
6893
  style,
@@ -7134,16 +7264,39 @@ async function routeCommand(command) {
7134
7264
  }
7135
7265
 
7136
7266
  // src/config/config-loader.ts
7137
- var import_node_fs3 = require("node:fs");
7267
+ var import_node_fs4 = require("node:fs");
7138
7268
  var import_promises2 = require("node:fs/promises");
7269
+ var import_node_os4 = require("node:os");
7270
+ var import_node_path4 = require("node:path");
7271
+
7272
+ // src/config/default-config-generator.ts
7273
+ var import_node_fs3 = require("node:fs");
7139
7274
  var import_node_os3 = require("node:os");
7140
7275
  var import_node_path3 = require("node:path");
7141
- function getConfigPath() {
7276
+ function getDefaultConfigPath() {
7142
7277
  return (0, import_node_path3.join)((0, import_node_os3.homedir)(), ".claude-scope", "config.json");
7143
7278
  }
7279
+ async function ensureDefaultConfig() {
7280
+ const configPath = getDefaultConfigPath();
7281
+ if ((0, import_node_fs3.existsSync)(configPath)) {
7282
+ return;
7283
+ }
7284
+ const configDir = (0, import_node_path3.join)((0, import_node_os3.homedir)(), ".claude-scope");
7285
+ if (!(0, import_node_fs3.existsSync)(configDir)) {
7286
+ (0, import_node_fs3.mkdirSync)(configDir, { recursive: true });
7287
+ }
7288
+ const defaultConfig = generateBalancedLayout("balanced", "cyberpunk-neon");
7289
+ (0, import_node_fs3.writeFileSync)(configPath, JSON.stringify(defaultConfig, null, 2), "utf-8");
7290
+ }
7291
+
7292
+ // src/config/config-loader.ts
7293
+ function getConfigPath() {
7294
+ return (0, import_node_path4.join)((0, import_node_os4.homedir)(), ".claude-scope", "config.json");
7295
+ }
7144
7296
  async function loadWidgetConfig() {
7145
7297
  const configPath = getConfigPath();
7146
- if (!(0, import_node_fs3.existsSync)(configPath)) {
7298
+ await ensureDefaultConfig();
7299
+ if (!(0, import_node_fs4.existsSync)(configPath)) {
7147
7300
  return null;
7148
7301
  }
7149
7302
  try {
@@ -7359,690 +7512,10 @@ init_config_count_widget();
7359
7512
  init_context_widget();
7360
7513
  init_cost_widget();
7361
7514
  init_duration_widget();
7362
-
7363
- // src/widgets/empty-line-widget.ts
7364
- init_widget_types();
7365
- init_stdin_data_widget();
7366
- var EmptyLineWidget = class extends StdinDataWidget {
7367
- id = "empty-line";
7368
- metadata = createWidgetMetadata(
7369
- "Empty Line",
7370
- "Empty line separator",
7371
- "1.0.0",
7372
- "claude-scope",
7373
- 5
7374
- // Sixth line (0-indexed)
7375
- );
7376
- /**
7377
- * All styles return the same value (Braille Pattern Blank).
7378
- * This method exists for API consistency with other widgets.
7379
- */
7380
- setStyle(_style) {
7381
- }
7382
- /**
7383
- * Return Braille Pattern Blank to create a visible empty separator line.
7384
- * U+2800 occupies cell width but appears blank, ensuring the line renders.
7385
- */
7386
- renderWithData(_data, _context) {
7387
- return "\u2800";
7388
- }
7389
- };
7390
-
7391
- // src/index.ts
7392
7515
  init_git_tag_widget();
7393
7516
  init_git_widget();
7394
7517
  init_lines_widget();
7395
7518
  init_model_widget();
7396
-
7397
- // src/widgets/poker-widget.ts
7398
- init_style_types();
7399
- init_widget_types();
7400
- init_theme();
7401
- init_stdin_data_widget();
7402
-
7403
- // src/widgets/poker/deck.ts
7404
- var import_node_crypto = require("node:crypto");
7405
-
7406
- // src/widgets/poker/types.ts
7407
- var Suit = {
7408
- Spades: "spades",
7409
- Hearts: "hearts",
7410
- Diamonds: "diamonds",
7411
- Clubs: "clubs"
7412
- };
7413
- var SUIT_SYMBOLS = {
7414
- spades: "\u2660",
7415
- hearts: "\u2665",
7416
- diamonds: "\u2666",
7417
- clubs: "\u2663"
7418
- };
7419
- var EMOJI_SYMBOLS = {
7420
- spades: "\u2660\uFE0F",
7421
- // ♠️
7422
- hearts: "\u2665\uFE0F",
7423
- // ♥️
7424
- diamonds: "\u2666\uFE0F",
7425
- // ♦️
7426
- clubs: "\u2663\uFE0F"
7427
- // ♣️
7428
- };
7429
- function isRedSuit(suit) {
7430
- return suit === "hearts" || suit === "diamonds";
7431
- }
7432
- var Rank = {
7433
- Two: "2",
7434
- Three: "3",
7435
- Four: "4",
7436
- Five: "5",
7437
- Six: "6",
7438
- Seven: "7",
7439
- Eight: "8",
7440
- Nine: "9",
7441
- Ten: "10",
7442
- Jack: "J",
7443
- Queen: "Q",
7444
- King: "K",
7445
- Ace: "A"
7446
- };
7447
- function getRankValue(rank) {
7448
- const values = {
7449
- "2": 2,
7450
- "3": 3,
7451
- "4": 4,
7452
- "5": 5,
7453
- "6": 6,
7454
- "7": 7,
7455
- "8": 8,
7456
- "9": 9,
7457
- "10": 10,
7458
- J: 11,
7459
- Q: 12,
7460
- K: 13,
7461
- A: 14
7462
- };
7463
- return values[rank];
7464
- }
7465
- function formatCard(card) {
7466
- return `${card.rank}${SUIT_SYMBOLS[card.suit]}`;
7467
- }
7468
- function formatCardEmoji(card) {
7469
- return `${card.rank}${EMOJI_SYMBOLS[card.suit]}`;
7470
- }
7471
-
7472
- // src/widgets/poker/deck.ts
7473
- var ALL_SUITS = [Suit.Spades, Suit.Hearts, Suit.Diamonds, Suit.Clubs];
7474
- var ALL_RANKS = [
7475
- Rank.Two,
7476
- Rank.Three,
7477
- Rank.Four,
7478
- Rank.Five,
7479
- Rank.Six,
7480
- Rank.Seven,
7481
- Rank.Eight,
7482
- Rank.Nine,
7483
- Rank.Ten,
7484
- Rank.Jack,
7485
- Rank.Queen,
7486
- Rank.King,
7487
- Rank.Ace
7488
- ];
7489
- var Deck = class {
7490
- cards = [];
7491
- constructor() {
7492
- this.initialize();
7493
- this.shuffle();
7494
- }
7495
- /**
7496
- * Create a standard 52-card deck
7497
- */
7498
- initialize() {
7499
- this.cards = [];
7500
- for (const suit of ALL_SUITS) {
7501
- for (const rank of ALL_RANKS) {
7502
- this.cards.push({ rank, suit });
7503
- }
7504
- }
7505
- }
7506
- /**
7507
- * Shuffle deck using Fisher-Yates algorithm with crypto.random
7508
- */
7509
- shuffle() {
7510
- for (let i = this.cards.length - 1; i > 0; i--) {
7511
- const j = (0, import_node_crypto.randomInt)(0, i + 1);
7512
- [this.cards[i], this.cards[j]] = [this.cards[j], this.cards[i]];
7513
- }
7514
- }
7515
- /**
7516
- * Deal one card from the top of the deck
7517
- * @throws Error if deck is empty
7518
- */
7519
- deal() {
7520
- if (this.cards.length === 0) {
7521
- throw new Error("Deck is empty");
7522
- }
7523
- return this.cards.pop();
7524
- }
7525
- /**
7526
- * Get number of remaining cards in deck
7527
- */
7528
- remaining() {
7529
- return this.cards.length;
7530
- }
7531
- };
7532
-
7533
- // src/widgets/poker/hand-evaluator.ts
7534
- var HAND_DISPLAY = {
7535
- [10 /* RoyalFlush */]: { name: "Royal Flush", emoji: "\u{1F3C6}" },
7536
- [9 /* StraightFlush */]: { name: "Straight Flush", emoji: "\u{1F525}" },
7537
- [8 /* FourOfAKind */]: { name: "Four of a Kind", emoji: "\u{1F48E}" },
7538
- [7 /* FullHouse */]: { name: "Full House", emoji: "\u{1F3E0}" },
7539
- [6 /* Flush */]: { name: "Flush", emoji: "\u{1F4A7}" },
7540
- [5 /* Straight */]: { name: "Straight", emoji: "\u{1F4C8}" },
7541
- [4 /* ThreeOfAKind */]: { name: "Three of a Kind", emoji: "\u{1F3AF}" },
7542
- [3 /* TwoPair */]: { name: "Two Pair", emoji: "\u270C\uFE0F" },
7543
- [2 /* OnePair */]: { name: "One Pair", emoji: "\u{1F44D}" },
7544
- [1 /* HighCard */]: { name: "High Card", emoji: "\u{1F0CF}" }
7545
- };
7546
- function countRanks(cards) {
7547
- const counts = /* @__PURE__ */ new Map();
7548
- for (const card of cards) {
7549
- const value = getRankValue(card.rank);
7550
- counts.set(value, (counts.get(value) || 0) + 1);
7551
- }
7552
- return counts;
7553
- }
7554
- function countSuits(cards) {
7555
- const counts = /* @__PURE__ */ new Map();
7556
- for (const card of cards) {
7557
- counts.set(card.suit, (counts.get(card.suit) || 0) + 1);
7558
- }
7559
- return counts;
7560
- }
7561
- function findCardsOfRank(cards, targetRank) {
7562
- const indices = [];
7563
- for (let i = 0; i < cards.length; i++) {
7564
- if (getRankValue(cards[i].rank) === targetRank) {
7565
- indices.push(i);
7566
- }
7567
- }
7568
- return indices;
7569
- }
7570
- function findCardsOfSuit(cards, targetSuit) {
7571
- const indices = [];
7572
- for (let i = 0; i < cards.length; i++) {
7573
- if (cards[i].suit === targetSuit) {
7574
- indices.push(i);
7575
- }
7576
- }
7577
- return indices;
7578
- }
7579
- function findFlushSuit(cards) {
7580
- const suitCounts = countSuits(cards);
7581
- for (const [suit, count] of suitCounts.entries()) {
7582
- if (count >= 5) return suit;
7583
- }
7584
- return null;
7585
- }
7586
- function getStraightIndices(cards, highCard) {
7587
- const uniqueValues = /* @__PURE__ */ new Set();
7588
- const cardIndicesByRank = /* @__PURE__ */ new Map();
7589
- for (let i = 0; i < cards.length; i++) {
7590
- const value = getRankValue(cards[i].rank);
7591
- if (!cardIndicesByRank.has(value)) {
7592
- cardIndicesByRank.set(value, []);
7593
- uniqueValues.add(value);
7594
- }
7595
- cardIndicesByRank.get(value)?.push(i);
7596
- }
7597
- const sortedValues = Array.from(uniqueValues).sort((a, b) => b - a);
7598
- if (sortedValues.includes(14)) {
7599
- sortedValues.push(1);
7600
- }
7601
- for (let i = 0; i <= sortedValues.length - 5; i++) {
7602
- const current = sortedValues[i];
7603
- const next1 = sortedValues[i + 1];
7604
- const next2 = sortedValues[i + 2];
7605
- const next3 = sortedValues[i + 3];
7606
- const next4 = sortedValues[i + 4];
7607
- if (current - next1 === 1 && current - next2 === 2 && current - next3 === 3 && current - next4 === 4) {
7608
- if (current === highCard) {
7609
- const indices = [];
7610
- indices.push(cardIndicesByRank.get(current)[0]);
7611
- indices.push(cardIndicesByRank.get(next1)[0]);
7612
- indices.push(cardIndicesByRank.get(next2)[0]);
7613
- indices.push(cardIndicesByRank.get(next3)[0]);
7614
- const rank4 = next4 === 1 ? 14 : next4;
7615
- indices.push(cardIndicesByRank.get(rank4)[0]);
7616
- return indices;
7617
- }
7618
- }
7619
- }
7620
- return [];
7621
- }
7622
- function getStraightFlushHighCard(cards, suit) {
7623
- const suitCards = cards.filter((c) => c.suit === suit);
7624
- return getStraightHighCard(suitCards);
7625
- }
7626
- function getStraightFlushIndices(cards, highCard, suit) {
7627
- const _suitCards = cards.filter((c) => c.suit === suit);
7628
- const suitCardIndices = [];
7629
- const indexMap = /* @__PURE__ */ new Map();
7630
- for (let i = 0; i < cards.length; i++) {
7631
- if (cards[i].suit === suit) {
7632
- indexMap.set(suitCardIndices.length, i);
7633
- suitCardIndices.push(cards[i]);
7634
- }
7635
- }
7636
- const indices = getStraightIndices(suitCardIndices, highCard);
7637
- return indices.map((idx) => indexMap.get(idx));
7638
- }
7639
- function getFullHouseIndices(cards) {
7640
- const rankCounts = countRanks(cards);
7641
- let tripsRank = 0;
7642
- for (const [rank, count] of rankCounts.entries()) {
7643
- if (count === 3) {
7644
- tripsRank = rank;
7645
- break;
7646
- }
7647
- }
7648
- let pairRank = 0;
7649
- for (const [rank, count] of rankCounts.entries()) {
7650
- if (count >= 2 && rank !== tripsRank) {
7651
- pairRank = rank;
7652
- break;
7653
- }
7654
- }
7655
- if (pairRank === 0) {
7656
- const tripsRanks = [];
7657
- for (const [rank, count] of rankCounts.entries()) {
7658
- if (count === 3) {
7659
- tripsRanks.push(rank);
7660
- }
7661
- }
7662
- if (tripsRanks.length >= 2) {
7663
- tripsRanks.sort((a, b) => b - a);
7664
- tripsRank = tripsRanks[0];
7665
- pairRank = tripsRanks[1];
7666
- }
7667
- }
7668
- const tripsIndices = findCardsOfRank(cards, tripsRank);
7669
- const pairIndices = findCardsOfRank(cards, pairRank);
7670
- return [...tripsIndices.slice(0, 3), ...pairIndices.slice(0, 2)];
7671
- }
7672
- function isFlush(cards) {
7673
- const suitCounts = countSuits(cards);
7674
- for (const count of suitCounts.values()) {
7675
- if (count >= 5) return true;
7676
- }
7677
- return false;
7678
- }
7679
- function getStraightHighCard(cards) {
7680
- const uniqueValues = /* @__PURE__ */ new Set();
7681
- for (const card of cards) {
7682
- uniqueValues.add(getRankValue(card.rank));
7683
- }
7684
- const sortedValues = Array.from(uniqueValues).sort((a, b) => b - a);
7685
- if (sortedValues.includes(14)) {
7686
- sortedValues.push(1);
7687
- }
7688
- for (let i = 0; i <= sortedValues.length - 5; i++) {
7689
- const current = sortedValues[i];
7690
- const next1 = sortedValues[i + 1];
7691
- const next2 = sortedValues[i + 2];
7692
- const next3 = sortedValues[i + 3];
7693
- const next4 = sortedValues[i + 4];
7694
- if (current - next1 === 1 && current - next2 === 2 && current - next3 === 3 && current - next4 === 4) {
7695
- return current;
7696
- }
7697
- }
7698
- return null;
7699
- }
7700
- function getMaxCount(cards) {
7701
- const rankCounts = countRanks(cards);
7702
- let maxCount = 0;
7703
- for (const count of rankCounts.values()) {
7704
- if (count > maxCount) {
7705
- maxCount = count;
7706
- }
7707
- }
7708
- return maxCount;
7709
- }
7710
- function getPairCount(cards) {
7711
- const rankCounts = countRanks(cards);
7712
- let pairCount = 0;
7713
- for (const count of rankCounts.values()) {
7714
- if (count === 2) {
7715
- pairCount++;
7716
- }
7717
- }
7718
- return pairCount;
7719
- }
7720
- function getMostCommonRank(cards) {
7721
- const rankCounts = countRanks(cards);
7722
- let bestRank = 0;
7723
- let bestCount = 0;
7724
- for (const [rank, count] of rankCounts.entries()) {
7725
- if (count > bestCount) {
7726
- bestCount = count;
7727
- bestRank = rank;
7728
- }
7729
- }
7730
- return bestRank > 0 ? bestRank : null;
7731
- }
7732
- function getTwoPairRanks(cards) {
7733
- const rankCounts = countRanks(cards);
7734
- const pairRanks = [];
7735
- for (const [rank, count] of rankCounts.entries()) {
7736
- if (count >= 2) {
7737
- pairRanks.push(rank);
7738
- }
7739
- }
7740
- pairRanks.sort((a, b) => b - a);
7741
- return pairRanks.slice(0, 2);
7742
- }
7743
- function getHighestCardIndex(cards) {
7744
- let highestIdx = 0;
7745
- let highestValue = 0;
7746
- for (let i = 0; i < cards.length; i++) {
7747
- const value = getRankValue(cards[i].rank);
7748
- if (value > highestValue) {
7749
- highestValue = value;
7750
- highestIdx = i;
7751
- }
7752
- }
7753
- return highestIdx;
7754
- }
7755
- function evaluateHand(hole, board) {
7756
- const allCards = [...hole, ...board];
7757
- const flush = isFlush(allCards);
7758
- const straightHighCard = getStraightHighCard(allCards);
7759
- const maxCount = getMaxCount(allCards);
7760
- const pairCount = getPairCount(allCards);
7761
- if (flush && straightHighCard === 14) {
7762
- const flushSuit = findFlushSuit(allCards);
7763
- const sfHighCard = getStraightFlushHighCard(allCards, flushSuit);
7764
- if (sfHighCard === 14) {
7765
- const participatingCards = getStraightFlushIndices(allCards, 14, flushSuit);
7766
- return {
7767
- rank: 10 /* RoyalFlush */,
7768
- ...HAND_DISPLAY[10 /* RoyalFlush */],
7769
- participatingCards
7770
- };
7771
- }
7772
- }
7773
- if (flush) {
7774
- const flushSuit = findFlushSuit(allCards);
7775
- const sfHighCard = getStraightFlushHighCard(allCards, flushSuit);
7776
- if (sfHighCard !== null) {
7777
- const participatingCards = getStraightFlushIndices(allCards, sfHighCard, flushSuit);
7778
- return {
7779
- rank: 9 /* StraightFlush */,
7780
- ...HAND_DISPLAY[9 /* StraightFlush */],
7781
- participatingCards
7782
- };
7783
- }
7784
- }
7785
- if (maxCount === 4) {
7786
- const rank = getMostCommonRank(allCards);
7787
- const participatingCards = findCardsOfRank(allCards, rank);
7788
- return {
7789
- rank: 8 /* FourOfAKind */,
7790
- ...HAND_DISPLAY[8 /* FourOfAKind */],
7791
- participatingCards
7792
- };
7793
- }
7794
- if (maxCount === 3 && pairCount >= 1) {
7795
- const participatingCards = getFullHouseIndices(allCards);
7796
- return { rank: 7 /* FullHouse */, ...HAND_DISPLAY[7 /* FullHouse */], participatingCards };
7797
- }
7798
- if (flush) {
7799
- const flushSuit = findFlushSuit(allCards);
7800
- const suitIndices = findCardsOfSuit(allCards, flushSuit);
7801
- const participatingCards = suitIndices.slice(0, 5);
7802
- return { rank: 6 /* Flush */, ...HAND_DISPLAY[6 /* Flush */], participatingCards };
7803
- }
7804
- if (straightHighCard !== null) {
7805
- const participatingCards = getStraightIndices(allCards, straightHighCard);
7806
- return { rank: 5 /* Straight */, ...HAND_DISPLAY[5 /* Straight */], participatingCards };
7807
- }
7808
- if (maxCount === 3) {
7809
- const rank = getMostCommonRank(allCards);
7810
- const participatingCards = findCardsOfRank(allCards, rank);
7811
- return {
7812
- rank: 4 /* ThreeOfAKind */,
7813
- ...HAND_DISPLAY[4 /* ThreeOfAKind */],
7814
- participatingCards
7815
- };
7816
- }
7817
- if (pairCount >= 2) {
7818
- const [rank1, rank2] = getTwoPairRanks(allCards);
7819
- const pair1Indices = findCardsOfRank(allCards, rank1);
7820
- const pair2Indices = findCardsOfRank(allCards, rank2);
7821
- const participatingCards = [...pair1Indices, ...pair2Indices];
7822
- return { rank: 3 /* TwoPair */, ...HAND_DISPLAY[3 /* TwoPair */], participatingCards };
7823
- }
7824
- if (pairCount === 1) {
7825
- const rank = getMostCommonRank(allCards);
7826
- const participatingCards = findCardsOfRank(allCards, rank);
7827
- return { rank: 2 /* OnePair */, ...HAND_DISPLAY[2 /* OnePair */], participatingCards };
7828
- }
7829
- const highestIdx = getHighestCardIndex(allCards);
7830
- return {
7831
- rank: 1 /* HighCard */,
7832
- ...HAND_DISPLAY[1 /* HighCard */],
7833
- participatingCards: [highestIdx]
7834
- };
7835
- }
7836
-
7837
- // src/widgets/poker/styles.ts
7838
- init_colors();
7839
- init_formatters();
7840
- var HAND_ABBREVIATIONS = {
7841
- "Royal Flush": "RF",
7842
- "Straight Flush": "SF",
7843
- "Four of a Kind": "4K",
7844
- "Full House": "FH",
7845
- Flush: "FL",
7846
- Straight: "ST",
7847
- "Three of a Kind": "3K",
7848
- "Two Pair": "2P",
7849
- "One Pair": "1P",
7850
- "High Card": "HC",
7851
- Nothing: "\u2014"
7852
- };
7853
- function formatCardByParticipation(cardData, isParticipating) {
7854
- const color = isRedSuit(cardData.card.suit) ? red : gray;
7855
- const cardText = formatCard(cardData.card);
7856
- if (isParticipating) {
7857
- return `${color}${bold}(${cardText})${reset} `;
7858
- } else {
7859
- return `${color}${cardText}${reset} `;
7860
- }
7861
- }
7862
- function formatCardCompact(cardData, isParticipating) {
7863
- const color = isRedSuit(cardData.card.suit) ? red : gray;
7864
- const cardText = formatCardTextCompact(cardData.card);
7865
- if (isParticipating) {
7866
- return `${color}${bold}(${cardText})${reset}`;
7867
- } else {
7868
- return `${color}${cardText}${reset}`;
7869
- }
7870
- }
7871
- function formatCardTextCompact(card) {
7872
- const rankSymbols = {
7873
- "10": "T",
7874
- "11": "J",
7875
- "12": "Q",
7876
- "13": "K",
7877
- "14": "A"
7878
- };
7879
- const rank = String(card.rank);
7880
- const rankSymbol = rankSymbols[rank] ?? rank;
7881
- return `${rankSymbol}${card.suit}`;
7882
- }
7883
- function formatCardEmojiByParticipation(cardData, isParticipating) {
7884
- const cardText = formatCardEmoji(cardData.card);
7885
- if (isParticipating) {
7886
- return `${bold}(${cardText})${reset} `;
7887
- } else {
7888
- return `${cardText} `;
7889
- }
7890
- }
7891
- function formatHandResult(handResult, colors2) {
7892
- if (!handResult) {
7893
- return "\u2014";
7894
- }
7895
- const playerParticipates = handResult.participatingIndices.some((idx) => idx < 2);
7896
- const resultText = !playerParticipates ? `Nothing \u{1F0CF}` : `${handResult.name}! ${handResult.emoji}`;
7897
- if (!colors2) return resultText;
7898
- return colorize2(resultText, colors2.result);
7899
- }
7900
- function getHandAbbreviation(handResult) {
7901
- if (!handResult) {
7902
- return "\u2014 (\u2014)";
7903
- }
7904
- const abbreviation = HAND_ABBREVIATIONS[handResult.name] ?? "\u2014";
7905
- return `${abbreviation} (${handResult.name})`;
7906
- }
7907
- function balancedStyle2(data, colors2) {
7908
- const { holeCards, boardCards, handResult } = data;
7909
- const participatingSet = new Set(handResult?.participatingIndices || []);
7910
- const handStr = holeCards.map((hc, idx) => formatCardByParticipation(hc, participatingSet.has(idx))).join("");
7911
- const boardStr = boardCards.map((bc, idx) => formatCardByParticipation(bc, participatingSet.has(idx + 2))).join("");
7912
- const labelColor = colors2?.participating ?? lightGray;
7913
- const handLabel = colorize2("Hand:", labelColor);
7914
- const boardLabel = colorize2("Board:", labelColor);
7915
- return `${handLabel} ${handStr}| ${boardLabel} ${boardStr}\u2192 ${formatHandResult(handResult, colors2)}`;
7916
- }
7917
- var pokerStyles = {
7918
- balanced: balancedStyle2,
7919
- compact: balancedStyle2,
7920
- playful: balancedStyle2,
7921
- "compact-verbose": (data, colors2) => {
7922
- const { holeCards, boardCards, handResult } = data;
7923
- const participatingSet = new Set(handResult?.participatingIndices || []);
7924
- const handStr = holeCards.map((hc, idx) => formatCardCompact(hc, participatingSet.has(idx))).join("");
7925
- const boardStr = boardCards.map((bc, idx) => formatCardCompact(bc, participatingSet.has(idx + 2))).join("");
7926
- const abbreviation = getHandAbbreviation(handResult);
7927
- const result = `${handStr}| ${boardStr}\u2192 ${abbreviation}`;
7928
- if (!colors2) return result;
7929
- return colorize2(result, colors2.result);
7930
- },
7931
- emoji: (data, colors2) => {
7932
- const { holeCards, boardCards, handResult } = data;
7933
- const participatingSet = new Set(handResult?.participatingIndices || []);
7934
- const handStr = holeCards.map((hc, idx) => formatCardEmojiByParticipation(hc, participatingSet.has(idx))).join("");
7935
- const boardStr = boardCards.map((bc, idx) => formatCardEmojiByParticipation(bc, participatingSet.has(idx + 2))).join("");
7936
- const labelColor = colors2?.participating ?? lightGray;
7937
- const handLabel = colorize2("Hand:", labelColor);
7938
- const boardLabel = colorize2("Board:", labelColor);
7939
- return `${handLabel} ${handStr}| ${boardLabel} ${boardStr}\u2192 ${formatHandResult(handResult, colors2)}`;
7940
- }
7941
- };
7942
-
7943
- // src/widgets/poker-widget.ts
7944
- var PokerWidget = class extends StdinDataWidget {
7945
- id = "poker";
7946
- metadata = createWidgetMetadata(
7947
- "Poker",
7948
- "Displays random Texas Hold'em hands for entertainment",
7949
- "1.0.0",
7950
- "claude-scope",
7951
- 4
7952
- // Fifth line (0-indexed)
7953
- );
7954
- holeCards = [];
7955
- boardCards = [];
7956
- handResult = null;
7957
- lastUpdateTimestamp = 0;
7958
- THROTTLE_MS = 5e3;
7959
- // 5 seconds
7960
- colors;
7961
- styleFn = pokerStyles.balanced;
7962
- setStyle(style = DEFAULT_WIDGET_STYLE) {
7963
- const fn = pokerStyles[style];
7964
- if (fn) {
7965
- this.styleFn = fn;
7966
- }
7967
- }
7968
- constructor(colors2) {
7969
- super();
7970
- this.colors = colors2 ?? DEFAULT_THEME;
7971
- }
7972
- /**
7973
- * Generate new poker hand on each update
7974
- */
7975
- async update(data) {
7976
- await super.update(data);
7977
- const now = Date.now();
7978
- if (this.lastUpdateTimestamp > 0 && now - this.lastUpdateTimestamp < this.THROTTLE_MS) {
7979
- return;
7980
- }
7981
- const deck = new Deck();
7982
- const hole = [deck.deal(), deck.deal()];
7983
- const board = [deck.deal(), deck.deal(), deck.deal(), deck.deal(), deck.deal()];
7984
- const result = evaluateHand(hole, board);
7985
- this.holeCards = hole.map((card) => ({
7986
- card,
7987
- formatted: this.formatCardColor(card)
7988
- }));
7989
- this.boardCards = board.map((card) => ({
7990
- card,
7991
- formatted: this.formatCardColor(card)
7992
- }));
7993
- const playerParticipates = result.participatingCards.some((idx) => idx < 2);
7994
- if (!playerParticipates) {
7995
- this.handResult = {
7996
- text: `Nothing \u{1F0CF}`,
7997
- participatingIndices: result.participatingCards
7998
- };
7999
- } else {
8000
- this.handResult = {
8001
- text: `${result.name}! ${result.emoji}`,
8002
- participatingIndices: result.participatingCards
8003
- };
8004
- }
8005
- this.lastUpdateTimestamp = now;
8006
- }
8007
- /**
8008
- * Format card with appropriate color (red for ♥♦, gray for ♠♣)
8009
- */
8010
- formatCardColor(card) {
8011
- const _color = isRedSuit(card.suit) ? "red" : "gray";
8012
- return formatCard(card);
8013
- }
8014
- renderWithData(_data, _context) {
8015
- const holeCardsData = this.holeCards.map((hc, idx) => ({
8016
- card: hc.card,
8017
- isParticipating: (this.handResult?.participatingIndices || []).includes(idx)
8018
- }));
8019
- const boardCardsData = this.boardCards.map((bc, idx) => ({
8020
- card: bc.card,
8021
- isParticipating: (this.handResult?.participatingIndices || []).includes(idx + 2)
8022
- }));
8023
- const handResult = this.handResult ? {
8024
- name: this.getHandName(this.handResult.text),
8025
- emoji: this.getHandEmoji(this.handResult.text),
8026
- participatingIndices: this.handResult.participatingIndices
8027
- } : null;
8028
- const renderData = {
8029
- holeCards: holeCardsData,
8030
- boardCards: boardCardsData,
8031
- handResult
8032
- };
8033
- return this.styleFn(renderData, this.colors.poker);
8034
- }
8035
- getHandName(text) {
8036
- const match = text.match(/^([^!]+)/);
8037
- return match ? match[1].trim() : "Nothing";
8038
- }
8039
- getHandEmoji(text) {
8040
- const match = text.match(/([🃏♠️♥️♦️♣️🎉✨🌟])/u);
8041
- return match ? match[1] : "\u{1F0CF}";
8042
- }
8043
- };
8044
-
8045
- // src/index.ts
8046
7519
  async function readStdin() {
8047
7520
  const chunks = [];
8048
7521
  for await (const chunk of process.stdin) {
@@ -8051,10 +7524,15 @@ async function readStdin() {
8051
7524
  return Buffer.concat(chunks).toString("utf8");
8052
7525
  }
8053
7526
  function applyWidgetConfig(widget, widgetId, config) {
8054
- for (const line of Object.values(config.lines)) {
8055
- const widgetConfig = line.find((w) => w.id === widgetId);
8056
- if (widgetConfig && typeof widget.setStyle === "function" && isValidWidgetStyle(widgetConfig.style)) {
8057
- widget.setStyle(widgetConfig.style);
7527
+ for (const [lineNum, widgets] of Object.entries(config.lines)) {
7528
+ const widgetConfig = widgets.find((w) => w.id === widgetId);
7529
+ if (widgetConfig) {
7530
+ if (typeof widget.setStyle === "function" && isValidWidgetStyle(widgetConfig.style)) {
7531
+ widget.setStyle(widgetConfig.style);
7532
+ }
7533
+ if (typeof widget.setLine === "function") {
7534
+ widget.setLine(parseInt(lineNum, 10));
7535
+ }
8058
7536
  break;
8059
7537
  }
8060
7538
  }
@@ -8106,8 +7584,6 @@ async function main() {
8106
7584
  widgetConfig
8107
7585
  );
8108
7586
  }
8109
- await registry.register(new PokerWidget());
8110
- await registry.register(new EmptyLineWidget());
8111
7587
  const renderer = new Renderer({
8112
7588
  separator: " \u2502 ",
8113
7589
  onError: (_error, _widget) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-scope",
3
- "version": "0.8.4",
3
+ "version": "0.8.6",
4
4
  "description": "Claude Code plugin for session status and analytics",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -19,12 +19,12 @@
19
19
  "build:tsc": "tsc",
20
20
  "build:bundle": "esbuild src/index.ts --bundle --platform=node --target=node18 --outfile=dist/claude-scope.cjs && chmod +x dist/claude-scope.cjs",
21
21
  "prebuild:bundle": "npm run build:tsc",
22
- "test": "tsx --test tests/e2e/stdin-flow.test.ts tests/integration/cli-flow.integration.test.ts tests/integration/five-widgets.integration.test.ts tests/integration/quick-config.integration.test.ts tests/integration/three-stage-config-flow.test.ts tests/unit/cli.test.ts tests/unit/cli/commands/quick-config/*.test.ts tests/unit/types.test.ts tests/unit/config/*.test.ts tests/unit/core/*.test.ts tests/unit/data/*.test.ts tests/unit/utils/*.test.ts tests/unit/widgets/*.test.ts tests/unit/ui/theme/*.test.ts",
23
- "test:unit": "tsx --test tests/unit/cli.test.ts tests/unit/types.test.ts tests/unit/config/*.test.ts tests/unit/core/*.test.ts tests/unit/data/*.test.ts tests/unit/utils/*.test.ts tests/unit/widgets/*.test.ts",
24
- "test:integration": "tsx --test tests/e2e/stdin-flow.test.ts tests/integration/cli-flow.integration.test.ts tests/integration/five-widgets.integration.test.ts tests/integration/quick-config.integration.test.ts tests/integration/three-stage-config-flow.test.ts",
25
- "test:coverage": "c8 --check-coverage --lines=80 --functions=75 --statements=80 --branches=65 --reporter=text --reporter=html --exclude='tests/**' --exclude='**/*.test.ts' tsx --test tests/e2e/stdin-flow.test.ts tests/integration/cli-flow.integration.test.ts tests/integration/five-widgets.integration.test.ts tests/integration/quick-config.integration.test.ts tests/integration/three-stage-config-flow.test.ts tests/unit/cli.test.ts tests/unit/cli/commands/quick-config/*.test.ts tests/unit/types.test.ts tests/unit/config/*.test.ts tests/unit/core/*.test.ts tests/unit/data/*.test.ts tests/unit/utils/*.test.ts tests/unit/widgets/*.test.ts tests/unit/ui/theme/*.test.ts",
26
- "test:snapshot": "SNAPSHOT_UPDATE=true tsx --test tests/e2e/stdin-flow.test.ts tests/integration/cli-flow.integration.test.ts tests/integration/five-widgets.integration.test.ts tests/integration/quick-config.integration.test.ts tests/integration/three-stage-config-flow.test.ts tests/unit/cli.test.ts tests/unit/cli/commands/quick-config/*.test.ts tests/unit/types.test.ts tests/unit/config/*.test.ts tests/unit/core/*.test.ts tests/unit/data/*.test.ts tests/unit/utils/*.test.ts tests/unit/widgets/*.test.ts",
27
- "test:snapshot:verify": "tsx --test tests/e2e/stdin-flow.test.ts tests/integration/cli-flow.integration.test.ts tests/integration/five-widgets.integration.test.ts tests/integration/quick-config.integration.test.ts tests/integration/three-stage-config-flow.test.ts tests/unit/cli.test.ts tests/unit/cli/commands/quick-config/*.test.ts tests/unit/types.test.ts tests/unit/config/*.test.ts tests/unit/core/*.test.ts tests/unit/data/*.test.ts tests/unit/utils/*.test.ts tests/unit/widgets/*.test.ts",
22
+ "test": "tsx --test tests/e2e/stdin-flow.test.ts tests/integration/cli-flow.integration.test.ts tests/integration/config-line-assignment.test.ts tests/integration/five-widgets.integration.test.ts tests/integration/preview-mock-config.test.ts tests/integration/quick-config.integration.test.ts tests/integration/three-stage-config-flow.test.ts tests/unit/cli.test.ts tests/unit/cli/commands/quick-config/*.test.ts tests/unit/providers/*.test.ts tests/unit/types.test.ts tests/unit/config/*.test.ts tests/unit/core/*.test.ts tests/unit/data/*.test.ts tests/unit/utils/*.test.ts tests/unit/widgets/*.test.ts tests/unit/ui/theme/*.test.ts",
23
+ "test:unit": "tsx --test tests/unit/cli.test.ts tests/unit/providers/*.test.ts tests/unit/types.test.ts tests/unit/config/*.test.ts tests/unit/core/*.test.ts tests/unit/data/*.test.ts tests/unit/utils/*.test.ts tests/unit/widgets/*.test.ts",
24
+ "test:integration": "tsx --test tests/e2e/stdin-flow.test.ts tests/integration/cli-flow.integration.test.ts tests/integration/config-line-assignment.test.ts tests/integration/five-widgets.integration.test.ts tests/integration/preview-mock-config.test.ts tests/integration/quick-config.integration.test.ts tests/integration/three-stage-config-flow.test.ts",
25
+ "test:coverage": "c8 --check-coverage --lines=80 --functions=75 --statements=80 --branches=65 --reporter=text --reporter=html --exclude='tests/**' --exclude='**/*.test.ts' tsx --test tests/e2e/stdin-flow.test.ts tests/integration/cli-flow.integration.test.ts tests/integration/config-line-assignment.test.ts tests/integration/five-widgets.integration.test.ts tests/integration/preview-mock-config.test.ts tests/integration/quick-config.integration.test.ts tests/integration/three-stage-config-flow.test.ts tests/unit/cli.test.ts tests/unit/cli/commands/quick-config/*.test.ts tests/unit/providers/*.test.ts tests/unit/types.test.ts tests/unit/config/*.test.ts tests/unit/core/*.test.ts tests/unit/data/*.test.ts tests/unit/utils/*.test.ts tests/unit/widgets/*.test.ts tests/unit/ui/theme/*.test.ts",
26
+ "test:snapshot": "SNAPSHOT_UPDATE=true tsx --test tests/e2e/stdin-flow.test.ts tests/integration/cli-flow.integration.test.ts tests/integration/config-line-assignment.test.ts tests/integration/five-widgets.integration.test.ts tests/integration/preview-mock-config.test.ts tests/integration/quick-config.integration.test.ts tests/integration/three-stage-config-flow.test.ts tests/unit/cli.test.ts tests/unit/cli/commands/quick-config/*.test.ts tests/unit/providers/*.test.ts tests/unit/types.test.ts tests/unit/config/*.test.ts tests/unit/core/*.test.ts tests/unit/data/*.test.ts tests/unit/utils/*.test.ts tests/unit/widgets/*.test.ts",
27
+ "test:snapshot:verify": "tsx --test tests/e2e/stdin-flow.test.ts tests/integration/cli-flow.integration.test.ts tests/integration/config-line-assignment.test.ts tests/integration/five-widgets.integration.test.ts tests/integration/preview-mock-config.test.ts tests/integration/quick-config.integration.test.ts tests/integration/three-stage-config-flow.test.ts tests/unit/cli.test.ts tests/unit/cli/commands/quick-config/*.test.ts tests/unit/providers/*.test.ts tests/unit/types.test.ts tests/unit/config/*.test.ts tests/unit/core/*.test.ts tests/unit/data/*.test.ts tests/unit/utils/*.test.ts tests/unit/widgets/*.test.ts",
28
28
  "dev": "tsx src/index.ts",
29
29
  "prepare": "husky",
30
30
  "lint": "biome check .",