claude-scope 0.8.26 → 0.8.29

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.
@@ -1559,52 +1559,73 @@ var init_constants = __esm({
1559
1559
  "use strict";
1560
1560
  TIME = {
1561
1561
  /** Milliseconds per second */
1562
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1562
1563
  MS_PER_SECOND: 1e3,
1563
1564
  /** Seconds per minute */
1565
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1564
1566
  SECONDS_PER_MINUTE: 60,
1565
1567
  /** Seconds per hour */
1568
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1566
1569
  SECONDS_PER_HOUR: 3600
1567
1570
  };
1568
1571
  DEFAULTS = {
1569
1572
  /** Default separator between widgets */
1573
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1570
1574
  SEPARATOR: " ",
1571
1575
  /** Default width for progress bars in characters */
1576
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1572
1577
  PROGRESS_BAR_WIDTH: 20
1573
1578
  };
1574
1579
  ANSI_COLORS = {
1575
1580
  /** Green color */
1581
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1576
1582
  GREEN: "\x1B[32m",
1577
1583
  /** Yellow color */
1584
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1578
1585
  YELLOW: "\x1B[33m",
1579
1586
  /** Red color */
1587
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1580
1588
  RED: "\x1B[31m",
1581
1589
  /** Reset color */
1590
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1582
1591
  RESET: "\x1B[0m"
1583
1592
  };
1584
1593
  DEMO_DATA = {
1585
1594
  /** Demo session cost in USD */
1595
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1586
1596
  COST_USD: 0.42,
1587
1597
  /** Demo session duration in milliseconds (~1h 1m 5s) */
1598
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1588
1599
  DURATION_MS: 3665e3,
1589
1600
  /** Demo API duration in milliseconds (~50m) */
1601
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1590
1602
  API_DURATION_MS: 3e6,
1591
1603
  /** Demo lines added */
1604
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1592
1605
  LINES_ADDED: 142,
1593
1606
  /** Demo lines removed */
1607
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1594
1608
  LINES_REMOVED: 27,
1595
1609
  /** Demo context window size in tokens */
1610
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1596
1611
  CONTEXT_WINDOW_SIZE: 2e5,
1597
1612
  /** Demo total input tokens */
1613
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1598
1614
  TOTAL_INPUT_TOKENS: 185e3,
1599
1615
  /** Demo total output tokens */
1616
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1600
1617
  TOTAL_OUTPUT_TOKENS: 5e4,
1601
1618
  /** Demo current input tokens */
1619
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1602
1620
  CURRENT_INPUT_TOKENS: 8e4,
1603
1621
  /** Demo current output tokens */
1622
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1604
1623
  CURRENT_OUTPUT_TOKENS: 3e4,
1605
1624
  /** Demo cache creation tokens */
1625
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1606
1626
  CACHE_CREATION_TOKENS: 1e3,
1607
1627
  /** Demo cache read tokens */
1628
+ // biome-ignore lint/style/useNamingConvention: UPPER_CASE is standard for constants
1608
1629
  CACHE_READ_TOKENS: 15e3
1609
1630
  };
1610
1631
  DEFAULT_PROGRESS_BAR_WIDTH = DEFAULTS.PROGRESS_BAR_WIDTH;
@@ -1633,6 +1654,8 @@ var init_renderer = __esm({
1633
1654
  * on separate lines. Widgets that throw errors are logged (via onError
1634
1655
  * callback) and skipped, allowing other widgets to continue rendering.
1635
1656
  *
1657
+ * Empty lines are preserved to maintain correct line positioning.
1658
+ *
1636
1659
  * @param widgets - Array of widgets to render
1637
1660
  * @param context - Render context with width and timestamp
1638
1661
  * @returns Array of rendered lines (one per line number)
@@ -1649,9 +1672,9 @@ var init_renderer = __esm({
1649
1672
  }
1650
1673
  lineMap.get(line)?.push(widget);
1651
1674
  }
1652
- const lines = [];
1675
+ const lineOutputs = /* @__PURE__ */ new Map();
1653
1676
  const sortedLines = Array.from(lineMap.entries()).sort((a, b) => a[0] - b[0]);
1654
- for (const [, widgetsForLine] of sortedLines) {
1677
+ for (const [lineNum, widgetsForLine] of sortedLines) {
1655
1678
  const outputs = [];
1656
1679
  for (const widget of widgetsForLine) {
1657
1680
  try {
@@ -1667,10 +1690,10 @@ var init_renderer = __esm({
1667
1690
  }
1668
1691
  }
1669
1692
  const line = outputs.join(this.separator);
1670
- if (outputs.length > 0) {
1671
- lines.push(line);
1672
- }
1693
+ lineOutputs.set(lineNum, line);
1673
1694
  }
1695
+ const sortedEntries = Array.from(lineOutputs.entries()).sort((a, b) => a[0] - b[0]);
1696
+ const lines = sortedEntries.map(([, output]) => output);
1674
1697
  return lines;
1675
1698
  }
1676
1699
  /**
@@ -26242,6 +26265,40 @@ init_model_widget();
26242
26265
 
26243
26266
  // src/widgets/sysmon-widget.ts
26244
26267
  init_widget_types();
26268
+
26269
+ // src/providers/metrics-cache.ts
26270
+ var MetricsCache = class {
26271
+ cached = null;
26272
+ cacheTime = 0;
26273
+ ttlMs;
26274
+ constructor(ttlMs = 1e3) {
26275
+ this.ttlMs = ttlMs;
26276
+ }
26277
+ /**
26278
+ * Get cached metrics or fetch fresh if cache expired
26279
+ * @param fetcher - Function to fetch fresh metrics
26280
+ * @returns Cached or fresh metrics, or null if fetcher returns null
26281
+ */
26282
+ async get(fetcher) {
26283
+ const now = Date.now();
26284
+ if (this.cached && now - this.cacheTime < this.ttlMs) {
26285
+ return this.cached;
26286
+ }
26287
+ const fresh = await fetcher();
26288
+ this.cached = fresh;
26289
+ this.cacheTime = now;
26290
+ return fresh;
26291
+ }
26292
+ /**
26293
+ * Clear the cache
26294
+ */
26295
+ clear() {
26296
+ this.cached = null;
26297
+ this.cacheTime = 0;
26298
+ }
26299
+ };
26300
+
26301
+ // src/widgets/sysmon-widget.ts
26245
26302
  init_theme();
26246
26303
 
26247
26304
  // src/widgets/sysmon/styles.ts
@@ -26313,29 +26370,27 @@ var SysmonWidget = class {
26313
26370
  provider;
26314
26371
  _lineOverride;
26315
26372
  styleFn = sysmonStyles.balanced;
26316
- currentMetrics = null;
26317
- updateIntervalMs = 2500;
26318
- // 2.5 seconds
26373
+ cache;
26374
+ cacheTtlMs = 1e3;
26375
+ // 1 second cache
26319
26376
  enabled = true;
26320
26377
  constructor(colors2, provider) {
26321
26378
  this.colors = colors2 ?? DEFAULT_THEME;
26322
26379
  this.provider = provider ?? null;
26380
+ this.cache = new MetricsCache(this.cacheTtlMs);
26323
26381
  }
26324
26382
  async initialize(context) {
26325
26383
  this.enabled = context.config?.enabled !== false;
26326
- if (!this.provider || !this.enabled) {
26327
- return;
26328
- }
26329
- this.currentMetrics = await this.provider.getMetrics();
26330
- this.provider.startUpdate(this.updateIntervalMs, (metrics) => {
26331
- this.currentMetrics = metrics;
26332
- });
26333
26384
  }
26334
26385
  async render(_context) {
26335
- if (!this.currentMetrics || !this.isEnabled()) {
26386
+ if (!this.provider || !this.isEnabled()) {
26336
26387
  return null;
26337
26388
  }
26338
- return this.styleFn(this.currentMetrics, this.colors.sysmon);
26389
+ const metrics = await this.cache.get(() => this.provider.getMetrics());
26390
+ if (!metrics) {
26391
+ return null;
26392
+ }
26393
+ return this.styleFn(metrics, this.colors.sysmon);
26339
26394
  }
26340
26395
  async update(_data) {
26341
26396
  }
@@ -26343,7 +26398,7 @@ var SysmonWidget = class {
26343
26398
  return this.enabled && this.provider !== null;
26344
26399
  }
26345
26400
  async cleanup() {
26346
- this.provider?.stopUpdate();
26401
+ this.cache.clear();
26347
26402
  }
26348
26403
  setStyle(style = "balanced") {
26349
26404
  const fn = sysmonStyles[style];
@@ -26533,6 +26588,9 @@ var SystemProvider = class {
26533
26588
  this.logError(error);
26534
26589
  });
26535
26590
  }, intervalMs);
26591
+ if (this.intervalId && typeof this.intervalId.unref === "function") {
26592
+ this.intervalId.unref();
26593
+ }
26536
26594
  }
26537
26595
  stopUpdate() {
26538
26596
  if (this.intervalId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-scope",
3
- "version": "0.8.26",
3
+ "version": "0.8.29",
4
4
  "description": "Claude Code plugin for session status and analytics",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -28,7 +28,8 @@
28
28
  "dev": "tsx src/index.ts",
29
29
  "prepare": "husky",
30
30
  "lint": "biome check .",
31
- "lint:fix": "biome check --write ."
31
+ "lint:fix": "biome check --write .",
32
+ "lint:file-size": "node scripts/check-file-size.js"
32
33
  },
33
34
  "devDependencies": {
34
35
  "@biomejs/biome": "^2.3.11",