@owloops/claude-powerline 1.5.1 → 1.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -52,9 +52,9 @@
52
52
 
53
53
  - **Vim-style powerline** with proper arrows and segments
54
54
  - **Real-time session tracking** with costs and tokens
55
- - **Billing window tracking** with 5-hour block usage
55
+ - **Billing window tracking** with 5-hour blocks and burn rates
56
56
  - **Daily usage monitoring** with budget alerts
57
- - **Performance metrics** with response times and burn rates
57
+ - **Performance metrics** with response times
58
58
  - **Context monitoring** showing tokens used and auto-compact threshold
59
59
  - **Git integration** with branch, status, ahead/behind counts
60
60
 
@@ -222,7 +222,7 @@ Configuration priority (top overrides bottom):
222
222
  "segments": {
223
223
  "directory": {
224
224
  "enabled": true,
225
- "useBasename": false
225
+ "showBasename": false
226
226
  },
227
227
  "git": {
228
228
  "enabled": true,
@@ -237,7 +237,7 @@ Configuration priority (top overrides bottom):
237
237
  },
238
238
  "model": { "enabled": true },
239
239
  "session": { "enabled": true, "type": "tokens" },
240
- "block": { "enabled": true, "type": "cost" },
240
+ "block": { "enabled": true, "type": "cost", "burnType": "cost" },
241
241
  "today": { "enabled": true, "type": "cost" },
242
242
  "context": { "enabled": true },
243
243
  "tmux": { "enabled": true },
@@ -246,9 +246,7 @@ Configuration priority (top overrides bottom):
246
246
  "showResponseTime": true,
247
247
  "showLastResponseTime": false,
248
248
  "showDuration": true,
249
- "showMessageCount": true,
250
- "showCostBurnRate": false,
251
- "showTokenBurnRate": false
249
+ "showMessageCount": true
252
250
  }
253
251
  }
254
252
  }
@@ -259,7 +257,7 @@ Configuration priority (top overrides bottom):
259
257
 
260
258
  ### Segment Details
261
259
 
262
- - **directory**: Current working directory name (supports `useBasename` option)
260
+ - **directory**: Current working directory name (supports `showBasename` option)
263
261
  - **git**: Branch, status, and extensive repository information (see Git Configuration below)
264
262
  - **model**: Current Claude model being used
265
263
  - **session**: Token usage and costs for current session
@@ -274,7 +272,7 @@ Configuration priority (top overrides bottom):
274
272
  ```json
275
273
  "directory": {
276
274
  "enabled": true,
277
- "useBasename": false // Show only folder name instead of full path
275
+ "showBasename": false // Show only folder name instead of full path
278
276
  }
279
277
  ```
280
278
 
@@ -315,9 +313,7 @@ The metrics segment displays performance analytics from your Claude sessions:
315
313
  "showResponseTime": true, // Average response time (`⧖ 3.2s`)
316
314
  "showLastResponseTime": false, // Last response time (`Δ 2.8s`)
317
315
  "showDuration": true, // Session duration (`⧗ 28m`)
318
- "showMessageCount": true, // User message count (`⟐ 93`)
319
- "showCostBurnRate": false, // Cost per hour (`⟢ $1.20/h`)
320
- "showTokenBurnRate": false // Tokens per hour (`⟢ 450K/h`)
316
+ "showMessageCount": true // User message count (`⟐ 93`)
321
317
  }
