claude-scope 0.8.33 → 0.8.34

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 +141 -31
  2. package/package.json +1 -1
@@ -2413,12 +2413,96 @@ var init_widget_types = __esm({
2413
2413
  }
2414
2414
  });
2415
2415
 
2416
+ // src/providers/usage-parser.ts
2417
+ var import_node_fs, import_node_readline, UsageParser;
2418
+ var init_usage_parser = __esm({
2419
+ "src/providers/usage-parser.ts"() {
2420
+ "use strict";
2421
+ import_node_fs = require("node:fs");
2422
+ import_node_readline = require("node:readline");
2423
+ UsageParser = class {
2424
+ /**
2425
+ * Parse the last assistant message with usage data from transcript
2426
+ * Reads file in reverse to find the most recent data quickly
2427
+ *
2428
+ * @param transcriptPath - Path to the JSONL transcript file
2429
+ * @returns ContextUsage or null if not found
2430
+ */
2431
+ async parseLastUsage(transcriptPath) {
2432
+ if (!(0, import_node_fs.existsSync)(transcriptPath)) {
2433
+ return null;
2434
+ }
2435
+ try {
2436
+ const lines = await this.readAllLines(transcriptPath);
2437
+ for (let i = lines.length - 1; i >= 0; i--) {
2438
+ const usage = this.parseLineForUsage(lines[i]);
2439
+ if (usage) {
2440
+ return usage;
2441
+ }
2442
+ }
2443
+ return null;
2444
+ } catch {
2445
+ return null;
2446
+ }
2447
+ }
2448
+ /**
2449
+ * Read all lines from transcript file
2450
+ */
2451
+ async readAllLines(transcriptPath) {
2452
+ const lines = [];
2453
+ try {
2454
+ const fileStream = (0, import_node_fs.createReadStream)(transcriptPath, { encoding: "utf-8" });
2455
+ const rl = (0, import_node_readline.createInterface)({
2456
+ input: fileStream,
2457
+ crlfDelay: Infinity
2458
+ });
2459
+ for await (const line of rl) {
2460
+ if (line.trim()) {
2461
+ lines.push(line);
2462
+ }
2463
+ }
2464
+ } catch {
2465
+ return [];
2466
+ }
2467
+ return lines;
2468
+ }
2469
+ /**
2470
+ * Parse a single transcript line for usage data
2471
+ * Returns null if line is not an assistant message with usage
2472
+ */
2473
+ parseLineForUsage(line) {
2474
+ try {
2475
+ const entry = JSON.parse(line);
2476
+ if (entry.type !== "assistant") {
2477
+ return null;
2478
+ }
2479
+ const usage = entry.message?.usage;
2480
+ if (!usage) {
2481
+ return null;
2482
+ }
2483
+ if (typeof usage.input_tokens !== "number" || typeof usage.output_tokens !== "number" || typeof usage.cache_read_input_tokens !== "number") {
2484
+ return null;
2485
+ }
2486
+ return {
2487
+ input_tokens: usage.input_tokens,
2488
+ output_tokens: usage.output_tokens,
2489
+ cache_creation_input_tokens: usage.cache_creation_input_tokens ?? 0,
2490
+ cache_read_input_tokens: usage.cache_read_input_tokens
2491
+ };
2492
+ } catch {
2493
+ return null;
2494
+ }
2495
+ }
2496
+ };
2497
+ }
2498
+ });
2499
+
2416
2500
  // src/storage/cache-manager.ts
