ccstatusline-usage 2.1.11 → 2.1.13
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 +11 -1
- package/dist/ccstatusline.js +140 -148
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ This fork adds API-based usage widgets beyond the upstream:
|
|
|
38
38
|
### Enhanced Status Line Preview
|
|
39
39
|
|
|
40
40
|
```
|
|
41
|
-
Session: [████░░░░░░░░░░░] 27.0% | Weekly: [
|
|
41
|
+
Session: [████░░░░░░░░░░░] 27.0% | Weekly: [███████████████] 100.0% | Extra: €2.50/€50.00 | Model: Opus 4.6 | Session ID: 0109b99d...
|
|
42
42
|
Context: [███████░░░░░░░░] 103k/200k (51%)
|
|
43
43
|
```
|
|
44
44
|
|
|
@@ -64,6 +64,16 @@ Session: [████░░░░░░░░░░░] 27.0% | Weekly: [██
|
|
|
64
64
|
|
|
65
65
|
## 🆕 Recent Updates
|
|
66
66
|
|
|
67
|
+
### [v2.1.13](https://github.com/pcvelz/ccstatusline-usage/releases/tag/v2.1.13) - Fix stale API cache causing stuck usage display
|
|
68
|
+
|
|
69
|
+
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Stale cache expiry** — API usage data older than 10 minutes is now discarded instead of served indefinitely, preventing frozen percentage displays
|
|
70
|
+
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **429 rate limit handling** — Properly detects HTTP 429 responses and backs off for 120s instead of hammering the API every 30s
|
|
71
|
+
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Token cache invalidation** — Automatically re-reads OAuth token from Keychain/disk when stale cache expires, recovering from expired tokens
|
|
72
|
+
|
|
73
|
+
### [v2.1.12](https://github.com/pcvelz/ccstatusline-usage/releases/tag/v2.1.12) - Remove thinking effort bars from model widget
|
|
74
|
+
|
|
75
|
+
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Remove thinking effort bars** — Claude Code now shows thinking intensity natively in its own UI, so the `▌▌▌` bars after the model name have been removed from the Model widget
|
|
76
|
+
|
|
67
77
|
### [v2.1.11](https://github.com/pcvelz/ccstatusline-usage/releases/tag/v2.1.11) - Configurable extra usage balance
|
|
68
78
|
|
|
69
79
|
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Configurable extra usage balance** — Add `extraUsageBalance` setting (in cents) to `~/.config/ccstatusline/settings.json` to override the API's monthly limit with your actual prepaid balance (e.g., `"extraUsageBalance": 5000` shows `Extra: €0.00/€50.00`)
|
package/dist/ccstatusline.js
CHANGED
|
@@ -32401,8 +32401,8 @@ var require_utils = __commonJS((exports) => {
|
|
|
32401
32401
|
}
|
|
32402
32402
|
return output;
|
|
32403
32403
|
};
|
|
32404
|
-
exports.basename = (
|
|
32405
|
-
const segs =
|
|
32404
|
+
exports.basename = (path6, { windows } = {}) => {
|
|
32405
|
+
const segs = path6.split(windows ? /[\\/]/ : "/");
|
|
32406
32406
|
const last2 = segs[segs.length - 1];
|
|
32407
32407
|
if (last2 === "") {
|
|
32408
32408
|
return segs[segs.length - 2];
|
|
@@ -33924,6 +33924,9 @@ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
|
33924
33924
|
if (env.TERM === "xterm-ghostty") {
|
|
33925
33925
|
return 3;
|
|
33926
33926
|
}
|
|
33927
|
+
if (env.TERM === "wezterm") {
|
|
33928
|
+
return 3;
|
|
33929
|
+
}
|
|
33927
33930
|
if ("TERM_PROGRAM" in env) {
|
|
33928
33931
|
const version = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
33929
33932
|
switch (env.TERM_PROGRAM) {
|
|
@@ -51470,7 +51473,7 @@ import { execSync as execSync3 } from "child_process";
|
|
|
51470
51473
|
import * as fs5 from "fs";
|
|
51471
51474
|
import * as path4 from "path";
|
|
51472
51475
|
var __dirname = "/Users/peter/Documents/Code/ccstatusline-usage/src/utils";
|
|
51473
|
-
var PACKAGE_VERSION = "2.1.
|
|
51476
|
+
var PACKAGE_VERSION = "2.1.13";
|
|
51474
51477
|
function getPackageVersion() {
|
|
51475
51478
|
if (/^\d+\.\d+\.\d+/.test(PACKAGE_VERSION)) {
|
|
51476
51479
|
return PACKAGE_VERSION;
|
|
@@ -52320,9 +52323,6 @@ var shouldInsertInput = (input, key) => {
|
|
|
52320
52323
|
};
|
|
52321
52324
|
|
|
52322
52325
|
// src/widgets/Model.ts
|
|
52323
|
-
import * as fs6 from "fs";
|
|
52324
|
-
import { homedir as homedir4 } from "os";
|
|
52325
|
-
import * as path5 from "path";
|
|
52326
52326
|
var MOBILE_THRESHOLD = 80;
|
|
52327
52327
|
function compactModelName(name) {
|
|
52328
52328
|
const stripped = name.replace(/^claude-/, "");
|
|
@@ -52333,44 +52333,6 @@ function compactModelName(name) {
|
|
|
52333
52333
|
}
|
|
52334
52334
|
return stripped;
|
|
52335
52335
|
}
|
|
52336
|
-
function getEffortLevel() {
|
|
52337
|
-
const envLevel = process.env.CLAUDE_CODE_EFFORT_LEVEL;
|
|
52338
|
-
if (envLevel)
|
|
52339
|
-
return envLevel.toLowerCase();
|
|
52340
|
-
try {
|
|
52341
|
-
const configDir = process.env.CLAUDE_CONFIG_DIR ?? path5.join(homedir4(), ".claude");
|
|
52342
|
-
const settingsPath = path5.join(configDir, "settings.json");
|
|
52343
|
-
const content = fs6.readFileSync(settingsPath, "utf-8");
|
|
52344
|
-
const settings = JSON.parse(content);
|
|
52345
|
-
if (settings.effortLevel)
|
|
52346
|
-
return settings.effortLevel.toLowerCase();
|
|
52347
|
-
} catch {}
|
|
52348
|
-
return "high";
|
|
52349
|
-
}
|
|
52350
|
-
function effortToLevel(effort) {
|
|
52351
|
-
switch (effort) {
|
|
52352
|
-
case "low":
|
|
52353
|
-
return 1;
|
|
52354
|
-
case "medium":
|
|
52355
|
-
return 2;
|
|
52356
|
-
default:
|
|
52357
|
-
return 3;
|
|
52358
|
-
}
|
|
52359
|
-
}
|
|
52360
|
-
function renderThinkingBars(level, settings) {
|
|
52361
|
-
if (level <= 0)
|
|
52362
|
-
return "";
|
|
52363
|
-
const colorLevel = getColorLevelString(settings.colorLevel);
|
|
52364
|
-
const activeChalk = getChalkColor("red", colorLevel);
|
|
52365
|
-
const dimChalk = getChalkColor("brightBlack", colorLevel);
|
|
52366
|
-
const bars = ["▌", "▌", "▌"];
|
|
52367
|
-
return " " + bars.map((bar, i) => {
|
|
52368
|
-
if (i < level) {
|
|
52369
|
-
return activeChalk ? activeChalk(bar) : bar;
|
|
52370
|
-
}
|
|
52371
|
-
return dimChalk ? dimChalk(bar) : bar;
|
|
52372
|
-
}).join("");
|
|
52373
|
-
}
|
|
52374
52336
|
|
|
52375
52337
|
class ModelWidget {
|
|
52376
52338
|
getDefaultColor() {
|
|
@@ -52390,21 +52352,18 @@ class ModelWidget {
|
|
|
52390
52352
|
}
|
|
52391
52353
|
render(item, context, settings) {
|
|
52392
52354
|
if (context.isPreview) {
|
|
52393
|
-
|
|
52394
|
-
return item.rawValue ? `Claude${bars2}` : `Model: Claude${bars2}`;
|
|
52355
|
+
return item.rawValue ? "Claude" : "Model: Claude";
|
|
52395
52356
|
}
|
|
52396
52357
|
const model = context.data?.model;
|
|
52397
52358
|
const modelId = typeof model === "string" ? model : model?.id;
|
|
52398
52359
|
const modelDisplayName = typeof model === "string" ? model : model?.display_name ?? model?.id;
|
|
52399
52360
|
if (!modelDisplayName)
|
|
52400
52361
|
return null;
|
|
52401
|
-
const level = effortToLevel(getEffortLevel());
|
|
52402
|
-
const bars = renderThinkingBars(level, settings);
|
|
52403
52362
|
const mobile = (context.terminalWidth ?? 0) > 0 && (context.terminalWidth ?? 0) < MOBILE_THRESHOLD;
|
|
52404
52363
|
if (mobile && modelId) {
|
|
52405
|
-
return `M: ${compactModelName(modelId)}
|
|
52364
|
+
return `M: ${compactModelName(modelId)}`;
|
|
52406
52365
|
}
|
|
52407
|
-
return item.rawValue ?
|
|
52366
|
+
return item.rawValue ? modelDisplayName : `Model: ${modelDisplayName}`;
|
|
52408
52367
|
}
|
|
52409
52368
|
supportsRawValue() {
|
|
52410
52369
|
return true;
|
|
@@ -54564,27 +54523,27 @@ class CurrentWorkingDirWidget {
|
|
|
54564
54523
|
supportsColors(item) {
|
|
54565
54524
|
return true;
|
|
54566
54525
|
}
|
|
54567
|
-
abbreviateHomeDir(
|
|
54526
|
+
abbreviateHomeDir(path5) {
|
|
54568
54527
|
const homeDir = os5.homedir();
|
|
54569
|
-
if (
|
|
54528
|
+
if (path5 === homeDir) {
|
|
54570
54529
|
return "~";
|
|
54571
54530
|
}
|
|
54572
|
-
if (
|
|
54573
|
-
const boundaryChar =
|
|
54531
|
+
if (path5.startsWith(homeDir)) {
|
|
54532
|
+
const boundaryChar = path5[homeDir.length];
|
|
54574
54533
|
if (boundaryChar !== "/" && boundaryChar !== "\\") {
|
|
54575
|
-
return
|
|
54534
|
+
return path5;
|
|
54576
54535
|
}
|
|
54577
|
-
return "~" +
|
|
54536
|
+
return "~" + path5.slice(homeDir.length);
|
|
54578
54537
|
}
|
|
54579
|
-
return
|
|
54538
|
+
return path5;
|
|
54580
54539
|
}
|
|
54581
|
-
abbreviatePath(
|
|
54540
|
+
abbreviatePath(path5) {
|
|
54582
54541
|
const homeDir = os5.homedir();
|
|
54583
|
-
const useBackslash =
|
|
54542
|
+
const useBackslash = path5.includes("\\") && !path5.includes("/");
|
|
54584
54543
|
const sep = useBackslash ? "\\" : "/";
|
|
54585
|
-
let normalizedPath =
|
|
54586
|
-
if (
|
|
54587
|
-
normalizedPath = "~" +
|
|
54544
|
+
let normalizedPath = path5;
|
|
54545
|
+
if (path5.startsWith(homeDir)) {
|
|
54546
|
+
normalizedPath = "~" + path5.slice(homeDir.length);
|
|
54588
54547
|
}
|
|
54589
54548
|
const parts = normalizedPath.split(/[\\/]+/).filter((part) => part !== "");
|
|
54590
54549
|
const abbreviated = parts.map((part, index) => {
|
|
@@ -54708,22 +54667,23 @@ import {
|
|
|
54708
54667
|
execSync as execSync6,
|
|
54709
54668
|
spawnSync
|
|
54710
54669
|
} from "child_process";
|
|
54711
|
-
import * as
|
|
54670
|
+
import * as fs6 from "fs";
|
|
54712
54671
|
import * as os6 from "os";
|
|
54713
|
-
import * as
|
|
54714
|
-
var CACHE_FILE =
|
|
54715
|
-
var LOCK_FILE =
|
|
54672
|
+
import * as path5 from "path";
|
|
54673
|
+
var CACHE_FILE = path5.join(os6.homedir(), ".cache", "ccstatusline-api.json");
|
|
54674
|
+
var LOCK_FILE = path5.join(os6.homedir(), ".cache", "ccstatusline-api.lock");
|
|
54716
54675
|
var CACHE_MAX_AGE = 180;
|
|
54717
54676
|
var LOCK_MAX_AGE = 30;
|
|
54718
54677
|
var TOKEN_CACHE_MAX_AGE = 3600;
|
|
54678
|
+
var STALE_MAX_AGE = 600;
|
|
54719
54679
|
var cachedData = null;
|
|
54720
54680
|
var cacheTime = 0;
|
|
54721
54681
|
var cachedToken = null;
|
|
54722
54682
|
var tokenCacheTime = 0;
|
|
54723
|
-
var CRED_FILE =
|
|
54683
|
+
var CRED_FILE = path5.join(os6.homedir(), ".claude", ".credentials.json");
|
|
54724
54684
|
function readTokenFromFile() {
|
|
54725
54685
|
try {
|
|
54726
|
-
const creds = JSON.parse(
|
|
54686
|
+
const creds = JSON.parse(fs6.readFileSync(CRED_FILE, "utf8"));
|
|
54727
54687
|
return creds?.claudeAiOauth?.accessToken ?? null;
|
|
54728
54688
|
} catch {
|
|
54729
54689
|
return null;
|
|
@@ -54760,7 +54720,18 @@ function getToken() {
|
|
|
54760
54720
|
}
|
|
54761
54721
|
function readStaleCache() {
|
|
54762
54722
|
try {
|
|
54763
|
-
|
|
54723
|
+
const data = JSON.parse(fs6.readFileSync(CACHE_FILE, "utf8"));
|
|
54724
|
+
if (data.fetchedAt) {
|
|
54725
|
+
const age = Math.floor(Date.now() / 1000) - data.fetchedAt;
|
|
54726
|
+
if (age > STALE_MAX_AGE)
|
|
54727
|
+
return null;
|
|
54728
|
+
} else {
|
|
54729
|
+
const stat = fs6.statSync(CACHE_FILE);
|
|
54730
|
+
const age = Math.floor(Date.now() / 1000) - Math.floor(stat.mtimeMs / 1000);
|
|
54731
|
+
if (age > STALE_MAX_AGE)
|
|
54732
|
+
return null;
|
|
54733
|
+
}
|
|
54734
|
+
return data;
|
|
54764
54735
|
} catch {
|
|
54765
54736
|
return null;
|
|
54766
54737
|
}
|
|
@@ -54786,6 +54757,8 @@ function fetchFromApi(token) {
|
|
|
54786
54757
|
process.stdout.write(data);
|
|
54787
54758
|
} else if (res.statusCode === 401) {
|
|
54788
54759
|
process.exit(2);
|
|
54760
|
+
} else if (res.statusCode === 429) {
|
|
54761
|
+
process.exit(3);
|
|
54789
54762
|
} else {
|
|
54790
54763
|
process.exit(1);
|
|
54791
54764
|
}
|
|
@@ -54803,11 +54776,15 @@ function fetchFromApi(token) {
|
|
|
54803
54776
|
if (result2.error || !result2.stdout) {
|
|
54804
54777
|
if (result2.status === 2)
|
|
54805
54778
|
return "auth-error";
|
|
54779
|
+
if (result2.status === 3)
|
|
54780
|
+
return "rate-limited";
|
|
54806
54781
|
return null;
|
|
54807
54782
|
}
|
|
54808
54783
|
if (result2.status !== 0) {
|
|
54809
54784
|
if (result2.status === 2)
|
|
54810
54785
|
return "auth-error";
|
|
54786
|
+
if (result2.status === 3)
|
|
54787
|
+
return "rate-limited";
|
|
54811
54788
|
return null;
|
|
54812
54789
|
}
|
|
54813
54790
|
return result2.stdout;
|
|
@@ -54818,10 +54795,10 @@ function fetchApiData() {
|
|
|
54818
54795
|
return cachedData;
|
|
54819
54796
|
}
|
|
54820
54797
|
try {
|
|
54821
|
-
const stat =
|
|
54798
|
+
const stat = fs6.statSync(CACHE_FILE);
|
|
54822
54799
|
const fileAge = now2 - Math.floor(stat.mtimeMs / 1000);
|
|
54823
54800
|
if (fileAge < CACHE_MAX_AGE) {
|
|
54824
|
-
const fileData = JSON.parse(
|
|
54801
|
+
const fileData = JSON.parse(fs6.readFileSync(CACHE_FILE, "utf8"));
|
|
54825
54802
|
if (!fileData.error) {
|
|
54826
54803
|
cachedData = fileData;
|
|
54827
54804
|
cacheTime = now2;
|
|
@@ -54830,7 +54807,7 @@ function fetchApiData() {
|
|
|
54830
54807
|
}
|
|
54831
54808
|
} catch {}
|
|
54832
54809
|
try {
|
|
54833
|
-
const lockStat =
|
|
54810
|
+
const lockStat = fs6.statSync(LOCK_FILE);
|
|
54834
54811
|
const lockAge = now2 - Math.floor(lockStat.mtimeMs / 1000);
|
|
54835
54812
|
if (lockAge < LOCK_MAX_AGE) {
|
|
54836
54813
|
const stale = readStaleCache();
|
|
@@ -54840,12 +54817,16 @@ function fetchApiData() {
|
|
|
54840
54817
|
}
|
|
54841
54818
|
} catch {}
|
|
54842
54819
|
try {
|
|
54843
|
-
const lockDir =
|
|
54844
|
-
if (!
|
|
54845
|
-
|
|
54820
|
+
const lockDir = path5.dirname(LOCK_FILE);
|
|
54821
|
+
if (!fs6.existsSync(lockDir)) {
|
|
54822
|
+
fs6.mkdirSync(lockDir, { recursive: true });
|
|
54846
54823
|
}
|
|
54847
|
-
|
|
54824
|
+
fs6.writeFileSync(LOCK_FILE, "");
|
|
54848
54825
|
} catch {}
|
|
54826
|
+
const staleBeforeFetch = readStaleCache();
|
|
54827
|
+
if (!staleBeforeFetch) {
|
|
54828
|
+
invalidateTokenCache();
|
|
54829
|
+
}
|
|
54849
54830
|
const token = getToken();
|
|
54850
54831
|
if (!token) {
|
|
54851
54832
|
const stale = readStaleCache();
|
|
@@ -54862,6 +54843,16 @@ function fetchApiData() {
|
|
|
54862
54843
|
return stale;
|
|
54863
54844
|
return { error: "api-error" };
|
|
54864
54845
|
}
|
|
54846
|
+
if (response === "rate-limited") {
|
|
54847
|
+
try {
|
|
54848
|
+
const futureTime = new Date(Date.now() + 90000);
|
|
54849
|
+
fs6.utimesSync(LOCK_FILE, futureTime, futureTime);
|
|
54850
|
+
} catch {}
|
|
54851
|
+
const stale = readStaleCache();
|
|
54852
|
+
if (stale && !stale.error)
|
|
54853
|
+
return stale;
|
|
54854
|
+
return { error: "timeout" };
|
|
54855
|
+
}
|
|
54865
54856
|
if (!response) {
|
|
54866
54857
|
const stale = readStaleCache();
|
|
54867
54858
|
if (stale && !stale.error)
|
|
@@ -54889,12 +54880,13 @@ function fetchApiData() {
|
|
|
54889
54880
|
return stale;
|
|
54890
54881
|
return { error: "parse-error" };
|
|
54891
54882
|
}
|
|
54883
|
+
apiData.fetchedAt = now2;
|
|
54892
54884
|
try {
|
|
54893
|
-
const cacheDir =
|
|
54894
|
-
if (!
|
|
54895
|
-
|
|
54885
|
+
const cacheDir = path5.dirname(CACHE_FILE);
|
|
54886
|
+
if (!fs6.existsSync(cacheDir)) {
|
|
54887
|
+
fs6.mkdirSync(cacheDir, { recursive: true });
|
|
54896
54888
|
}
|
|
54897
|
-
|
|
54889
|
+
fs6.writeFileSync(CACHE_FILE, JSON.stringify(apiData));
|
|
54898
54890
|
} catch {}
|
|
54899
54891
|
cachedData = apiData;
|
|
54900
54892
|
cacheTime = now2;
|
|
@@ -55114,7 +55106,7 @@ class ContextBarWidget {
|
|
|
55114
55106
|
}
|
|
55115
55107
|
}
|
|
55116
55108
|
// src/widgets/SessionName.ts
|
|
55117
|
-
import * as
|
|
55109
|
+
import * as fs7 from "fs";
|
|
55118
55110
|
|
|
55119
55111
|
class SessionNameWidget {
|
|
55120
55112
|
getDefaultColor() {
|
|
@@ -55141,7 +55133,7 @@ class SessionNameWidget {
|
|
|
55141
55133
|
return null;
|
|
55142
55134
|
}
|
|
55143
55135
|
try {
|
|
55144
|
-
const content =
|
|
55136
|
+
const content = fs7.readFileSync(transcriptPath, "utf-8");
|
|
55145
55137
|
const lines = content.split(`
|
|
55146
55138
|
`);
|
|
55147
55139
|
for (let i = lines.length - 1;i >= 0; i--) {
|
|
@@ -55250,7 +55242,7 @@ class FreeMemoryWidget {
|
|
|
55250
55242
|
}
|
|
55251
55243
|
// src/widgets/Battery.ts
|
|
55252
55244
|
import { execSync as execSync8 } from "child_process";
|
|
55253
|
-
import { readFileSync as
|
|
55245
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
55254
55246
|
function getMacBatteryInfo() {
|
|
55255
55247
|
try {
|
|
55256
55248
|
const output = execSync8("pmset -g batt", { encoding: "utf-8", timeout: 2000 });
|
|
@@ -55270,8 +55262,8 @@ function getMacBatteryInfo() {
|
|
|
55270
55262
|
}
|
|
55271
55263
|
function getLinuxBatteryInfo() {
|
|
55272
55264
|
try {
|
|
55273
|
-
const capacity =
|
|
55274
|
-
const status =
|
|
55265
|
+
const capacity = readFileSync5("/sys/class/power_supply/BAT0/capacity", "utf-8").trim();
|
|
55266
|
+
const status = readFileSync5("/sys/class/power_supply/BAT0/status", "utf-8").trim().toLowerCase();
|
|
55275
55267
|
const percent = parseInt(capacity, 10);
|
|
55276
55268
|
if (isNaN(percent)) {
|
|
55277
55269
|
return null;
|
|
@@ -59720,44 +59712,44 @@ function renderCompactOutput(preRenderedLines, settings, maxWidth) {
|
|
|
59720
59712
|
}
|
|
59721
59713
|
|
|
59722
59714
|
// src/utils/jsonl.ts
|
|
59723
|
-
import * as
|
|
59715
|
+
import * as fs8 from "fs";
|
|
59724
59716
|
import { createHash } from "node:crypto";
|
|
59725
59717
|
import os9 from "node:os";
|
|
59726
|
-
import
|
|
59718
|
+
import path7 from "node:path";
|
|
59727
59719
|
|
|
59728
59720
|
// node_modules/tinyglobby/dist/index.mjs
|
|
59729
|
-
import
|
|
59721
|
+
import path6, { posix } from "path";
|
|
59730
59722
|
|
|
59731
59723
|
// node_modules/fdir/dist/index.mjs
|
|
59732
59724
|
import { createRequire as createRequire2 } from "module";
|
|
59733
59725
|
import { basename as basename2, dirname as dirname3, normalize, relative, resolve as resolve2, sep } from "path";
|
|
59734
59726
|
import * as nativeFs from "fs";
|
|
59735
59727
|
var __require2 = /* @__PURE__ */ createRequire2(import.meta.url);
|
|
59736
|
-
function cleanPath(
|
|
59737
|
-
let normalized = normalize(
|
|
59728
|
+
function cleanPath(path6) {
|
|
59729
|
+
let normalized = normalize(path6);
|
|
59738
59730
|
if (normalized.length > 1 && normalized[normalized.length - 1] === sep)
|
|
59739
59731
|
normalized = normalized.substring(0, normalized.length - 1);
|
|
59740
59732
|
return normalized;
|
|
59741
59733
|
}
|
|
59742
59734
|
var SLASHES_REGEX = /[\\/]/g;
|
|
59743
|
-
function convertSlashes(
|
|
59744
|
-
return
|
|
59735
|
+
function convertSlashes(path6, separator) {
|
|
59736
|
+
return path6.replace(SLASHES_REGEX, separator);
|
|
59745
59737
|
}
|
|
59746
59738
|
var WINDOWS_ROOT_DIR_REGEX = /^[a-z]:[\\/]$/i;
|
|
59747
|
-
function isRootDirectory(
|
|
59748
|
-
return
|
|
59739
|
+
function isRootDirectory(path6) {
|
|
59740
|
+
return path6 === "/" || WINDOWS_ROOT_DIR_REGEX.test(path6);
|
|
59749
59741
|
}
|
|
59750
|
-
function normalizePath(
|
|
59742
|
+
function normalizePath(path6, options) {
|
|
59751
59743
|
const { resolvePaths, normalizePath: normalizePath$1, pathSeparator } = options;
|
|
59752
|
-
const pathNeedsCleaning = process.platform === "win32" &&
|
|
59744
|
+
const pathNeedsCleaning = process.platform === "win32" && path6.includes("/") || path6.startsWith(".");
|
|
59753
59745
|
if (resolvePaths)
|
|
59754
|
-
|
|
59746
|
+
path6 = resolve2(path6);
|
|
59755
59747
|
if (normalizePath$1 || pathNeedsCleaning)
|
|
59756
|
-
|
|
59757
|
-
if (
|
|
59748
|
+
path6 = cleanPath(path6);
|
|
59749
|
+
if (path6 === ".")
|
|
59758
59750
|
return "";
|
|
59759
|
-
const needsSeperator =
|
|
59760
|
-
return convertSlashes(needsSeperator ?
|
|
59751
|
+
const needsSeperator = path6[path6.length - 1] !== pathSeparator;
|
|
59752
|
+
return convertSlashes(needsSeperator ? path6 + pathSeparator : path6, pathSeparator);
|
|
59761
59753
|
}
|
|
59762
59754
|
function joinPathWithBasePath(filename, directoryPath) {
|
|
59763
59755
|
return directoryPath + filename;
|
|
@@ -59797,9 +59789,9 @@ var pushDirectory = (directoryPath, paths) => {
|
|
|
59797
59789
|
paths.push(directoryPath || ".");
|
|
59798
59790
|
};
|
|
59799
59791
|
var pushDirectoryFilter = (directoryPath, paths, filters) => {
|
|
59800
|
-
const
|
|
59801
|
-
if (filters.every((filter2) => filter2(
|
|
59802
|
-
paths.push(
|
|
59792
|
+
const path6 = directoryPath || ".";
|
|
59793
|
+
if (filters.every((filter2) => filter2(path6, true)))
|
|
59794
|
+
paths.push(path6);
|
|
59803
59795
|
};
|
|
59804
59796
|
var empty$2 = () => {};
|
|
59805
59797
|
function build$6(root, options) {
|
|
@@ -59856,29 +59848,29 @@ var empty = () => {};
|
|
|
59856
59848
|
function build$3(options) {
|
|
59857
59849
|
return options.group ? groupFiles : empty;
|
|
59858
59850
|
}
|
|
59859
|
-
var resolveSymlinksAsync = function(
|
|
59860
|
-
const { queue, fs:
|
|
59851
|
+
var resolveSymlinksAsync = function(path6, state, callback$1) {
|
|
59852
|
+
const { queue, fs: fs8, options: { suppressErrors } } = state;
|
|
59861
59853
|
queue.enqueue();
|
|
59862
|
-
|
|
59854
|
+
fs8.realpath(path6, (error43, resolvedPath) => {
|
|
59863
59855
|
if (error43)
|
|
59864
59856
|
return queue.dequeue(suppressErrors ? null : error43, state);
|
|
59865
|
-
|
|
59857
|
+
fs8.stat(resolvedPath, (error$1, stat) => {
|
|
59866
59858
|
if (error$1)
|
|
59867
59859
|
return queue.dequeue(suppressErrors ? null : error$1, state);
|
|
59868
|
-
if (stat.isDirectory() && isRecursive(
|
|
59860
|
+
if (stat.isDirectory() && isRecursive(path6, resolvedPath, state))
|
|
59869
59861
|
return queue.dequeue(null, state);
|
|
59870
59862
|
callback$1(stat, resolvedPath);
|
|
59871
59863
|
queue.dequeue(null, state);
|
|
59872
59864
|
});
|
|
59873
59865
|
});
|
|
59874
59866
|
};
|
|
59875
|
-
var resolveSymlinks = function(
|
|
59876
|
-
const { queue, fs:
|
|
59867
|
+
var resolveSymlinks = function(path6, state, callback$1) {
|
|
59868
|
+
const { queue, fs: fs8, options: { suppressErrors } } = state;
|
|
59877
59869
|
queue.enqueue();
|
|
59878
59870
|
try {
|
|
59879
|
-
const resolvedPath =
|
|
59880
|
-
const stat =
|
|
59881
|
-
if (stat.isDirectory() && isRecursive(
|
|
59871
|
+
const resolvedPath = fs8.realpathSync(path6);
|
|
59872
|
+
const stat = fs8.statSync(resolvedPath);
|
|
59873
|
+
if (stat.isDirectory() && isRecursive(path6, resolvedPath, state))
|
|
59882
59874
|
return;
|
|
59883
59875
|
callback$1(stat, resolvedPath);
|
|
59884
59876
|
} catch (e) {
|
|
@@ -59891,10 +59883,10 @@ function build$2(options, isSynchronous) {
|
|
|
59891
59883
|
return null;
|
|
59892
59884
|
return isSynchronous ? resolveSymlinks : resolveSymlinksAsync;
|
|
59893
59885
|
}
|
|
59894
|
-
function isRecursive(
|
|
59886
|
+
function isRecursive(path6, resolved, state) {
|
|
59895
59887
|
if (state.options.useRealPaths)
|
|
59896
59888
|
return isRecursiveUsingRealPaths(resolved, state);
|
|
59897
|
-
let parent = dirname3(
|
|
59889
|
+
let parent = dirname3(path6);
|
|
59898
59890
|
let depth = 1;
|
|
59899
59891
|
while (parent !== state.root && depth < 2) {
|
|
59900
59892
|
const resolvedPath = state.symlinks.get(parent);
|
|
@@ -59904,7 +59896,7 @@ function isRecursive(path7, resolved, state) {
|
|
|
59904
59896
|
else
|
|
59905
59897
|
parent = dirname3(parent);
|
|
59906
59898
|
}
|
|
59907
|
-
state.symlinks.set(
|
|
59899
|
+
state.symlinks.set(path6, resolved);
|
|
59908
59900
|
return depth > 1;
|
|
59909
59901
|
}
|
|
59910
59902
|
function isRecursiveUsingRealPaths(resolved, state) {
|
|
@@ -59960,23 +59952,23 @@ var walkAsync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
|
|
|
59960
59952
|
state.queue.enqueue();
|
|
59961
59953
|
if (currentDepth < 0)
|
|
59962
59954
|
return state.queue.dequeue(null, state);
|
|
59963
|
-
const { fs:
|
|
59955
|
+
const { fs: fs8 } = state;
|
|
59964
59956
|
state.visited.push(crawlPath);
|
|
59965
59957
|
state.counts.directories++;
|
|
59966
|
-
|
|
59958
|
+
fs8.readdir(crawlPath || ".", readdirOpts, (error43, entries = []) => {
|
|
59967
59959
|
callback$1(entries, directoryPath, currentDepth);
|
|
59968
59960
|
state.queue.dequeue(state.options.suppressErrors ? null : error43, state);
|
|
59969
59961
|
});
|
|
59970
59962
|
};
|
|
59971
59963
|
var walkSync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
|
|
59972
|
-
const { fs:
|
|
59964
|
+
const { fs: fs8 } = state;
|
|
59973
59965
|
if (currentDepth < 0)
|
|
59974
59966
|
return;
|
|
59975
59967
|
state.visited.push(crawlPath);
|
|
59976
59968
|
state.counts.directories++;
|
|
59977
59969
|
let entries = [];
|
|
59978
59970
|
try {
|
|
59979
|
-
entries =
|
|
59971
|
+
entries = fs8.readdirSync(crawlPath || ".", readdirOpts);
|
|
59980
59972
|
} catch (e) {
|
|
59981
59973
|
if (!state.options.suppressErrors)
|
|
59982
59974
|
throw e;
|
|
@@ -60082,21 +60074,21 @@ var Walker = class {
|
|
|
60082
60074
|
const filename = this.joinPath(entry.name, directoryPath);
|
|
60083
60075
|
this.pushFile(filename, files, this.state.counts, filters);
|
|
60084
60076
|
} else if (entry.isDirectory()) {
|
|
60085
|
-
let
|
|
60086
|
-
if (exclude && exclude(entry.name,
|
|
60077
|
+
let path6 = joinDirectoryPath(entry.name, directoryPath, this.state.options.pathSeparator);
|
|
60078
|
+
if (exclude && exclude(entry.name, path6))
|
|
60087
60079
|
continue;
|
|
60088
|
-
this.pushDirectory(
|
|
60089
|
-
this.walkDirectory(this.state,
|
|
60080
|
+
this.pushDirectory(path6, paths, filters);
|
|
60081
|
+
this.walkDirectory(this.state, path6, path6, depth - 1, this.walk);
|
|
60090
60082
|
} else if (this.resolveSymlink && entry.isSymbolicLink()) {
|
|
60091
|
-
let
|
|
60092
|
-
this.resolveSymlink(
|
|
60083
|
+
let path6 = joinPathWithBasePath(entry.name, directoryPath);
|
|
60084
|
+
this.resolveSymlink(path6, this.state, (stat, resolvedPath) => {
|
|
60093
60085
|
if (stat.isDirectory()) {
|
|
60094
60086
|
resolvedPath = normalizePath(resolvedPath, this.state.options);
|
|
60095
|
-
if (exclude && exclude(entry.name, useRealPaths ? resolvedPath :
|
|
60087
|
+
if (exclude && exclude(entry.name, useRealPaths ? resolvedPath : path6 + pathSeparator))
|
|
60096
60088
|
return;
|
|
60097
|
-
this.walkDirectory(this.state, resolvedPath, useRealPaths ? resolvedPath :
|
|
60089
|
+
this.walkDirectory(this.state, resolvedPath, useRealPaths ? resolvedPath : path6 + pathSeparator, depth - 1, this.walk);
|
|
60098
60090
|
} else {
|
|
60099
|
-
resolvedPath = useRealPaths ? resolvedPath :
|
|
60091
|
+
resolvedPath = useRealPaths ? resolvedPath : path6;
|
|
60100
60092
|
const filename = basename2(resolvedPath);
|
|
60101
60093
|
const directoryPath$1 = normalizePath(dirname3(resolvedPath), this.state.options);
|
|
60102
60094
|
resolvedPath = this.joinPath(filename, directoryPath$1);
|
|
@@ -60256,7 +60248,7 @@ var Builder = class {
|
|
|
60256
60248
|
isMatch2 = globFn(patterns, ...options);
|
|
60257
60249
|
this.globCache[patterns.join("\x00")] = isMatch2;
|
|
60258
60250
|
}
|
|
60259
|
-
this.options.filters.push((
|
|
60251
|
+
this.options.filters.push((path6) => isMatch2(path6));
|
|
60260
60252
|
return this;
|
|
60261
60253
|
}
|
|
60262
60254
|
};
|
|
@@ -60335,7 +60327,7 @@ function normalizePattern(pattern, expandDirectories, cwd2, props, isIgnore) {
|
|
|
60335
60327
|
if (!result2.endsWith("*") && expandDirectories)
|
|
60336
60328
|
result2 += "/**";
|
|
60337
60329
|
const escapedCwd = escapePath(cwd2);
|
|
60338
|
-
if (
|
|
60330
|
+
if (path6.isAbsolute(result2.replace(ESCAPING_BACKSLASHES, "")))
|
|
60339
60331
|
result2 = posix.relative(escapedCwd, result2);
|
|
60340
60332
|
else
|
|
60341
60333
|
result2 = posix.normalize(result2);
|
|
@@ -60372,7 +60364,7 @@ function normalizePattern(pattern, expandDirectories, cwd2, props, isIgnore) {
|
|
|
60372
60364
|
}
|
|
60373
60365
|
props.depthOffset = newCommonPath.length;
|
|
60374
60366
|
props.commonPath = newCommonPath;
|
|
60375
|
-
props.root = newCommonPath.length > 0 ?
|
|
60367
|
+
props.root = newCommonPath.length > 0 ? path6.posix.join(cwd2, ...newCommonPath) : cwd2;
|
|
60376
60368
|
}
|
|
60377
60369
|
return result2;
|
|
60378
60370
|
}
|
|
@@ -60505,25 +60497,25 @@ function globSync(patternsOrOptions, options) {
|
|
|
60505
60497
|
...options,
|
|
60506
60498
|
patterns: patternsOrOptions
|
|
60507
60499
|
} : patternsOrOptions;
|
|
60508
|
-
const cwd2 = opts.cwd ?
|
|
60500
|
+
const cwd2 = opts.cwd ? path6.resolve(opts.cwd).replace(BACKSLASHES, "/") : process.cwd().replace(BACKSLASHES, "/");
|
|
60509
60501
|
return crawl(opts, cwd2, true);
|
|
60510
60502
|
}
|
|
60511
60503
|
|
|
60512
60504
|
// src/utils/jsonl.ts
|
|
60513
60505
|
import { promisify } from "util";
|
|
60514
|
-
var readFile4 = promisify(
|
|
60515
|
-
var
|
|
60516
|
-
var statSync5 =
|
|
60517
|
-
var writeFileSync3 =
|
|
60518
|
-
var mkdirSync4 =
|
|
60519
|
-
var existsSync8 =
|
|
60506
|
+
var readFile4 = promisify(fs8.readFile);
|
|
60507
|
+
var readFileSync7 = fs8.readFileSync;
|
|
60508
|
+
var statSync5 = fs8.statSync;
|
|
60509
|
+
var writeFileSync3 = fs8.writeFileSync;
|
|
60510
|
+
var mkdirSync4 = fs8.mkdirSync;
|
|
60511
|
+
var existsSync8 = fs8.existsSync;
|
|
60520
60512
|
function normalizeConfigDir(configDir) {
|
|
60521
|
-
return
|
|
60513
|
+
return path7.resolve(configDir);
|
|
60522
60514
|
}
|
|
60523
60515
|
function getBlockCachePath(configDir = getClaudeConfigDir()) {
|
|
60524
60516
|
const normalizedConfigDir = normalizeConfigDir(configDir);
|
|
60525
60517
|
const configHash = createHash("sha256").update(normalizedConfigDir).digest("hex").slice(0, 16);
|
|
60526
|
-
return
|
|
60518
|
+
return path7.join(os9.homedir(), ".cache", "ccstatusline", `block-cache-${configHash}.json`);
|
|
60527
60519
|
}
|
|
60528
60520
|
function readBlockCache(expectedConfigDir) {
|
|
60529
60521
|
try {
|
|
@@ -60532,7 +60524,7 @@ function readBlockCache(expectedConfigDir) {
|
|
|
60532
60524
|
if (!existsSync8(cachePath)) {
|
|
60533
60525
|
return null;
|
|
60534
60526
|
}
|
|
60535
|
-
const content =
|
|
60527
|
+
const content = readFileSync7(cachePath, "utf-8");
|
|
60536
60528
|
const cache3 = JSON.parse(content);
|
|
60537
60529
|
if (typeof cache3.startTime !== "string") {
|
|
60538
60530
|
return null;
|
|
@@ -60558,7 +60550,7 @@ function writeBlockCache(startTime, configDir = getClaudeConfigDir()) {
|
|
|
60558
60550
|
try {
|
|
60559
60551
|
const normalizedConfigDir = normalizeConfigDir(configDir);
|
|
60560
60552
|
const cachePath = getBlockCachePath(normalizedConfigDir);
|
|
60561
|
-
const cacheDir =
|
|
60553
|
+
const cacheDir = path7.dirname(cachePath);
|
|
60562
60554
|
if (!existsSync8(cacheDir)) {
|
|
60563
60555
|
mkdirSync4(cacheDir, { recursive: true });
|
|
60564
60556
|
}
|
|
@@ -60591,7 +60583,7 @@ function getCachedBlockMetrics(sessionDurationHours = 5) {
|
|
|
60591
60583
|
}
|
|
60592
60584
|
async function getSessionDuration(transcriptPath) {
|
|
60593
60585
|
try {
|
|
60594
|
-
if (!
|
|
60586
|
+
if (!fs8.existsSync(transcriptPath)) {
|
|
60595
60587
|
return null;
|
|
60596
60588
|
}
|
|
60597
60589
|
const content = await readFile4(transcriptPath, "utf-8");
|
|
@@ -60643,7 +60635,7 @@ async function getSessionDuration(transcriptPath) {
|
|
|
60643
60635
|
}
|
|
60644
60636
|
async function getTokenMetrics(transcriptPath) {
|
|
60645
60637
|
try {
|
|
60646
|
-
if (!
|
|
60638
|
+
if (!fs8.existsSync(transcriptPath)) {
|
|
60647
60639
|
return { inputTokens: 0, outputTokens: 0, cachedTokens: 0, totalTokens: 0, contextLength: 0 };
|
|
60648
60640
|
}
|
|
60649
60641
|
const content = await readFile4(transcriptPath, "utf-8");
|
|
@@ -60696,7 +60688,7 @@ function getBlockMetrics() {
|
|
|
60696
60688
|
function findMostRecentBlockStartTime(rootDir, sessionDurationHours = 5) {
|
|
60697
60689
|
const sessionDurationMs = sessionDurationHours * 60 * 60 * 1000;
|
|
60698
60690
|
const now2 = new Date;
|
|
60699
|
-
const pattern =
|
|
60691
|
+
const pattern = path7.posix.join(rootDir.replace(/\\/g, "/"), "projects", "**", "*.jsonl");
|
|
60700
60692
|
const files = globSync([pattern], {
|
|
60701
60693
|
absolute: true,
|
|
60702
60694
|
cwd: rootDir
|
|
@@ -60790,7 +60782,7 @@ function findMostRecentBlockStartTime(rootDir, sessionDurationHours = 5) {
|
|
|
60790
60782
|
function getAllTimestampsFromFile(filePath) {
|
|
60791
60783
|
const timestamps = [];
|
|
60792
60784
|
try {
|
|
60793
|
-
const content =
|
|
60785
|
+
const content = readFileSync7(filePath, "utf-8");
|
|
60794
60786
|
const lines = content.trim().split(`
|
|
60795
60787
|
`).filter((line) => line.length > 0);
|
|
60796
60788
|
for (const line of lines) {
|