ccstatusline 2.1.7 → 2.1.9
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 +3 -1
- package/dist/ccstatusline.js +1011 -833
- package/package.json +2 -2
package/dist/ccstatusline.js
CHANGED
|
@@ -32056,8 +32056,8 @@ var require_utils = __commonJS((exports) => {
|
|
|
32056
32056
|
}
|
|
32057
32057
|
return output;
|
|
32058
32058
|
};
|
|
32059
|
-
exports.basename = (
|
|
32060
|
-
const segs =
|
|
32059
|
+
exports.basename = (path6, { windows } = {}) => {
|
|
32060
|
+
const segs = path6.split(windows ? /[\\/]/ : "/");
|
|
32061
32061
|
const last = segs[segs.length - 1];
|
|
32062
32062
|
if (last === "") {
|
|
32063
32063
|
return segs[segs.length - 2];
|
|
@@ -32408,7 +32408,7 @@ var require_parse = __commonJS((exports, module) => {
|
|
|
32408
32408
|
var syntaxError = (type, char) => {
|
|
32409
32409
|
return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`;
|
|
32410
32410
|
};
|
|
32411
|
-
var
|
|
32411
|
+
var parse6 = (input, options) => {
|
|
32412
32412
|
if (typeof input !== "string") {
|
|
32413
32413
|
throw new TypeError("Expected a string");
|
|
32414
32414
|
}
|
|
@@ -32557,7 +32557,7 @@ var require_parse = __commonJS((exports, module) => {
|
|
|
32557
32557
|
output = token.close = `)$))${extglobStar}`;
|
|
32558
32558
|
}
|
|
32559
32559
|
if (token.inner.includes("*") && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) {
|
|
32560
|
-
const expression =
|
|
32560
|
+
const expression = parse6(rest, { ...options, fastpaths: false }).output;
|
|
32561
32561
|
output = token.close = `)${expression})${extglobStar})`;
|
|
32562
32562
|
}
|
|
32563
32563
|
if (token.prev.type === "bos") {
|
|
@@ -33083,7 +33083,7 @@ var require_parse = __commonJS((exports, module) => {
|
|
|
33083
33083
|
}
|
|
33084
33084
|
return state;
|
|
33085
33085
|
};
|
|
33086
|
-
|
|
33086
|
+
parse6.fastpaths = (input, options) => {
|
|
33087
33087
|
const opts = { ...options };
|
|
33088
33088
|
const max = typeof opts.maxLength === "number" ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
|
|
33089
33089
|
const len = input.length;
|
|
@@ -33151,13 +33151,13 @@ var require_parse = __commonJS((exports, module) => {
|
|
|
33151
33151
|
}
|
|
33152
33152
|
return source;
|
|
33153
33153
|
};
|
|
33154
|
-
module.exports =
|
|
33154
|
+
module.exports = parse6;
|
|
33155
33155
|
});
|
|
33156
33156
|
|
|
33157
33157
|
// node_modules/picomatch/lib/picomatch.js
|
|
33158
33158
|
var require_picomatch = __commonJS((exports, module) => {
|
|
33159
33159
|
var scan = require_scan();
|
|
33160
|
-
var
|
|
33160
|
+
var parse6 = require_parse();
|
|
33161
33161
|
var utils = require_utils();
|
|
33162
33162
|
var constants2 = require_constants3();
|
|
33163
33163
|
var isObject2 = (val) => val && typeof val === "object" && !Array.isArray(val);
|
|
@@ -33247,7 +33247,7 @@ var require_picomatch = __commonJS((exports, module) => {
|
|
|
33247
33247
|
picomatch.parse = (pattern, options) => {
|
|
33248
33248
|
if (Array.isArray(pattern))
|
|
33249
33249
|
return pattern.map((p) => picomatch.parse(p, options));
|
|
33250
|
-
return
|
|
33250
|
+
return parse6(pattern, { ...options, fastpaths: false });
|
|
33251
33251
|
};
|
|
33252
33252
|
picomatch.scan = (input, options) => scan(input, options);
|
|
33253
33253
|
picomatch.compileRe = (state, options, returnOutput = false, returnState = false) => {
|
|
@@ -33273,10 +33273,10 @@ var require_picomatch = __commonJS((exports, module) => {
|
|
|
33273
33273
|
}
|
|
33274
33274
|
let parsed = { negated: false, fastpaths: true };
|
|
33275
33275
|
if (options.fastpaths !== false && (input[0] === "." || input[0] === "*")) {
|
|
33276
|
-
parsed.output =
|
|
33276
|
+
parsed.output = parse6.fastpaths(input, options);
|
|
33277
33277
|
}
|
|
33278
33278
|
if (!parsed.output) {
|
|
33279
|
-
parsed =
|
|
33279
|
+
parsed = parse6(input, options);
|
|
33280
33280
|
}
|
|
33281
33281
|
return picomatch.compileRe(parsed, options, returnOutput, returnState);
|
|
33282
33282
|
};
|
|
@@ -39277,108 +39277,15 @@ var import_react46 = __toESM(require_react(), 1);
|
|
|
39277
39277
|
|
|
39278
39278
|
// src/utils/claude-settings.ts
|
|
39279
39279
|
import { execSync } from "child_process";
|
|
39280
|
-
import * as fs2 from "fs";
|
|
39281
|
-
import * as os2 from "os";
|
|
39282
|
-
import * as path from "path";
|
|
39283
|
-
var readFile = fs2.promises.readFile;
|
|
39284
|
-
var writeFile = fs2.promises.writeFile;
|
|
39285
|
-
var mkdir = fs2.promises.mkdir;
|
|
39286
|
-
var CCSTATUSLINE_COMMANDS = {
|
|
39287
|
-
NPM: "npx -y ccstatusline@latest",
|
|
39288
|
-
BUNX: "bunx -y ccstatusline@latest",
|
|
39289
|
-
SELF_MANAGED: "ccstatusline"
|
|
39290
|
-
};
|
|
39291
|
-
function getClaudeConfigDir() {
|
|
39292
|
-
const envConfigDir = process.env.CLAUDE_CONFIG_DIR;
|
|
39293
|
-
if (envConfigDir) {
|
|
39294
|
-
try {
|
|
39295
|
-
const resolvedPath = path.resolve(envConfigDir);
|
|
39296
|
-
if (fs2.existsSync(resolvedPath)) {
|
|
39297
|
-
const stats = fs2.statSync(resolvedPath);
|
|
39298
|
-
if (stats.isDirectory()) {
|
|
39299
|
-
return resolvedPath;
|
|
39300
|
-
}
|
|
39301
|
-
} else {
|
|
39302
|
-
return resolvedPath;
|
|
39303
|
-
}
|
|
39304
|
-
} catch {}
|
|
39305
|
-
}
|
|
39306
|
-
return path.join(os2.homedir(), ".claude");
|
|
39307
|
-
}
|
|
39308
|
-
function getClaudeSettingsPath() {
|
|
39309
|
-
return path.join(getClaudeConfigDir(), "settings.json");
|
|
39310
|
-
}
|
|
39311
|
-
async function loadClaudeSettings() {
|
|
39312
|
-
try {
|
|
39313
|
-
const settingsPath = getClaudeSettingsPath();
|
|
39314
|
-
if (!fs2.existsSync(settingsPath)) {
|
|
39315
|
-
return {};
|
|
39316
|
-
}
|
|
39317
|
-
const content = await readFile(settingsPath, "utf-8");
|
|
39318
|
-
return JSON.parse(content);
|
|
39319
|
-
} catch {
|
|
39320
|
-
return {};
|
|
39321
|
-
}
|
|
39322
|
-
}
|
|
39323
|
-
async function saveClaudeSettings(settings) {
|
|
39324
|
-
const settingsPath = getClaudeSettingsPath();
|
|
39325
|
-
const dir = path.dirname(settingsPath);
|
|
39326
|
-
await mkdir(dir, { recursive: true });
|
|
39327
|
-
await writeFile(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
39328
|
-
}
|
|
39329
|
-
async function isInstalled() {
|
|
39330
|
-
const settings = await loadClaudeSettings();
|
|
39331
|
-
const validCommands = [
|
|
39332
|
-
CCSTATUSLINE_COMMANDS.NPM,
|
|
39333
|
-
CCSTATUSLINE_COMMANDS.BUNX,
|
|
39334
|
-
CCSTATUSLINE_COMMANDS.SELF_MANAGED
|
|
39335
|
-
];
|
|
39336
|
-
return validCommands.includes(settings.statusLine?.command ?? "") && (settings.statusLine?.padding === 0 || settings.statusLine?.padding === undefined);
|
|
39337
|
-
}
|
|
39338
|
-
function isBunxAvailable() {
|
|
39339
|
-
try {
|
|
39340
|
-
const command = process.platform === "win32" ? "where bunx" : "which bunx";
|
|
39341
|
-
execSync(command, { stdio: "ignore" });
|
|
39342
|
-
return true;
|
|
39343
|
-
} catch {
|
|
39344
|
-
return false;
|
|
39345
|
-
}
|
|
39346
|
-
}
|
|
39347
|
-
async function installStatusLine(useBunx = false) {
|
|
39348
|
-
const settings = await loadClaudeSettings();
|
|
39349
|
-
settings.statusLine = {
|
|
39350
|
-
type: "command",
|
|
39351
|
-
command: useBunx ? CCSTATUSLINE_COMMANDS.BUNX : CCSTATUSLINE_COMMANDS.NPM,
|
|
39352
|
-
padding: 0
|
|
39353
|
-
};
|
|
39354
|
-
await saveClaudeSettings(settings);
|
|
39355
|
-
}
|
|
39356
|
-
async function uninstallStatusLine() {
|
|
39357
|
-
const settings = await loadClaudeSettings();
|
|
39358
|
-
if (settings.statusLine) {
|
|
39359
|
-
delete settings.statusLine;
|
|
39360
|
-
await saveClaudeSettings(settings);
|
|
39361
|
-
}
|
|
39362
|
-
}
|
|
39363
|
-
async function getExistingStatusLine() {
|
|
39364
|
-
const settings = await loadClaudeSettings();
|
|
39365
|
-
return settings.statusLine?.command ?? null;
|
|
39366
|
-
}
|
|
39367
|
-
|
|
39368
|
-
// src/utils/clone-settings.ts
|
|
39369
|
-
function cloneSettings(settings) {
|
|
39370
|
-
const cloneFn = globalThis.structuredClone;
|
|
39371
|
-
if (typeof cloneFn === "function") {
|
|
39372
|
-
return cloneFn(settings);
|
|
39373
|
-
}
|
|
39374
|
-
return JSON.parse(JSON.stringify(settings));
|
|
39375
|
-
}
|
|
39376
|
-
|
|
39377
|
-
// src/utils/config.ts
|
|
39378
39280
|
import * as fs3 from "fs";
|
|
39379
39281
|
import * as os3 from "os";
|
|
39380
39282
|
import * as path2 from "path";
|
|
39381
39283
|
|
|
39284
|
+
// src/utils/config.ts
|
|
39285
|
+
import * as fs2 from "fs";
|
|
39286
|
+
import * as os2 from "os";
|
|
39287
|
+
import * as path from "path";
|
|
39288
|
+
|
|
39382
39289
|
// node_modules/zod/v4/classic/external.js
|
|
39383
39290
|
var exports_external = {};
|
|
39384
39291
|
__export(exports_external, {
|
|
@@ -40060,15 +39967,15 @@ function mergeDefs(...defs) {
|
|
|
40060
39967
|
function cloneDef(schema) {
|
|
40061
39968
|
return mergeDefs(schema._zod.def);
|
|
40062
39969
|
}
|
|
40063
|
-
function getElementAtPath(obj,
|
|
40064
|
-
if (!
|
|
39970
|
+
function getElementAtPath(obj, path) {
|
|
39971
|
+
if (!path)
|
|
40065
39972
|
return obj;
|
|
40066
|
-
return
|
|
39973
|
+
return path.reduce((acc, key) => acc?.[key], obj);
|
|
40067
39974
|
}
|
|
40068
39975
|
function promiseAllObject(promisesObj) {
|
|
40069
39976
|
const keys = Object.keys(promisesObj);
|
|
40070
|
-
const
|
|
40071
|
-
return Promise.all(
|
|
39977
|
+
const promises = keys.map((key) => promisesObj[key]);
|
|
39978
|
+
return Promise.all(promises).then((results) => {
|
|
40072
39979
|
const resolvedObj = {};
|
|
40073
39980
|
for (let i = 0;i < keys.length; i++) {
|
|
40074
39981
|
resolvedObj[keys[i]] = results[i];
|
|
@@ -40398,11 +40305,11 @@ function aborted(x, startIndex = 0) {
|
|
|
40398
40305
|
}
|
|
40399
40306
|
return false;
|
|
40400
40307
|
}
|
|
40401
|
-
function prefixIssues(
|
|
40308
|
+
function prefixIssues(path, issues) {
|
|
40402
40309
|
return issues.map((iss) => {
|
|
40403
40310
|
var _a;
|
|
40404
40311
|
(_a = iss).path ?? (_a.path = []);
|
|
40405
|
-
iss.path.unshift(
|
|
40312
|
+
iss.path.unshift(path);
|
|
40406
40313
|
return iss;
|
|
40407
40314
|
});
|
|
40408
40315
|
}
|
|
@@ -40533,7 +40440,7 @@ function treeifyError(error, _mapper) {
|
|
|
40533
40440
|
return issue2.message;
|
|
40534
40441
|
};
|
|
40535
40442
|
const result = { errors: [] };
|
|
40536
|
-
const processError = (error2,
|
|
40443
|
+
const processError = (error2, path = []) => {
|
|
40537
40444
|
var _a, _b;
|
|
40538
40445
|
for (const issue2 of error2.issues) {
|
|
40539
40446
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -40543,7 +40450,7 @@ function treeifyError(error, _mapper) {
|
|
|
40543
40450
|
} else if (issue2.code === "invalid_element") {
|
|
40544
40451
|
processError({ issues: issue2.issues }, issue2.path);
|
|
40545
40452
|
} else {
|
|
40546
|
-
const fullpath = [...
|
|
40453
|
+
const fullpath = [...path, ...issue2.path];
|
|
40547
40454
|
if (fullpath.length === 0) {
|
|
40548
40455
|
result.errors.push(mapper(issue2));
|
|
40549
40456
|
continue;
|
|
@@ -40575,8 +40482,8 @@ function treeifyError(error, _mapper) {
|
|
|
40575
40482
|
}
|
|
40576
40483
|
function toDotPath(_path) {
|
|
40577
40484
|
const segs = [];
|
|
40578
|
-
const
|
|
40579
|
-
for (const seg of
|
|
40485
|
+
const path = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
40486
|
+
for (const seg of path) {
|
|
40580
40487
|
if (typeof seg === "number")
|
|
40581
40488
|
segs.push(`[${seg}]`);
|
|
40582
40489
|
else if (typeof seg === "symbol")
|
|
@@ -50999,6 +50906,84 @@ function generateGuid() {
|
|
|
50999
50906
|
function isRecord(value) {
|
|
51000
50907
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
51001
50908
|
}
|
|
50909
|
+
var V1_FIELD_RULES = [
|
|
50910
|
+
{
|
|
50911
|
+
key: "flexMode",
|
|
50912
|
+
isValid: (value) => typeof value === "string"
|
|
50913
|
+
},
|
|
50914
|
+
{
|
|
50915
|
+
key: "compactThreshold",
|
|
50916
|
+
isValid: (value) => typeof value === "number"
|
|
50917
|
+
},
|
|
50918
|
+
{
|
|
50919
|
+
key: "colorLevel",
|
|
50920
|
+
isValid: (value) => typeof value === "number"
|
|
50921
|
+
},
|
|
50922
|
+
{
|
|
50923
|
+
key: "defaultSeparator",
|
|
50924
|
+
isValid: (value) => typeof value === "string"
|
|
50925
|
+
},
|
|
50926
|
+
{
|
|
50927
|
+
key: "defaultPadding",
|
|
50928
|
+
isValid: (value) => typeof value === "string"
|
|
50929
|
+
},
|
|
50930
|
+
{
|
|
50931
|
+
key: "inheritSeparatorColors",
|
|
50932
|
+
isValid: (value) => typeof value === "boolean"
|
|
50933
|
+
},
|
|
50934
|
+
{
|
|
50935
|
+
key: "overrideBackgroundColor",
|
|
50936
|
+
isValid: (value) => typeof value === "string"
|
|
50937
|
+
},
|
|
50938
|
+
{
|
|
50939
|
+
key: "overrideForegroundColor",
|
|
50940
|
+
isValid: (value) => typeof value === "string"
|
|
50941
|
+
},
|
|
50942
|
+
{
|
|
50943
|
+
key: "globalBold",
|
|
50944
|
+
isValid: (value) => typeof value === "boolean"
|
|
50945
|
+
}
|
|
50946
|
+
];
|
|
50947
|
+
function toWidgetLine(line, stripSeparators) {
|
|
50948
|
+
const lineToProcess = stripSeparators ? line.filter((item) => {
|
|
50949
|
+
if (isRecord(item)) {
|
|
50950
|
+
return item.type !== "separator";
|
|
50951
|
+
}
|
|
50952
|
+
return true;
|
|
50953
|
+
}) : line;
|
|
50954
|
+
const typedLine = [];
|
|
50955
|
+
for (const item of lineToProcess) {
|
|
50956
|
+
if (isRecord(item) && typeof item.type === "string") {
|
|
50957
|
+
typedLine.push({
|
|
50958
|
+
...item,
|
|
50959
|
+
id: generateGuid(),
|
|
50960
|
+
type: item.type
|
|
50961
|
+
});
|
|
50962
|
+
}
|
|
50963
|
+
}
|
|
50964
|
+
return typedLine;
|
|
50965
|
+
}
|
|
50966
|
+
function migrateV1Lines(data) {
|
|
50967
|
+
if (!Array.isArray(data.lines)) {
|
|
50968
|
+
return;
|
|
50969
|
+
}
|
|
50970
|
+
const stripSeparators = Boolean(data.defaultSeparator);
|
|
50971
|
+
const processedLines = [];
|
|
50972
|
+
for (const line of data.lines) {
|
|
50973
|
+
if (Array.isArray(line)) {
|
|
50974
|
+
processedLines.push(toWidgetLine(line, stripSeparators));
|
|
50975
|
+
}
|
|
50976
|
+
}
|
|
50977
|
+
return processedLines;
|
|
50978
|
+
}
|
|
50979
|
+
function copyV1Fields(data, target) {
|
|
50980
|
+
for (const rule of V1_FIELD_RULES) {
|
|
50981
|
+
const value = data[rule.key];
|
|
50982
|
+
if (rule.isValid(value)) {
|
|
50983
|
+
target[rule.key] = value;
|
|
50984
|
+
}
|
|
50985
|
+
}
|
|
50986
|
+
}
|
|
51002
50987
|
var migrations = [
|
|
51003
50988
|
{
|
|
51004
50989
|
fromVersion: 1,
|
|
@@ -51006,52 +50991,11 @@ var migrations = [
|
|
|
51006
50991
|
description: "Migrate from v1 to v2",
|
|
51007
50992
|
migrate: (data) => {
|
|
51008
50993
|
const migrated = {};
|
|
51009
|
-
|
|
51010
|
-
|
|
51011
|
-
for (const line of data.lines) {
|
|
51012
|
-
if (Array.isArray(line)) {
|
|
51013
|
-
let processedLine = line;
|
|
51014
|
-
if (data.defaultSeparator) {
|
|
51015
|
-
processedLine = line.filter((item) => {
|
|
51016
|
-
if (isRecord(item)) {
|
|
51017
|
-
return item.type !== "separator";
|
|
51018
|
-
}
|
|
51019
|
-
return true;
|
|
51020
|
-
});
|
|
51021
|
-
}
|
|
51022
|
-
const typedLine = [];
|
|
51023
|
-
for (const item of processedLine) {
|
|
51024
|
-
if (isRecord(item) && typeof item.type === "string") {
|
|
51025
|
-
typedLine.push({
|
|
51026
|
-
...item,
|
|
51027
|
-
id: generateGuid(),
|
|
51028
|
-
type: item.type
|
|
51029
|
-
});
|
|
51030
|
-
}
|
|
51031
|
-
}
|
|
51032
|
-
processedLines.push(typedLine);
|
|
51033
|
-
}
|
|
51034
|
-
}
|
|
50994
|
+
const processedLines = migrateV1Lines(data);
|
|
50995
|
+
if (processedLines) {
|
|
51035
50996
|
migrated.lines = processedLines;
|
|
51036
50997
|
}
|
|
51037
|
-
|
|
51038
|
-
migrated.flexMode = data.flexMode;
|
|
51039
|
-
if (typeof data.compactThreshold === "number")
|
|
51040
|
-
migrated.compactThreshold = data.compactThreshold;
|
|
51041
|
-
if (typeof data.colorLevel === "number")
|
|
51042
|
-
migrated.colorLevel = data.colorLevel;
|
|
51043
|
-
if (typeof data.defaultSeparator === "string")
|
|
51044
|
-
migrated.defaultSeparator = data.defaultSeparator;
|
|
51045
|
-
if (typeof data.defaultPadding === "string")
|
|
51046
|
-
migrated.defaultPadding = data.defaultPadding;
|
|
51047
|
-
if (typeof data.inheritSeparatorColors === "boolean")
|
|
51048
|
-
migrated.inheritSeparatorColors = data.inheritSeparatorColors;
|
|
51049
|
-
if (typeof data.overrideBackgroundColor === "string")
|
|
51050
|
-
migrated.overrideBackgroundColor = data.overrideBackgroundColor;
|
|
51051
|
-
if (typeof data.overrideForegroundColor === "string")
|
|
51052
|
-
migrated.overrideForegroundColor = data.overrideForegroundColor;
|
|
51053
|
-
if (typeof data.globalBold === "boolean")
|
|
51054
|
-
migrated.globalBold = data.globalBold;
|
|
50998
|
+
copyV1Fields(data, migrated);
|
|
51055
50999
|
migrated.version = 2;
|
|
51056
51000
|
migrated.updatemessage = {
|
|
51057
51001
|
message: "ccstatusline updated to v2.0.0, launch tui to use new settings",
|
|
@@ -51101,85 +51045,224 @@ function needsMigration(data, targetVersion) {
|
|
|
51101
51045
|
}
|
|
51102
51046
|
|
|
51103
51047
|
// src/utils/config.ts
|
|
51104
|
-
var
|
|
51105
|
-
var
|
|
51106
|
-
var
|
|
51107
|
-
var
|
|
51108
|
-
var
|
|
51109
|
-
|
|
51110
|
-
|
|
51048
|
+
var readFile = fs2.promises.readFile;
|
|
51049
|
+
var writeFile = fs2.promises.writeFile;
|
|
51050
|
+
var mkdir = fs2.promises.mkdir;
|
|
51051
|
+
var DEFAULT_SETTINGS_PATH = path.join(os2.homedir(), ".config", "ccstatusline", "settings.json");
|
|
51052
|
+
var settingsPath = DEFAULT_SETTINGS_PATH;
|
|
51053
|
+
function initConfigPath(filePath) {
|
|
51054
|
+
settingsPath = filePath ? path.resolve(filePath) : DEFAULT_SETTINGS_PATH;
|
|
51055
|
+
}
|
|
51056
|
+
function getConfigPath() {
|
|
51057
|
+
return settingsPath;
|
|
51058
|
+
}
|
|
51059
|
+
function isCustomConfigPath() {
|
|
51060
|
+
return settingsPath !== DEFAULT_SETTINGS_PATH;
|
|
51061
|
+
}
|
|
51062
|
+
function getSettingsPaths() {
|
|
51063
|
+
const configDir = path.dirname(settingsPath);
|
|
51064
|
+
const parsedPath = path.parse(settingsPath);
|
|
51065
|
+
const backupBaseName = parsedPath.ext ? `${parsedPath.name}.bak` : `${parsedPath.base}.bak`;
|
|
51066
|
+
return {
|
|
51067
|
+
configDir,
|
|
51068
|
+
settingsPath,
|
|
51069
|
+
settingsBackupPath: path.join(configDir, backupBaseName)
|
|
51070
|
+
};
|
|
51071
|
+
}
|
|
51072
|
+
async function writeSettingsJson(settings, paths) {
|
|
51073
|
+
await mkdir(paths.configDir, { recursive: true });
|
|
51074
|
+
await writeFile(paths.settingsPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
51075
|
+
}
|
|
51076
|
+
async function backupBadSettings(paths) {
|
|
51111
51077
|
try {
|
|
51112
|
-
if (
|
|
51113
|
-
const content = await
|
|
51114
|
-
await
|
|
51115
|
-
console.error(`Bad settings backed up to ${
|
|
51078
|
+
if (fs2.existsSync(paths.settingsPath)) {
|
|
51079
|
+
const content = await readFile(paths.settingsPath, "utf-8");
|
|
51080
|
+
await writeFile(paths.settingsBackupPath, content, "utf-8");
|
|
51081
|
+
console.error(`Bad settings backed up to ${paths.settingsBackupPath}`);
|
|
51116
51082
|
}
|
|
51117
51083
|
} catch (error43) {
|
|
51118
51084
|
console.error("Failed to backup bad settings:", error43);
|
|
51119
51085
|
}
|
|
51120
51086
|
}
|
|
51121
|
-
async function writeDefaultSettings() {
|
|
51087
|
+
async function writeDefaultSettings(paths) {
|
|
51122
51088
|
const defaults = SettingsSchema.parse({});
|
|
51123
51089
|
const settingsWithVersion = {
|
|
51124
51090
|
...defaults,
|
|
51125
51091
|
version: CURRENT_VERSION
|
|
51126
51092
|
};
|
|
51127
51093
|
try {
|
|
51128
|
-
await
|
|
51129
|
-
|
|
51130
|
-
console.error(`Default settings written to ${SETTINGS_PATH}`);
|
|
51094
|
+
await writeSettingsJson(settingsWithVersion, paths);
|
|
51095
|
+
console.error(`Default settings written to ${paths.settingsPath}`);
|
|
51131
51096
|
} catch (error43) {
|
|
51132
51097
|
console.error("Failed to write default settings:", error43);
|
|
51133
51098
|
}
|
|
51134
51099
|
return defaults;
|
|
51135
51100
|
}
|
|
51101
|
+
async function recoverWithDefaults(paths) {
|
|
51102
|
+
await backupBadSettings(paths);
|
|
51103
|
+
return await writeDefaultSettings(paths);
|
|
51104
|
+
}
|
|
51136
51105
|
async function loadSettings() {
|
|
51106
|
+
const paths = getSettingsPaths();
|
|
51137
51107
|
try {
|
|
51138
|
-
if (!
|
|
51139
|
-
return await writeDefaultSettings();
|
|
51140
|
-
const content = await
|
|
51108
|
+
if (!fs2.existsSync(paths.settingsPath))
|
|
51109
|
+
return await writeDefaultSettings(paths);
|
|
51110
|
+
const content = await readFile(paths.settingsPath, "utf-8");
|
|
51141
51111
|
let rawData;
|
|
51142
51112
|
try {
|
|
51143
51113
|
rawData = JSON.parse(content);
|
|
51144
51114
|
} catch {
|
|
51145
51115
|
console.error("Failed to parse settings.json, backing up and using defaults");
|
|
51146
|
-
await
|
|
51147
|
-
return await writeDefaultSettings();
|
|
51116
|
+
return await recoverWithDefaults(paths);
|
|
51148
51117
|
}
|
|
51149
51118
|
const hasVersion = typeof rawData === "object" && rawData !== null && "version" in rawData;
|
|
51150
51119
|
if (!hasVersion) {
|
|
51151
51120
|
const v1Result = SettingsSchema_v1.safeParse(rawData);
|
|
51152
51121
|
if (!v1Result.success) {
|
|
51153
51122
|
console.error("Invalid v1 settings format:", v1Result.error);
|
|
51154
|
-
await
|
|
51155
|
-
return await writeDefaultSettings();
|
|
51123
|
+
return await recoverWithDefaults(paths);
|
|
51156
51124
|
}
|
|
51157
51125
|
rawData = migrateConfig(rawData, CURRENT_VERSION);
|
|
51158
|
-
await
|
|
51126
|
+
await writeSettingsJson(rawData, paths);
|
|
51159
51127
|
} else if (needsMigration(rawData, CURRENT_VERSION)) {
|
|
51160
51128
|
rawData = migrateConfig(rawData, CURRENT_VERSION);
|
|
51161
|
-
await
|
|
51129
|
+
await writeSettingsJson(rawData, paths);
|
|
51162
51130
|
}
|
|
51163
51131
|
const result = SettingsSchema.safeParse(rawData);
|
|
51164
51132
|
if (!result.success) {
|
|
51165
51133
|
console.error("Failed to parse settings:", result.error);
|
|
51166
|
-
await
|
|
51167
|
-
return await writeDefaultSettings();
|
|
51134
|
+
return await recoverWithDefaults(paths);
|
|
51168
51135
|
}
|
|
51169
51136
|
return result.data;
|
|
51170
51137
|
} catch (error43) {
|
|
51171
51138
|
console.error("Error loading settings:", error43);
|
|
51172
|
-
await
|
|
51173
|
-
return await writeDefaultSettings();
|
|
51139
|
+
return await recoverWithDefaults(paths);
|
|
51174
51140
|
}
|
|
51175
51141
|
}
|
|
51176
51142
|
async function saveSettings(settings) {
|
|
51177
|
-
|
|
51143
|
+
const paths = getSettingsPaths();
|
|
51178
51144
|
const settingsWithVersion = {
|
|
51179
51145
|
...settings,
|
|
51180
51146
|
version: CURRENT_VERSION
|
|
51181
51147
|
};
|
|
51182
|
-
await
|
|
51148
|
+
await writeSettingsJson(settingsWithVersion, paths);
|
|
51149
|
+
}
|
|
51150
|
+
|
|
51151
|
+
// src/utils/claude-settings.ts
|
|
51152
|
+
var readFile2 = fs3.promises.readFile;
|
|
51153
|
+
var writeFile2 = fs3.promises.writeFile;
|
|
51154
|
+
var mkdir2 = fs3.promises.mkdir;
|
|
51155
|
+
var CCSTATUSLINE_COMMANDS = {
|
|
51156
|
+
NPM: "npx -y ccstatusline@latest",
|
|
51157
|
+
BUNX: "bunx -y ccstatusline@latest",
|
|
51158
|
+
SELF_MANAGED: "ccstatusline"
|
|
51159
|
+
};
|
|
51160
|
+
function isKnownCommand(command) {
|
|
51161
|
+
const prefixes = [CCSTATUSLINE_COMMANDS.NPM, CCSTATUSLINE_COMMANDS.BUNX, CCSTATUSLINE_COMMANDS.SELF_MANAGED];
|
|
51162
|
+
return prefixes.some((prefix) => command === prefix || command.startsWith(`${prefix} --config `));
|
|
51163
|
+
}
|
|
51164
|
+
function needsQuoting(filePath) {
|
|
51165
|
+
if (process.platform === "win32") {
|
|
51166
|
+
return /[\s&()<>|^"]/.test(filePath);
|
|
51167
|
+
}
|
|
51168
|
+
return /[\s()[\];&#|'"\\$`]/.test(filePath);
|
|
51169
|
+
}
|
|
51170
|
+
function quotePathIfNeeded(filePath) {
|
|
51171
|
+
if (!needsQuoting(filePath)) {
|
|
51172
|
+
return filePath;
|
|
51173
|
+
}
|
|
51174
|
+
if (process.platform === "win32") {
|
|
51175
|
+
return `"${filePath.replace(/"/g, '""')}"`;
|
|
51176
|
+
}
|
|
51177
|
+
return `'${filePath.replace(/'/g, "'\\''")}'`;
|
|
51178
|
+
}
|
|
51179
|
+
function getClaudeConfigDir() {
|
|
51180
|
+
const envConfigDir = process.env.CLAUDE_CONFIG_DIR;
|
|
51181
|
+
if (envConfigDir) {
|
|
51182
|
+
try {
|
|
51183
|
+
const resolvedPath = path2.resolve(envConfigDir);
|
|
51184
|
+
if (fs3.existsSync(resolvedPath)) {
|
|
51185
|
+
const stats = fs3.statSync(resolvedPath);
|
|
51186
|
+
if (stats.isDirectory()) {
|
|
51187
|
+
return resolvedPath;
|
|
51188
|
+
}
|
|
51189
|
+
} else {
|
|
51190
|
+
return resolvedPath;
|
|
51191
|
+
}
|
|
51192
|
+
} catch {}
|
|
51193
|
+
}
|
|
51194
|
+
return path2.join(os3.homedir(), ".claude");
|
|
51195
|
+
}
|
|
51196
|
+
function getClaudeSettingsPath() {
|
|
51197
|
+
return path2.join(getClaudeConfigDir(), "settings.json");
|
|
51198
|
+
}
|
|
51199
|
+
async function loadClaudeSettings() {
|
|
51200
|
+
try {
|
|
51201
|
+
const settingsPath2 = getClaudeSettingsPath();
|
|
51202
|
+
if (!fs3.existsSync(settingsPath2)) {
|
|
51203
|
+
return {};
|
|
51204
|
+
}
|
|
51205
|
+
const content = await readFile2(settingsPath2, "utf-8");
|
|
51206
|
+
return JSON.parse(content);
|
|
51207
|
+
} catch {
|
|
51208
|
+
return {};
|
|
51209
|
+
}
|
|
51210
|
+
}
|
|
51211
|
+
async function saveClaudeSettings(settings) {
|
|
51212
|
+
const settingsPath2 = getClaudeSettingsPath();
|
|
51213
|
+
const dir = path2.dirname(settingsPath2);
|
|
51214
|
+
await mkdir2(dir, { recursive: true });
|
|
51215
|
+
await writeFile2(settingsPath2, JSON.stringify(settings, null, 2), "utf-8");
|
|
51216
|
+
}
|
|
51217
|
+
async function isInstalled() {
|
|
51218
|
+
const settings = await loadClaudeSettings();
|
|
51219
|
+
const command = settings.statusLine?.command ?? "";
|
|
51220
|
+
return isKnownCommand(command) && (settings.statusLine?.padding === 0 || settings.statusLine?.padding === undefined);
|
|
51221
|
+
}
|
|
51222
|
+
function isBunxAvailable() {
|
|
51223
|
+
try {
|
|
51224
|
+
const command = process.platform === "win32" ? "where bunx" : "which bunx";
|
|
51225
|
+
execSync(command, { stdio: "ignore" });
|
|
51226
|
+
return true;
|
|
51227
|
+
} catch {
|
|
51228
|
+
return false;
|
|
51229
|
+
}
|
|
51230
|
+
}
|
|
51231
|
+
function buildCommand(baseCommand) {
|
|
51232
|
+
if (isCustomConfigPath()) {
|
|
51233
|
+
return `${baseCommand} --config ${quotePathIfNeeded(getConfigPath())}`;
|
|
51234
|
+
}
|
|
51235
|
+
return baseCommand;
|
|
51236
|
+
}
|
|
51237
|
+
async function installStatusLine(useBunx = false) {
|
|
51238
|
+
const settings = await loadClaudeSettings();
|
|
51239
|
+
const baseCommand = useBunx ? CCSTATUSLINE_COMMANDS.BUNX : CCSTATUSLINE_COMMANDS.NPM;
|
|
51240
|
+
settings.statusLine = {
|
|
51241
|
+
type: "command",
|
|
51242
|
+
command: buildCommand(baseCommand),
|
|
51243
|
+
padding: 0
|
|
51244
|
+
};
|
|
51245
|
+
await saveClaudeSettings(settings);
|
|
51246
|
+
}
|
|
51247
|
+
async function uninstallStatusLine() {
|
|
51248
|
+
const settings = await loadClaudeSettings();
|
|
51249
|
+
if (settings.statusLine) {
|
|
51250
|
+
delete settings.statusLine;
|
|
51251
|
+
await saveClaudeSettings(settings);
|
|
51252
|
+
}
|
|
51253
|
+
}
|
|
51254
|
+
async function getExistingStatusLine() {
|
|
51255
|
+
const settings = await loadClaudeSettings();
|
|
51256
|
+
return settings.statusLine?.command ?? null;
|
|
51257
|
+
}
|
|
51258
|
+
|
|
51259
|
+
// src/utils/clone-settings.ts
|
|
51260
|
+
function cloneSettings(settings) {
|
|
51261
|
+
const cloneFn = globalThis.structuredClone;
|
|
51262
|
+
if (typeof cloneFn === "function") {
|
|
51263
|
+
return cloneFn(settings);
|
|
51264
|
+
}
|
|
51265
|
+
return JSON.parse(JSON.stringify(settings));
|
|
51183
51266
|
}
|
|
51184
51267
|
|
|
51185
51268
|
// src/utils/open-url.ts
|
|
@@ -51201,6 +51284,32 @@ function runOpenCommand(command, args) {
|
|
|
51201
51284
|
}
|
|
51202
51285
|
return null;
|
|
51203
51286
|
}
|
|
51287
|
+
var PLATFORM_OPEN_PLANS = {
|
|
51288
|
+
darwin: [
|
|
51289
|
+
{
|
|
51290
|
+
command: "open",
|
|
51291
|
+
args: (url2) => [url2]
|
|
51292
|
+
}
|
|
51293
|
+
],
|
|
51294
|
+
win32: [
|
|
51295
|
+
{
|
|
51296
|
+
command: "cmd",
|
|
51297
|
+
args: (url2) => ["/c", "start", "", url2]
|
|
51298
|
+
}
|
|
51299
|
+
],
|
|
51300
|
+
linux: [
|
|
51301
|
+
{
|
|
51302
|
+
command: "xdg-open",
|
|
51303
|
+
args: (url2) => [url2],
|
|
51304
|
+
errorPrefix: "xdg-open failed: "
|
|
51305
|
+
},
|
|
51306
|
+
{
|
|
51307
|
+
command: "gio",
|
|
51308
|
+
args: (url2) => ["open", url2],
|
|
51309
|
+
errorPrefix: "gio open failed: "
|
|
51310
|
+
}
|
|
51311
|
+
]
|
|
51312
|
+
};
|
|
51204
51313
|
function openExternalUrl(url2) {
|
|
51205
51314
|
let parsedUrl;
|
|
51206
51315
|
try {
|
|
@@ -51218,31 +51327,28 @@ function openExternalUrl(url2) {
|
|
|
51218
51327
|
};
|
|
51219
51328
|
}
|
|
51220
51329
|
const platform3 = os4.platform();
|
|
51221
|
-
|
|
51222
|
-
|
|
51223
|
-
return
|
|
51224
|
-
|
|
51225
|
-
|
|
51226
|
-
|
|
51227
|
-
return commandError ? { success: false, error: commandError } : { success: true };
|
|
51330
|
+
const plans = PLATFORM_OPEN_PLANS[platform3];
|
|
51331
|
+
if (!plans) {
|
|
51332
|
+
return {
|
|
51333
|
+
success: false,
|
|
51334
|
+
error: `Unsupported platform: ${platform3}`
|
|
51335
|
+
};
|
|
51228
51336
|
}
|
|
51229
|
-
|
|
51230
|
-
|
|
51231
|
-
|
|
51337
|
+
const errors3 = [];
|
|
51338
|
+
for (const plan of plans) {
|
|
51339
|
+
const commandError = runOpenCommand(plan.command, plan.args(url2));
|
|
51340
|
+
if (!commandError) {
|
|
51232
51341
|
return { success: true };
|
|
51233
51342
|
}
|
|
51234
|
-
|
|
51235
|
-
|
|
51236
|
-
|
|
51343
|
+
if (plan.errorPrefix) {
|
|
51344
|
+
errors3.push(`${plan.errorPrefix}${commandError}`);
|
|
51345
|
+
} else {
|
|
51346
|
+
errors3.push(commandError);
|
|
51237
51347
|
}
|
|
51238
|
-
return {
|
|
51239
|
-
success: false,
|
|
51240
|
-
error: `xdg-open failed: ${xdgError}; gio open failed: ${gioError}`
|
|
51241
|
-
};
|
|
51242
51348
|
}
|
|
51243
51349
|
return {
|
|
51244
51350
|
success: false,
|
|
51245
|
-
error:
|
|
51351
|
+
error: errors3.join("; ")
|
|
51246
51352
|
};
|
|
51247
51353
|
}
|
|
51248
51354
|
|
|
@@ -51478,7 +51584,7 @@ import { execSync as execSync3 } from "child_process";
|
|
|
51478
51584
|
import * as fs5 from "fs";
|
|
51479
51585
|
import * as path4 from "path";
|
|
51480
51586
|
var __dirname = "/Users/sirmalloc/Projects/Personal/ccstatusline/src/utils";
|
|
51481
|
-
var PACKAGE_VERSION = "2.1.
|
|
51587
|
+
var PACKAGE_VERSION = "2.1.9";
|
|
51482
51588
|
function getPackageVersion() {
|
|
51483
51589
|
if (/^\d+\.\d+\.\d+/.test(PACKAGE_VERSION)) {
|
|
51484
51590
|
return PACKAGE_VERSION;
|
|
@@ -52032,23 +52138,27 @@ function applyColors(text, foregroundColor, backgroundColor, bold, colorLevel =
|
|
|
52032
52138
|
if (!foregroundColor && !backgroundColor && !bold) {
|
|
52033
52139
|
return text;
|
|
52034
52140
|
}
|
|
52035
|
-
let
|
|
52141
|
+
let prefix = "";
|
|
52142
|
+
let suffix = "";
|
|
52143
|
+
if (bold) {
|
|
52144
|
+
prefix += "\x1B[1m";
|
|
52145
|
+
suffix = "\x1B[22m" + suffix;
|
|
52146
|
+
}
|
|
52036
52147
|
if (backgroundColor) {
|
|
52037
|
-
const
|
|
52038
|
-
if (
|
|
52039
|
-
|
|
52148
|
+
const bgCode = getColorAnsiCode(backgroundColor, colorLevel, true);
|
|
52149
|
+
if (bgCode) {
|
|
52150
|
+
prefix += bgCode;
|
|
52151
|
+
suffix = "\x1B[49m" + suffix;
|
|
52040
52152
|
}
|
|
52041
52153
|
}
|
|
52042
52154
|
if (foregroundColor) {
|
|
52043
|
-
const
|
|
52044
|
-
if (
|
|
52045
|
-
|
|
52155
|
+
const fgCode = getColorAnsiCode(foregroundColor, colorLevel, false);
|
|
52156
|
+
if (fgCode) {
|
|
52157
|
+
prefix += fgCode;
|
|
52158
|
+
suffix = "\x1B[39m" + suffix;
|
|
52046
52159
|
}
|
|
52047
52160
|
}
|
|
52048
|
-
|
|
52049
|
-
result = source_default.bold(result);
|
|
52050
|
-
}
|
|
52051
|
-
return result;
|
|
52161
|
+
return prefix + text + suffix;
|
|
52052
52162
|
}
|
|
52053
52163
|
function getColorAnsiCode(colorName, colorLevel = "ansi16", isBackground = false) {
|
|
52054
52164
|
if (!colorName)
|
|
@@ -54566,54 +54676,309 @@ var CustomCommandEditor = ({ widget, onComplete, onCancel, action }) => {
|
|
|
54566
54676
|
children: "Unknown editor mode"
|
|
54567
54677
|
}, undefined, false, undefined, this);
|
|
54568
54678
|
};
|
|
54569
|
-
// src/utils/usage.ts
|
|
54570
|
-
import {
|
|
54571
|
-
execSync as execSync6,
|
|
54572
|
-
spawnSync as spawnSync2
|
|
54573
|
-
} from "child_process";
|
|
54574
|
-
import * as fs7 from "fs";
|
|
54575
|
-
import * as os7 from "os";
|
|
54576
|
-
import * as path7 from "path";
|
|
54577
|
-
|
|
54578
|
-
// src/utils/jsonl.ts
|
|
54679
|
+
// src/utils/usage-fetch.ts
|
|
54680
|
+
import { execSync as execSync6 } from "child_process";
|
|
54579
54681
|
import * as fs6 from "fs";
|
|
54580
|
-
import
|
|
54581
|
-
import os6 from "
|
|
54582
|
-
import
|
|
54583
|
-
|
|
54584
|
-
//
|
|
54585
|
-
|
|
54682
|
+
import * as https from "https";
|
|
54683
|
+
import * as os6 from "os";
|
|
54684
|
+
import * as path5 from "path";
|
|
54685
|
+
|
|
54686
|
+
// src/utils/usage-types.ts
|
|
54687
|
+
var FIVE_HOUR_BLOCK_MS = 5 * 60 * 60 * 1000;
|
|
54688
|
+
var SEVEN_DAY_WINDOW_MS = 7 * 24 * 60 * 60 * 1000;
|
|
54689
|
+
var UsageErrorSchema = exports_external.enum(["no-credentials", "timeout", "api-error", "parse-error"]);
|
|
54690
|
+
|
|
54691
|
+
// src/utils/usage-fetch.ts
|
|
54692
|
+
var CACHE_DIR = path5.join(os6.homedir(), ".cache", "ccstatusline");
|
|
54693
|
+
var CACHE_FILE = path5.join(CACHE_DIR, "usage.json");
|
|
54694
|
+
var LOCK_FILE = path5.join(CACHE_DIR, "usage.lock");
|
|
54695
|
+
var CACHE_MAX_AGE = 180;
|
|
54696
|
+
var LOCK_MAX_AGE = 30;
|
|
54697
|
+
var TOKEN_CACHE_MAX_AGE = 3600;
|
|
54698
|
+
var UsageCredentialsSchema = exports_external.object({ claudeAiOauth: exports_external.object({ accessToken: exports_external.string().nullable().optional() }).optional() });
|
|
54699
|
+
var CachedUsageDataSchema = exports_external.object({
|
|
54700
|
+
sessionUsage: exports_external.number().nullable().optional(),
|
|
54701
|
+
sessionResetAt: exports_external.string().nullable().optional(),
|
|
54702
|
+
weeklyUsage: exports_external.number().nullable().optional(),
|
|
54703
|
+
weeklyResetAt: exports_external.string().nullable().optional(),
|
|
54704
|
+
extraUsageEnabled: exports_external.boolean().nullable().optional(),
|
|
54705
|
+
extraUsageLimit: exports_external.number().nullable().optional(),
|
|
54706
|
+
extraUsageUsed: exports_external.number().nullable().optional(),
|
|
54707
|
+
extraUsageUtilization: exports_external.number().nullable().optional(),
|
|
54708
|
+
error: exports_external.string().nullable().optional()
|
|
54709
|
+
});
|
|
54710
|
+
var UsageApiResponseSchema = exports_external.object({
|
|
54711
|
+
five_hour: exports_external.object({
|
|
54712
|
+
utilization: exports_external.number().nullable().optional(),
|
|
54713
|
+
resets_at: exports_external.string().nullable().optional()
|
|
54714
|
+
}).optional(),
|
|
54715
|
+
seven_day: exports_external.object({
|
|
54716
|
+
utilization: exports_external.number().nullable().optional(),
|
|
54717
|
+
resets_at: exports_external.string().nullable().optional()
|
|
54718
|
+
}).optional(),
|
|
54719
|
+
extra_usage: exports_external.object({
|
|
54720
|
+
is_enabled: exports_external.boolean().nullable().optional(),
|
|
54721
|
+
monthly_limit: exports_external.number().nullable().optional(),
|
|
54722
|
+
used_credits: exports_external.number().nullable().optional(),
|
|
54723
|
+
utilization: exports_external.number().nullable().optional()
|
|
54724
|
+
}).optional()
|
|
54725
|
+
});
|
|
54726
|
+
function parseJsonWithSchema(rawJson, schema) {
|
|
54727
|
+
try {
|
|
54728
|
+
const parsed = schema.safeParse(JSON.parse(rawJson));
|
|
54729
|
+
return parsed.success ? parsed.data : null;
|
|
54730
|
+
} catch {
|
|
54731
|
+
return null;
|
|
54732
|
+
}
|
|
54733
|
+
}
|
|
54734
|
+
function parseUsageAccessToken(rawJson) {
|
|
54735
|
+
const parsed = parseJsonWithSchema(rawJson, UsageCredentialsSchema);
|
|
54736
|
+
return parsed?.claudeAiOauth?.accessToken ?? null;
|
|
54737
|
+
}
|
|
54738
|
+
function parseCachedUsageData(rawJson) {
|
|
54739
|
+
const parsed = parseJsonWithSchema(rawJson, CachedUsageDataSchema);
|
|
54740
|
+
if (!parsed) {
|
|
54741
|
+
return null;
|
|
54742
|
+
}
|
|
54743
|
+
const parsedError = UsageErrorSchema.safeParse(parsed.error);
|
|
54744
|
+
return {
|
|
54745
|
+
sessionUsage: parsed.sessionUsage ?? undefined,
|
|
54746
|
+
sessionResetAt: parsed.sessionResetAt ?? undefined,
|
|
54747
|
+
weeklyUsage: parsed.weeklyUsage ?? undefined,
|
|
54748
|
+
weeklyResetAt: parsed.weeklyResetAt ?? undefined,
|
|
54749
|
+
extraUsageEnabled: parsed.extraUsageEnabled ?? undefined,
|
|
54750
|
+
extraUsageLimit: parsed.extraUsageLimit ?? undefined,
|
|
54751
|
+
extraUsageUsed: parsed.extraUsageUsed ?? undefined,
|
|
54752
|
+
extraUsageUtilization: parsed.extraUsageUtilization ?? undefined,
|
|
54753
|
+
error: parsedError.success ? parsedError.data : undefined
|
|
54754
|
+
};
|
|
54755
|
+
}
|
|
54756
|
+
function parseUsageApiResponse(rawJson) {
|
|
54757
|
+
const parsed = parseJsonWithSchema(rawJson, UsageApiResponseSchema);
|
|
54758
|
+
if (!parsed) {
|
|
54759
|
+
return null;
|
|
54760
|
+
}
|
|
54761
|
+
return {
|
|
54762
|
+
sessionUsage: parsed.five_hour?.utilization ?? undefined,
|
|
54763
|
+
sessionResetAt: parsed.five_hour?.resets_at ?? undefined,
|
|
54764
|
+
weeklyUsage: parsed.seven_day?.utilization ?? undefined,
|
|
54765
|
+
weeklyResetAt: parsed.seven_day?.resets_at ?? undefined,
|
|
54766
|
+
extraUsageEnabled: parsed.extra_usage?.is_enabled ?? undefined,
|
|
54767
|
+
extraUsageLimit: parsed.extra_usage?.monthly_limit ?? undefined,
|
|
54768
|
+
extraUsageUsed: parsed.extra_usage?.used_credits ?? undefined,
|
|
54769
|
+
extraUsageUtilization: parsed.extra_usage?.utilization ?? undefined
|
|
54770
|
+
};
|
|
54771
|
+
}
|
|
54772
|
+
var cachedUsageData = null;
|
|
54773
|
+
var usageCacheTime = 0;
|
|
54774
|
+
var cachedUsageToken = null;
|
|
54775
|
+
var usageTokenCacheTime = 0;
|
|
54776
|
+
function setCachedUsageError(error43, now) {
|
|
54777
|
+
const errorData = { error: error43 };
|
|
54778
|
+
cachedUsageData = errorData;
|
|
54779
|
+
usageCacheTime = now;
|
|
54780
|
+
return errorData;
|
|
54781
|
+
}
|
|
54782
|
+
function getStaleUsageOrError(error43, now) {
|
|
54783
|
+
const stale = readStaleUsageCache();
|
|
54784
|
+
if (stale && !stale.error) {
|
|
54785
|
+
cachedUsageData = stale;
|
|
54786
|
+
usageCacheTime = now;
|
|
54787
|
+
return stale;
|
|
54788
|
+
}
|
|
54789
|
+
return setCachedUsageError(error43, now);
|
|
54790
|
+
}
|
|
54791
|
+
function getUsageToken() {
|
|
54792
|
+
const now = Math.floor(Date.now() / 1000);
|
|
54793
|
+
if (cachedUsageToken && now - usageTokenCacheTime < TOKEN_CACHE_MAX_AGE) {
|
|
54794
|
+
return cachedUsageToken;
|
|
54795
|
+
}
|
|
54796
|
+
try {
|
|
54797
|
+
const isMac = process.platform === "darwin";
|
|
54798
|
+
if (isMac) {
|
|
54799
|
+
const result = execSync6('security find-generic-password -s "Claude Code-credentials" -w 2>/dev/null', { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
54800
|
+
const token2 = parseUsageAccessToken(result);
|
|
54801
|
+
if (token2) {
|
|
54802
|
+
cachedUsageToken = token2;
|
|
54803
|
+
usageTokenCacheTime = now;
|
|
54804
|
+
}
|
|
54805
|
+
return token2;
|
|
54806
|
+
}
|
|
54807
|
+
const credFile = path5.join(getClaudeConfigDir(), ".credentials.json");
|
|
54808
|
+
const token = parseUsageAccessToken(fs6.readFileSync(credFile, "utf8"));
|
|
54809
|
+
if (token) {
|
|
54810
|
+
cachedUsageToken = token;
|
|
54811
|
+
usageTokenCacheTime = now;
|
|
54812
|
+
}
|
|
54813
|
+
return token;
|
|
54814
|
+
} catch {
|
|
54815
|
+
return null;
|
|
54816
|
+
}
|
|
54817
|
+
}
|
|
54818
|
+
function readStaleUsageCache() {
|
|
54819
|
+
try {
|
|
54820
|
+
return parseCachedUsageData(fs6.readFileSync(CACHE_FILE, "utf8"));
|
|
54821
|
+
} catch {
|
|
54822
|
+
return null;
|
|
54823
|
+
}
|
|
54824
|
+
}
|
|
54825
|
+
var USAGE_API_HOST = "api.anthropic.com";
|
|
54826
|
+
var USAGE_API_PATH = "/api/oauth/usage";
|
|
54827
|
+
async function fetchFromUsageApi(token) {
|
|
54828
|
+
return new Promise((resolve3) => {
|
|
54829
|
+
let settled = false;
|
|
54830
|
+
const finish = (value) => {
|
|
54831
|
+
if (settled) {
|
|
54832
|
+
return;
|
|
54833
|
+
}
|
|
54834
|
+
settled = true;
|
|
54835
|
+
resolve3(value);
|
|
54836
|
+
};
|
|
54837
|
+
const request2 = https.request({
|
|
54838
|
+
hostname: USAGE_API_HOST,
|
|
54839
|
+
path: USAGE_API_PATH,
|
|
54840
|
+
method: "GET",
|
|
54841
|
+
headers: {
|
|
54842
|
+
Authorization: `Bearer ${token}`,
|
|
54843
|
+
"anthropic-beta": "oauth-2025-04-20"
|
|
54844
|
+
},
|
|
54845
|
+
timeout: 5000
|
|
54846
|
+
}, (response) => {
|
|
54847
|
+
let data = "";
|
|
54848
|
+
response.setEncoding("utf8");
|
|
54849
|
+
response.on("data", (chunk) => {
|
|
54850
|
+
data += chunk;
|
|
54851
|
+
});
|
|
54852
|
+
response.on("end", () => {
|
|
54853
|
+
if (response.statusCode === 200 && data) {
|
|
54854
|
+
finish(data);
|
|
54855
|
+
return;
|
|
54856
|
+
}
|
|
54857
|
+
finish(null);
|
|
54858
|
+
});
|
|
54859
|
+
});
|
|
54860
|
+
request2.on("error", () => {
|
|
54861
|
+
finish(null);
|
|
54862
|
+
});
|
|
54863
|
+
request2.on("timeout", () => {
|
|
54864
|
+
request2.destroy();
|
|
54865
|
+
finish(null);
|
|
54866
|
+
});
|
|
54867
|
+
request2.end();
|
|
54868
|
+
});
|
|
54869
|
+
}
|
|
54870
|
+
async function fetchUsageData() {
|
|
54871
|
+
const now = Math.floor(Date.now() / 1000);
|
|
54872
|
+
if (cachedUsageData) {
|
|
54873
|
+
const cacheAge = now - usageCacheTime;
|
|
54874
|
+
if (!cachedUsageData.error && cacheAge < CACHE_MAX_AGE) {
|
|
54875
|
+
return cachedUsageData;
|
|
54876
|
+
}
|
|
54877
|
+
if (cachedUsageData.error && cacheAge < LOCK_MAX_AGE) {
|
|
54878
|
+
return cachedUsageData;
|
|
54879
|
+
}
|
|
54880
|
+
}
|
|
54881
|
+
try {
|
|
54882
|
+
const stat = fs6.statSync(CACHE_FILE);
|
|
54883
|
+
const fileAge = now - Math.floor(stat.mtimeMs / 1000);
|
|
54884
|
+
if (fileAge < CACHE_MAX_AGE) {
|
|
54885
|
+
const fileData = parseCachedUsageData(fs6.readFileSync(CACHE_FILE, "utf8"));
|
|
54886
|
+
if (fileData && !fileData.error) {
|
|
54887
|
+
cachedUsageData = fileData;
|
|
54888
|
+
usageCacheTime = now;
|
|
54889
|
+
return fileData;
|
|
54890
|
+
}
|
|
54891
|
+
}
|
|
54892
|
+
} catch {}
|
|
54893
|
+
const token = getUsageToken();
|
|
54894
|
+
if (!token) {
|
|
54895
|
+
return getStaleUsageOrError("no-credentials", now);
|
|
54896
|
+
}
|
|
54897
|
+
try {
|
|
54898
|
+
const lockStat = fs6.statSync(LOCK_FILE);
|
|
54899
|
+
const lockAge = now - Math.floor(lockStat.mtimeMs / 1000);
|
|
54900
|
+
if (lockAge < LOCK_MAX_AGE) {
|
|
54901
|
+
const stale = readStaleUsageCache();
|
|
54902
|
+
if (stale && !stale.error)
|
|
54903
|
+
return stale;
|
|
54904
|
+
return { error: "timeout" };
|
|
54905
|
+
}
|
|
54906
|
+
} catch {}
|
|
54907
|
+
try {
|
|
54908
|
+
const lockDir = path5.dirname(LOCK_FILE);
|
|
54909
|
+
if (!fs6.existsSync(lockDir)) {
|
|
54910
|
+
fs6.mkdirSync(lockDir, { recursive: true });
|
|
54911
|
+
}
|
|
54912
|
+
fs6.writeFileSync(LOCK_FILE, "");
|
|
54913
|
+
} catch {}
|
|
54914
|
+
try {
|
|
54915
|
+
const response = await fetchFromUsageApi(token);
|
|
54916
|
+
if (!response) {
|
|
54917
|
+
return getStaleUsageOrError("api-error", now);
|
|
54918
|
+
}
|
|
54919
|
+
const usageData = parseUsageApiResponse(response);
|
|
54920
|
+
if (!usageData) {
|
|
54921
|
+
return getStaleUsageOrError("parse-error", now);
|
|
54922
|
+
}
|
|
54923
|
+
if (usageData.sessionUsage === undefined && usageData.weeklyUsage === undefined) {
|
|
54924
|
+
return getStaleUsageOrError("parse-error", now);
|
|
54925
|
+
}
|
|
54926
|
+
try {
|
|
54927
|
+
if (!fs6.existsSync(CACHE_DIR)) {
|
|
54928
|
+
fs6.mkdirSync(CACHE_DIR, { recursive: true });
|
|
54929
|
+
}
|
|
54930
|
+
fs6.writeFileSync(CACHE_FILE, JSON.stringify(usageData));
|
|
54931
|
+
} catch {}
|
|
54932
|
+
cachedUsageData = usageData;
|
|
54933
|
+
usageCacheTime = now;
|
|
54934
|
+
return usageData;
|
|
54935
|
+
} catch {
|
|
54936
|
+
return getStaleUsageOrError("parse-error", now);
|
|
54937
|
+
}
|
|
54938
|
+
}
|
|
54939
|
+
// src/utils/jsonl-cache.ts
|
|
54940
|
+
import * as fs9 from "fs";
|
|
54941
|
+
import { createHash } from "node:crypto";
|
|
54942
|
+
import os7 from "node:os";
|
|
54943
|
+
import path8 from "node:path";
|
|
54944
|
+
|
|
54945
|
+
// src/utils/jsonl-blocks.ts
|
|
54946
|
+
import * as fs8 from "fs";
|
|
54947
|
+
import path7 from "node:path";
|
|
54948
|
+
|
|
54949
|
+
// node_modules/tinyglobby/dist/index.mjs
|
|
54950
|
+
import path6, { posix } from "path";
|
|
54586
54951
|
|
|
54587
54952
|
// node_modules/fdir/dist/index.mjs
|
|
54588
54953
|
import { createRequire as createRequire2 } from "module";
|
|
54589
|
-
import { basename as basename2, dirname as
|
|
54954
|
+
import { basename as basename2, dirname as dirname4, normalize, relative, resolve as resolve3, sep } from "path";
|
|
54590
54955
|
import * as nativeFs from "fs";
|
|
54591
54956
|
var __require2 = /* @__PURE__ */ createRequire2(import.meta.url);
|
|
54592
|
-
function cleanPath(
|
|
54593
|
-
let normalized = normalize(
|
|
54957
|
+
function cleanPath(path6) {
|
|
54958
|
+
let normalized = normalize(path6);
|
|
54594
54959
|
if (normalized.length > 1 && normalized[normalized.length - 1] === sep)
|
|
54595
54960
|
normalized = normalized.substring(0, normalized.length - 1);
|
|
54596
54961
|
return normalized;
|
|
54597
54962
|
}
|
|
54598
54963
|
var SLASHES_REGEX = /[\\/]/g;
|
|
54599
|
-
function convertSlashes(
|
|
54600
|
-
return
|
|
54964
|
+
function convertSlashes(path6, separator) {
|
|
54965
|
+
return path6.replace(SLASHES_REGEX, separator);
|
|
54601
54966
|
}
|
|
54602
54967
|
var WINDOWS_ROOT_DIR_REGEX = /^[a-z]:[\\/]$/i;
|
|
54603
|
-
function isRootDirectory(
|
|
54604
|
-
return
|
|
54968
|
+
function isRootDirectory(path6) {
|
|
54969
|
+
return path6 === "/" || WINDOWS_ROOT_DIR_REGEX.test(path6);
|
|
54605
54970
|
}
|
|
54606
|
-
function normalizePath(
|
|
54971
|
+
function normalizePath(path6, options) {
|
|
54607
54972
|
const { resolvePaths, normalizePath: normalizePath$1, pathSeparator } = options;
|
|
54608
|
-
const pathNeedsCleaning = process.platform === "win32" &&
|
|
54973
|
+
const pathNeedsCleaning = process.platform === "win32" && path6.includes("/") || path6.startsWith(".");
|
|
54609
54974
|
if (resolvePaths)
|
|
54610
|
-
|
|
54975
|
+
path6 = resolve3(path6);
|
|
54611
54976
|
if (normalizePath$1 || pathNeedsCleaning)
|
|
54612
|
-
|
|
54613
|
-
if (
|
|
54977
|
+
path6 = cleanPath(path6);
|
|
54978
|
+
if (path6 === ".")
|
|
54614
54979
|
return "";
|
|
54615
|
-
const needsSeperator =
|
|
54616
|
-
return convertSlashes(needsSeperator ?
|
|
54980
|
+
const needsSeperator = path6[path6.length - 1] !== pathSeparator;
|
|
54981
|
+
return convertSlashes(needsSeperator ? path6 + pathSeparator : path6, pathSeparator);
|
|
54617
54982
|
}
|
|
54618
54983
|
function joinPathWithBasePath(filename, directoryPath) {
|
|
54619
54984
|
return directoryPath + filename;
|
|
@@ -54653,9 +55018,9 @@ var pushDirectory = (directoryPath, paths) => {
|
|
|
54653
55018
|
paths.push(directoryPath || ".");
|
|
54654
55019
|
};
|
|
54655
55020
|
var pushDirectoryFilter = (directoryPath, paths, filters) => {
|
|
54656
|
-
const
|
|
54657
|
-
if (filters.every((filter) => filter(
|
|
54658
|
-
paths.push(
|
|
55021
|
+
const path6 = directoryPath || ".";
|
|
55022
|
+
if (filters.every((filter) => filter(path6, true)))
|
|
55023
|
+
paths.push(path6);
|
|
54659
55024
|
};
|
|
54660
55025
|
var empty$2 = () => {};
|
|
54661
55026
|
function build$6(root, options) {
|
|
@@ -54712,29 +55077,29 @@ var empty = () => {};
|
|
|
54712
55077
|
function build$3(options) {
|
|
54713
55078
|
return options.group ? groupFiles : empty;
|
|
54714
55079
|
}
|
|
54715
|
-
var resolveSymlinksAsync = function(
|
|
54716
|
-
const { queue, fs:
|
|
55080
|
+
var resolveSymlinksAsync = function(path6, state, callback$1) {
|
|
55081
|
+
const { queue, fs: fs7, options: { suppressErrors } } = state;
|
|
54717
55082
|
queue.enqueue();
|
|
54718
|
-
|
|
55083
|
+
fs7.realpath(path6, (error43, resolvedPath) => {
|
|
54719
55084
|
if (error43)
|
|
54720
55085
|
return queue.dequeue(suppressErrors ? null : error43, state);
|
|
54721
|
-
|
|
55086
|
+
fs7.stat(resolvedPath, (error$1, stat) => {
|
|
54722
55087
|
if (error$1)
|
|
54723
55088
|
return queue.dequeue(suppressErrors ? null : error$1, state);
|
|
54724
|
-
if (stat.isDirectory() && isRecursive(
|
|
55089
|
+
if (stat.isDirectory() && isRecursive(path6, resolvedPath, state))
|
|
54725
55090
|
return queue.dequeue(null, state);
|
|
54726
55091
|
callback$1(stat, resolvedPath);
|
|
54727
55092
|
queue.dequeue(null, state);
|
|
54728
55093
|
});
|
|
54729
55094
|
});
|
|
54730
55095
|
};
|
|
54731
|
-
var resolveSymlinks = function(
|
|
54732
|
-
const { queue, fs:
|
|
55096
|
+
var resolveSymlinks = function(path6, state, callback$1) {
|
|
55097
|
+
const { queue, fs: fs7, options: { suppressErrors } } = state;
|
|
54733
55098
|
queue.enqueue();
|
|
54734
55099
|
try {
|
|
54735
|
-
const resolvedPath =
|
|
54736
|
-
const stat =
|
|
54737
|
-
if (stat.isDirectory() && isRecursive(
|
|
55100
|
+
const resolvedPath = fs7.realpathSync(path6);
|
|
55101
|
+
const stat = fs7.statSync(resolvedPath);
|
|
55102
|
+
if (stat.isDirectory() && isRecursive(path6, resolvedPath, state))
|
|
54738
55103
|
return;
|
|
54739
55104
|
callback$1(stat, resolvedPath);
|
|
54740
55105
|
} catch (e) {
|
|
@@ -54747,10 +55112,10 @@ function build$2(options, isSynchronous) {
|
|
|
54747
55112
|
return null;
|
|
54748
55113
|
return isSynchronous ? resolveSymlinks : resolveSymlinksAsync;
|
|
54749
55114
|
}
|
|
54750
|
-
function isRecursive(
|
|
55115
|
+
function isRecursive(path6, resolved, state) {
|
|
54751
55116
|
if (state.options.useRealPaths)
|
|
54752
55117
|
return isRecursiveUsingRealPaths(resolved, state);
|
|
54753
|
-
let parent =
|
|
55118
|
+
let parent = dirname4(path6);
|
|
54754
55119
|
let depth = 1;
|
|
54755
55120
|
while (parent !== state.root && depth < 2) {
|
|
54756
55121
|
const resolvedPath = state.symlinks.get(parent);
|
|
@@ -54758,9 +55123,9 @@ function isRecursive(path5, resolved, state) {
|
|
|
54758
55123
|
if (isSameRoot)
|
|
54759
55124
|
depth++;
|
|
54760
55125
|
else
|
|
54761
|
-
parent =
|
|
55126
|
+
parent = dirname4(parent);
|
|
54762
55127
|
}
|
|
54763
|
-
state.symlinks.set(
|
|
55128
|
+
state.symlinks.set(path6, resolved);
|
|
54764
55129
|
return depth > 1;
|
|
54765
55130
|
}
|
|
54766
55131
|
function isRecursiveUsingRealPaths(resolved, state) {
|
|
@@ -54816,23 +55181,23 @@ var walkAsync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
|
|
|
54816
55181
|
state.queue.enqueue();
|
|
54817
55182
|
if (currentDepth < 0)
|
|
54818
55183
|
return state.queue.dequeue(null, state);
|
|
54819
|
-
const { fs:
|
|
55184
|
+
const { fs: fs7 } = state;
|
|
54820
55185
|
state.visited.push(crawlPath);
|
|
54821
55186
|
state.counts.directories++;
|
|
54822
|
-
|
|
55187
|
+
fs7.readdir(crawlPath || ".", readdirOpts, (error43, entries = []) => {
|
|
54823
55188
|
callback$1(entries, directoryPath, currentDepth);
|
|
54824
55189
|
state.queue.dequeue(state.options.suppressErrors ? null : error43, state);
|
|
54825
55190
|
});
|
|
54826
55191
|
};
|
|
54827
55192
|
var walkSync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
|
|
54828
|
-
const { fs:
|
|
55193
|
+
const { fs: fs7 } = state;
|
|
54829
55194
|
if (currentDepth < 0)
|
|
54830
55195
|
return;
|
|
54831
55196
|
state.visited.push(crawlPath);
|
|
54832
55197
|
state.counts.directories++;
|
|
54833
55198
|
let entries = [];
|
|
54834
55199
|
try {
|
|
54835
|
-
entries =
|
|
55200
|
+
entries = fs7.readdirSync(crawlPath || ".", readdirOpts);
|
|
54836
55201
|
} catch (e) {
|
|
54837
55202
|
if (!state.options.suppressErrors)
|
|
54838
55203
|
throw e;
|
|
@@ -54938,23 +55303,23 @@ var Walker = class {
|
|
|
54938
55303
|
const filename = this.joinPath(entry.name, directoryPath);
|
|
54939
55304
|
this.pushFile(filename, files, this.state.counts, filters);
|
|
54940
55305
|
} else if (entry.isDirectory()) {
|
|
54941
|
-
let
|
|
54942
|
-
if (exclude && exclude(entry.name,
|
|
55306
|
+
let path6 = joinDirectoryPath(entry.name, directoryPath, this.state.options.pathSeparator);
|
|
55307
|
+
if (exclude && exclude(entry.name, path6))
|
|
54943
55308
|
continue;
|
|
54944
|
-
this.pushDirectory(
|
|
54945
|
-
this.walkDirectory(this.state,
|
|
55309
|
+
this.pushDirectory(path6, paths, filters);
|
|
55310
|
+
this.walkDirectory(this.state, path6, path6, depth - 1, this.walk);
|
|
54946
55311
|
} else if (this.resolveSymlink && entry.isSymbolicLink()) {
|
|
54947
|
-
let
|
|
54948
|
-
this.resolveSymlink(
|
|
55312
|
+
let path6 = joinPathWithBasePath(entry.name, directoryPath);
|
|
55313
|
+
this.resolveSymlink(path6, this.state, (stat, resolvedPath) => {
|
|
54949
55314
|
if (stat.isDirectory()) {
|
|
54950
55315
|
resolvedPath = normalizePath(resolvedPath, this.state.options);
|
|
54951
|
-
if (exclude && exclude(entry.name, useRealPaths ? resolvedPath :
|
|
55316
|
+
if (exclude && exclude(entry.name, useRealPaths ? resolvedPath : path6 + pathSeparator))
|
|
54952
55317
|
return;
|
|
54953
|
-
this.walkDirectory(this.state, resolvedPath, useRealPaths ? resolvedPath :
|
|
55318
|
+
this.walkDirectory(this.state, resolvedPath, useRealPaths ? resolvedPath : path6 + pathSeparator, depth - 1, this.walk);
|
|
54954
55319
|
} else {
|
|
54955
|
-
resolvedPath = useRealPaths ? resolvedPath :
|
|
55320
|
+
resolvedPath = useRealPaths ? resolvedPath : path6;
|
|
54956
55321
|
const filename = basename2(resolvedPath);
|
|
54957
|
-
const directoryPath$1 = normalizePath(
|
|
55322
|
+
const directoryPath$1 = normalizePath(dirname4(resolvedPath), this.state.options);
|
|
54958
55323
|
resolvedPath = this.joinPath(filename, directoryPath$1);
|
|
54959
55324
|
this.pushFile(resolvedPath, files, this.state.counts, filters);
|
|
54960
55325
|
}
|
|
@@ -55112,7 +55477,7 @@ var Builder = class {
|
|
|
55112
55477
|
isMatch = globFn(patterns, ...options);
|
|
55113
55478
|
this.globCache[patterns.join("\x00")] = isMatch;
|
|
55114
55479
|
}
|
|
55115
|
-
this.options.filters.push((
|
|
55480
|
+
this.options.filters.push((path6) => isMatch(path6));
|
|
55116
55481
|
return this;
|
|
55117
55482
|
}
|
|
55118
55483
|
};
|
|
@@ -55191,7 +55556,7 @@ function normalizePattern(pattern, expandDirectories, cwd2, props, isIgnore) {
|
|
|
55191
55556
|
if (!result.endsWith("*") && expandDirectories)
|
|
55192
55557
|
result += "/**";
|
|
55193
55558
|
const escapedCwd = escapePath(cwd2);
|
|
55194
|
-
if (
|
|
55559
|
+
if (path6.isAbsolute(result.replace(ESCAPING_BACKSLASHES, "")))
|
|
55195
55560
|
result = posix.relative(escapedCwd, result);
|
|
55196
55561
|
else
|
|
55197
55562
|
result = posix.normalize(result);
|
|
@@ -55228,7 +55593,7 @@ function normalizePattern(pattern, expandDirectories, cwd2, props, isIgnore) {
|
|
|
55228
55593
|
}
|
|
55229
55594
|
props.depthOffset = newCommonPath.length;
|
|
55230
55595
|
props.commonPath = newCommonPath;
|
|
55231
|
-
props.root = newCommonPath.length > 0 ?
|
|
55596
|
+
props.root = newCommonPath.length > 0 ? path6.posix.join(cwd2, ...newCommonPath) : cwd2;
|
|
55232
55597
|
}
|
|
55233
55598
|
return result;
|
|
55234
55599
|
}
|
|
@@ -55361,184 +55726,37 @@ function globSync(patternsOrOptions, options) {
|
|
|
55361
55726
|
...options,
|
|
55362
55727
|
patterns: patternsOrOptions
|
|
55363
55728
|
} : patternsOrOptions;
|
|
55364
|
-
const cwd2 = opts.cwd ?
|
|
55729
|
+
const cwd2 = opts.cwd ? path6.resolve(opts.cwd).replace(BACKSLASHES, "/") : process.cwd().replace(BACKSLASHES, "/");
|
|
55365
55730
|
return crawl(opts, cwd2, true);
|
|
55366
55731
|
}
|
|
55367
55732
|
|
|
55368
|
-
// src/utils/jsonl.ts
|
|
55733
|
+
// src/utils/jsonl-lines.ts
|
|
55734
|
+
import * as fs7 from "fs";
|
|
55369
55735
|
import { promisify } from "util";
|
|
55370
|
-
var readFile4 = promisify(
|
|
55371
|
-
var
|
|
55372
|
-
|
|
55373
|
-
|
|
55374
|
-
|
|
55375
|
-
var existsSync7 = fs6.existsSync;
|
|
55376
|
-
function normalizeConfigDir(configDir) {
|
|
55377
|
-
return path6.resolve(configDir);
|
|
55378
|
-
}
|
|
55379
|
-
function getBlockCachePath(configDir = getClaudeConfigDir()) {
|
|
55380
|
-
const normalizedConfigDir = normalizeConfigDir(configDir);
|
|
55381
|
-
const configHash = createHash("sha256").update(normalizedConfigDir).digest("hex").slice(0, 16);
|
|
55382
|
-
return path6.join(os6.homedir(), ".cache", "ccstatusline", `block-cache-${configHash}.json`);
|
|
55383
|
-
}
|
|
55384
|
-
function readBlockCache(expectedConfigDir) {
|
|
55385
|
-
try {
|
|
55386
|
-
const normalizedExpectedConfigDir = expectedConfigDir !== undefined ? normalizeConfigDir(expectedConfigDir) : undefined;
|
|
55387
|
-
const cachePath = getBlockCachePath(normalizedExpectedConfigDir);
|
|
55388
|
-
if (!existsSync7(cachePath)) {
|
|
55389
|
-
return null;
|
|
55390
|
-
}
|
|
55391
|
-
const content = readFileSync4(cachePath, "utf-8");
|
|
55392
|
-
const cache3 = JSON.parse(content);
|
|
55393
|
-
if (typeof cache3.startTime !== "string") {
|
|
55394
|
-
return null;
|
|
55395
|
-
}
|
|
55396
|
-
if (normalizedExpectedConfigDir !== undefined) {
|
|
55397
|
-
if (typeof cache3.configDir !== "string") {
|
|
55398
|
-
return null;
|
|
55399
|
-
}
|
|
55400
|
-
if (cache3.configDir !== normalizedExpectedConfigDir) {
|
|
55401
|
-
return null;
|
|
55402
|
-
}
|
|
55403
|
-
}
|
|
55404
|
-
const date5 = new Date(cache3.startTime);
|
|
55405
|
-
if (Number.isNaN(date5.getTime())) {
|
|
55406
|
-
return null;
|
|
55407
|
-
}
|
|
55408
|
-
return date5;
|
|
55409
|
-
} catch {
|
|
55410
|
-
return null;
|
|
55411
|
-
}
|
|
55736
|
+
var readFile4 = promisify(fs7.readFile);
|
|
55737
|
+
var readFileSync5 = fs7.readFileSync;
|
|
55738
|
+
function splitJsonlContent(content) {
|
|
55739
|
+
return content.trim().split(`
|
|
55740
|
+
`).filter((line) => line.length > 0);
|
|
55412
55741
|
}
|
|
55413
|
-
function
|
|
55414
|
-
|
|
55415
|
-
|
|
55416
|
-
const cachePath = getBlockCachePath(normalizedConfigDir);
|
|
55417
|
-
const cacheDir = path6.dirname(cachePath);
|
|
55418
|
-
if (!existsSync7(cacheDir)) {
|
|
55419
|
-
mkdirSync3(cacheDir, { recursive: true });
|
|
55420
|
-
}
|
|
55421
|
-
const cache3 = {
|
|
55422
|
-
startTime: startTime.toISOString(),
|
|
55423
|
-
configDir: normalizedConfigDir
|
|
55424
|
-
};
|
|
55425
|
-
writeFileSync2(cachePath, JSON.stringify(cache3), "utf-8");
|
|
55426
|
-
} catch {}
|
|
55742
|
+
async function readJsonlLines(filePath) {
|
|
55743
|
+
const content = await readFile4(filePath, "utf-8");
|
|
55744
|
+
return splitJsonlContent(content);
|
|
55427
55745
|
}
|
|
55428
|
-
function
|
|
55429
|
-
const
|
|
55430
|
-
|
|
55431
|
-
const activeConfigDir = getClaudeConfigDir();
|
|
55432
|
-
const cachedStartTime = readBlockCache(activeConfigDir);
|
|
55433
|
-
if (cachedStartTime) {
|
|
55434
|
-
const blockEndTime = new Date(cachedStartTime.getTime() + sessionDurationMs);
|
|
55435
|
-
if (now.getTime() <= blockEndTime.getTime()) {
|
|
55436
|
-
return {
|
|
55437
|
-
startTime: cachedStartTime,
|
|
55438
|
-
lastActivity: now
|
|
55439
|
-
};
|
|
55440
|
-
}
|
|
55441
|
-
}
|
|
55442
|
-
const metrics = getBlockMetrics();
|
|
55443
|
-
if (metrics) {
|
|
55444
|
-
writeBlockCache(metrics.startTime, activeConfigDir);
|
|
55445
|
-
}
|
|
55446
|
-
return metrics;
|
|
55746
|
+
function readJsonlLinesSync(filePath) {
|
|
55747
|
+
const content = readFileSync5(filePath, "utf-8");
|
|
55748
|
+
return splitJsonlContent(content);
|
|
55447
55749
|
}
|
|
55448
|
-
|
|
55750
|
+
function parseJsonlLine(line) {
|
|
55449
55751
|
try {
|
|
55450
|
-
|
|
55451
|
-
return null;
|
|
55452
|
-
}
|
|
55453
|
-
const content = await readFile4(transcriptPath, "utf-8");
|
|
55454
|
-
const lines = content.trim().split(`
|
|
55455
|
-
`).filter((line) => line.trim());
|
|
55456
|
-
if (lines.length === 0) {
|
|
55457
|
-
return null;
|
|
55458
|
-
}
|
|
55459
|
-
let firstTimestamp = null;
|
|
55460
|
-
let lastTimestamp = null;
|
|
55461
|
-
for (const line of lines) {
|
|
55462
|
-
try {
|
|
55463
|
-
const data = JSON.parse(line);
|
|
55464
|
-
if (data.timestamp) {
|
|
55465
|
-
firstTimestamp = new Date(data.timestamp);
|
|
55466
|
-
break;
|
|
55467
|
-
}
|
|
55468
|
-
} catch {}
|
|
55469
|
-
}
|
|
55470
|
-
for (let i = lines.length - 1;i >= 0; i--) {
|
|
55471
|
-
try {
|
|
55472
|
-
const data = JSON.parse(lines[i] ?? "");
|
|
55473
|
-
if (data.timestamp) {
|
|
55474
|
-
lastTimestamp = new Date(data.timestamp);
|
|
55475
|
-
break;
|
|
55476
|
-
}
|
|
55477
|
-
} catch {}
|
|
55478
|
-
}
|
|
55479
|
-
if (!firstTimestamp || !lastTimestamp) {
|
|
55480
|
-
return null;
|
|
55481
|
-
}
|
|
55482
|
-
const durationMs = lastTimestamp.getTime() - firstTimestamp.getTime();
|
|
55483
|
-
const totalMinutes = Math.floor(durationMs / (1000 * 60));
|
|
55484
|
-
if (totalMinutes < 1) {
|
|
55485
|
-
return "<1m";
|
|
55486
|
-
}
|
|
55487
|
-
const hours = Math.floor(totalMinutes / 60);
|
|
55488
|
-
const minutes = totalMinutes % 60;
|
|
55489
|
-
if (hours === 0) {
|
|
55490
|
-
return `${minutes}m`;
|
|
55491
|
-
} else if (minutes === 0) {
|
|
55492
|
-
return `${hours}hr`;
|
|
55493
|
-
} else {
|
|
55494
|
-
return `${hours}hr ${minutes}m`;
|
|
55495
|
-
}
|
|
55752
|
+
return JSON.parse(line);
|
|
55496
55753
|
} catch {
|
|
55497
55754
|
return null;
|
|
55498
55755
|
}
|
|
55499
55756
|
}
|
|
55500
|
-
|
|
55501
|
-
|
|
55502
|
-
|
|
55503
|
-
return { inputTokens: 0, outputTokens: 0, cachedTokens: 0, totalTokens: 0, contextLength: 0 };
|
|
55504
|
-
}
|
|
55505
|
-
const content = await readFile4(transcriptPath, "utf-8");
|
|
55506
|
-
const lines = content.trim().split(`
|
|
55507
|
-
`);
|
|
55508
|
-
let inputTokens = 0;
|
|
55509
|
-
let outputTokens = 0;
|
|
55510
|
-
let cachedTokens = 0;
|
|
55511
|
-
let contextLength = 0;
|
|
55512
|
-
let mostRecentMainChainEntry = null;
|
|
55513
|
-
let mostRecentTimestamp = null;
|
|
55514
|
-
for (const line of lines) {
|
|
55515
|
-
try {
|
|
55516
|
-
const data = JSON.parse(line);
|
|
55517
|
-
if (data.message?.usage) {
|
|
55518
|
-
inputTokens += data.message.usage.input_tokens || 0;
|
|
55519
|
-
outputTokens += data.message.usage.output_tokens || 0;
|
|
55520
|
-
cachedTokens += data.message.usage.cache_read_input_tokens ?? 0;
|
|
55521
|
-
cachedTokens += data.message.usage.cache_creation_input_tokens ?? 0;
|
|
55522
|
-
if (data.isSidechain !== true && data.timestamp && !data.isApiErrorMessage) {
|
|
55523
|
-
const entryTime = new Date(data.timestamp);
|
|
55524
|
-
if (!mostRecentTimestamp || entryTime > mostRecentTimestamp) {
|
|
55525
|
-
mostRecentTimestamp = entryTime;
|
|
55526
|
-
mostRecentMainChainEntry = data;
|
|
55527
|
-
}
|
|
55528
|
-
}
|
|
55529
|
-
}
|
|
55530
|
-
} catch {}
|
|
55531
|
-
}
|
|
55532
|
-
if (mostRecentMainChainEntry?.message?.usage) {
|
|
55533
|
-
const usage = mostRecentMainChainEntry.message.usage;
|
|
55534
|
-
contextLength = (usage.input_tokens || 0) + (usage.cache_read_input_tokens ?? 0) + (usage.cache_creation_input_tokens ?? 0);
|
|
55535
|
-
}
|
|
55536
|
-
const totalTokens = inputTokens + outputTokens + cachedTokens;
|
|
55537
|
-
return { inputTokens, outputTokens, cachedTokens, totalTokens, contextLength };
|
|
55538
|
-
} catch {
|
|
55539
|
-
return { inputTokens: 0, outputTokens: 0, cachedTokens: 0, totalTokens: 0, contextLength: 0 };
|
|
55540
|
-
}
|
|
55541
|
-
}
|
|
55757
|
+
|
|
55758
|
+
// src/utils/jsonl-blocks.ts
|
|
55759
|
+
var statSync5 = fs8.statSync;
|
|
55542
55760
|
function getBlockMetrics() {
|
|
55543
55761
|
const claudeDir = getClaudeConfigDir();
|
|
55544
55762
|
if (!claudeDir)
|
|
@@ -55552,7 +55770,7 @@ function getBlockMetrics() {
|
|
|
55552
55770
|
function findMostRecentBlockStartTime(rootDir, sessionDurationHours = 5) {
|
|
55553
55771
|
const sessionDurationMs = sessionDurationHours * 60 * 60 * 1000;
|
|
55554
55772
|
const now = new Date;
|
|
55555
|
-
const pattern =
|
|
55773
|
+
const pattern = path7.posix.join(rootDir.replace(/\\/g, "/"), "projects", "**", "*.jsonl");
|
|
55556
55774
|
const files = globSync([pattern], {
|
|
55557
55775
|
absolute: true,
|
|
55558
55776
|
cwd: rootDir
|
|
@@ -55560,7 +55778,7 @@ function findMostRecentBlockStartTime(rootDir, sessionDurationHours = 5) {
|
|
|
55560
55778
|
if (files.length === 0)
|
|
55561
55779
|
return null;
|
|
55562
55780
|
const filesWithStats = files.map((file2) => {
|
|
55563
|
-
const stats =
|
|
55781
|
+
const stats = statSync5(file2);
|
|
55564
55782
|
return { file: file2, mtime: stats.mtime };
|
|
55565
55783
|
});
|
|
55566
55784
|
filesWithStats.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
|
|
@@ -55628,315 +55846,225 @@ function findMostRecentBlockStartTime(rootDir, sessionDurationHours = 5) {
|
|
|
55628
55846
|
currentBlockStart = floorToHour(timestamp);
|
|
55629
55847
|
currentBlockEnd = new Date(currentBlockStart.getTime() + sessionDurationMs);
|
|
55630
55848
|
blocks.push({ start: currentBlockStart, end: currentBlockEnd });
|
|
55631
|
-
}
|
|
55632
|
-
}
|
|
55633
|
-
for (const block of blocks) {
|
|
55634
|
-
if (now.getTime() >= block.start.getTime() && now.getTime() <= block.end.getTime()) {
|
|
55635
|
-
const hasActivity = timestamps.some((t) => t.getTime() >= block.start.getTime() && t.getTime() <= block.end.getTime());
|
|
55636
|
-
if (hasActivity) {
|
|
55637
|
-
return {
|
|
55638
|
-
startTime: block.start,
|
|
55639
|
-
lastActivity: mostRecentTimestamp
|
|
55640
|
-
};
|
|
55641
|
-
}
|
|
55642
|
-
}
|
|
55643
|
-
}
|
|
55644
|
-
return null;
|
|
55645
|
-
}
|
|
55646
|
-
function getAllTimestampsFromFile(filePath) {
|
|
55647
|
-
const timestamps = [];
|
|
55648
|
-
try {
|
|
55649
|
-
const content = readFileSync4(filePath, "utf-8");
|
|
55650
|
-
const lines = content.trim().split(`
|
|
55651
|
-
`).filter((line) => line.length > 0);
|
|
55652
|
-
for (const line of lines) {
|
|
55653
|
-
try {
|
|
55654
|
-
const json2 = JSON.parse(line);
|
|
55655
|
-
const usage = json2.message?.usage;
|
|
55656
|
-
if (!usage)
|
|
55657
|
-
continue;
|
|
55658
|
-
const hasInputTokens = typeof usage.input_tokens === "number";
|
|
55659
|
-
const hasOutputTokens = typeof usage.output_tokens === "number";
|
|
55660
|
-
if (!hasInputTokens || !hasOutputTokens)
|
|
55661
|
-
continue;
|
|
55662
|
-
if (json2.isSidechain === true)
|
|
55663
|
-
continue;
|
|
55664
|
-
const timestamp = json2.timestamp;
|
|
55665
|
-
if (typeof timestamp !== "string")
|
|
55666
|
-
continue;
|
|
55667
|
-
const date5 = new Date(timestamp);
|
|
55668
|
-
if (!Number.isNaN(date5.getTime()))
|
|
55669
|
-
timestamps.push(date5);
|
|
55670
|
-
} catch {
|
|
55671
|
-
continue;
|
|
55672
|
-
}
|
|
55673
|
-
}
|
|
55674
|
-
return timestamps;
|
|
55675
|
-
} catch {
|
|
55676
|
-
return [];
|
|
55677
|
-
}
|
|
55678
|
-
}
|
|
55679
|
-
function floorToHour(timestamp) {
|
|
55680
|
-
const floored = new Date(timestamp);
|
|
55681
|
-
floored.setUTCMinutes(0, 0, 0);
|
|
55682
|
-
return floored;
|
|
55683
|
-
}
|
|
55684
|
-
|
|
55685
|
-
// src/utils/usage.ts
|
|
55686
|
-
var CACHE_DIR = path7.join(os7.homedir(), ".cache", "ccstatusline");
|
|
55687
|
-
var CACHE_FILE = path7.join(CACHE_DIR, "usage.json");
|
|
55688
|
-
var LOCK_FILE = path7.join(CACHE_DIR, "usage.lock");
|
|
55689
|
-
var CACHE_MAX_AGE = 180;
|
|
55690
|
-
var LOCK_MAX_AGE = 30;
|
|
55691
|
-
var TOKEN_CACHE_MAX_AGE = 3600;
|
|
55692
|
-
var FIVE_HOUR_BLOCK_MS = 5 * 60 * 60 * 1000;
|
|
55693
|
-
var SEVEN_DAY_WINDOW_MS = 7 * 24 * 60 * 60 * 1000;
|
|
55694
|
-
var UsageErrorSchema = exports_external.enum(["no-credentials", "timeout", "api-error", "parse-error"]);
|
|
55695
|
-
var UsageCredentialsSchema = exports_external.object({ claudeAiOauth: exports_external.object({ accessToken: exports_external.string().nullable().optional() }).optional() });
|
|
55696
|
-
var CachedUsageDataSchema = exports_external.object({
|
|
55697
|
-
sessionUsage: exports_external.number().nullable().optional(),
|
|
55698
|
-
sessionResetAt: exports_external.string().nullable().optional(),
|
|
55699
|
-
weeklyUsage: exports_external.number().nullable().optional(),
|
|
55700
|
-
weeklyResetAt: exports_external.string().nullable().optional(),
|
|
55701
|
-
extraUsageEnabled: exports_external.boolean().nullable().optional(),
|
|
55702
|
-
extraUsageLimit: exports_external.number().nullable().optional(),
|
|
55703
|
-
extraUsageUsed: exports_external.number().nullable().optional(),
|
|
55704
|
-
extraUsageUtilization: exports_external.number().nullable().optional(),
|
|
55705
|
-
error: exports_external.string().nullable().optional()
|
|
55706
|
-
});
|
|
55707
|
-
var UsageApiResponseSchema = exports_external.object({
|
|
55708
|
-
five_hour: exports_external.object({
|
|
55709
|
-
utilization: exports_external.number().nullable().optional(),
|
|
55710
|
-
resets_at: exports_external.string().nullable().optional()
|
|
55711
|
-
}).optional(),
|
|
55712
|
-
seven_day: exports_external.object({
|
|
55713
|
-
utilization: exports_external.number().nullable().optional(),
|
|
55714
|
-
resets_at: exports_external.string().nullable().optional()
|
|
55715
|
-
}).optional(),
|
|
55716
|
-
extra_usage: exports_external.object({
|
|
55717
|
-
is_enabled: exports_external.boolean().nullable().optional(),
|
|
55718
|
-
monthly_limit: exports_external.number().nullable().optional(),
|
|
55719
|
-
used_credits: exports_external.number().nullable().optional(),
|
|
55720
|
-
utilization: exports_external.number().nullable().optional()
|
|
55721
|
-
}).optional()
|
|
55722
|
-
});
|
|
55723
|
-
function parseJsonWithSchema(rawJson, schema) {
|
|
55724
|
-
try {
|
|
55725
|
-
const parsed = schema.safeParse(JSON.parse(rawJson));
|
|
55726
|
-
return parsed.success ? parsed.data : null;
|
|
55727
|
-
} catch {
|
|
55728
|
-
return null;
|
|
55729
|
-
}
|
|
55730
|
-
}
|
|
55731
|
-
function parseUsageAccessToken(rawJson) {
|
|
55732
|
-
const parsed = parseJsonWithSchema(rawJson, UsageCredentialsSchema);
|
|
55733
|
-
return parsed?.claudeAiOauth?.accessToken ?? null;
|
|
55734
|
-
}
|
|
55735
|
-
function parseCachedUsageData(rawJson) {
|
|
55736
|
-
const parsed = parseJsonWithSchema(rawJson, CachedUsageDataSchema);
|
|
55737
|
-
if (!parsed) {
|
|
55738
|
-
return null;
|
|
55739
|
-
}
|
|
55740
|
-
const parsedError = UsageErrorSchema.safeParse(parsed.error);
|
|
55741
|
-
return {
|
|
55742
|
-
sessionUsage: parsed.sessionUsage ?? undefined,
|
|
55743
|
-
sessionResetAt: parsed.sessionResetAt ?? undefined,
|
|
55744
|
-
weeklyUsage: parsed.weeklyUsage ?? undefined,
|
|
55745
|
-
weeklyResetAt: parsed.weeklyResetAt ?? undefined,
|
|
55746
|
-
extraUsageEnabled: parsed.extraUsageEnabled ?? undefined,
|
|
55747
|
-
extraUsageLimit: parsed.extraUsageLimit ?? undefined,
|
|
55748
|
-
extraUsageUsed: parsed.extraUsageUsed ?? undefined,
|
|
55749
|
-
extraUsageUtilization: parsed.extraUsageUtilization ?? undefined,
|
|
55750
|
-
error: parsedError.success ? parsedError.data : undefined
|
|
55751
|
-
};
|
|
55752
|
-
}
|
|
55753
|
-
function parseUsageApiResponse(rawJson) {
|
|
55754
|
-
const parsed = parseJsonWithSchema(rawJson, UsageApiResponseSchema);
|
|
55755
|
-
if (!parsed) {
|
|
55756
|
-
return null;
|
|
55757
|
-
}
|
|
55758
|
-
return {
|
|
55759
|
-
sessionUsage: parsed.five_hour?.utilization ?? undefined,
|
|
55760
|
-
sessionResetAt: parsed.five_hour?.resets_at ?? undefined,
|
|
55761
|
-
weeklyUsage: parsed.seven_day?.utilization ?? undefined,
|
|
55762
|
-
weeklyResetAt: parsed.seven_day?.resets_at ?? undefined,
|
|
55763
|
-
extraUsageEnabled: parsed.extra_usage?.is_enabled ?? undefined,
|
|
55764
|
-
extraUsageLimit: parsed.extra_usage?.monthly_limit ?? undefined,
|
|
55765
|
-
extraUsageUsed: parsed.extra_usage?.used_credits ?? undefined,
|
|
55766
|
-
extraUsageUtilization: parsed.extra_usage?.utilization ?? undefined
|
|
55767
|
-
};
|
|
55768
|
-
}
|
|
55769
|
-
var cachedUsageData = null;
|
|
55770
|
-
var usageCacheTime = 0;
|
|
55771
|
-
var cachedUsageToken = null;
|
|
55772
|
-
var usageTokenCacheTime = 0;
|
|
55773
|
-
function setCachedUsageError(error43, now) {
|
|
55774
|
-
const errorData = { error: error43 };
|
|
55775
|
-
cachedUsageData = errorData;
|
|
55776
|
-
usageCacheTime = now;
|
|
55777
|
-
return errorData;
|
|
55778
|
-
}
|
|
55779
|
-
function getStaleUsageOrError(error43, now) {
|
|
55780
|
-
const stale = readStaleUsageCache();
|
|
55781
|
-
if (stale && !stale.error) {
|
|
55782
|
-
cachedUsageData = stale;
|
|
55783
|
-
usageCacheTime = now;
|
|
55784
|
-
return stale;
|
|
55785
|
-
}
|
|
55786
|
-
return setCachedUsageError(error43, now);
|
|
55787
|
-
}
|
|
55788
|
-
function getUsageToken() {
|
|
55789
|
-
const now = Math.floor(Date.now() / 1000);
|
|
55790
|
-
if (cachedUsageToken && now - usageTokenCacheTime < TOKEN_CACHE_MAX_AGE) {
|
|
55791
|
-
return cachedUsageToken;
|
|
55849
|
+
}
|
|
55792
55850
|
}
|
|
55793
|
-
|
|
55794
|
-
|
|
55795
|
-
|
|
55796
|
-
|
|
55797
|
-
|
|
55798
|
-
|
|
55799
|
-
|
|
55800
|
-
|
|
55851
|
+
for (const block of blocks) {
|
|
55852
|
+
if (now.getTime() >= block.start.getTime() && now.getTime() <= block.end.getTime()) {
|
|
55853
|
+
const hasActivity = timestamps.some((t) => t.getTime() >= block.start.getTime() && t.getTime() <= block.end.getTime());
|
|
55854
|
+
if (hasActivity) {
|
|
55855
|
+
return {
|
|
55856
|
+
startTime: block.start,
|
|
55857
|
+
lastActivity: mostRecentTimestamp
|
|
55858
|
+
};
|
|
55801
55859
|
}
|
|
55802
|
-
return token2;
|
|
55803
|
-
}
|
|
55804
|
-
const credFile = path7.join(getClaudeConfigDir(), ".credentials.json");
|
|
55805
|
-
const token = parseUsageAccessToken(fs7.readFileSync(credFile, "utf8"));
|
|
55806
|
-
if (token) {
|
|
55807
|
-
cachedUsageToken = token;
|
|
55808
|
-
usageTokenCacheTime = now;
|
|
55809
55860
|
}
|
|
55810
|
-
return token;
|
|
55811
|
-
} catch {
|
|
55812
|
-
return null;
|
|
55813
55861
|
}
|
|
55862
|
+
return null;
|
|
55814
55863
|
}
|
|
55815
|
-
function
|
|
55864
|
+
function getAllTimestampsFromFile(filePath) {
|
|
55865
|
+
const timestamps = [];
|
|
55816
55866
|
try {
|
|
55817
|
-
|
|
55867
|
+
const lines = readJsonlLinesSync(filePath);
|
|
55868
|
+
for (const line of lines) {
|
|
55869
|
+
const json2 = parseJsonlLine(line);
|
|
55870
|
+
if (!json2) {
|
|
55871
|
+
continue;
|
|
55872
|
+
}
|
|
55873
|
+
const usage = json2.message?.usage;
|
|
55874
|
+
if (!usage)
|
|
55875
|
+
continue;
|
|
55876
|
+
const hasInputTokens = typeof usage.input_tokens === "number";
|
|
55877
|
+
const hasOutputTokens = typeof usage.output_tokens === "number";
|
|
55878
|
+
if (!hasInputTokens || !hasOutputTokens)
|
|
55879
|
+
continue;
|
|
55880
|
+
if (json2.isSidechain === true)
|
|
55881
|
+
continue;
|
|
55882
|
+
const timestamp = json2.timestamp;
|
|
55883
|
+
if (typeof timestamp !== "string")
|
|
55884
|
+
continue;
|
|
55885
|
+
const date5 = new Date(timestamp);
|
|
55886
|
+
if (!Number.isNaN(date5.getTime()))
|
|
55887
|
+
timestamps.push(date5);
|
|
55888
|
+
}
|
|
55889
|
+
return timestamps;
|
|
55818
55890
|
} catch {
|
|
55819
|
-
return
|
|
55891
|
+
return [];
|
|
55820
55892
|
}
|
|
55821
55893
|
}
|
|
55822
|
-
function
|
|
55823
|
-
const
|
|
55824
|
-
|
|
55825
|
-
|
|
55826
|
-
|
|
55827
|
-
}
|
|
55828
|
-
|
|
55829
|
-
const https = require('https');
|
|
55830
|
-
const options = {
|
|
55831
|
-
hostname: 'api.anthropic.com',
|
|
55832
|
-
path: '/api/oauth/usage',
|
|
55833
|
-
method: 'GET',
|
|
55834
|
-
headers: {
|
|
55835
|
-
'Authorization': 'Bearer ' + token,
|
|
55836
|
-
'anthropic-beta': 'oauth-2025-04-20'
|
|
55837
|
-
},
|
|
55838
|
-
timeout: 5000
|
|
55839
|
-
};
|
|
55840
|
-
|
|
55841
|
-
const req = https.request(options, (res) => {
|
|
55842
|
-
let data = '';
|
|
55843
|
-
res.on('data', chunk => data += chunk);
|
|
55844
|
-
res.on('end', () => {
|
|
55845
|
-
if (res.statusCode === 200 && data) {
|
|
55846
|
-
process.stdout.write(data);
|
|
55847
|
-
} else {
|
|
55848
|
-
process.exit(1);
|
|
55849
|
-
}
|
|
55850
|
-
});
|
|
55851
|
-
});
|
|
55894
|
+
function floorToHour(timestamp) {
|
|
55895
|
+
const floored = new Date(timestamp);
|
|
55896
|
+
floored.setUTCMinutes(0, 0, 0);
|
|
55897
|
+
return floored;
|
|
55898
|
+
}
|
|
55852
55899
|
|
|
55853
|
-
|
|
55854
|
-
|
|
55855
|
-
|
|
55856
|
-
|
|
55857
|
-
|
|
55858
|
-
|
|
55859
|
-
|
|
55860
|
-
const runtimePath = process.execPath || "node";
|
|
55861
|
-
const result = spawnSync2(runtimePath, ["-e", script], {
|
|
55862
|
-
encoding: "utf8",
|
|
55863
|
-
timeout: 6000,
|
|
55864
|
-
env: { ...process.env, TOKEN: token }
|
|
55865
|
-
});
|
|
55866
|
-
if (result.error || result.status !== 0 || !result.stdout) {
|
|
55867
|
-
return null;
|
|
55868
|
-
}
|
|
55869
|
-
return result.stdout;
|
|
55900
|
+
// src/utils/jsonl-cache.ts
|
|
55901
|
+
var readFileSync7 = fs9.readFileSync;
|
|
55902
|
+
var writeFileSync3 = fs9.writeFileSync;
|
|
55903
|
+
var mkdirSync4 = fs9.mkdirSync;
|
|
55904
|
+
var existsSync8 = fs9.existsSync;
|
|
55905
|
+
function normalizeConfigDir(configDir) {
|
|
55906
|
+
return path8.resolve(configDir);
|
|
55870
55907
|
}
|
|
55871
|
-
function
|
|
55872
|
-
const
|
|
55873
|
-
|
|
55874
|
-
|
|
55875
|
-
|
|
55876
|
-
|
|
55908
|
+
function getBlockCachePath(configDir = getClaudeConfigDir()) {
|
|
55909
|
+
const normalizedConfigDir = normalizeConfigDir(configDir);
|
|
55910
|
+
const configHash = createHash("sha256").update(normalizedConfigDir).digest("hex").slice(0, 16);
|
|
55911
|
+
return path8.join(os7.homedir(), ".cache", "ccstatusline", `block-cache-${configHash}.json`);
|
|
55912
|
+
}
|
|
55913
|
+
function readBlockCache(expectedConfigDir) {
|
|
55914
|
+
try {
|
|
55915
|
+
const normalizedExpectedConfigDir = expectedConfigDir !== undefined ? normalizeConfigDir(expectedConfigDir) : undefined;
|
|
55916
|
+
const cachePath = getBlockCachePath(normalizedExpectedConfigDir);
|
|
55917
|
+
if (!existsSync8(cachePath)) {
|
|
55918
|
+
return null;
|
|
55877
55919
|
}
|
|
55878
|
-
|
|
55879
|
-
|
|
55920
|
+
const content = readFileSync7(cachePath, "utf-8");
|
|
55921
|
+
const cache3 = JSON.parse(content);
|
|
55922
|
+
if (typeof cache3.startTime !== "string") {
|
|
55923
|
+
return null;
|
|
55880
55924
|
}
|
|
55881
|
-
|
|
55882
|
-
|
|
55883
|
-
|
|
55884
|
-
|
|
55885
|
-
|
|
55886
|
-
|
|
55887
|
-
if (fileData && !fileData.error) {
|
|
55888
|
-
cachedUsageData = fileData;
|
|
55889
|
-
usageCacheTime = now;
|
|
55890
|
-
return fileData;
|
|
55925
|
+
if (normalizedExpectedConfigDir !== undefined) {
|
|
55926
|
+
if (typeof cache3.configDir !== "string") {
|
|
55927
|
+
return null;
|
|
55928
|
+
}
|
|
55929
|
+
if (cache3.configDir !== normalizedExpectedConfigDir) {
|
|
55930
|
+
return null;
|
|
55891
55931
|
}
|
|
55892
55932
|
}
|
|
55893
|
-
|
|
55894
|
-
|
|
55895
|
-
|
|
55896
|
-
|
|
55933
|
+
const date5 = new Date(cache3.startTime);
|
|
55934
|
+
if (Number.isNaN(date5.getTime())) {
|
|
55935
|
+
return null;
|
|
55936
|
+
}
|
|
55937
|
+
return date5;
|
|
55938
|
+
} catch {
|
|
55939
|
+
return null;
|
|
55897
55940
|
}
|
|
55941
|
+
}
|
|
55942
|
+
function writeBlockCache(startTime, configDir = getClaudeConfigDir()) {
|
|
55898
55943
|
try {
|
|
55899
|
-
const
|
|
55900
|
-
const
|
|
55901
|
-
|
|
55902
|
-
|
|
55903
|
-
|
|
55904
|
-
return stale;
|
|
55905
|
-
return { error: "timeout" };
|
|
55944
|
+
const normalizedConfigDir = normalizeConfigDir(configDir);
|
|
55945
|
+
const cachePath = getBlockCachePath(normalizedConfigDir);
|
|
55946
|
+
const cacheDir = path8.dirname(cachePath);
|
|
55947
|
+
if (!existsSync8(cacheDir)) {
|
|
55948
|
+
mkdirSync4(cacheDir, { recursive: true });
|
|
55906
55949
|
}
|
|
55950
|
+
const cache3 = {
|
|
55951
|
+
startTime: startTime.toISOString(),
|
|
55952
|
+
configDir: normalizedConfigDir
|
|
55953
|
+
};
|
|
55954
|
+
writeFileSync3(cachePath, JSON.stringify(cache3), "utf-8");
|
|
55907
55955
|
} catch {}
|
|
55908
|
-
|
|
55909
|
-
|
|
55910
|
-
|
|
55911
|
-
|
|
55956
|
+
}
|
|
55957
|
+
function getCachedBlockMetrics(sessionDurationHours = 5) {
|
|
55958
|
+
const sessionDurationMs = sessionDurationHours * 60 * 60 * 1000;
|
|
55959
|
+
const now = new Date;
|
|
55960
|
+
const activeConfigDir = getClaudeConfigDir();
|
|
55961
|
+
const cachedStartTime = readBlockCache(activeConfigDir);
|
|
55962
|
+
if (cachedStartTime) {
|
|
55963
|
+
const blockEndTime = new Date(cachedStartTime.getTime() + sessionDurationMs);
|
|
55964
|
+
if (now.getTime() <= blockEndTime.getTime()) {
|
|
55965
|
+
return {
|
|
55966
|
+
startTime: cachedStartTime,
|
|
55967
|
+
lastActivity: now
|
|
55968
|
+
};
|
|
55912
55969
|
}
|
|
55913
|
-
|
|
55914
|
-
|
|
55970
|
+
}
|
|
55971
|
+
const metrics = getBlockMetrics();
|
|
55972
|
+
if (metrics) {
|
|
55973
|
+
writeBlockCache(metrics.startTime, activeConfigDir);
|
|
55974
|
+
}
|
|
55975
|
+
return metrics;
|
|
55976
|
+
}
|
|
55977
|
+
// src/utils/jsonl-metrics.ts
|
|
55978
|
+
import * as fs10 from "fs";
|
|
55979
|
+
async function getSessionDuration(transcriptPath) {
|
|
55915
55980
|
try {
|
|
55916
|
-
|
|
55917
|
-
|
|
55918
|
-
return getStaleUsageOrError("api-error", now);
|
|
55981
|
+
if (!fs10.existsSync(transcriptPath)) {
|
|
55982
|
+
return null;
|
|
55919
55983
|
}
|
|
55920
|
-
const
|
|
55921
|
-
if (
|
|
55922
|
-
return
|
|
55984
|
+
const lines = await readJsonlLines(transcriptPath);
|
|
55985
|
+
if (lines.length === 0) {
|
|
55986
|
+
return null;
|
|
55923
55987
|
}
|
|
55924
|
-
|
|
55925
|
-
|
|
55988
|
+
let firstTimestamp = null;
|
|
55989
|
+
let lastTimestamp = null;
|
|
55990
|
+
for (const line of lines) {
|
|
55991
|
+
const data = parseJsonlLine(line);
|
|
55992
|
+
if (data?.timestamp) {
|
|
55993
|
+
firstTimestamp = new Date(data.timestamp);
|
|
55994
|
+
break;
|
|
55995
|
+
}
|
|
55926
55996
|
}
|
|
55927
|
-
|
|
55928
|
-
|
|
55929
|
-
|
|
55997
|
+
for (let i = lines.length - 1;i >= 0; i--) {
|
|
55998
|
+
const line = lines[i];
|
|
55999
|
+
if (!line) {
|
|
56000
|
+
continue;
|
|
55930
56001
|
}
|
|
55931
|
-
|
|
55932
|
-
|
|
55933
|
-
|
|
55934
|
-
|
|
55935
|
-
|
|
56002
|
+
const data = parseJsonlLine(line);
|
|
56003
|
+
if (data?.timestamp) {
|
|
56004
|
+
lastTimestamp = new Date(data.timestamp);
|
|
56005
|
+
break;
|
|
56006
|
+
}
|
|
56007
|
+
}
|
|
56008
|
+
if (!firstTimestamp || !lastTimestamp) {
|
|
56009
|
+
return null;
|
|
56010
|
+
}
|
|
56011
|
+
const durationMs = lastTimestamp.getTime() - firstTimestamp.getTime();
|
|
56012
|
+
const totalMinutes = Math.floor(durationMs / (1000 * 60));
|
|
56013
|
+
if (totalMinutes < 1) {
|
|
56014
|
+
return "<1m";
|
|
56015
|
+
}
|
|
56016
|
+
const hours = Math.floor(totalMinutes / 60);
|
|
56017
|
+
const minutes = totalMinutes % 60;
|
|
56018
|
+
if (hours === 0) {
|
|
56019
|
+
return `${minutes}m`;
|
|
56020
|
+
} else if (minutes === 0) {
|
|
56021
|
+
return `${hours}hr`;
|
|
56022
|
+
} else {
|
|
56023
|
+
return `${hours}hr ${minutes}m`;
|
|
56024
|
+
}
|
|
55936
56025
|
} catch {
|
|
55937
|
-
return
|
|
56026
|
+
return null;
|
|
56027
|
+
}
|
|
56028
|
+
}
|
|
56029
|
+
async function getTokenMetrics(transcriptPath) {
|
|
56030
|
+
try {
|
|
56031
|
+
if (!fs10.existsSync(transcriptPath)) {
|
|
56032
|
+
return { inputTokens: 0, outputTokens: 0, cachedTokens: 0, totalTokens: 0, contextLength: 0 };
|
|
56033
|
+
}
|
|
56034
|
+
const lines = await readJsonlLines(transcriptPath);
|
|
56035
|
+
let inputTokens = 0;
|
|
56036
|
+
let outputTokens = 0;
|
|
56037
|
+
let cachedTokens = 0;
|
|
56038
|
+
let contextLength = 0;
|
|
56039
|
+
let mostRecentMainChainEntry = null;
|
|
56040
|
+
let mostRecentTimestamp = null;
|
|
56041
|
+
for (const line of lines) {
|
|
56042
|
+
const data = parseJsonlLine(line);
|
|
56043
|
+
if (data?.message?.usage) {
|
|
56044
|
+
inputTokens += data.message.usage.input_tokens || 0;
|
|
56045
|
+
outputTokens += data.message.usage.output_tokens || 0;
|
|
56046
|
+
cachedTokens += data.message.usage.cache_read_input_tokens ?? 0;
|
|
56047
|
+
cachedTokens += data.message.usage.cache_creation_input_tokens ?? 0;
|
|
56048
|
+
if (data.isSidechain !== true && data.timestamp && !data.isApiErrorMessage) {
|
|
56049
|
+
const entryTime = new Date(data.timestamp);
|
|
56050
|
+
if (!mostRecentTimestamp || entryTime > mostRecentTimestamp) {
|
|
56051
|
+
mostRecentTimestamp = entryTime;
|
|
56052
|
+
mostRecentMainChainEntry = data;
|
|
56053
|
+
}
|
|
56054
|
+
}
|
|
56055
|
+
}
|
|
56056
|
+
}
|
|
56057
|
+
if (mostRecentMainChainEntry?.message?.usage) {
|
|
56058
|
+
const usage = mostRecentMainChainEntry.message.usage;
|
|
56059
|
+
contextLength = (usage.input_tokens || 0) + (usage.cache_read_input_tokens ?? 0) + (usage.cache_creation_input_tokens ?? 0);
|
|
56060
|
+
}
|
|
56061
|
+
const totalTokens = inputTokens + outputTokens + cachedTokens;
|
|
56062
|
+
return { inputTokens, outputTokens, cachedTokens, totalTokens, contextLength };
|
|
56063
|
+
} catch {
|
|
56064
|
+
return { inputTokens: 0, outputTokens: 0, cachedTokens: 0, totalTokens: 0, contextLength: 0 };
|
|
55938
56065
|
}
|
|
55939
56066
|
}
|
|
56067
|
+
// src/utils/usage-windows.ts
|
|
55940
56068
|
function clamp(value, min, max) {
|
|
55941
56069
|
return Math.max(min, Math.min(max, value));
|
|
55942
56070
|
}
|
|
@@ -56023,7 +56151,6 @@ function makeUsageProgressBar(percent, width = 15) {
|
|
|
56023
56151
|
const empty2 = width - filled;
|
|
56024
56152
|
return "[" + "█".repeat(filled) + "░".repeat(empty2) + "]";
|
|
56025
56153
|
}
|
|
56026
|
-
|
|
56027
56154
|
// src/widgets/shared/usage-display.ts
|
|
56028
56155
|
function getUsageDisplayMode(item) {
|
|
56029
56156
|
const mode = item.metadata?.display;
|
|
@@ -56121,7 +56248,7 @@ class BlockTimerWidget {
|
|
|
56121
56248
|
}
|
|
56122
56249
|
return formatRawOrLabeledValue(item, "Block: ", "3hr 45m");
|
|
56123
56250
|
}
|
|
56124
|
-
const usageData =
|
|
56251
|
+
const usageData = context.usageData ?? {};
|
|
56125
56252
|
const window2 = resolveUsageWindowWithFallback(usageData, context.blockMetrics);
|
|
56126
56253
|
if (!window2) {
|
|
56127
56254
|
if (isUsageProgressMode(displayMode)) {
|
|
@@ -56302,27 +56429,27 @@ class CurrentWorkingDirWidget {
|
|
|
56302
56429
|
supportsColors(item) {
|
|
56303
56430
|
return true;
|
|
56304
56431
|
}
|
|
56305
|
-
abbreviateHomeDir(
|
|
56432
|
+
abbreviateHomeDir(path9) {
|
|
56306
56433
|
const homeDir = os8.homedir();
|
|
56307
|
-
if (
|
|
56434
|
+
if (path9 === homeDir) {
|
|
56308
56435
|
return "~";
|
|
56309
56436
|
}
|
|
56310
|
-
if (
|
|
56311
|
-
const boundaryChar =
|
|
56437
|
+
if (path9.startsWith(homeDir)) {
|
|
56438
|
+
const boundaryChar = path9[homeDir.length];
|
|
56312
56439
|
if (boundaryChar !== "/" && boundaryChar !== "\\") {
|
|
56313
|
-
return
|
|
56440
|
+
return path9;
|
|
56314
56441
|
}
|
|
56315
|
-
return "~" +
|
|
56442
|
+
return "~" + path9.slice(homeDir.length);
|
|
56316
56443
|
}
|
|
56317
|
-
return
|
|
56444
|
+
return path9;
|
|
56318
56445
|
}
|
|
56319
|
-
abbreviatePath(
|
|
56446
|
+
abbreviatePath(path9) {
|
|
56320
56447
|
const homeDir = os8.homedir();
|
|
56321
|
-
const useBackslash =
|
|
56448
|
+
const useBackslash = path9.includes("\\") && !path9.includes("/");
|
|
56322
56449
|
const sep2 = useBackslash ? "\\" : "/";
|
|
56323
|
-
let normalizedPath =
|
|
56324
|
-
if (
|
|
56325
|
-
normalizedPath = "~" +
|
|
56450
|
+
let normalizedPath = path9;
|
|
56451
|
+
if (path9.startsWith(homeDir)) {
|
|
56452
|
+
normalizedPath = "~" + path9.slice(homeDir.length);
|
|
56326
56453
|
}
|
|
56327
56454
|
const parts = normalizedPath.split(/[\\/]+/).filter((part) => part !== "");
|
|
56328
56455
|
const abbreviated = parts.map((part, index) => {
|
|
@@ -56522,7 +56649,7 @@ class FreeMemoryWidget {
|
|
|
56522
56649
|
}
|
|
56523
56650
|
}
|
|
56524
56651
|
// src/widgets/SessionName.ts
|
|
56525
|
-
import * as
|
|
56652
|
+
import * as fs11 from "fs";
|
|
56526
56653
|
|
|
56527
56654
|
class SessionNameWidget {
|
|
56528
56655
|
getDefaultColor() {
|
|
@@ -56549,7 +56676,7 @@ class SessionNameWidget {
|
|
|
56549
56676
|
return null;
|
|
56550
56677
|
}
|
|
56551
56678
|
try {
|
|
56552
|
-
const content =
|
|
56679
|
+
const content = fs11.readFileSync(transcriptPath, "utf-8");
|
|
56553
56680
|
const lines = content.split(`
|
|
56554
56681
|
`);
|
|
56555
56682
|
for (let i = lines.length - 1;i >= 0; i--) {
|
|
@@ -56615,7 +56742,7 @@ class SessionUsageWidget {
|
|
|
56615
56742
|
}
|
|
56616
56743
|
return formatRawOrLabeledValue(item, "Session: ", `${previewPercent.toFixed(1)}%`);
|
|
56617
56744
|
}
|
|
56618
|
-
const data =
|
|
56745
|
+
const data = context.usageData ?? {};
|
|
56619
56746
|
if (data.error)
|
|
56620
56747
|
return getUsageErrorMessage(data.error);
|
|
56621
56748
|
if (data.sessionUsage === undefined)
|
|
@@ -56684,7 +56811,7 @@ class WeeklyUsageWidget {
|
|
|
56684
56811
|
}
|
|
56685
56812
|
return formatRawOrLabeledValue(item, "Weekly: ", `${previewPercent.toFixed(1)}%`);
|
|
56686
56813
|
}
|
|
56687
|
-
const data =
|
|
56814
|
+
const data = context.usageData ?? {};
|
|
56688
56815
|
if (data.error)
|
|
56689
56816
|
return getUsageErrorMessage(data.error);
|
|
56690
56817
|
if (data.weeklyUsage === undefined)
|
|
@@ -56759,7 +56886,7 @@ class BlockResetTimerWidget {
|
|
|
56759
56886
|
}
|
|
56760
56887
|
return formatRawOrLabeledValue(item, "Reset: ", "4hr 30m");
|
|
56761
56888
|
}
|
|
56762
|
-
const usageData =
|
|
56889
|
+
const usageData = context.usageData ?? {};
|
|
56763
56890
|
const window2 = resolveUsageWindowWithFallback(usageData, context.blockMetrics);
|
|
56764
56891
|
if (!window2) {
|
|
56765
56892
|
if (usageData.error) {
|
|
@@ -56838,7 +56965,7 @@ class WeeklyResetTimerWidget {
|
|
|
56838
56965
|
}
|
|
56839
56966
|
return formatRawOrLabeledValue(item, "Weekly Reset: ", "36hr 30m");
|
|
56840
56967
|
}
|
|
56841
|
-
const usageData =
|
|
56968
|
+
const usageData = context.usageData ?? {};
|
|
56842
56969
|
const window2 = resolveWeeklyUsageWindow(usageData);
|
|
56843
56970
|
if (!window2) {
|
|
56844
56971
|
if (usageData.error) {
|
|
@@ -57145,46 +57272,64 @@ var LinkEditor = ({ widget, onComplete, onCancel, action }) => {
|
|
|
57145
57272
|
]
|
|
57146
57273
|
}, undefined, true, undefined, this);
|
|
57147
57274
|
};
|
|
57275
|
+
// src/utils/widget-manifest.ts
|
|
57276
|
+
var WIDGET_MANIFEST = [
|
|
57277
|
+
{ type: "model", create: () => new ModelWidget },
|
|
57278
|
+
{ type: "output-style", create: () => new OutputStyleWidget },
|
|
57279
|
+
{ type: "git-branch", create: () => new GitBranchWidget },
|
|
57280
|
+
{ type: "git-changes", create: () => new GitChangesWidget },
|
|
57281
|
+
{ type: "git-insertions", create: () => new GitInsertionsWidget },
|
|
57282
|
+
{ type: "git-deletions", create: () => new GitDeletionsWidget },
|
|
57283
|
+
{ type: "git-root-dir", create: () => new GitRootDirWidget },
|
|
57284
|
+
{ type: "git-worktree", create: () => new GitWorktreeWidget },
|
|
57285
|
+
{ type: "current-working-dir", create: () => new CurrentWorkingDirWidget },
|
|
57286
|
+
{ type: "tokens-input", create: () => new TokensInputWidget },
|
|
57287
|
+
{ type: "tokens-output", create: () => new TokensOutputWidget },
|
|
57288
|
+
{ type: "tokens-cached", create: () => new TokensCachedWidget },
|
|
57289
|
+
{ type: "tokens-total", create: () => new TokensTotalWidget },
|
|
57290
|
+
{ type: "context-length", create: () => new ContextLengthWidget },
|
|
57291
|
+
{ type: "context-percentage", create: () => new ContextPercentageWidget },
|
|
57292
|
+
{ type: "context-percentage-usable", create: () => new ContextPercentageUsableWidget },
|
|
57293
|
+
{ type: "session-clock", create: () => new SessionClockWidget },
|
|
57294
|
+
{ type: "session-cost", create: () => new SessionCostWidget },
|
|
57295
|
+
{ type: "block-timer", create: () => new BlockTimerWidget },
|
|
57296
|
+
{ type: "terminal-width", create: () => new TerminalWidthWidget },
|
|
57297
|
+
{ type: "version", create: () => new VersionWidget },
|
|
57298
|
+
{ type: "custom-text", create: () => new CustomTextWidget },
|
|
57299
|
+
{ type: "custom-command", create: () => new CustomCommandWidget },
|
|
57300
|
+
{ type: "link", create: () => new LinkWidget },
|
|
57301
|
+
{ type: "claude-session-id", create: () => new ClaudeSessionIdWidget },
|
|
57302
|
+
{ type: "session-name", create: () => new SessionNameWidget },
|
|
57303
|
+
{ type: "free-memory", create: () => new FreeMemoryWidget },
|
|
57304
|
+
{ type: "session-usage", create: () => new SessionUsageWidget },
|
|
57305
|
+
{ type: "weekly-usage", create: () => new WeeklyUsageWidget },
|
|
57306
|
+
{ type: "reset-timer", create: () => new BlockResetTimerWidget },
|
|
57307
|
+
{ type: "weekly-reset-timer", create: () => new WeeklyResetTimerWidget },
|
|
57308
|
+
{ type: "context-bar", create: () => new ContextBarWidget }
|
|
57309
|
+
];
|
|
57310
|
+
var LAYOUT_WIDGET_MANIFEST = [
|
|
57311
|
+
{
|
|
57312
|
+
type: "separator",
|
|
57313
|
+
displayName: "Separator",
|
|
57314
|
+
description: "A separator character between status line widgets",
|
|
57315
|
+
category: "Layout"
|
|
57316
|
+
},
|
|
57317
|
+
{
|
|
57318
|
+
type: "flex-separator",
|
|
57319
|
+
displayName: "Flex Separator",
|
|
57320
|
+
description: "Expands to fill available terminal width",
|
|
57321
|
+
category: "Layout"
|
|
57322
|
+
}
|
|
57323
|
+
];
|
|
57324
|
+
|
|
57148
57325
|
// src/utils/widgets.ts
|
|
57149
|
-
var widgetRegistry = new Map([
|
|
57150
|
-
|
|
57151
|
-
["output-style", new OutputStyleWidget],
|
|
57152
|
-
["git-branch", new GitBranchWidget],
|
|
57153
|
-
["git-changes", new GitChangesWidget],
|
|
57154
|
-
["git-insertions", new GitInsertionsWidget],
|
|
57155
|
-
["git-deletions", new GitDeletionsWidget],
|
|
57156
|
-
["git-root-dir", new GitRootDirWidget],
|
|
57157
|
-
["git-worktree", new GitWorktreeWidget],
|
|
57158
|
-
["current-working-dir", new CurrentWorkingDirWidget],
|
|
57159
|
-
["tokens-input", new TokensInputWidget],
|
|
57160
|
-
["tokens-output", new TokensOutputWidget],
|
|
57161
|
-
["tokens-cached", new TokensCachedWidget],
|
|
57162
|
-
["tokens-total", new TokensTotalWidget],
|
|
57163
|
-
["context-length", new ContextLengthWidget],
|
|
57164
|
-
["context-percentage", new ContextPercentageWidget],
|
|
57165
|
-
["context-percentage-usable", new ContextPercentageUsableWidget],
|
|
57166
|
-
["session-clock", new SessionClockWidget],
|
|
57167
|
-
["session-cost", new SessionCostWidget],
|
|
57168
|
-
["block-timer", new BlockTimerWidget],
|
|
57169
|
-
["terminal-width", new TerminalWidthWidget],
|
|
57170
|
-
["version", new VersionWidget],
|
|
57171
|
-
["custom-text", new CustomTextWidget],
|
|
57172
|
-
["custom-command", new CustomCommandWidget],
|
|
57173
|
-
["link", new LinkWidget],
|
|
57174
|
-
["claude-session-id", new ClaudeSessionIdWidget],
|
|
57175
|
-
["session-name", new SessionNameWidget],
|
|
57176
|
-
["free-memory", new FreeMemoryWidget],
|
|
57177
|
-
["session-usage", new SessionUsageWidget],
|
|
57178
|
-
["weekly-usage", new WeeklyUsageWidget],
|
|
57179
|
-
["reset-timer", new BlockResetTimerWidget],
|
|
57180
|
-
["weekly-reset-timer", new WeeklyResetTimerWidget],
|
|
57181
|
-
["context-bar", new ContextBarWidget]
|
|
57182
|
-
]);
|
|
57326
|
+
var widgetRegistry = new Map(WIDGET_MANIFEST.map((entry) => [entry.type, entry.create()]));
|
|
57327
|
+
var layoutWidgetTypes = new Set(LAYOUT_WIDGET_MANIFEST.map((entry) => entry.type));
|
|
57183
57328
|
function getWidget(type) {
|
|
57184
57329
|
return widgetRegistry.get(type) ?? null;
|
|
57185
57330
|
}
|
|
57186
57331
|
function getAllWidgetTypes(settings) {
|
|
57187
|
-
const allTypes =
|
|
57332
|
+
const allTypes = WIDGET_MANIFEST.map((entry) => entry.type);
|
|
57188
57333
|
if (!settings.powerline.enabled) {
|
|
57189
57334
|
if (!settings.defaultSeparator) {
|
|
57190
57335
|
allTypes.push("separator");
|
|
@@ -57193,30 +57338,18 @@ function getAllWidgetTypes(settings) {
|
|
|
57193
57338
|
}
|
|
57194
57339
|
return allTypes;
|
|
57195
57340
|
}
|
|
57196
|
-
var
|
|
57197
|
-
|
|
57198
|
-
|
|
57199
|
-
|
|
57200
|
-
|
|
57201
|
-
|
|
57202
|
-
|
|
57203
|
-
|
|
57204
|
-
description: "Expands to fill available terminal width",
|
|
57205
|
-
category: "Layout"
|
|
57341
|
+
var layoutCatalogEntries = new Map(LAYOUT_WIDGET_MANIFEST.map((entry) => [
|
|
57342
|
+
entry.type,
|
|
57343
|
+
{
|
|
57344
|
+
type: entry.type,
|
|
57345
|
+
displayName: entry.displayName,
|
|
57346
|
+
description: entry.description,
|
|
57347
|
+
category: entry.category,
|
|
57348
|
+
searchText: `${entry.displayName} ${entry.description} ${entry.type}`.toLowerCase()
|
|
57206
57349
|
}
|
|
57207
|
-
|
|
57350
|
+
]));
|
|
57208
57351
|
function getLayoutCatalogEntry(type) {
|
|
57209
|
-
|
|
57210
|
-
if (!layout) {
|
|
57211
|
-
return null;
|
|
57212
|
-
}
|
|
57213
|
-
return {
|
|
57214
|
-
type,
|
|
57215
|
-
displayName: layout.displayName,
|
|
57216
|
-
description: layout.description,
|
|
57217
|
-
category: layout.category,
|
|
57218
|
-
searchText: `${layout.displayName} ${layout.description} ${type}`.toLowerCase()
|
|
57219
|
-
};
|
|
57352
|
+
return layoutCatalogEntries.get(type) ?? null;
|
|
57220
57353
|
}
|
|
57221
57354
|
function getWidgetCatalog(settings) {
|
|
57222
57355
|
return getAllWidgetTypes(settings).map((type) => {
|
|
@@ -59772,8 +59905,9 @@ var PowerlineSeparatorEditor = ({
|
|
|
59772
59905
|
const inversionText = mode === "separator" && invertBg ? " [Inverted]" : "";
|
|
59773
59906
|
return `${preset.char} - ${preset.name}${inversionText}`;
|
|
59774
59907
|
}
|
|
59775
|
-
const
|
|
59776
|
-
|
|
59908
|
+
const codePoint = char.codePointAt(0) ?? 0;
|
|
59909
|
+
const hexCode = codePoint.toString(16).toUpperCase().padStart(4, "0");
|
|
59910
|
+
return `${char} - Custom (U+${hexCode})${invertBg ? " [Inverted]" : ""}`;
|
|
59777
59911
|
};
|
|
59778
59912
|
const updateSeparators = (newSeparators, newInvertBgs) => {
|
|
59779
59913
|
const updatedPowerline = { ...powerlineConfig };
|
|
@@ -59801,23 +59935,26 @@ var PowerlineSeparatorEditor = ({
|
|
|
59801
59935
|
setHexInput("");
|
|
59802
59936
|
setCursorPos(0);
|
|
59803
59937
|
} else if (key.return) {
|
|
59804
|
-
if (hexInput.length
|
|
59805
|
-
const
|
|
59806
|
-
|
|
59807
|
-
|
|
59808
|
-
newSeparators
|
|
59809
|
-
|
|
59810
|
-
|
|
59938
|
+
if (hexInput.length >= 4 && hexInput.length <= 6) {
|
|
59939
|
+
const codePoint = parseInt(hexInput, 16);
|
|
59940
|
+
if (codePoint >= 0 && codePoint <= 1114111) {
|
|
59941
|
+
const char = String.fromCodePoint(codePoint);
|
|
59942
|
+
const newSeparators = [...separators];
|
|
59943
|
+
if (separators.length === 0) {
|
|
59944
|
+
newSeparators.push(char);
|
|
59945
|
+
} else {
|
|
59946
|
+
newSeparators[selectedIndex] = char;
|
|
59947
|
+
}
|
|
59948
|
+
updateSeparators(newSeparators);
|
|
59949
|
+
setHexInputMode(false);
|
|
59950
|
+
setHexInput("");
|
|
59951
|
+
setCursorPos(0);
|
|
59811
59952
|
}
|
|
59812
|
-
updateSeparators(newSeparators);
|
|
59813
|
-
setHexInputMode(false);
|
|
59814
|
-
setHexInput("");
|
|
59815
|
-
setCursorPos(0);
|
|
59816
59953
|
}
|
|
59817
59954
|
} else if (key.backspace && cursorPos > 0) {
|
|
59818
59955
|
setHexInput(hexInput.slice(0, cursorPos - 1) + hexInput.slice(cursorPos));
|
|
59819
59956
|
setCursorPos(cursorPos - 1);
|
|
59820
|
-
} else if (shouldInsertInput(input, key) && /[0-9a-fA-F]/.test(input) && hexInput.length <
|
|
59957
|
+
} else if (shouldInsertInput(input, key) && /[0-9a-fA-F]/.test(input) && hexInput.length < 6) {
|
|
59821
59958
|
setHexInput(hexInput.slice(0, cursorPos) + input.toUpperCase() + hexInput.slice(cursorPos));
|
|
59822
59959
|
setCursorPos(cursorPos + 1);
|
|
59823
59960
|
}
|
|
@@ -59941,7 +60078,7 @@ var PowerlineSeparatorEditor = ({
|
|
|
59941
60078
|
children: [
|
|
59942
60079
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
59943
60080
|
children: [
|
|
59944
|
-
"Enter 4-
|
|
60081
|
+
"Enter hex code (4-6 digits) for",
|
|
59945
60082
|
" ",
|
|
59946
60083
|
mode === "separator" ? "separator" : "cap",
|
|
59947
60084
|
separators.length > 0 ? ` ${selectedIndex + 1}` : "",
|
|
@@ -59950,7 +60087,7 @@ var PowerlineSeparatorEditor = ({
|
|
|
59950
60087
|
}, undefined, true, undefined, this),
|
|
59951
60088
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
59952
60089
|
children: [
|
|
59953
|
-
"
|
|
60090
|
+
"U+",
|
|
59954
60091
|
hexInput.slice(0, cursorPos),
|
|
59955
60092
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
59956
60093
|
backgroundColor: "gray",
|
|
@@ -59958,15 +60095,19 @@ var PowerlineSeparatorEditor = ({
|
|
|
59958
60095
|
children: hexInput[cursorPos] ?? "_"
|
|
59959
60096
|
}, undefined, false, undefined, this),
|
|
59960
60097
|
hexInput.slice(cursorPos + 1),
|
|
59961
|
-
hexInput.length <
|
|
60098
|
+
hexInput.length < 6 && hexInput.length === cursorPos && /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
59962
60099
|
dimColor: true,
|
|
59963
|
-
children: "_".repeat(
|
|
60100
|
+
children: "_".repeat(6 - hexInput.length - 1)
|
|
59964
60101
|
}, undefined, false, undefined, this)
|
|
59965
60102
|
]
|
|
59966
60103
|
}, undefined, true, undefined, this),
|
|
59967
60104
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
59968
60105
|
dimColor: true,
|
|
59969
|
-
children: "Enter 4 hex digits (0-9, A-F), then press Enter. ESC to cancel."
|
|
60106
|
+
children: "Enter 4-6 hex digits (0-9, A-F) for a Unicode code point, then press Enter. ESC to cancel."
|
|
60107
|
+
}, undefined, false, undefined, this),
|
|
60108
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
60109
|
+
dimColor: true,
|
|
60110
|
+
children: "Examples: E0B0 (powerline), 1F984 (\uD83E\uDD84), 2764 (❤)"
|
|
59970
60111
|
}, undefined, false, undefined, this)
|
|
59971
60112
|
]
|
|
59972
60113
|
}, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(jsx_dev_runtime12.Fragment, {
|
|
@@ -61299,7 +61440,7 @@ var App2 = () => {
|
|
|
61299
61440
|
});
|
|
61300
61441
|
const handleInstallSelection = import_react46.useCallback((command, displayName, useBunx) => {
|
|
61301
61442
|
getExistingStatusLine().then((existing) => {
|
|
61302
|
-
const isAlreadyInstalled =
|
|
61443
|
+
const isAlreadyInstalled = isKnownCommand(existing ?? "");
|
|
61303
61444
|
let message;
|
|
61304
61445
|
if (existing && !isAlreadyInstalled) {
|
|
61305
61446
|
message = `This will modify ${getClaudeSettingsPath()}
|
|
@@ -61446,6 +61587,10 @@ ${GITHUB_REPO_URL}`,
|
|
|
61446
61587
|
}, undefined, false, undefined, this)
|
|
61447
61588
|
]
|
|
61448
61589
|
}, undefined, true, undefined, this),
|
|
61590
|
+
isCustomConfigPath() && /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
|
|
61591
|
+
dimColor: true,
|
|
61592
|
+
children: `Config: ${getConfigPath()}`
|
|
61593
|
+
}, undefined, false, undefined, this),
|
|
61449
61594
|
/* @__PURE__ */ jsx_dev_runtime18.jsxDEV(StatusLinePreview, {
|
|
61450
61595
|
lines: settings.lines,
|
|
61451
61596
|
terminalWidth,
|
|
@@ -61677,6 +61822,24 @@ var StatusJSONSchema = exports_external.looseObject({
|
|
|
61677
61822
|
}).nullable().optional()
|
|
61678
61823
|
});
|
|
61679
61824
|
|
|
61825
|
+
// src/utils/usage-prefetch.ts
|
|
61826
|
+
var USAGE_WIDGET_TYPES = new Set([
|
|
61827
|
+
"session-usage",
|
|
61828
|
+
"weekly-usage",
|
|
61829
|
+
"block-timer",
|
|
61830
|
+
"reset-timer",
|
|
61831
|
+
"weekly-reset-timer"
|
|
61832
|
+
]);
|
|
61833
|
+
function hasUsageDependentWidgets(lines) {
|
|
61834
|
+
return lines.some((line) => line.some((item) => USAGE_WIDGET_TYPES.has(item.type)));
|
|
61835
|
+
}
|
|
61836
|
+
async function prefetchUsageDataIfNeeded(lines) {
|
|
61837
|
+
if (!hasUsageDependentWidgets(lines)) {
|
|
61838
|
+
return null;
|
|
61839
|
+
}
|
|
61840
|
+
return await fetchUsageData();
|
|
61841
|
+
}
|
|
61842
|
+
|
|
61680
61843
|
// src/ccstatusline.ts
|
|
61681
61844
|
function hasSessionDurationInStatusJson(data) {
|
|
61682
61845
|
const durationMs = data.cost?.total_duration_ms;
|
|
@@ -61727,9 +61890,11 @@ async function renderMultipleLines(data) {
|
|
|
61727
61890
|
if (hasSessionClock && !hasSessionDurationInStatusJson(data) && data.transcript_path) {
|
|
61728
61891
|
sessionDuration = await getSessionDuration(data.transcript_path);
|
|
61729
61892
|
}
|
|
61893
|
+
const usageData = await prefetchUsageDataIfNeeded(lines);
|
|
61730
61894
|
const context = {
|
|
61731
61895
|
data,
|
|
61732
61896
|
tokenMetrics,
|
|
61897
|
+
usageData,
|
|
61733
61898
|
sessionDuration,
|
|
61734
61899
|
isPreview: false
|
|
61735
61900
|
};
|
|
@@ -61768,7 +61933,20 @@ async function renderMultipleLines(data) {
|
|
|
61768
61933
|
}
|
|
61769
61934
|
}
|
|
61770
61935
|
}
|
|
61936
|
+
function parseConfigArg() {
|
|
61937
|
+
const idx = process.argv.indexOf("--config");
|
|
61938
|
+
if (idx === -1)
|
|
61939
|
+
return;
|
|
61940
|
+
const configPath = process.argv[idx + 1];
|
|
61941
|
+
if (!configPath || configPath.startsWith("--")) {
|
|
61942
|
+
console.error("--config requires a file path argument");
|
|
61943
|
+
process.exit(1);
|
|
61944
|
+
}
|
|
61945
|
+
process.argv.splice(idx, 2);
|
|
61946
|
+
return configPath;
|
|
61947
|
+
}
|
|
61771
61948
|
async function main() {
|
|
61949
|
+
initConfigPath(parseConfigArg());
|
|
61772
61950
|
if (!process.stdin.isTTY) {
|
|
61773
61951
|
await ensureWindowsUtf8CodePage();
|
|
61774
61952
|
const input = await readStdin();
|