2417
- var import_node_fs, import_node_os2, import_node_path2, DEFAULT_CACHE_PATH, DEFAULT_EXPIRY_MS, CacheManager;
2501
+ var import_node_fs2, import_node_os2, import_node_path2, DEFAULT_CACHE_PATH, DEFAULT_EXPIRY_MS, CacheManager;
2418
2502
  var init_cache_manager = __esm({
2419
2503
  "src/storage/cache-manager.ts"() {
2420
2504
  "use strict";
2421
- import_node_fs = require("node:fs");
2505
+ import_node_fs2 = require("node:fs");
2422
2506
  import_node_os2 = require("node:os");
2423
2507
  import_node_path2 = require("node:path");
2424
2508
  DEFAULT_CACHE_PATH = `${(0, import_node_os2.homedir)()}/.config/claude-scope/cache.json`;
@@ -2491,11 +2575,11 @@ var init_cache_manager = __esm({
2491
2575
  * Load cache from file
2492
2576
  */
2493
2577
  loadCache() {
2494
- if (!(0, import_node_fs.existsSync)(this.cachePath)) {
2578
+ if (!(0, import_node_fs2.existsSync)(this.cachePath)) {
2495
2579
  return { sessions: {}, version: 1 };
2496
2580
  }
2497
2581
  try {
2498
- const content = (0, import_node_fs.readFileSync)(this.cachePath, "utf-8");
2582
+ const content = (0, import_node_fs2.readFileSync)(this.cachePath, "utf-8");
2499
2583
  return JSON.parse(content);
2500
2584
  } catch {
2501
2585
  return { sessions: {}, version: 1 };
@@ -2506,7 +2590,7 @@ var init_cache_manager = __esm({
2506
2590
  */
2507
2591
  saveCache(cache) {
2508
2592
  try {
2509
- (0, import_node_fs.writeFileSync)(this.cachePath, JSON.stringify(cache, null, 2), "utf-8");
2593
+ (0, import_node_fs2.writeFileSync)(this.cachePath, JSON.stringify(cache, null, 2), "utf-8");
2510
2594
  } catch {
2511
2595
  }
2512
2596
  }
@@ -2516,8 +2600,8 @@ var init_cache_manager = __esm({
2516
2600
  ensureCacheDir() {
2517
2601
  try {
2518
2602
  const dir = (0, import_node_path2.dirname)(this.cachePath);
2519
- if (!(0, import_node_fs.existsSync)(dir)) {
2520
- (0, import_node_fs.mkdirSync)(dir, { recursive: true });
2603
+ if (!(0, import_node_fs2.existsSync)(dir)) {
2604
+ (0, import_node_fs2.mkdirSync)(dir, { recursive: true });
2521
2605
  }
2522
2606
  } catch {
2523
2607
  }
@@ -2665,6 +2749,7 @@ var init_cache_metrics_widget = __esm({
2665
2749
  "src/widgets/cache-metrics/cache-metrics-widget.ts"() {
2666
2750
  "use strict";
2667
2751
  init_widget_types();
2752
+ init_usage_parser();
2668
2753
  init_cache_manager();
2669
2754
  init_theme();
2670
2755
  init_stdin_data_widget();
@@ -2684,11 +2769,15 @@ var init_cache_metrics_widget = __esm({
2684
2769
  style = "balanced";
2685
2770
  renderData;
2686
2771
  cacheManager;
2772
+ usageParser;
2687
2773
  lastSessionId;
2774
+ cachedUsage;
2775
+ // Cache parsed usage within render cycle
2688
2776
  constructor(theme) {
2689
2777
  super();
2690
2778
  this.theme = theme ?? DEFAULT_THEME;
2691
2779
  this.cacheManager = new CacheManager();
2780
+ this.usageParser = new UsageParser();
2692
2781
  }
2693
2782
  /**
2694
2783
  * Set display style
@@ -2706,14 +2795,7 @@ var init_cache_metrics_widget = __esm({
2706
2795
  * Calculate cache metrics from context usage data
2707
2796
  * Returns zero metrics if no usage data is available (widget should always be visible)
2708
2797
  */
2709
- calculateMetrics(data) {
2710
- let usage = data.context_window?.current_usage;
2711
- if (!usage) {
2712
- const cached = this.cacheManager.getCachedUsage(data.session_id);
2713
- if (cached) {
2714
- usage = cached.usage;
2715
- }
2716
- }
2798
+ calculateMetrics(usage) {
2717
2799
  if (!usage) {
2718
2800
  return {
2719
2801
  cacheRead: 0,
@@ -2763,16 +2845,31 @@ var init_cache_metrics_widget = __esm({
2763
2845
  });
2764
2846
  }
2765
2847
  }
2766
- const metrics = this.calculateMetrics(data);
2767
- this.renderData = metrics ?? void 0;
2848
+ if (!usage) {
2849
+ this.cachedUsage = await this.usageParser.parseLastUsage(data.transcript_path);
2850
+ } else {
2851
+ this.cachedUsage = void 0;
2852
+ }
2768
2853
  }
2769
2854
  /**
2770
2855
  * Render the cache metrics display
2771
2856
  */
2772
- renderWithData(_data, _context) {
2773
- if (!this.renderData) {
2857
+ renderWithData(data, _context) {
2858
+ let usage = data.context_window?.current_usage;
2859
+ if (!usage && this.cachedUsage) {
2860
+ usage = this.cachedUsage;
2861
+ }
2862
+ if (!usage) {
2863
+ const cached = this.cacheManager.getCachedUsage(data.session_id);
2864
+ if (cached) {
2865
+ usage = cached.usage;
2866
+ }
2867
+ }
2868
+ const metrics = this.calculateMetrics(usage);
2869
+ if (!metrics) {
2774
2870
  return null;
2775
2871
  }
2872
+ this.renderData = metrics;
2776
2873
  const styleFn = cacheMetricsStyles[this.style] ?? cacheMetricsStyles.balanced;
2777
2874
  if (!styleFn) {
2778
2875
  return null;
@@ -3259,6 +3356,7 @@ var init_context_widget = __esm({
3259
3356
  "src/widgets/context-widget.ts"() {
3260
3357
  "use strict";
3261
3358
  init_widget_types();
3359
+ init_usage_parser();
3262
3360
  init_cache_manager();
3263
3361
  init_theme();
3264
3362
  init_styles4();
@@ -3277,11 +3375,15 @@ var init_context_widget = __esm({
3277
3375
  _lineOverride;
3278
3376
  styleFn = contextStyles.balanced;
3279
3377
  cacheManager;
3378
+ usageParser;
3280
3379
  lastSessionId;
3380
+ cachedUsage;
3381
+ // Cache parsed usage within render cycle
3281
3382
  constructor(colors2) {
3282
3383
  super();
3283
3384
  this.colors = colors2 ?? DEFAULT_THEME;
3284
3385
  this.cacheManager = new CacheManager();
3386
+ this.usageParser = new UsageParser();
3285
3387
  }
3286
3388
  setStyle(style = "balanced") {
3287
3389
  const fn = contextStyles[style];
@@ -3314,10 +3416,18 @@ var init_context_widget = __esm({
3314
3416
  });
3315
3417
  }
3316
3418
  }
3419
+ if (!current_usage) {
3420
+ this.cachedUsage = await this.usageParser.parseLastUsage(data.transcript_path);
3421
+ } else {
3422
+ this.cachedUsage = void 0;
3423
+ }
3317
3424
  }
3318
3425
  renderWithData(data, _context) {
3319
3426
  const { current_usage, context_window_size } = data.context_window;
3320
3427
  let usage = current_usage;
3428
+ if (!usage && this.cachedUsage) {
3429
+ usage = this.cachedUsage;
3430
+ }
3321
3431
  if (!usage) {
3322
3432
  const cached = this.cacheManager.getCachedUsage(data.session_id);
3323
3433
  if (cached) {
@@ -26149,8 +26259,8 @@ init_renderer();
26149
26259
  init_widget_registry();
26150
26260
 
26151
26261
  // src/providers/transcript-provider.ts
26152
- var import_node_fs2 = require("node:fs");
26153
- var import_node_readline = require("node:readline");
26262
+ var import_node_fs3 = require("node:fs");
26263
+ var import_node_readline2 = require("node:readline");
26154
26264
  var TranscriptProvider = class {
26155
26265
  MAX_TOOLS = 20;
26156
26266
  /**
@@ -26159,13 +26269,13 @@ var TranscriptProvider = class {
26159
26269
  * @returns Array of tool entries, limited to last 20
26160
26270
  */
26161
26271
  async parseTools(transcriptPath) {
26162
- if (!(0, import_node_fs2.existsSync)(transcriptPath)) {
26272
+ if (!(0, import_node_fs3.existsSync)(transcriptPath)) {
26163
26273
  return [];
26164
26274
  }
26165
26275
  const toolMap = /* @__PURE__ */ new Map();
26166
26276
  try {
26167
- const fileStream = (0, import_node_fs2.createReadStream)(transcriptPath, { encoding: "utf-8" });
26168
- const rl = (0, import_node_readline.createInterface)({
26277
+ const fileStream = (0, import_node_fs3.createReadStream)(transcriptPath, { encoding: "utf-8" });
26278
+ const rl = (0, import_node_readline2.createInterface)({
26169
26279
  input: fileStream,
26170
26280
  crlfDelay: Infinity
26171
26281
  });
@@ -26444,13 +26554,13 @@ async function routeCommand(command) {
26444
26554
  }
26445
26555
 
26446
26556
  // src/config/config-loader.ts
26447
- var import_node_fs4 = require("node:fs");
26557
+ var import_node_fs5 = require("node:fs");
26448
26558
  var import_promises2 = require("node:fs/promises");
26449
26559
  var import_node_os4 = require("node:os");
26450
26560
  var import_node_path4 = require("node:path");
26451
26561
 
26452
26562
  // src/config/default-config-generator.ts
26453
- var import_node_fs3 = require("node:fs");
26563
+ var import_node_fs4 = require("node:fs");
26454
26564
  var import_node_os3 = require("node:os");
26455
26565
  var import_node_path3 = require("node:path");
26456
26566
  function getDefaultConfigPath() {
@@ -26458,15 +26568,15 @@ function getDefaultConfigPath() {
26458
26568
  }
26459
26569
  async function ensureDefaultConfig() {
26460
26570
  const configPath = getDefaultConfigPath();
26461
- if ((0, import_node_fs3.existsSync)(configPath)) {
26571
+ if ((0, import_node_fs4.existsSync)(configPath)) {
26462
26572
  return;
26463
26573
  }
26464
26574
  const configDir = (0, import_node_path3.join)((0, import_node_os3.homedir)(), ".claude-scope");
26465
- if (!(0, import_node_fs3.existsSync)(configDir)) {
26466
- (0, import_node_fs3.mkdirSync)(configDir, { recursive: true });
26575
+ if (!(0, import_node_fs4.existsSync)(configDir)) {
26576
+ (0, import_node_fs4.mkdirSync)(configDir, { recursive: true });
26467
26577
  }
26468
26578
  const defaultConfig = generateRichLayout("balanced", "dracula");
26469
- (0, import_node_fs3.writeFileSync)(configPath, JSON.stringify(defaultConfig, null, 2), "utf-8");
26579
+ (0, import_node_fs4.writeFileSync)(configPath, JSON.stringify(defaultConfig, null, 2), "utf-8");
26470
26580
  }
26471
26581
 
26472
26582
  // src/config/config-loader.ts
@@ -26479,7 +26589,7 @@ function getConfigPath() {
26479
26589
  async function loadWidgetConfig() {
26480
26590
  const configPath = getConfigPath();
26481
26591
  await ensureDefaultConfig();
26482
- if (!(0, import_node_fs4.existsSync)(configPath)) {
26592
+ if (!(0, import_node_fs5.existsSync)(configPath)) {
26483
26593
  return null;
26484
26594
  }
26485
26595
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-scope",
3
- "version": "0.8.33",
3
+ "version": "0.8.34",
4
4
  "description": "Claude Code plugin for session status and analytics",
5
5
  "license": "MIT",
6
6
  "type": "module",