322
318
  ```
323
319
 
@@ -327,8 +323,6 @@ The metrics segment displays performance analytics from your Claude sessions:
327
323
  - `showLastResponseTime`: Time for the last response (shows `0.0s` while waiting)
328
324
  - `showDuration`: Total time since session started
329
325
  - `showMessageCount`: Number of user messages sent
330
- - `showCostBurnRate`: Spending rate per hour
331
- - `showTokenBurnRate`: Token consumption rate per hour
332
326
 
333
327
  ![Metrics Segment Example](images/claude-powerline-metrics.png)
334
328
 
@@ -369,6 +363,19 @@ The powerline includes three complementary usage segments:
369
363
 
370
364
  - `cost`: Show cost + time (`$0.05 (2h 30m left)`)
371
365
  - `tokens`: Show tokens + time (`1.2K tokens (2h 30m left)`)
366
+ - `both`: Show both cost and tokens + time
367
+ - `time`: Show only time remaining
368
+
369
+ **Block burn rates** (configured with `burnType`):
370
+
371
+ ```json
372
+ "block": { "enabled": true, "type": "cost", "burnType": "cost" }
373
+ ```
374
+
375
+ - `cost`: Show cost burn rate (`$0.05 | $1.20/h (2h 30m left)`)
376
+ - `tokens`: Show token burn rate (`1.2K | 450K/h (2h 30m left)`)
377
+ - `both`: Show both burn rates
378
+ - `none`: Hide burn rates
372
379
 
373
380
  **Budget Configuration:**
374
381
 
@@ -415,7 +422,7 @@ To prevent segment cutoff, configure multiple lines:
415
422
  {
416
423
  "segments": {
417
424
  "session": { "enabled": true, "type": "tokens" },
418
- "block": { "enabled": true, "type": "cost" },
425
+ "block": { "enabled": true, "type": "cost", "burnType": "cost" },
419
426
  "today": { "enabled": true, "type": "cost" },
420
427
  "context": { "enabled": true },
421
428
  "tmux": { "enabled": false },
package/dist/index.js CHANGED
@@ -858,6 +858,14 @@ async function getFileModificationDate(filePath) {
858
858
  return null;
859
859
  }
860
860
  }
861
+ function createUniqueHash(entry) {
862
+ const messageId = entry.message?.id || (typeof entry.raw.message === "object" && entry.raw.message !== null && "id" in entry.raw.message ? entry.raw.message.id : void 0);
863
+ const requestId = "requestId" in entry.raw ? entry.raw.requestId : void 0;
864
+ if (!messageId || !requestId) {
865
+ return null;
866
+ }
867
+ return `${messageId}:${requestId}`;
868
+ }
861
869
  async function parseJsonlFile(filePath) {
862
870
  try {
863
871
  const content = await readFile(filePath, "utf-8");
@@ -890,6 +898,7 @@ async function loadEntriesFromProjects(timeFilter, fileFilter, sortFiles = false
890
898
  const entries = [];
891
899
  const claudePaths = getClaudePaths();
892
900
  const projectPaths = await findProjectPaths(claudePaths);
901
+ const processedHashes = /* @__PURE__ */ new Set();
893
902
  const allFiles = [];
894
903
  for (const projectPath of projectPaths) {
895
904
  try {
@@ -922,6 +931,14 @@ async function loadEntriesFromProjects(timeFilter, fileFilter, sortFiles = false
922
931
  for (const filePath of allFiles) {
923
932
  const fileEntries = await parseJsonlFile(filePath);
924
933
  for (const entry of fileEntries) {
934
+ const uniqueHash = createUniqueHash(entry);
935
+ if (uniqueHash && processedHashes.has(uniqueHash)) {
936
+ debug(`Skipping duplicate entry: ${uniqueHash}`);
937
+ continue;
938
+ }
939
+ if (uniqueHash) {
940
+ processedHashes.add(uniqueHash);
941
+ }
925
942
  if (!timeFilter || timeFilter(entry)) {
926
943
  entries.push(entry);
927
944
  }
@@ -1612,7 +1629,7 @@ var SegmentRenderer = class {
1612
1629
  fgColor: colors.contextFg
1613
1630
  };
1614
1631
  }
1615
- renderMetrics(metricsInfo, colors, config) {
1632
+ renderMetrics(metricsInfo, colors, _blockInfo, config) {
1616
1633
  if (!metricsInfo) {
1617
1634
  return {
1618
1635
  text: `${this.symbols.metrics_response} new`,
@@ -1638,14 +1655,6 @@ var SegmentRenderer = class {
1638
1655
  `${this.symbols.metrics_messages} ${metricsInfo.messageCount}`
1639
1656
  );
1640
1657
  }
1641
- if (config?.showCostBurnRate && metricsInfo.costBurnRate !== null) {
1642
- const burnRate = metricsInfo.costBurnRate < 1 ? `${(metricsInfo.costBurnRate * 100).toFixed(0)}\xA2/h` : `$${metricsInfo.costBurnRate.toFixed(2)}/h`;
1643
- parts.push(`${this.symbols.metrics_burn} ${burnRate}`);
1644
- }
1645
- if (config?.showTokenBurnRate && metricsInfo.tokenBurnRate !== null) {
1646
- const tokenRate = formatTokens(Math.round(metricsInfo.tokenBurnRate));
1647
- parts.push(`${this.symbols.metrics_burn} ${tokenRate}/h`);
1648
- }
1649
1658
  if (parts.length === 0) {
1650
1659
  return {
1651
1660
  text: `${this.symbols.metrics_response} active`,
@@ -1659,25 +1668,57 @@ var SegmentRenderer = class {
1659
1668
  fgColor: colors.metricsFg
1660
1669
  };
1661
1670
  }
1662
- renderBlock(blockInfo, colors, type = "cost") {
1671
+ renderBlock(blockInfo, colors, config) {
1663
1672
  let displayText;
1664
1673
  if (blockInfo.cost === null && blockInfo.tokens === null) {
1665
1674
  displayText = "No active block";
1666
1675
  } else {
1676
+ const type = config?.type || "cost";
1677
+ const burnType = config?.burnType;
1667
1678
  const timeStr = blockInfo.timeRemaining !== null ? (() => {
1668
1679
  const hours = Math.floor(blockInfo.timeRemaining / 60);
1669
1680
  const minutes = blockInfo.timeRemaining % 60;
1670
1681
  return hours > 0 ? `${hours}h ${minutes}m` : `${minutes}m`;
1671
1682
  })() : null;
1683
+ let mainContent;
1672
1684
  switch (type) {
1673
1685
  case "cost":
1674
- displayText = timeStr ? `${formatCost(blockInfo.cost)} (${timeStr} left)` : formatCost(blockInfo.cost);
1686
+ mainContent = formatCost(blockInfo.cost);
1675
1687
  break;
1676
1688
  case "tokens":
1677
- displayText = timeStr ? `${formatTokens(blockInfo.tokens)} (${timeStr} left)` : formatTokens(blockInfo.tokens);
1689
+ mainContent = formatTokens(blockInfo.tokens);
1690
+ break;
1691
+ case "both":
1692
+ mainContent = `${formatCost(blockInfo.cost)} / ${formatTokens(blockInfo.tokens)}`;
1693
+ break;
1694
+ case "time":
1695
+ mainContent = timeStr || "N/A";
1678
1696
  break;
1679
1697
  default:
1680
- displayText = timeStr ? `${formatCost(blockInfo.cost)} (${timeStr} left)` : formatCost(blockInfo.cost);
1698
+ mainContent = formatCost(blockInfo.cost);
1699
+ }
1700
+ let burnContent = "";
1701
+ if (burnType && burnType !== "none") {
1702
+ switch (burnType) {
1703
+ case "cost":
1704
+ const costBurnRate = blockInfo.burnRate !== null ? blockInfo.burnRate < 1 ? `${(blockInfo.burnRate * 100).toFixed(0)}\xA2/h` : `$${blockInfo.burnRate.toFixed(2)}/h` : "N/A";
1705
+ burnContent = ` | ${costBurnRate}`;
1706
+ break;
1707
+ case "tokens":
1708
+ const tokenBurnRate = blockInfo.tokenBurnRate !== null ? `${formatTokens(Math.round(blockInfo.tokenBurnRate))}/h` : "N/A";
1709
+ burnContent = ` | ${tokenBurnRate}`;
1710
+ break;
1711
+ case "both":
1712
+ const costBurn = blockInfo.burnRate !== null ? blockInfo.burnRate < 1 ? `${(blockInfo.burnRate * 100).toFixed(0)}\xA2/h` : `$${blockInfo.burnRate.toFixed(2)}/h` : "N/A";
1713
+ const tokenBurn = blockInfo.tokenBurnRate !== null ? `${formatTokens(Math.round(blockInfo.tokenBurnRate))}/h` : "N/A";
1714
+ burnContent = ` | ${costBurn} / ${tokenBurn}`;
1715
+ break;
1716
+ }
1717
+ }
1718
+ if (type === "time") {
1719
+ displayText = mainContent;
1720
+ } else {
1721
+ displayText = timeStr ? `${mainContent}${burnContent} (${timeStr} left)` : `${mainContent}${burnContent}`;
1681
1722
  }
1682
1723
  }
1683
1724
  return {
@@ -1770,73 +1811,185 @@ function convertToUsageEntry(entry) {
1770
1811
  };
1771
1812
  }
1772
1813
  var BlockProvider = class {
1773
- async loadUsageEntries() {
1774
- const now = /* @__PURE__ */ new Date();
1775
- const hoursSinceMidnight = now.getHours();
1776
- const blockNumber = Math.floor(hoursSinceMidnight / 5);
1777
- const blockStart = /* @__PURE__ */ new Date();
1778
- blockStart.setHours(blockNumber * 5, 0, 0, 0);
1779
- const blockEnd = /* @__PURE__ */ new Date();
1780
- blockEnd.setHours((blockNumber + 1) * 5, 0, 0, 0);
1781
- debug(
1782
- `Block segment: Current block ${blockNumber} (${blockStart.toLocaleString()} - ${blockEnd.toLocaleString()})`
1814
+ sessionDurationHours = 5;
1815
+ floorToHour(timestamp) {
1816
+ const floored = new Date(timestamp);
1817
+ floored.setUTCMinutes(0, 0, 0);
1818
+ return floored;
1819
+ }
1820
+ identifySessionBlocks(entries) {
1821
+ if (entries.length === 0) return [];
1822
+ const sessionDurationMs = this.sessionDurationHours * 60 * 60 * 1e3;
1823
+ const blocks = [];
1824
+ const sortedEntries = [...entries].sort(
1825
+ (a, b) => a.timestamp.getTime() - b.timestamp.getTime()
1783
1826
  );
1827
+ let currentBlockStart = null;
1828
+ let currentBlockEntries = [];
1829
+ for (const entry of sortedEntries) {
1830
+ const entryTime = entry.timestamp;
1831
+ if (currentBlockStart == null) {
1832
+ currentBlockStart = this.floorToHour(entryTime);
1833
+ currentBlockEntries = [entry];
1834
+ } else {
1835
+ const timeSinceBlockStart = entryTime.getTime() - currentBlockStart.getTime();
1836
+ const lastEntry = currentBlockEntries[currentBlockEntries.length - 1];
1837
+ if (lastEntry == null) {
1838
+ continue;
1839
+ }
1840
+ const lastEntryTime = lastEntry.timestamp;
1841
+ const timeSinceLastEntry = entryTime.getTime() - lastEntryTime.getTime();
1842
+ if (timeSinceBlockStart > sessionDurationMs || timeSinceLastEntry > sessionDurationMs) {
1843
+ blocks.push(currentBlockEntries);
1844
+ currentBlockStart = this.floorToHour(entryTime);
1845
+ currentBlockEntries = [entry];
1846
+ } else {
1847
+ currentBlockEntries.push(entry);
1848
+ }
1849
+ }
1850
+ }
1851
+ if (currentBlockStart != null && currentBlockEntries.length > 0) {
1852
+ blocks.push(currentBlockEntries);
1853
+ }
1854
+ return blocks;
1855
+ }
1856
+ createBlockInfo(startTime, entries) {
1857
+ const now = /* @__PURE__ */ new Date();
1858
+ const sessionDurationMs = this.sessionDurationHours * 60 * 60 * 1e3;
1859
+ const endTime = new Date(startTime.getTime() + sessionDurationMs);
1860
+ const lastEntry = entries[entries.length - 1];
1861
+ const actualEndTime = lastEntry != null ? lastEntry.timestamp : startTime;
1862
+ const isActive = now.getTime() - actualEndTime.getTime() < sessionDurationMs && now < endTime;
1863
+ return { block: entries, isActive };
1864
+ }
1865
+ findActiveBlock(blocks) {
1866
+ for (let i = blocks.length - 1; i >= 0; i--) {
1867
+ const block = blocks[i];
1868
+ if (!block || block.length === 0) continue;
1869
+ const firstEntry = block[0];
1870
+ if (!firstEntry) continue;
1871
+ const blockStartTime = this.floorToHour(firstEntry.timestamp);
1872
+ const blockInfo = this.createBlockInfo(blockStartTime, block);
1873
+ if (blockInfo.isActive) {
1874
+ return blockInfo.block;
1875
+ }
1876
+ }
1877
+ return null;
1878
+ }
1879
+ async loadUsageEntries() {
1880
+ debug(`Block segment: Loading entries for dynamic session blocks`);
1881
+ const dayAgo = /* @__PURE__ */ new Date();
1882
+ dayAgo.setDate(dayAgo.getDate() - 1);
1784
1883
  const fileFilter = (_filePath, modTime) => {
1785
- return modTime >= blockStart;
1884
+ return modTime >= dayAgo;
1786
1885
  };
1787
1886
  const parsedEntries = await loadEntriesFromProjects(
1788
1887
  void 0,
1789
1888
  fileFilter,
1790
1889
  true
1791
1890
  );
1792
- const usageEntries = [];
1793
- let entriesInBlock = 0;
1891
+ const allUsageEntries = [];
1794
1892
  for (const entry of parsedEntries) {
1795
- if (entry.message?.usage && entry.timestamp >= blockStart && entry.timestamp < blockEnd) {
1893
+ if (entry.message?.usage) {
1796
1894
  const usageEntry = convertToUsageEntry(entry);
1797
1895
  if (!usageEntry.costUSD && entry.raw) {
1798
1896
  usageEntry.costUSD = await PricingService.calculateCostForEntry(
1799
1897
  entry.raw
1800
1898
  );
1801
1899
  }
1802
- usageEntries.push(usageEntry);
1803
- entriesInBlock++;
1900
+ allUsageEntries.push(usageEntry);
1901
+ }
1902
+ }
1903
+ const sessionBlocks = this.identifySessionBlocks(allUsageEntries);
1904
+ debug(`Block segment: Found ${sessionBlocks.length} session blocks`);
1905
+ const activeBlock = this.findActiveBlock(sessionBlocks);
1906
+ if (activeBlock && activeBlock.length > 0) {
1907
+ debug(
1908
+ `Block segment: Found active block with ${activeBlock.length} entries`
1909
+ );
1910
+ const blockStart = activeBlock[0];
1911
+ const blockEnd = activeBlock[activeBlock.length - 1];
1912
+ if (blockStart && blockEnd) {
1913
+ debug(
1914
+ `Block segment: Active block from ${blockStart.timestamp.toISOString()} to ${blockEnd.timestamp.toISOString()}`
1915
+ );
1804
1916
  }
1917
+ return activeBlock;
1918
+ } else {
1919
+ debug(`Block segment: No active block found`);
1920
+ return [];
1805
1921
  }
1806
- debug(`Block segment: Found ${entriesInBlock} entries in current block`);
1807
- return usageEntries;
1808
1922
  }
1809
1923
  async getActiveBlockInfo() {
1810
1924
  try {
1811
1925
  const entries = await this.loadUsageEntries();
1812
1926
  if (entries.length === 0) {
1813
1927
  debug("Block segment: No entries in current block");
1814
- return { cost: null, tokens: null, timeRemaining: null };
1928
+ return {
1929
+ cost: null,
1930
+ tokens: null,
1931
+ timeRemaining: null,
1932
+ burnRate: null,
1933
+ tokenBurnRate: null
1934
+ };
1815
1935
  }
1816
1936
  const totalCost = entries.reduce((sum, entry) => sum + entry.costUSD, 0);
1817
1937
  const totalTokens = entries.reduce((sum, entry) => {
1818
1938
  return sum + entry.usage.inputTokens + entry.usage.outputTokens + entry.usage.cacheCreationInputTokens + entry.usage.cacheReadInputTokens;
1819
1939
  }, 0);
1820
1940
  const now = /* @__PURE__ */ new Date();
1821
- const hoursSinceMidnight = now.getHours();
1822
- const blockNumber = Math.floor(hoursSinceMidnight / 5);
1823
- const blockEnd = /* @__PURE__ */ new Date();
1824
- blockEnd.setHours((blockNumber + 1) * 5, 0, 0, 0);
1825
- const timeRemaining = Math.max(
1826
- 0,
1827
- Math.round((blockEnd.getTime() - now.getTime()) / (1e3 * 60))
1828
- );
1941
+ let timeRemaining = null;
1942
+ if (entries.length > 0) {
1943
+ const firstEntry = entries[0];
1944
+ if (firstEntry) {
1945
+ const sessionDurationMs = this.sessionDurationHours * 60 * 60 * 1e3;
1946
+ const blockStartTime = this.floorToHour(firstEntry.timestamp);
1947
+ const sessionEndTime = new Date(
1948
+ blockStartTime.getTime() + sessionDurationMs
1949
+ );
1950
+ timeRemaining = Math.max(
1951
+ 0,
1952
+ Math.round((sessionEndTime.getTime() - now.getTime()) / (1e3 * 60))
1953
+ );
1954
+ }
1955
+ }
1956
+ let burnRate = null;
1957
+ let tokenBurnRate = null;
1958
+ if (entries.length >= 1 && (totalCost > 0 || totalTokens > 0)) {
1959
+ const timestamps = entries.map((entry) => entry.timestamp).sort((a, b) => a.getTime() - b.getTime());
1960
+ const firstEntry = timestamps[0];
1961
+ const lastEntry = timestamps[timestamps.length - 1];
1962
+ if (firstEntry && lastEntry) {
1963
+ const durationMinutes = (lastEntry.getTime() - firstEntry.getTime()) / (1e3 * 60);
1964
+ if (durationMinutes > 0) {
1965
+ if (totalCost > 0) {
1966
+ burnRate = totalCost / durationMinutes * 60;
1967
+ }
1968
+ if (totalTokens > 0) {
1969
+ tokenBurnRate = totalTokens / durationMinutes * 60;
1970
+ }
1971
+ }
1972
+ }
1973
+ }
1829
1974
  debug(
1830
- `Block segment: $${totalCost.toFixed(2)}, ${totalTokens} tokens, ${timeRemaining}m remaining`
1975
+ `Block segment: $${totalCost.toFixed(2)}, ${totalTokens} tokens, ${timeRemaining}m remaining, burn rate: ${burnRate ? "$" + burnRate.toFixed(2) + "/hr" : "N/A"}`
1831
1976
  );
1832
1977
  return {
1833
1978
  cost: totalCost,
1834
1979
  tokens: totalTokens,
1835
- timeRemaining
1980
+ timeRemaining,
1981
+ burnRate,
1982
+ tokenBurnRate
1836
1983
  };
1837
1984
  } catch (error) {
1838
1985
  debug("Error getting active block info:", error);
1839
- return { cost: null, tokens: null, timeRemaining: null };
1986
+ return {
1987
+ cost: null,
1988
+ tokens: null,
1989
+ timeRemaining: null,
1990
+ burnRate: null,
1991
+ tokenBurnRate: null
1992
+ };
1840
1993
  }
1841
1994
  }
1842
1995
  };
@@ -1848,10 +2001,6 @@ function formatDate(date) {
1848
2001
  const day = String(date.getDate()).padStart(2, "0");
1849
2002
  return `${year}-${month}-${day}`;
1850
2003
  }
1851
- function isToday(date) {
1852
- const today = /* @__PURE__ */ new Date();
1853
- return formatDate(date) === formatDate(today);
1854
- }
1855
2004
  function getTotalTokens(usage) {
1856
2005
  return usage.inputTokens + usage.outputTokens + usage.cacheCreationInputTokens + usage.cacheReadInputTokens;
1857
2006
  }
@@ -1872,13 +2021,13 @@ var TodayProvider = class {
1872
2021
  cache = /* @__PURE__ */ new Map();
1873
2022
  CACHE_TTL = 3e5;
1874
2023
  async loadTodayEntries() {
1875
- const todayStart = /* @__PURE__ */ new Date();
1876
- todayStart.setHours(0, 0, 0, 0);
1877
- debug(
1878
- `Today segment: Loading entries since ${todayStart.toLocaleString()}`
1879
- );
2024
+ const today = /* @__PURE__ */ new Date();
2025
+ const todayDateString = formatDate(today);
2026
+ debug(`Today segment: Loading entries for date ${todayDateString}`);
2027
+ const weekAgo = /* @__PURE__ */ new Date();
2028
+ weekAgo.setDate(weekAgo.getDate() - 7);
1880
2029
  const fileFilter = (_filePath, modTime) => {
1881
- return modTime >= todayStart;
2030
+ return modTime >= weekAgo;
1882
2031
  };
1883
2032
  const parsedEntries = await loadEntriesFromProjects(
1884
2033
  void 0,
@@ -1888,11 +2037,8 @@ var TodayProvider = class {
1888
2037
  const todayEntries = [];
1889
2038
  let entriesFound = 0;
1890
2039
  for (const entry of parsedEntries) {
1891
- if (entry.timestamp < todayStart) {
1892
- debug(`Today segment: Early exit at ${entry.timestamp.toISOString()}`);
1893
- break;
1894
- }
1895
- if (entry.message?.usage && isToday(entry.timestamp)) {
2040
+ const entryDateString = formatDate(entry.timestamp);
2041
+ if (entryDateString === todayDateString && entry.message?.usage) {
1896
2042
  const todayEntry = convertToTodayEntry(entry);
1897
2043
  if (!todayEntry.costUSD && entry.raw) {
1898
2044
  todayEntry.costUSD = await PricingService.calculateCostForEntry(
@@ -1903,7 +2049,9 @@ var TodayProvider = class {
1903
2049
  entriesFound++;
1904
2050
  }
1905
2051
  }
1906
- debug(`Today segment: Found ${entriesFound} entries for today`);
2052
+ debug(
2053
+ `Today segment: Found ${entriesFound} entries for today (${todayDateString})`
2054
+ );
1907
2055
  return todayEntries;
1908
2056
  }
1909
2057
  async getTodayEntries() {
@@ -2131,12 +2279,13 @@ var PowerlineRenderer = class {
2131
2279
  return this.segmentRenderer.renderMetrics(
2132
2280
  metricsInfo,
2133
2281
  colors,
2282
+ blockInfo,
2134
2283
  metricsConfig
2135
2284
  );
2136
2285
  case "block":
2137
2286
  if (!blockInfo) return null;
2138
- const blockType = segment.config?.type || "cost";
2139
- return this.segmentRenderer.renderBlock(blockInfo, colors, blockType);
2287
+ const blockConfig = segment.config;
2288
+ return this.segmentRenderer.renderBlock(blockInfo, colors, blockConfig);
2140
2289
  case "today":
2141
2290
  if (!todayInfo) return null;
2142
2291
  const todayType = segment.config?.type || "cost";
@@ -2282,7 +2431,7 @@ var DEFAULT_CONFIG = {
2282
2431
  model: { enabled: true },
2283
2432
  session: { enabled: true, type: "tokens" },
2284
2433
  today: { enabled: false, type: "cost" },
2285
- block: { enabled: true, type: "cost" },
2434
+ block: { enabled: true, type: "cost", burnType: "cost" },
2286
2435
  tmux: { enabled: false },
2287
2436
  context: { enabled: true },
2288
2437
  metrics: {
@@ -2290,9 +2439,7 @@ var DEFAULT_CONFIG = {
2290
2439
  showResponseTime: true,
2291
2440
  showLastResponseTime: false,
2292
2441
  showDuration: true,
2293
- showMessageCount: true,
2294
- showCostBurnRate: false,
2295
- showTokenBurnRate: false
2442
+ showMessageCount: true
2296
2443
  }
2297
2444
  }
2298
2445
  }