nairon-bench 0.3.13 → 0.3.15
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/dist/index.js +2169 -1632
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4447,8 +4447,8 @@ function defineCommand2(def) {
|
|
|
4447
4447
|
|
|
4448
4448
|
// src/commands/scan.ts
|
|
4449
4449
|
init_dist();
|
|
4450
|
-
import { existsSync as
|
|
4451
|
-
import { join as
|
|
4450
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4, readFileSync as readFileSync9 } from "node:fs";
|
|
4451
|
+
import { join as join9 } from "node:path";
|
|
4452
4452
|
|
|
4453
4453
|
// ../../node_modules/simple-git/dist/esm/index.js
|
|
4454
4454
|
var import_file_exists = __toESM(require_dist(), 1);
|
|
@@ -11458,854 +11458,448 @@ function renderBar(value, width) {
|
|
|
11458
11458
|
return "█".repeat(filled) + "░".repeat(empty);
|
|
11459
11459
|
}
|
|
11460
11460
|
|
|
11461
|
-
// src/lib/
|
|
11462
|
-
import {
|
|
11463
|
-
import { existsSync as existsSync7, writeFileSync as writeFileSync3, readFileSync as readFileSync7, mkdirSync as mkdirSync3, readdirSync as readdirSync4 } from "node:fs";
|
|
11464
|
-
import { join as join7 } from "node:path";
|
|
11461
|
+
// src/lib/frustration-detector.ts
|
|
11462
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7, readdirSync as fsReaddirSync } from "node:fs";
|
|
11465
11463
|
import { homedir as homedir6 } from "node:os";
|
|
11466
|
-
|
|
11467
|
-
|
|
11468
|
-
|
|
11469
|
-
|
|
11470
|
-
|
|
11471
|
-
|
|
11472
|
-
|
|
11473
|
-
|
|
11474
|
-
|
|
11475
|
-
|
|
11476
|
-
|
|
11477
|
-
|
|
11478
|
-
|
|
11479
|
-
|
|
11480
|
-
|
|
11481
|
-
|
|
11482
|
-
|
|
11483
|
-
|
|
11484
|
-
|
|
11485
|
-
|
|
11486
|
-
|
|
11487
|
-
|
|
11488
|
-
|
|
11489
|
-
|
|
11490
|
-
|
|
11491
|
-
|
|
11492
|
-
|
|
11493
|
-
|
|
11494
|
-
|
|
11495
|
-
|
|
11496
|
-
|
|
11497
|
-
|
|
11498
|
-
|
|
11499
|
-
|
|
11500
|
-
|
|
11501
|
-
|
|
11502
|
-
|
|
11503
|
-
|
|
11504
|
-
|
|
11505
|
-
|
|
11506
|
-
|
|
11507
|
-
|
|
11508
|
-
|
|
11509
|
-
|
|
11510
|
-
|
|
11511
|
-
|
|
11512
|
-
|
|
11513
|
-
|
|
11514
|
-
|
|
11515
|
-
|
|
11516
|
-
|
|
11517
|
-
|
|
11518
|
-
|
|
11519
|
-
|
|
11520
|
-
|
|
11521
|
-
|
|
11522
|
-
|
|
11523
|
-
|
|
11524
|
-
|
|
11525
|
-
|
|
11526
|
-
|
|
11527
|
-
|
|
11528
|
-
}
|
|
11529
|
-
if (opt.id === "beads" || opt.name.toLowerCase().includes("beads")) {
|
|
11530
|
-
try {
|
|
11531
|
-
execSync2("bun add -g beads", { encoding: "utf-8", stdio: "pipe", timeout: 60000 });
|
|
11532
|
-
execSync2("bd init", { cwd: projectDir, encoding: "utf-8", stdio: "pipe", timeout: 30000 });
|
|
11533
|
-
return {
|
|
11534
|
-
id: opt.id,
|
|
11535
|
-
name: opt.name,
|
|
11536
|
-
success: true,
|
|
11537
|
-
message: "Installed Beads globally and initialized in project"
|
|
11538
|
-
};
|
|
11539
|
-
} catch (err) {
|
|
11540
|
-
return {
|
|
11541
|
-
id: opt.id,
|
|
11542
|
-
name: opt.name,
|
|
11543
|
-
success: false,
|
|
11544
|
-
message: "Failed to install Beads",
|
|
11545
|
-
error: err instanceof Error ? err.message : String(err)
|
|
11546
|
-
};
|
|
11547
|
-
}
|
|
11464
|
+
import { join as join7 } from "node:path";
|
|
11465
|
+
|
|
11466
|
+
// ../../node_modules/ora/index.js
|
|
11467
|
+
import process8 from "node:process";
|
|
11468
|
+
import { stripVTControlCharacters } from "node:util";
|
|
11469
|
+
|
|
11470
|
+
// ../../node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
11471
|
+
var ANSI_BACKGROUND_OFFSET = 10;
|
|
11472
|
+
var wrapAnsi16 = (offset = 0) => (code2) => `\x1B[${code2 + offset}m`;
|
|
11473
|
+
var wrapAnsi256 = (offset = 0) => (code2) => `\x1B[${38 + offset};5;${code2}m`;
|
|
11474
|
+
var wrapAnsi16m = (offset = 0) => (red, green, blue) => `\x1B[${38 + offset};2;${red};${green};${blue}m`;
|
|
11475
|
+
var styles = {
|
|
11476
|
+
modifier: {
|
|
11477
|
+
reset: [0, 0],
|
|
11478
|
+
bold: [1, 22],
|
|
11479
|
+
dim: [2, 22],
|
|
11480
|
+
italic: [3, 23],
|
|
11481
|
+
underline: [4, 24],
|
|
11482
|
+
overline: [53, 55],
|
|
11483
|
+
inverse: [7, 27],
|
|
11484
|
+
hidden: [8, 28],
|
|
11485
|
+
strikethrough: [9, 29]
|
|
11486
|
+
},
|
|
11487
|
+
color: {
|
|
11488
|
+
black: [30, 39],
|
|
11489
|
+
red: [31, 39],
|
|
11490
|
+
green: [32, 39],
|
|
11491
|
+
yellow: [33, 39],
|
|
11492
|
+
blue: [34, 39],
|
|
11493
|
+
magenta: [35, 39],
|
|
11494
|
+
cyan: [36, 39],
|
|
11495
|
+
white: [37, 39],
|
|
11496
|
+
blackBright: [90, 39],
|
|
11497
|
+
gray: [90, 39],
|
|
11498
|
+
grey: [90, 39],
|
|
11499
|
+
redBright: [91, 39],
|
|
11500
|
+
greenBright: [92, 39],
|
|
11501
|
+
yellowBright: [93, 39],
|
|
11502
|
+
blueBright: [94, 39],
|
|
11503
|
+
magentaBright: [95, 39],
|
|
11504
|
+
cyanBright: [96, 39],
|
|
11505
|
+
whiteBright: [97, 39]
|
|
11506
|
+
},
|
|
11507
|
+
bgColor: {
|
|
11508
|
+
bgBlack: [40, 49],
|
|
11509
|
+
bgRed: [41, 49],
|
|
11510
|
+
bgGreen: [42, 49],
|
|
11511
|
+
bgYellow: [43, 49],
|
|
11512
|
+
bgBlue: [44, 49],
|
|
11513
|
+
bgMagenta: [45, 49],
|
|
11514
|
+
bgCyan: [46, 49],
|
|
11515
|
+
bgWhite: [47, 49],
|
|
11516
|
+
bgBlackBright: [100, 49],
|
|
11517
|
+
bgGray: [100, 49],
|
|
11518
|
+
bgGrey: [100, 49],
|
|
11519
|
+
bgRedBright: [101, 49],
|
|
11520
|
+
bgGreenBright: [102, 49],
|
|
11521
|
+
bgYellowBright: [103, 49],
|
|
11522
|
+
bgBlueBright: [104, 49],
|
|
11523
|
+
bgMagentaBright: [105, 49],
|
|
11524
|
+
bgCyanBright: [106, 49],
|
|
11525
|
+
bgWhiteBright: [107, 49]
|
|
11548
11526
|
}
|
|
11549
|
-
|
|
11550
|
-
|
|
11551
|
-
|
|
11552
|
-
|
|
11553
|
-
|
|
11554
|
-
|
|
11555
|
-
|
|
11556
|
-
|
|
11557
|
-
|
|
11558
|
-
|
|
11559
|
-
|
|
11560
|
-
|
|
11561
|
-
};
|
|
11562
|
-
} catch (err) {
|
|
11563
|
-
return {
|
|
11564
|
-
id: opt.id,
|
|
11565
|
-
name: opt.name,
|
|
11566
|
-
success: false,
|
|
11567
|
-
message: "Failed to install MCP",
|
|
11568
|
-
error: err instanceof Error ? err.message : String(err)
|
|
11527
|
+
};
|
|
11528
|
+
var modifierNames = Object.keys(styles.modifier);
|
|
11529
|
+
var foregroundColorNames = Object.keys(styles.color);
|
|
11530
|
+
var backgroundColorNames = Object.keys(styles.bgColor);
|
|
11531
|
+
var colorNames = [...foregroundColorNames, ...backgroundColorNames];
|
|
11532
|
+
function assembleStyles() {
|
|
11533
|
+
const codes = new Map;
|
|
11534
|
+
for (const [groupName, group] of Object.entries(styles)) {
|
|
11535
|
+
for (const [styleName, style] of Object.entries(group)) {
|
|
11536
|
+
styles[styleName] = {
|
|
11537
|
+
open: `\x1B[${style[0]}m`,
|
|
11538
|
+
close: `\x1B[${style[1]}m`
|
|
11569
11539
|
};
|
|
11540
|
+
group[styleName] = styles[styleName];
|
|
11541
|
+
codes.set(style[0], style[1]);
|
|
11570
11542
|
}
|
|
11571
|
-
|
|
11572
|
-
|
|
11573
|
-
|
|
11574
|
-
name: opt.name,
|
|
11575
|
-
success: false,
|
|
11576
|
-
message: "No install command available"
|
|
11577
|
-
};
|
|
11578
|
-
}
|
|
11579
|
-
function installSkill(opt) {
|
|
11580
|
-
if (!opt.installCommand) {
|
|
11581
|
-
return {
|
|
11582
|
-
id: opt.id,
|
|
11583
|
-
name: opt.name,
|
|
11584
|
-
success: false,
|
|
11585
|
-
message: "No install command for skill"
|
|
11586
|
-
};
|
|
11587
|
-
}
|
|
11588
|
-
try {
|
|
11589
|
-
const skillPath = opt.installCommand.replace(/^npx\s+/, "").replace(/^bunx\s+/, "").replace(/^skills\s+add\s+/, "").trim();
|
|
11590
|
-
let result = spawnSync("bunx", ["--bun", "skills", "add", skillPath], {
|
|
11591
|
-
encoding: "utf-8",
|
|
11592
|
-
stdio: "pipe",
|
|
11593
|
-
timeout: 120000
|
|
11543
|
+
Object.defineProperty(styles, groupName, {
|
|
11544
|
+
value: group,
|
|
11545
|
+
enumerable: false
|
|
11594
11546
|
});
|
|
11595
|
-
if (result.status !== 0) {
|
|
11596
|
-
result = spawnSync("npx", ["-y", "skills", "add", skillPath], {
|
|
11597
|
-
encoding: "utf-8",
|
|
11598
|
-
stdio: "pipe",
|
|
11599
|
-
timeout: 120000
|
|
11600
|
-
});
|
|
11601
|
-
}
|
|
11602
|
-
if (result.status === 0) {
|
|
11603
|
-
return {
|
|
11604
|
-
id: opt.id,
|
|
11605
|
-
name: opt.name,
|
|
11606
|
-
success: true,
|
|
11607
|
-
message: `Skill installed successfully`
|
|
11608
|
-
};
|
|
11609
|
-
} else {
|
|
11610
|
-
const output = (result.stderr || result.stdout || "").toLowerCase();
|
|
11611
|
-
if (output.includes("already exists") || output.includes("already installed")) {
|
|
11612
|
-
return {
|
|
11613
|
-
id: opt.id,
|
|
11614
|
-
name: opt.name,
|
|
11615
|
-
success: true,
|
|
11616
|
-
message: `Skill already installed`
|
|
11617
|
-
};
|
|
11618
|
-
}
|
|
11619
|
-
return {
|
|
11620
|
-
id: opt.id,
|
|
11621
|
-
name: opt.name,
|
|
11622
|
-
success: false,
|
|
11623
|
-
message: "Skill installation failed",
|
|
11624
|
-
error: result.stderr || result.stdout || "Unknown error"
|
|
11625
|
-
};
|
|
11626
|
-
}
|
|
11627
|
-
} catch (err) {
|
|
11628
|
-
return {
|
|
11629
|
-
id: opt.id,
|
|
11630
|
-
name: opt.name,
|
|
11631
|
-
success: false,
|
|
11632
|
-
message: "Failed to install skill",
|
|
11633
|
-
error: err instanceof Error ? err.message : String(err)
|
|
11634
|
-
};
|
|
11635
11547
|
}
|
|
11636
|
-
|
|
11637
|
-
|
|
11638
|
-
|
|
11639
|
-
|
|
11640
|
-
|
|
11641
|
-
|
|
11642
|
-
|
|
11643
|
-
|
|
11644
|
-
|
|
11645
|
-
|
|
11646
|
-
|
|
11647
|
-
|
|
11648
|
-
|
|
11649
|
-
|
|
11650
|
-
|
|
11651
|
-
|
|
11652
|
-
|
|
11653
|
-
|
|
11654
|
-
|
|
11655
|
-
|
|
11656
|
-
|
|
11657
|
-
|
|
11658
|
-
|
|
11548
|
+
Object.defineProperty(styles, "codes", {
|
|
11549
|
+
value: codes,
|
|
11550
|
+
enumerable: false
|
|
11551
|
+
});
|
|
11552
|
+
styles.color.close = "\x1B[39m";
|
|
11553
|
+
styles.bgColor.close = "\x1B[49m";
|
|
11554
|
+
styles.color.ansi = wrapAnsi16();
|
|
11555
|
+
styles.color.ansi256 = wrapAnsi256();
|
|
11556
|
+
styles.color.ansi16m = wrapAnsi16m();
|
|
11557
|
+
styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
|
|
11558
|
+
styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
|
|
11559
|
+
styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
|
|
11560
|
+
Object.defineProperties(styles, {
|
|
11561
|
+
rgbToAnsi256: {
|
|
11562
|
+
value(red, green, blue) {
|
|
11563
|
+
if (red === green && green === blue) {
|
|
11564
|
+
if (red < 8) {
|
|
11565
|
+
return 16;
|
|
11566
|
+
}
|
|
11567
|
+
if (red > 248) {
|
|
11568
|
+
return 231;
|
|
11569
|
+
}
|
|
11570
|
+
return Math.round((red - 8) / 247 * 24) + 232;
|
|
11571
|
+
}
|
|
11572
|
+
return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
|
|
11573
|
+
},
|
|
11574
|
+
enumerable: false
|
|
11575
|
+
},
|
|
11576
|
+
hexToRgb: {
|
|
11577
|
+
value(hex) {
|
|
11578
|
+
const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
|
|
11579
|
+
if (!matches) {
|
|
11580
|
+
return [0, 0, 0];
|
|
11581
|
+
}
|
|
11582
|
+
let [colorString] = matches;
|
|
11583
|
+
if (colorString.length === 3) {
|
|
11584
|
+
colorString = [...colorString].map((character) => character + character).join("");
|
|
11585
|
+
}
|
|
11586
|
+
const integer = Number.parseInt(colorString, 16);
|
|
11587
|
+
return [
|
|
11588
|
+
integer >> 16 & 255,
|
|
11589
|
+
integer >> 8 & 255,
|
|
11590
|
+
integer & 255
|
|
11591
|
+
];
|
|
11592
|
+
},
|
|
11593
|
+
enumerable: false
|
|
11594
|
+
},
|
|
11595
|
+
hexToAnsi256: {
|
|
11596
|
+
value: (hex) => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
|
|
11597
|
+
enumerable: false
|
|
11598
|
+
},
|
|
11599
|
+
ansi256ToAnsi: {
|
|
11600
|
+
value(code2) {
|
|
11601
|
+
if (code2 < 8) {
|
|
11602
|
+
return 30 + code2;
|
|
11603
|
+
}
|
|
11604
|
+
if (code2 < 16) {
|
|
11605
|
+
return 90 + (code2 - 8);
|
|
11606
|
+
}
|
|
11607
|
+
let red;
|
|
11608
|
+
let green;
|
|
11609
|
+
let blue;
|
|
11610
|
+
if (code2 >= 232) {
|
|
11611
|
+
red = ((code2 - 232) * 10 + 8) / 255;
|
|
11612
|
+
green = red;
|
|
11613
|
+
blue = red;
|
|
11614
|
+
} else {
|
|
11615
|
+
code2 -= 16;
|
|
11616
|
+
const remainder = code2 % 36;
|
|
11617
|
+
red = Math.floor(code2 / 36) / 5;
|
|
11618
|
+
green = Math.floor(remainder / 6) / 5;
|
|
11619
|
+
blue = remainder % 6 / 5;
|
|
11620
|
+
}
|
|
11621
|
+
const value = Math.max(red, green, blue) * 2;
|
|
11622
|
+
if (value === 0) {
|
|
11623
|
+
return 30;
|
|
11624
|
+
}
|
|
11625
|
+
let result = 30 + (Math.round(blue) << 2 | Math.round(green) << 1 | Math.round(red));
|
|
11626
|
+
if (value === 2) {
|
|
11627
|
+
result += 60;
|
|
11628
|
+
}
|
|
11629
|
+
return result;
|
|
11630
|
+
},
|
|
11631
|
+
enumerable: false
|
|
11632
|
+
},
|
|
11633
|
+
rgbToAnsi: {
|
|
11634
|
+
value: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),
|
|
11635
|
+
enumerable: false
|
|
11636
|
+
},
|
|
11637
|
+
hexToAnsi: {
|
|
11638
|
+
value: (hex) => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),
|
|
11639
|
+
enumerable: false
|
|
11659
11640
|
}
|
|
11660
|
-
|
|
11661
|
-
|
|
11662
|
-
id: opt.id,
|
|
11663
|
-
name: opt.name,
|
|
11664
|
-
success: true,
|
|
11665
|
-
message: `Created: ${opt.configPath}`
|
|
11666
|
-
};
|
|
11667
|
-
} catch (err) {
|
|
11668
|
-
return {
|
|
11669
|
-
id: opt.id,
|
|
11670
|
-
name: opt.name,
|
|
11671
|
-
success: false,
|
|
11672
|
-
message: "Failed to create config",
|
|
11673
|
-
error: err instanceof Error ? err.message : String(err)
|
|
11674
|
-
};
|
|
11675
|
-
}
|
|
11641
|
+
});
|
|
11642
|
+
return styles;
|
|
11676
11643
|
}
|
|
11677
|
-
|
|
11678
|
-
|
|
11679
|
-
try {
|
|
11680
|
-
let content = "";
|
|
11681
|
-
if (existsSync7(agentsMdPath)) {
|
|
11682
|
-
content = readFileSync7(agentsMdPath, "utf-8");
|
|
11683
|
-
} else {
|
|
11684
|
-
content = `# Agent Instructions
|
|
11644
|
+
var ansiStyles = assembleStyles();
|
|
11645
|
+
var ansi_styles_default = ansiStyles;
|
|
11685
11646
|
|
|
11686
|
-
|
|
11647
|
+
// ../../node_modules/chalk/source/vendor/supports-color/index.js
|
|
11648
|
+
import process2 from "node:process";
|
|
11649
|
+
import os from "node:os";
|
|
11650
|
+
import tty2 from "node:tty";
|
|
11651
|
+
function hasFlag(flag, argv2 = globalThis.Deno ? globalThis.Deno.args : process2.argv) {
|
|
11652
|
+
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
11653
|
+
const position = argv2.indexOf(prefix + flag);
|
|
11654
|
+
const terminatorPosition = argv2.indexOf("--");
|
|
11655
|
+
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
11656
|
+
}
|
|
11657
|
+
var { env: env2 } = process2;
|
|
11658
|
+
var flagForceColor;
|
|
11659
|
+
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
|
|
11660
|
+
flagForceColor = 0;
|
|
11661
|
+
} else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
|
|
11662
|
+
flagForceColor = 1;
|
|
11663
|
+
}
|
|
11664
|
+
function envForceColor() {
|
|
11665
|
+
if ("FORCE_COLOR" in env2) {
|
|
11666
|
+
if (env2.FORCE_COLOR === "true") {
|
|
11667
|
+
return 1;
|
|
11687
11668
|
}
|
|
11688
|
-
|
|
11689
|
-
|
|
11690
|
-
return {
|
|
11691
|
-
id: opt.id,
|
|
11692
|
-
name: opt.name,
|
|
11693
|
-
success: true,
|
|
11694
|
-
message: "Hook already configured in AGENTS.md"
|
|
11695
|
-
};
|
|
11669
|
+
if (env2.FORCE_COLOR === "false") {
|
|
11670
|
+
return 0;
|
|
11696
11671
|
}
|
|
11697
|
-
|
|
11698
|
-
## ${opt.name}
|
|
11699
|
-
${opt.description}
|
|
11700
|
-
`;
|
|
11701
|
-
content += `
|
|
11702
|
-
` + hookSection;
|
|
11703
|
-
writeFileSync3(agentsMdPath, content);
|
|
11704
|
-
return {
|
|
11705
|
-
id: opt.id,
|
|
11706
|
-
name: opt.name,
|
|
11707
|
-
success: true,
|
|
11708
|
-
message: "Added hook to AGENTS.md"
|
|
11709
|
-
};
|
|
11710
|
-
} catch (err) {
|
|
11711
|
-
return {
|
|
11712
|
-
id: opt.id,
|
|
11713
|
-
name: opt.name,
|
|
11714
|
-
success: false,
|
|
11715
|
-
message: "Failed to add hook",
|
|
11716
|
-
error: err instanceof Error ? err.message : String(err)
|
|
11717
|
-
};
|
|
11672
|
+
return env2.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env2.FORCE_COLOR, 10), 3);
|
|
11718
11673
|
}
|
|
11719
11674
|
}
|
|
11720
|
-
function
|
|
11675
|
+
function translateLevel(level) {
|
|
11676
|
+
if (level === 0) {
|
|
11677
|
+
return false;
|
|
11678
|
+
}
|
|
11721
11679
|
return {
|
|
11722
|
-
|
|
11723
|
-
|
|
11724
|
-
|
|
11725
|
-
|
|
11726
|
-
installCommand: rec.installCommand,
|
|
11727
|
-
selected: false
|
|
11680
|
+
level,
|
|
11681
|
+
hasBasic: true,
|
|
11682
|
+
has256: level >= 2,
|
|
11683
|
+
has16m: level >= 3
|
|
11728
11684
|
};
|
|
11729
11685
|
}
|
|
11730
|
-
function
|
|
11731
|
-
const
|
|
11732
|
-
|
|
11733
|
-
|
|
11734
|
-
supermemory: false,
|
|
11735
|
-
nia: false,
|
|
11736
|
-
beads: false,
|
|
11737
|
-
skills: []
|
|
11738
|
-
};
|
|
11739
|
-
const mcpConfigPaths = [
|
|
11740
|
-
join7(home, ".claude.json"),
|
|
11741
|
-
join7(home, ".claude", "claude_desktop_config.json"),
|
|
11742
|
-
join7(home, ".claude", "settings.json"),
|
|
11743
|
-
join7(home, ".claude", "settings.local.json"),
|
|
11744
|
-
join7(projectDir, ".mcp.json"),
|
|
11745
|
-
join7(projectDir, ".claude", "settings.local.json")
|
|
11746
|
-
];
|
|
11747
|
-
for (const configPath of mcpConfigPaths) {
|
|
11748
|
-
if (existsSync7(configPath)) {
|
|
11749
|
-
try {
|
|
11750
|
-
const config = JSON.parse(readFileSync7(configPath, "utf-8"));
|
|
11751
|
-
const mcpServers = config.mcpServers || config.mcp_servers || {};
|
|
11752
|
-
for (const name of Object.keys(mcpServers)) {
|
|
11753
|
-
const mcpName = name.toLowerCase();
|
|
11754
|
-
if (mcpName.includes("context7") || mcpName === "c7") {
|
|
11755
|
-
status.context7 = true;
|
|
11756
|
-
}
|
|
11757
|
-
if (mcpName.includes("supermemory") || mcpName.includes("memory")) {
|
|
11758
|
-
status.supermemory = true;
|
|
11759
|
-
}
|
|
11760
|
-
if (mcpName.includes("nia")) {
|
|
11761
|
-
status.nia = true;
|
|
11762
|
-
}
|
|
11763
|
-
}
|
|
11764
|
-
} catch {}
|
|
11765
|
-
}
|
|
11686
|
+
function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
11687
|
+
const noFlagForceColor = envForceColor();
|
|
11688
|
+
if (noFlagForceColor !== undefined) {
|
|
11689
|
+
flagForceColor = noFlagForceColor;
|
|
11766
11690
|
}
|
|
11767
|
-
|
|
11768
|
-
|
|
11769
|
-
|
|
11770
|
-
|
|
11771
|
-
|
|
11772
|
-
|
|
11773
|
-
|
|
11774
|
-
|
|
11775
|
-
if (
|
|
11776
|
-
|
|
11777
|
-
const skills = readdirSync4(dir);
|
|
11778
|
-
for (const skill of skills) {
|
|
11779
|
-
if (!status.skills.includes(skill.toLowerCase())) {
|
|
11780
|
-
status.skills.push(skill.toLowerCase());
|
|
11781
|
-
}
|
|
11782
|
-
}
|
|
11783
|
-
} catch {}
|
|
11691
|
+
const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
|
|
11692
|
+
if (forceColor === 0) {
|
|
11693
|
+
return 0;
|
|
11694
|
+
}
|
|
11695
|
+
if (sniffFlags) {
|
|
11696
|
+
if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
|
|
11697
|
+
return 3;
|
|
11698
|
+
}
|
|
11699
|
+
if (hasFlag("color=256")) {
|
|
11700
|
+
return 2;
|
|
11784
11701
|
}
|
|
11785
11702
|
}
|
|
11786
|
-
|
|
11787
|
-
|
|
11788
|
-
|
|
11789
|
-
|
|
11790
|
-
|
|
11791
|
-
|
|
11792
|
-
|
|
11793
|
-
|
|
11794
|
-
|
|
11795
|
-
|
|
11796
|
-
|
|
11797
|
-
|
|
11798
|
-
|
|
11799
|
-
|
|
11800
|
-
|
|
11801
|
-
|
|
11802
|
-
|
|
11703
|
+
if ("TF_BUILD" in env2 && "AGENT_NAME" in env2) {
|
|
11704
|
+
return 1;
|
|
11705
|
+
}
|
|
11706
|
+
if (haveStream && !streamIsTTY && forceColor === undefined) {
|
|
11707
|
+
return 0;
|
|
11708
|
+
}
|
|
11709
|
+
const min = forceColor || 0;
|
|
11710
|
+
if (env2.TERM === "dumb") {
|
|
11711
|
+
return min;
|
|
11712
|
+
}
|
|
11713
|
+
if (process2.platform === "win32") {
|
|
11714
|
+
const osRelease = os.release().split(".");
|
|
11715
|
+
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
11716
|
+
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
11717
|
+
}
|
|
11718
|
+
return 1;
|
|
11719
|
+
}
|
|
11720
|
+
if ("CI" in env2) {
|
|
11721
|
+
if (["GITHUB_ACTIONS", "GITEA_ACTIONS", "CIRCLECI"].some((key) => (key in env2))) {
|
|
11722
|
+
return 3;
|
|
11723
|
+
}
|
|
11724
|
+
if (["TRAVIS", "APPVEYOR", "GITLAB_CI", "BUILDKITE", "DRONE"].some((sign) => (sign in env2)) || env2.CI_NAME === "codeship") {
|
|
11725
|
+
return 1;
|
|
11726
|
+
}
|
|
11727
|
+
return min;
|
|
11728
|
+
}
|
|
11729
|
+
if ("TEAMCITY_VERSION" in env2) {
|
|
11730
|
+
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env2.TEAMCITY_VERSION) ? 1 : 0;
|
|
11731
|
+
}
|
|
11732
|
+
if (env2.COLORTERM === "truecolor") {
|
|
11733
|
+
return 3;
|
|
11734
|
+
}
|
|
11735
|
+
if (env2.TERM === "xterm-kitty") {
|
|
11736
|
+
return 3;
|
|
11737
|
+
}
|
|
11738
|
+
if (env2.TERM === "xterm-ghostty") {
|
|
11739
|
+
return 3;
|
|
11740
|
+
}
|
|
11741
|
+
if (env2.TERM === "wezterm") {
|
|
11742
|
+
return 3;
|
|
11743
|
+
}
|
|
11744
|
+
if ("TERM_PROGRAM" in env2) {
|
|
11745
|
+
const version2 = Number.parseInt((env2.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
11746
|
+
switch (env2.TERM_PROGRAM) {
|
|
11747
|
+
case "iTerm.app": {
|
|
11748
|
+
return version2 >= 3 ? 3 : 2;
|
|
11749
|
+
}
|
|
11750
|
+
case "Apple_Terminal": {
|
|
11751
|
+
return 2;
|
|
11803
11752
|
}
|
|
11804
11753
|
}
|
|
11805
|
-
|
|
11754
|
+
}
|
|
11755
|
+
if (/-256(color)?$/i.test(env2.TERM)) {
|
|
11756
|
+
return 2;
|
|
11757
|
+
}
|
|
11758
|
+
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env2.TERM)) {
|
|
11759
|
+
return 1;
|
|
11760
|
+
}
|
|
11761
|
+
if ("COLORTERM" in env2) {
|
|
11762
|
+
return 1;
|
|
11763
|
+
}
|
|
11764
|
+
return min;
|
|
11765
|
+
}
|
|
11766
|
+
function createSupportsColor(stream, options = {}) {
|
|
11767
|
+
const level = _supportsColor(stream, {
|
|
11768
|
+
streamIsTTY: stream && stream.isTTY,
|
|
11769
|
+
...options
|
|
11806
11770
|
});
|
|
11771
|
+
return translateLevel(level);
|
|
11807
11772
|
}
|
|
11808
|
-
var
|
|
11809
|
-
|
|
11810
|
-
|
|
11811
|
-
id: "context7",
|
|
11812
|
-
name: "Context7 MCP",
|
|
11813
|
-
type: "mcp",
|
|
11814
|
-
description: "Up-to-date library documentation",
|
|
11815
|
-
installCommand: "claude mcp add context7 https://mcp.context7.com/mcp --transport http",
|
|
11816
|
-
selected: true
|
|
11817
|
-
},
|
|
11818
|
-
{
|
|
11819
|
-
id: "supermemory",
|
|
11820
|
-
name: "Supermemory MCP",
|
|
11821
|
-
type: "mcp",
|
|
11822
|
-
description: "Persistent memory across sessions",
|
|
11823
|
-
installCommand: "claude mcp add supermemory -- npx -y @supermemory/mcp@latest",
|
|
11824
|
-
selected: true
|
|
11825
|
-
},
|
|
11826
|
-
{
|
|
11827
|
-
id: "beads",
|
|
11828
|
-
name: "Beads Task Manager",
|
|
11829
|
-
type: "mcp",
|
|
11830
|
-
description: "Persistent task tracking",
|
|
11831
|
-
installCommand: "bun add -g beads && bd init",
|
|
11832
|
-
selected: true
|
|
11833
|
-
}
|
|
11834
|
-
],
|
|
11835
|
-
productivity: [
|
|
11836
|
-
{
|
|
11837
|
-
id: "claude-md",
|
|
11838
|
-
name: "CLAUDE.md",
|
|
11839
|
-
type: "config",
|
|
11840
|
-
description: "Project context file",
|
|
11841
|
-
configPath: "CLAUDE.md",
|
|
11842
|
-
configContent: `# Project Instructions
|
|
11843
|
-
|
|
11844
|
-
## Build & Test Commands
|
|
11845
|
-
\`\`\`bash
|
|
11846
|
-
bun test # Run tests
|
|
11847
|
-
bun run build # Build project
|
|
11848
|
-
bun run lint # Run linter
|
|
11849
|
-
\`\`\`
|
|
11850
|
-
|
|
11851
|
-
## Architecture
|
|
11852
|
-
Describe your project structure here.
|
|
11853
|
-
|
|
11854
|
-
## Conventions
|
|
11855
|
-
- Use TypeScript
|
|
11856
|
-
- Write tests for new features
|
|
11857
|
-
- Use conventional commits
|
|
11858
|
-
`,
|
|
11859
|
-
selected: true
|
|
11860
|
-
},
|
|
11861
|
-
{
|
|
11862
|
-
id: "vitest",
|
|
11863
|
-
name: "Vitest",
|
|
11864
|
-
type: "library",
|
|
11865
|
-
description: "Fast unit testing framework",
|
|
11866
|
-
installCommand: "bun add -D vitest",
|
|
11867
|
-
selected: true
|
|
11868
|
-
}
|
|
11869
|
-
]
|
|
11773
|
+
var supportsColor = {
|
|
11774
|
+
stdout: createSupportsColor({ isTTY: tty2.isatty(1) }),
|
|
11775
|
+
stderr: createSupportsColor({ isTTY: tty2.isatty(2) })
|
|
11870
11776
|
};
|
|
11777
|
+
var supports_color_default = supportsColor;
|
|
11871
11778
|
|
|
11872
|
-
// ../../node_modules/
|
|
11873
|
-
|
|
11874
|
-
|
|
11779
|
+
// ../../node_modules/chalk/source/utilities.js
|
|
11780
|
+
function stringReplaceAll(string, substring, replacer) {
|
|
11781
|
+
let index = string.indexOf(substring);
|
|
11782
|
+
if (index === -1) {
|
|
11783
|
+
return string;
|
|
11784
|
+
}
|
|
11785
|
+
const substringLength = substring.length;
|
|
11786
|
+
let endIndex = 0;
|
|
11787
|
+
let returnValue = "";
|
|
11788
|
+
do {
|
|
11789
|
+
returnValue += string.slice(endIndex, index) + substring + replacer;
|
|
11790
|
+
endIndex = index + substringLength;
|
|
11791
|
+
index = string.indexOf(substring, endIndex);
|
|
11792
|
+
} while (index !== -1);
|
|
11793
|
+
returnValue += string.slice(endIndex);
|
|
11794
|
+
return returnValue;
|
|
11795
|
+
}
|
|
11796
|
+
function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
|
|
11797
|
+
let endIndex = 0;
|
|
11798
|
+
let returnValue = "";
|
|
11799
|
+
do {
|
|
11800
|
+
const gotCR = string[index - 1] === "\r";
|
|
11801
|
+
returnValue += string.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? `\r
|
|
11802
|
+
` : `
|
|
11803
|
+
`) + postfix;
|
|
11804
|
+
endIndex = index + 1;
|
|
11805
|
+
index = string.indexOf(`
|
|
11806
|
+
`, endIndex);
|
|
11807
|
+
} while (index !== -1);
|
|
11808
|
+
returnValue += string.slice(endIndex);
|
|
11809
|
+
return returnValue;
|
|
11810
|
+
}
|
|
11875
11811
|
|
|
11876
|
-
// ../../node_modules/chalk/source/
|
|
11877
|
-
var
|
|
11878
|
-
var
|
|
11879
|
-
var
|
|
11880
|
-
var
|
|
11881
|
-
var
|
|
11882
|
-
|
|
11883
|
-
|
|
11884
|
-
|
|
11885
|
-
|
|
11886
|
-
|
|
11887
|
-
|
|
11888
|
-
|
|
11889
|
-
|
|
11890
|
-
|
|
11891
|
-
strikethrough: [9, 29]
|
|
11892
|
-
},
|
|
11893
|
-
color: {
|
|
11894
|
-
black: [30, 39],
|
|
11895
|
-
red: [31, 39],
|
|
11896
|
-
green: [32, 39],
|
|
11897
|
-
yellow: [33, 39],
|
|
11898
|
-
blue: [34, 39],
|
|
11899
|
-
magenta: [35, 39],
|
|
11900
|
-
cyan: [36, 39],
|
|
11901
|
-
white: [37, 39],
|
|
11902
|
-
blackBright: [90, 39],
|
|
11903
|
-
gray: [90, 39],
|
|
11904
|
-
grey: [90, 39],
|
|
11905
|
-
redBright: [91, 39],
|
|
11906
|
-
greenBright: [92, 39],
|
|
11907
|
-
yellowBright: [93, 39],
|
|
11908
|
-
blueBright: [94, 39],
|
|
11909
|
-
magentaBright: [95, 39],
|
|
11910
|
-
cyanBright: [96, 39],
|
|
11911
|
-
whiteBright: [97, 39]
|
|
11912
|
-
},
|
|
11913
|
-
bgColor: {
|
|
11914
|
-
bgBlack: [40, 49],
|
|
11915
|
-
bgRed: [41, 49],
|
|
11916
|
-
bgGreen: [42, 49],
|
|
11917
|
-
bgYellow: [43, 49],
|
|
11918
|
-
bgBlue: [44, 49],
|
|
11919
|
-
bgMagenta: [45, 49],
|
|
11920
|
-
bgCyan: [46, 49],
|
|
11921
|
-
bgWhite: [47, 49],
|
|
11922
|
-
bgBlackBright: [100, 49],
|
|
11923
|
-
bgGray: [100, 49],
|
|
11924
|
-
bgGrey: [100, 49],
|
|
11925
|
-
bgRedBright: [101, 49],
|
|
11926
|
-
bgGreenBright: [102, 49],
|
|
11927
|
-
bgYellowBright: [103, 49],
|
|
11928
|
-
bgBlueBright: [104, 49],
|
|
11929
|
-
bgMagentaBright: [105, 49],
|
|
11930
|
-
bgCyanBright: [106, 49],
|
|
11931
|
-
bgWhiteBright: [107, 49]
|
|
11812
|
+
// ../../node_modules/chalk/source/index.js
|
|
11813
|
+
var { stdout: stdoutColor, stderr: stderrColor } = supports_color_default;
|
|
11814
|
+
var GENERATOR = Symbol("GENERATOR");
|
|
11815
|
+
var STYLER = Symbol("STYLER");
|
|
11816
|
+
var IS_EMPTY = Symbol("IS_EMPTY");
|
|
11817
|
+
var levelMapping = [
|
|
11818
|
+
"ansi",
|
|
11819
|
+
"ansi",
|
|
11820
|
+
"ansi256",
|
|
11821
|
+
"ansi16m"
|
|
11822
|
+
];
|
|
11823
|
+
var styles2 = Object.create(null);
|
|
11824
|
+
var applyOptions = (object, options = {}) => {
|
|
11825
|
+
if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
|
|
11826
|
+
throw new Error("The `level` option should be an integer from 0 to 3");
|
|
11932
11827
|
}
|
|
11828
|
+
const colorLevel = stdoutColor ? stdoutColor.level : 0;
|
|
11829
|
+
object.level = options.level === undefined ? colorLevel : options.level;
|
|
11933
11830
|
};
|
|
11934
|
-
var
|
|
11935
|
-
|
|
11936
|
-
|
|
11937
|
-
|
|
11938
|
-
|
|
11939
|
-
|
|
11940
|
-
|
|
11941
|
-
|
|
11942
|
-
styles[styleName] = {
|
|
11943
|
-
open: `\x1B[${style[0]}m`,
|
|
11944
|
-
close: `\x1B[${style[1]}m`
|
|
11945
|
-
};
|
|
11946
|
-
group[styleName] = styles[styleName];
|
|
11947
|
-
codes.set(style[0], style[1]);
|
|
11948
|
-
}
|
|
11949
|
-
Object.defineProperty(styles, groupName, {
|
|
11950
|
-
value: group,
|
|
11951
|
-
enumerable: false
|
|
11952
|
-
});
|
|
11953
|
-
}
|
|
11954
|
-
Object.defineProperty(styles, "codes", {
|
|
11955
|
-
value: codes,
|
|
11956
|
-
enumerable: false
|
|
11957
|
-
});
|
|
11958
|
-
styles.color.close = "\x1B[39m";
|
|
11959
|
-
styles.bgColor.close = "\x1B[49m";
|
|
11960
|
-
styles.color.ansi = wrapAnsi16();
|
|
11961
|
-
styles.color.ansi256 = wrapAnsi256();
|
|
11962
|
-
styles.color.ansi16m = wrapAnsi16m();
|
|
11963
|
-
styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
|
|
11964
|
-
styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
|
|
11965
|
-
styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
|
|
11966
|
-
Object.defineProperties(styles, {
|
|
11967
|
-
rgbToAnsi256: {
|
|
11968
|
-
value(red, green, blue) {
|
|
11969
|
-
if (red === green && green === blue) {
|
|
11970
|
-
if (red < 8) {
|
|
11971
|
-
return 16;
|
|
11972
|
-
}
|
|
11973
|
-
if (red > 248) {
|
|
11974
|
-
return 231;
|
|
11975
|
-
}
|
|
11976
|
-
return Math.round((red - 8) / 247 * 24) + 232;
|
|
11977
|
-
}
|
|
11978
|
-
return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
|
|
11979
|
-
},
|
|
11980
|
-
enumerable: false
|
|
11981
|
-
},
|
|
11982
|
-
hexToRgb: {
|
|
11983
|
-
value(hex) {
|
|
11984
|
-
const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
|
|
11985
|
-
if (!matches) {
|
|
11986
|
-
return [0, 0, 0];
|
|
11987
|
-
}
|
|
11988
|
-
let [colorString] = matches;
|
|
11989
|
-
if (colorString.length === 3) {
|
|
11990
|
-
colorString = [...colorString].map((character) => character + character).join("");
|
|
11991
|
-
}
|
|
11992
|
-
const integer = Number.parseInt(colorString, 16);
|
|
11993
|
-
return [
|
|
11994
|
-
integer >> 16 & 255,
|
|
11995
|
-
integer >> 8 & 255,
|
|
11996
|
-
integer & 255
|
|
11997
|
-
];
|
|
11998
|
-
},
|
|
11999
|
-
enumerable: false
|
|
12000
|
-
},
|
|
12001
|
-
hexToAnsi256: {
|
|
12002
|
-
value: (hex) => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
|
|
12003
|
-
enumerable: false
|
|
12004
|
-
},
|
|
12005
|
-
ansi256ToAnsi: {
|
|
12006
|
-
value(code2) {
|
|
12007
|
-
if (code2 < 8) {
|
|
12008
|
-
return 30 + code2;
|
|
12009
|
-
}
|
|
12010
|
-
if (code2 < 16) {
|
|
12011
|
-
return 90 + (code2 - 8);
|
|
12012
|
-
}
|
|
12013
|
-
let red;
|
|
12014
|
-
let green;
|
|
12015
|
-
let blue;
|
|
12016
|
-
if (code2 >= 232) {
|
|
12017
|
-
red = ((code2 - 232) * 10 + 8) / 255;
|
|
12018
|
-
green = red;
|
|
12019
|
-
blue = red;
|
|
12020
|
-
} else {
|
|
12021
|
-
code2 -= 16;
|
|
12022
|
-
const remainder = code2 % 36;
|
|
12023
|
-
red = Math.floor(code2 / 36) / 5;
|
|
12024
|
-
green = Math.floor(remainder / 6) / 5;
|
|
12025
|
-
blue = remainder % 6 / 5;
|
|
12026
|
-
}
|
|
12027
|
-
const value = Math.max(red, green, blue) * 2;
|
|
12028
|
-
if (value === 0) {
|
|
12029
|
-
return 30;
|
|
12030
|
-
}
|
|
12031
|
-
let result = 30 + (Math.round(blue) << 2 | Math.round(green) << 1 | Math.round(red));
|
|
12032
|
-
if (value === 2) {
|
|
12033
|
-
result += 60;
|
|
12034
|
-
}
|
|
12035
|
-
return result;
|
|
12036
|
-
},
|
|
12037
|
-
enumerable: false
|
|
12038
|
-
},
|
|
12039
|
-
rgbToAnsi: {
|
|
12040
|
-
value: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),
|
|
12041
|
-
enumerable: false
|
|
12042
|
-
},
|
|
12043
|
-
hexToAnsi: {
|
|
12044
|
-
value: (hex) => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),
|
|
12045
|
-
enumerable: false
|
|
12046
|
-
}
|
|
12047
|
-
});
|
|
12048
|
-
return styles;
|
|
12049
|
-
}
|
|
12050
|
-
var ansiStyles = assembleStyles();
|
|
12051
|
-
var ansi_styles_default = ansiStyles;
|
|
12052
|
-
|
|
12053
|
-
// ../../node_modules/chalk/source/vendor/supports-color/index.js
|
|
12054
|
-
import process2 from "node:process";
|
|
12055
|
-
import os from "node:os";
|
|
12056
|
-
import tty2 from "node:tty";
|
|
12057
|
-
function hasFlag(flag, argv2 = globalThis.Deno ? globalThis.Deno.args : process2.argv) {
|
|
12058
|
-
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
12059
|
-
const position = argv2.indexOf(prefix + flag);
|
|
12060
|
-
const terminatorPosition = argv2.indexOf("--");
|
|
12061
|
-
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
12062
|
-
}
|
|
12063
|
-
var { env: env2 } = process2;
|
|
12064
|
-
var flagForceColor;
|
|
12065
|
-
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
|
|
12066
|
-
flagForceColor = 0;
|
|
12067
|
-
} else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
|
|
12068
|
-
flagForceColor = 1;
|
|
11831
|
+
var chalkFactory = (options) => {
|
|
11832
|
+
const chalk = (...strings) => strings.join(" ");
|
|
11833
|
+
applyOptions(chalk, options);
|
|
11834
|
+
Object.setPrototypeOf(chalk, createChalk.prototype);
|
|
11835
|
+
return chalk;
|
|
11836
|
+
};
|
|
11837
|
+
function createChalk(options) {
|
|
11838
|
+
return chalkFactory(options);
|
|
12069
11839
|
}
|
|
12070
|
-
|
|
12071
|
-
|
|
12072
|
-
|
|
12073
|
-
|
|
12074
|
-
|
|
12075
|
-
|
|
12076
|
-
return
|
|
11840
|
+
Object.setPrototypeOf(createChalk.prototype, Function.prototype);
|
|
11841
|
+
for (const [styleName, style] of Object.entries(ansi_styles_default)) {
|
|
11842
|
+
styles2[styleName] = {
|
|
11843
|
+
get() {
|
|
11844
|
+
const builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);
|
|
11845
|
+
Object.defineProperty(this, styleName, { value: builder });
|
|
11846
|
+
return builder;
|
|
12077
11847
|
}
|
|
12078
|
-
return env2.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env2.FORCE_COLOR, 10), 3);
|
|
12079
|
-
}
|
|
12080
|
-
}
|
|
12081
|
-
function translateLevel(level) {
|
|
12082
|
-
if (level === 0) {
|
|
12083
|
-
return false;
|
|
12084
|
-
}
|
|
12085
|
-
return {
|
|
12086
|
-
level,
|
|
12087
|
-
hasBasic: true,
|
|
12088
|
-
has256: level >= 2,
|
|
12089
|
-
has16m: level >= 3
|
|
12090
11848
|
};
|
|
12091
11849
|
}
|
|
12092
|
-
|
|
12093
|
-
|
|
12094
|
-
|
|
12095
|
-
|
|
12096
|
-
|
|
12097
|
-
const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
|
|
12098
|
-
if (forceColor === 0) {
|
|
12099
|
-
return 0;
|
|
11850
|
+
styles2.visible = {
|
|
11851
|
+
get() {
|
|
11852
|
+
const builder = createBuilder(this, this[STYLER], true);
|
|
11853
|
+
Object.defineProperty(this, "visible", { value: builder });
|
|
11854
|
+
return builder;
|
|
12100
11855
|
}
|
|
12101
|
-
|
|
12102
|
-
|
|
12103
|
-
|
|
11856
|
+
};
|
|
11857
|
+
var getModelAnsi = (model, level, type, ...arguments_) => {
|
|
11858
|
+
if (model === "rgb") {
|
|
11859
|
+
if (level === "ansi16m") {
|
|
11860
|
+
return ansi_styles_default[type].ansi16m(...arguments_);
|
|
12104
11861
|
}
|
|
12105
|
-
if (
|
|
12106
|
-
return
|
|
11862
|
+
if (level === "ansi256") {
|
|
11863
|
+
return ansi_styles_default[type].ansi256(ansi_styles_default.rgbToAnsi256(...arguments_));
|
|
12107
11864
|
}
|
|
11865
|
+
return ansi_styles_default[type].ansi(ansi_styles_default.rgbToAnsi(...arguments_));
|
|
12108
11866
|
}
|
|
12109
|
-
if (
|
|
12110
|
-
return
|
|
12111
|
-
}
|
|
12112
|
-
if (haveStream && !streamIsTTY && forceColor === undefined) {
|
|
12113
|
-
return 0;
|
|
12114
|
-
}
|
|
12115
|
-
const min = forceColor || 0;
|
|
12116
|
-
if (env2.TERM === "dumb") {
|
|
12117
|
-
return min;
|
|
11867
|
+
if (model === "hex") {
|
|
11868
|
+
return getModelAnsi("rgb", level, type, ...ansi_styles_default.hexToRgb(...arguments_));
|
|
12118
11869
|
}
|
|
12119
|
-
|
|
12120
|
-
|
|
12121
|
-
|
|
12122
|
-
|
|
11870
|
+
return ansi_styles_default[type][model](...arguments_);
|
|
11871
|
+
};
|
|
11872
|
+
var usedModels = ["rgb", "hex", "ansi256"];
|
|
11873
|
+
for (const model of usedModels) {
|
|
11874
|
+
styles2[model] = {
|
|
11875
|
+
get() {
|
|
11876
|
+
const { level } = this;
|
|
11877
|
+
return function(...arguments_) {
|
|
11878
|
+
const styler = createStyler(getModelAnsi(model, levelMapping[level], "color", ...arguments_), ansi_styles_default.color.close, this[STYLER]);
|
|
11879
|
+
return createBuilder(this, styler, this[IS_EMPTY]);
|
|
11880
|
+
};
|
|
12123
11881
|
}
|
|
12124
|
-
|
|
12125
|
-
|
|
12126
|
-
|
|
12127
|
-
|
|
12128
|
-
|
|
11882
|
+
};
|
|
11883
|
+
const bgModel = "bg" + model[0].toUpperCase() + model.slice(1);
|
|
11884
|
+
styles2[bgModel] = {
|
|
11885
|
+
get() {
|
|
11886
|
+
const { level } = this;
|
|
11887
|
+
return function(...arguments_) {
|
|
11888
|
+
const styler = createStyler(getModelAnsi(model, levelMapping[level], "bgColor", ...arguments_), ansi_styles_default.bgColor.close, this[STYLER]);
|
|
11889
|
+
return createBuilder(this, styler, this[IS_EMPTY]);
|
|
11890
|
+
};
|
|
12129
11891
|
}
|
|
12130
|
-
|
|
12131
|
-
|
|
12132
|
-
|
|
12133
|
-
|
|
12134
|
-
|
|
12135
|
-
|
|
12136
|
-
|
|
12137
|
-
|
|
12138
|
-
|
|
12139
|
-
|
|
12140
|
-
|
|
12141
|
-
if (env2.TERM === "xterm-kitty") {
|
|
12142
|
-
return 3;
|
|
12143
|
-
}
|
|
12144
|
-
if (env2.TERM === "xterm-ghostty") {
|
|
12145
|
-
return 3;
|
|
12146
|
-
}
|
|
12147
|
-
if (env2.TERM === "wezterm") {
|
|
12148
|
-
return 3;
|
|
12149
|
-
}
|
|
12150
|
-
if ("TERM_PROGRAM" in env2) {
|
|
12151
|
-
const version2 = Number.parseInt((env2.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
12152
|
-
switch (env2.TERM_PROGRAM) {
|
|
12153
|
-
case "iTerm.app": {
|
|
12154
|
-
return version2 >= 3 ? 3 : 2;
|
|
12155
|
-
}
|
|
12156
|
-
case "Apple_Terminal": {
|
|
12157
|
-
return 2;
|
|
12158
|
-
}
|
|
12159
|
-
}
|
|
12160
|
-
}
|
|
12161
|
-
if (/-256(color)?$/i.test(env2.TERM)) {
|
|
12162
|
-
return 2;
|
|
12163
|
-
}
|
|
12164
|
-
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env2.TERM)) {
|
|
12165
|
-
return 1;
|
|
12166
|
-
}
|
|
12167
|
-
if ("COLORTERM" in env2) {
|
|
12168
|
-
return 1;
|
|
12169
|
-
}
|
|
12170
|
-
return min;
|
|
12171
|
-
}
|
|
12172
|
-
function createSupportsColor(stream, options = {}) {
|
|
12173
|
-
const level = _supportsColor(stream, {
|
|
12174
|
-
streamIsTTY: stream && stream.isTTY,
|
|
12175
|
-
...options
|
|
12176
|
-
});
|
|
12177
|
-
return translateLevel(level);
|
|
12178
|
-
}
|
|
12179
|
-
var supportsColor = {
|
|
12180
|
-
stdout: createSupportsColor({ isTTY: tty2.isatty(1) }),
|
|
12181
|
-
stderr: createSupportsColor({ isTTY: tty2.isatty(2) })
|
|
12182
|
-
};
|
|
12183
|
-
var supports_color_default = supportsColor;
|
|
12184
|
-
|
|
12185
|
-
// ../../node_modules/chalk/source/utilities.js
|
|
12186
|
-
function stringReplaceAll(string, substring, replacer) {
|
|
12187
|
-
let index = string.indexOf(substring);
|
|
12188
|
-
if (index === -1) {
|
|
12189
|
-
return string;
|
|
12190
|
-
}
|
|
12191
|
-
const substringLength = substring.length;
|
|
12192
|
-
let endIndex = 0;
|
|
12193
|
-
let returnValue = "";
|
|
12194
|
-
do {
|
|
12195
|
-
returnValue += string.slice(endIndex, index) + substring + replacer;
|
|
12196
|
-
endIndex = index + substringLength;
|
|
12197
|
-
index = string.indexOf(substring, endIndex);
|
|
12198
|
-
} while (index !== -1);
|
|
12199
|
-
returnValue += string.slice(endIndex);
|
|
12200
|
-
return returnValue;
|
|
12201
|
-
}
|
|
12202
|
-
function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
|
|
12203
|
-
let endIndex = 0;
|
|
12204
|
-
let returnValue = "";
|
|
12205
|
-
do {
|
|
12206
|
-
const gotCR = string[index - 1] === "\r";
|
|
12207
|
-
returnValue += string.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? `\r
|
|
12208
|
-
` : `
|
|
12209
|
-
`) + postfix;
|
|
12210
|
-
endIndex = index + 1;
|
|
12211
|
-
index = string.indexOf(`
|
|
12212
|
-
`, endIndex);
|
|
12213
|
-
} while (index !== -1);
|
|
12214
|
-
returnValue += string.slice(endIndex);
|
|
12215
|
-
return returnValue;
|
|
12216
|
-
}
|
|
12217
|
-
|
|
12218
|
-
// ../../node_modules/chalk/source/index.js
|
|
12219
|
-
var { stdout: stdoutColor, stderr: stderrColor } = supports_color_default;
|
|
12220
|
-
var GENERATOR = Symbol("GENERATOR");
|
|
12221
|
-
var STYLER = Symbol("STYLER");
|
|
12222
|
-
var IS_EMPTY = Symbol("IS_EMPTY");
|
|
12223
|
-
var levelMapping = [
|
|
12224
|
-
"ansi",
|
|
12225
|
-
"ansi",
|
|
12226
|
-
"ansi256",
|
|
12227
|
-
"ansi16m"
|
|
12228
|
-
];
|
|
12229
|
-
var styles2 = Object.create(null);
|
|
12230
|
-
var applyOptions = (object, options = {}) => {
|
|
12231
|
-
if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
|
|
12232
|
-
throw new Error("The `level` option should be an integer from 0 to 3");
|
|
12233
|
-
}
|
|
12234
|
-
const colorLevel = stdoutColor ? stdoutColor.level : 0;
|
|
12235
|
-
object.level = options.level === undefined ? colorLevel : options.level;
|
|
12236
|
-
};
|
|
12237
|
-
var chalkFactory = (options) => {
|
|
12238
|
-
const chalk = (...strings) => strings.join(" ");
|
|
12239
|
-
applyOptions(chalk, options);
|
|
12240
|
-
Object.setPrototypeOf(chalk, createChalk.prototype);
|
|
12241
|
-
return chalk;
|
|
12242
|
-
};
|
|
12243
|
-
function createChalk(options) {
|
|
12244
|
-
return chalkFactory(options);
|
|
12245
|
-
}
|
|
12246
|
-
Object.setPrototypeOf(createChalk.prototype, Function.prototype);
|
|
12247
|
-
for (const [styleName, style] of Object.entries(ansi_styles_default)) {
|
|
12248
|
-
styles2[styleName] = {
|
|
12249
|
-
get() {
|
|
12250
|
-
const builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);
|
|
12251
|
-
Object.defineProperty(this, styleName, { value: builder });
|
|
12252
|
-
return builder;
|
|
12253
|
-
}
|
|
12254
|
-
};
|
|
12255
|
-
}
|
|
12256
|
-
styles2.visible = {
|
|
12257
|
-
get() {
|
|
12258
|
-
const builder = createBuilder(this, this[STYLER], true);
|
|
12259
|
-
Object.defineProperty(this, "visible", { value: builder });
|
|
12260
|
-
return builder;
|
|
12261
|
-
}
|
|
12262
|
-
};
|
|
12263
|
-
var getModelAnsi = (model, level, type, ...arguments_) => {
|
|
12264
|
-
if (model === "rgb") {
|
|
12265
|
-
if (level === "ansi16m") {
|
|
12266
|
-
return ansi_styles_default[type].ansi16m(...arguments_);
|
|
12267
|
-
}
|
|
12268
|
-
if (level === "ansi256") {
|
|
12269
|
-
return ansi_styles_default[type].ansi256(ansi_styles_default.rgbToAnsi256(...arguments_));
|
|
12270
|
-
}
|
|
12271
|
-
return ansi_styles_default[type].ansi(ansi_styles_default.rgbToAnsi(...arguments_));
|
|
12272
|
-
}
|
|
12273
|
-
if (model === "hex") {
|
|
12274
|
-
return getModelAnsi("rgb", level, type, ...ansi_styles_default.hexToRgb(...arguments_));
|
|
12275
|
-
}
|
|
12276
|
-
return ansi_styles_default[type][model](...arguments_);
|
|
12277
|
-
};
|
|
12278
|
-
var usedModels = ["rgb", "hex", "ansi256"];
|
|
12279
|
-
for (const model of usedModels) {
|
|
12280
|
-
styles2[model] = {
|
|
12281
|
-
get() {
|
|
12282
|
-
const { level } = this;
|
|
12283
|
-
return function(...arguments_) {
|
|
12284
|
-
const styler = createStyler(getModelAnsi(model, levelMapping[level], "color", ...arguments_), ansi_styles_default.color.close, this[STYLER]);
|
|
12285
|
-
return createBuilder(this, styler, this[IS_EMPTY]);
|
|
12286
|
-
};
|
|
12287
|
-
}
|
|
12288
|
-
};
|
|
12289
|
-
const bgModel = "bg" + model[0].toUpperCase() + model.slice(1);
|
|
12290
|
-
styles2[bgModel] = {
|
|
12291
|
-
get() {
|
|
12292
|
-
const { level } = this;
|
|
12293
|
-
return function(...arguments_) {
|
|
12294
|
-
const styler = createStyler(getModelAnsi(model, levelMapping[level], "bgColor", ...arguments_), ansi_styles_default.bgColor.close, this[STYLER]);
|
|
12295
|
-
return createBuilder(this, styler, this[IS_EMPTY]);
|
|
12296
|
-
};
|
|
12297
|
-
}
|
|
12298
|
-
};
|
|
12299
|
-
}
|
|
12300
|
-
var proto = Object.defineProperties(() => {}, {
|
|
12301
|
-
...styles2,
|
|
12302
|
-
level: {
|
|
12303
|
-
enumerable: true,
|
|
12304
|
-
get() {
|
|
12305
|
-
return this[GENERATOR].level;
|
|
12306
|
-
},
|
|
12307
|
-
set(level) {
|
|
12308
|
-
this[GENERATOR].level = level;
|
|
11892
|
+
};
|
|
11893
|
+
}
|
|
11894
|
+
var proto = Object.defineProperties(() => {}, {
|
|
11895
|
+
...styles2,
|
|
11896
|
+
level: {
|
|
11897
|
+
enumerable: true,
|
|
11898
|
+
get() {
|
|
11899
|
+
return this[GENERATOR].level;
|
|
11900
|
+
},
|
|
11901
|
+
set(level) {
|
|
11902
|
+
this[GENERATOR].level = level;
|
|
12309
11903
|
}
|
|
12310
11904
|
}
|
|
12311
11905
|
});
|
|
@@ -14524,748 +14118,1662 @@ function validate2(codePoint) {
|
|
|
14524
14118
|
if (!Number.isSafeInteger(codePoint)) {
|
|
14525
14119
|
throw new TypeError(`Expected a code point, got \`${typeof codePoint}\`.`);
|
|
14526
14120
|
}
|
|
14527
|
-
}
|
|
14528
|
-
function eastAsianWidth2(codePoint, { ambiguousAsWide = false } = {}) {
|
|
14529
|
-
validate2(codePoint);
|
|
14530
|
-
if (isFullWidth2(codePoint) || isWide2(codePoint) || ambiguousAsWide && isAmbiguous2(codePoint)) {
|
|
14531
|
-
return 2;
|
|
14121
|
+
}
|
|
14122
|
+
function eastAsianWidth2(codePoint, { ambiguousAsWide = false } = {}) {
|
|
14123
|
+
validate2(codePoint);
|
|
14124
|
+
if (isFullWidth2(codePoint) || isWide2(codePoint) || ambiguousAsWide && isAmbiguous2(codePoint)) {
|
|
14125
|
+
return 2;
|
|
14126
|
+
}
|
|
14127
|
+
return 1;
|
|
14128
|
+
}
|
|
14129
|
+
|
|
14130
|
+
// ../../node_modules/string-width/index.js
|
|
14131
|
+
var segmenter2 = new Intl.Segmenter;
|
|
14132
|
+
var zeroWidthClusterRegex = /^(?:\p{Default_Ignorable_Code_Point}|\p{Control}|\p{Format}|\p{Mark}|\p{Surrogate})+$/v;
|
|
14133
|
+
var leadingNonPrintingRegex = /^[\p{Default_Ignorable_Code_Point}\p{Control}\p{Format}\p{Mark}\p{Surrogate}]+/v;
|
|
14134
|
+
var rgiEmojiRegex = /^\p{RGI_Emoji}$/v;
|
|
14135
|
+
function baseVisible(segment) {
|
|
14136
|
+
return segment.replace(leadingNonPrintingRegex, "");
|
|
14137
|
+
}
|
|
14138
|
+
function isZeroWidthCluster(segment) {
|
|
14139
|
+
return zeroWidthClusterRegex.test(segment);
|
|
14140
|
+
}
|
|
14141
|
+
function trailingHalfwidthWidth(segment, eastAsianWidthOptions) {
|
|
14142
|
+
let extra = 0;
|
|
14143
|
+
if (segment.length > 1) {
|
|
14144
|
+
for (const char of segment.slice(1)) {
|
|
14145
|
+
if (char >= "" && char <= "") {
|
|
14146
|
+
extra += eastAsianWidth2(char.codePointAt(0), eastAsianWidthOptions);
|
|
14147
|
+
}
|
|
14148
|
+
}
|
|
14149
|
+
}
|
|
14150
|
+
return extra;
|
|
14151
|
+
}
|
|
14152
|
+
function stringWidth2(input, options = {}) {
|
|
14153
|
+
if (typeof input !== "string" || input.length === 0) {
|
|
14154
|
+
return 0;
|
|
14155
|
+
}
|
|
14156
|
+
const {
|
|
14157
|
+
ambiguousIsNarrow = true,
|
|
14158
|
+
countAnsiEscapeCodes = false
|
|
14159
|
+
} = options;
|
|
14160
|
+
let string = input;
|
|
14161
|
+
if (!countAnsiEscapeCodes) {
|
|
14162
|
+
string = stripAnsi3(string);
|
|
14163
|
+
}
|
|
14164
|
+
if (string.length === 0) {
|
|
14165
|
+
return 0;
|
|
14166
|
+
}
|
|
14167
|
+
let width = 0;
|
|
14168
|
+
const eastAsianWidthOptions = { ambiguousAsWide: !ambiguousIsNarrow };
|
|
14169
|
+
for (const { segment } of segmenter2.segment(string)) {
|
|
14170
|
+
if (isZeroWidthCluster(segment)) {
|
|
14171
|
+
continue;
|
|
14172
|
+
}
|
|
14173
|
+
if (rgiEmojiRegex.test(segment)) {
|
|
14174
|
+
width += 2;
|
|
14175
|
+
continue;
|
|
14176
|
+
}
|
|
14177
|
+
const codePoint = baseVisible(segment).codePointAt(0);
|
|
14178
|
+
width += eastAsianWidth2(codePoint, eastAsianWidthOptions);
|
|
14179
|
+
width += trailingHalfwidthWidth(segment, eastAsianWidthOptions);
|
|
14180
|
+
}
|
|
14181
|
+
return width;
|
|
14182
|
+
}
|
|
14183
|
+
|
|
14184
|
+
// ../../node_modules/is-interactive/index.js
|
|
14185
|
+
function isInteractive({ stream = process.stdout } = {}) {
|
|
14186
|
+
return Boolean(stream && stream.isTTY && process.env.TERM !== "dumb" && !("CI" in process.env));
|
|
14187
|
+
}
|
|
14188
|
+
|
|
14189
|
+
// ../../node_modules/stdin-discarder/index.js
|
|
14190
|
+
import process7 from "node:process";
|
|
14191
|
+
var ASCII_ETX_CODE = 3;
|
|
14192
|
+
|
|
14193
|
+
class StdinDiscarder {
|
|
14194
|
+
#activeCount = 0;
|
|
14195
|
+
#stdin;
|
|
14196
|
+
#stdinWasPaused = false;
|
|
14197
|
+
#stdinWasRaw = false;
|
|
14198
|
+
#handleInputBound = (chunk) => {
|
|
14199
|
+
if (!chunk?.length) {
|
|
14200
|
+
return;
|
|
14201
|
+
}
|
|
14202
|
+
const code2 = typeof chunk === "string" ? chunk.codePointAt(0) : chunk[0];
|
|
14203
|
+
if (code2 === ASCII_ETX_CODE) {
|
|
14204
|
+
if (process7.listenerCount("SIGINT") > 0) {
|
|
14205
|
+
process7.emit("SIGINT");
|
|
14206
|
+
} else {
|
|
14207
|
+
process7.kill(process7.pid, "SIGINT");
|
|
14208
|
+
}
|
|
14209
|
+
}
|
|
14210
|
+
};
|
|
14211
|
+
start() {
|
|
14212
|
+
this.#activeCount++;
|
|
14213
|
+
if (this.#activeCount === 1) {
|
|
14214
|
+
this.#realStart();
|
|
14215
|
+
}
|
|
14216
|
+
}
|
|
14217
|
+
stop() {
|
|
14218
|
+
if (this.#activeCount === 0) {
|
|
14219
|
+
return;
|
|
14220
|
+
}
|
|
14221
|
+
if (--this.#activeCount === 0) {
|
|
14222
|
+
this.#realStop();
|
|
14223
|
+
}
|
|
14224
|
+
}
|
|
14225
|
+
#realStart() {
|
|
14226
|
+
const { stdin: stdin2 } = process7;
|
|
14227
|
+
if (process7.platform === "win32" || !stdin2?.isTTY || typeof stdin2.setRawMode !== "function") {
|
|
14228
|
+
this.#stdin = undefined;
|
|
14229
|
+
return;
|
|
14230
|
+
}
|
|
14231
|
+
this.#stdin = stdin2;
|
|
14232
|
+
this.#stdinWasPaused = stdin2.isPaused();
|
|
14233
|
+
this.#stdinWasRaw = Boolean(stdin2.isRaw);
|
|
14234
|
+
stdin2.setRawMode(true);
|
|
14235
|
+
stdin2.prependListener("data", this.#handleInputBound);
|
|
14236
|
+
if (this.#stdinWasPaused) {
|
|
14237
|
+
stdin2.resume();
|
|
14238
|
+
}
|
|
14239
|
+
}
|
|
14240
|
+
#realStop() {
|
|
14241
|
+
if (!this.#stdin) {
|
|
14242
|
+
return;
|
|
14243
|
+
}
|
|
14244
|
+
const stdin2 = this.#stdin;
|
|
14245
|
+
stdin2.off("data", this.#handleInputBound);
|
|
14246
|
+
if (stdin2.isTTY) {
|
|
14247
|
+
stdin2.setRawMode?.(this.#stdinWasRaw);
|
|
14248
|
+
}
|
|
14249
|
+
if (this.#stdinWasPaused) {
|
|
14250
|
+
stdin2.pause();
|
|
14251
|
+
}
|
|
14252
|
+
this.#stdin = undefined;
|
|
14253
|
+
this.#stdinWasPaused = false;
|
|
14254
|
+
this.#stdinWasRaw = false;
|
|
14255
|
+
}
|
|
14256
|
+
}
|
|
14257
|
+
var stdinDiscarder = new StdinDiscarder;
|
|
14258
|
+
var stdin_discarder_default = Object.freeze(stdinDiscarder);
|
|
14259
|
+
|
|
14260
|
+
// ../../node_modules/ora/index.js
|
|
14261
|
+
var RENDER_DEFERRAL_TIMEOUT = 200;
|
|
14262
|
+
var SYNCHRONIZED_OUTPUT_ENABLE = "\x1B[?2026h";
|
|
14263
|
+
var SYNCHRONIZED_OUTPUT_DISABLE = "\x1B[?2026l";
|
|
14264
|
+
var activeHooksPerStream = new Map;
|
|
14265
|
+
|
|
14266
|
+
class Ora {
|
|
14267
|
+
#linesToClear = 0;
|
|
14268
|
+
#frameIndex = -1;
|
|
14269
|
+
#lastFrameTime = 0;
|
|
14270
|
+
#options;
|
|
14271
|
+
#spinner;
|
|
14272
|
+
#stream;
|
|
14273
|
+
#id;
|
|
14274
|
+
#hookedStreams = new Map;
|
|
14275
|
+
#isInternalWrite = false;
|
|
14276
|
+
#drainHandler;
|
|
14277
|
+
#deferRenderTimer;
|
|
14278
|
+
#isDiscardingStdin = false;
|
|
14279
|
+
color;
|
|
14280
|
+
#internalWrite(fn) {
|
|
14281
|
+
this.#isInternalWrite = true;
|
|
14282
|
+
try {
|
|
14283
|
+
return fn();
|
|
14284
|
+
} finally {
|
|
14285
|
+
this.#isInternalWrite = false;
|
|
14286
|
+
}
|
|
14287
|
+
}
|
|
14288
|
+
#tryRender() {
|
|
14289
|
+
if (this.isSpinning) {
|
|
14290
|
+
this.render();
|
|
14291
|
+
}
|
|
14292
|
+
}
|
|
14293
|
+
#stringifyChunk(chunk, encoding) {
|
|
14294
|
+
if (chunk === undefined || chunk === null) {
|
|
14295
|
+
return "";
|
|
14296
|
+
}
|
|
14297
|
+
if (typeof chunk === "string") {
|
|
14298
|
+
return chunk;
|
|
14299
|
+
}
|
|
14300
|
+
if (Buffer.isBuffer(chunk) || ArrayBuffer.isView(chunk)) {
|
|
14301
|
+
const normalizedEncoding = typeof encoding === "string" && encoding && encoding !== "buffer" ? encoding : "utf8";
|
|
14302
|
+
return Buffer.from(chunk).toString(normalizedEncoding);
|
|
14303
|
+
}
|
|
14304
|
+
return String(chunk);
|
|
14305
|
+
}
|
|
14306
|
+
#chunkTerminatesLine(chunkString) {
|
|
14307
|
+
if (!chunkString) {
|
|
14308
|
+
return false;
|
|
14309
|
+
}
|
|
14310
|
+
const lastCharacter = chunkString.at(-1);
|
|
14311
|
+
return lastCharacter === `
|
|
14312
|
+
` || lastCharacter === "\r";
|
|
14313
|
+
}
|
|
14314
|
+
#scheduleRenderDeferral() {
|
|
14315
|
+
if (this.#deferRenderTimer) {
|
|
14316
|
+
return;
|
|
14317
|
+
}
|
|
14318
|
+
this.#deferRenderTimer = setTimeout(() => {
|
|
14319
|
+
this.#deferRenderTimer = undefined;
|
|
14320
|
+
if (this.isSpinning) {
|
|
14321
|
+
this.#tryRender();
|
|
14322
|
+
}
|
|
14323
|
+
}, RENDER_DEFERRAL_TIMEOUT);
|
|
14324
|
+
if (typeof this.#deferRenderTimer?.unref === "function") {
|
|
14325
|
+
this.#deferRenderTimer.unref();
|
|
14326
|
+
}
|
|
14327
|
+
}
|
|
14328
|
+
#clearRenderDeferral() {
|
|
14329
|
+
if (this.#deferRenderTimer) {
|
|
14330
|
+
clearTimeout(this.#deferRenderTimer);
|
|
14331
|
+
this.#deferRenderTimer = undefined;
|
|
14332
|
+
}
|
|
14333
|
+
}
|
|
14334
|
+
#buildOutputLine(symbol, text, prefixText, suffixText) {
|
|
14335
|
+
const fullPrefixText = this.#getFullPrefixText(prefixText, " ");
|
|
14336
|
+
const separatorText = symbol ? " " : "";
|
|
14337
|
+
const fullText = typeof text === "string" ? separatorText + text : "";
|
|
14338
|
+
const fullSuffixText = this.#getFullSuffixText(suffixText, " ");
|
|
14339
|
+
return fullPrefixText + symbol + fullText + fullSuffixText;
|
|
14340
|
+
}
|
|
14341
|
+
constructor(options) {
|
|
14342
|
+
if (typeof options === "string") {
|
|
14343
|
+
options = {
|
|
14344
|
+
text: options
|
|
14345
|
+
};
|
|
14346
|
+
}
|
|
14347
|
+
this.#options = {
|
|
14348
|
+
color: "cyan",
|
|
14349
|
+
stream: process8.stderr,
|
|
14350
|
+
discardStdin: true,
|
|
14351
|
+
hideCursor: true,
|
|
14352
|
+
...options
|
|
14353
|
+
};
|
|
14354
|
+
this.color = this.#options.color;
|
|
14355
|
+
this.#stream = this.#options.stream;
|
|
14356
|
+
if (typeof this.#options.isEnabled !== "boolean") {
|
|
14357
|
+
this.#options.isEnabled = isInteractive({ stream: this.#stream });
|
|
14358
|
+
}
|
|
14359
|
+
if (typeof this.#options.isSilent !== "boolean") {
|
|
14360
|
+
this.#options.isSilent = false;
|
|
14361
|
+
}
|
|
14362
|
+
const userInterval = this.#options.interval;
|
|
14363
|
+
this.spinner = this.#options.spinner;
|
|
14364
|
+
this.#options.interval = userInterval;
|
|
14365
|
+
this.text = this.#options.text;
|
|
14366
|
+
this.prefixText = this.#options.prefixText;
|
|
14367
|
+
this.suffixText = this.#options.suffixText;
|
|
14368
|
+
this.indent = this.#options.indent;
|
|
14369
|
+
if (process8.env.NODE_ENV === "test") {
|
|
14370
|
+
this._stream = this.#stream;
|
|
14371
|
+
this._isEnabled = this.#options.isEnabled;
|
|
14372
|
+
Object.defineProperty(this, "_linesToClear", {
|
|
14373
|
+
get() {
|
|
14374
|
+
return this.#linesToClear;
|
|
14375
|
+
},
|
|
14376
|
+
set(newValue) {
|
|
14377
|
+
this.#linesToClear = newValue;
|
|
14378
|
+
}
|
|
14379
|
+
});
|
|
14380
|
+
Object.defineProperty(this, "_frameIndex", {
|
|
14381
|
+
get() {
|
|
14382
|
+
return this.#frameIndex;
|
|
14383
|
+
}
|
|
14384
|
+
});
|
|
14385
|
+
Object.defineProperty(this, "_lineCount", {
|
|
14386
|
+
get() {
|
|
14387
|
+
const columns = this.#stream.columns ?? 80;
|
|
14388
|
+
const prefixText = typeof this.#options.prefixText === "function" ? "" : this.#options.prefixText;
|
|
14389
|
+
const suffixText = typeof this.#options.suffixText === "function" ? "" : this.#options.suffixText;
|
|
14390
|
+
const fullPrefixText = typeof prefixText === "string" && prefixText !== "" ? prefixText + " " : "";
|
|
14391
|
+
const fullSuffixText = typeof suffixText === "string" && suffixText !== "" ? " " + suffixText : "";
|
|
14392
|
+
const spinnerChar = "-";
|
|
14393
|
+
const fullText = " ".repeat(this.#options.indent) + fullPrefixText + spinnerChar + (typeof this.#options.text === "string" ? " " + this.#options.text : "") + fullSuffixText;
|
|
14394
|
+
return this.#computeLineCountFrom(fullText, columns);
|
|
14395
|
+
}
|
|
14396
|
+
});
|
|
14397
|
+
}
|
|
14398
|
+
}
|
|
14399
|
+
get indent() {
|
|
14400
|
+
return this.#options.indent;
|
|
14401
|
+
}
|
|
14402
|
+
set indent(indent = 0) {
|
|
14403
|
+
if (!(indent >= 0 && Number.isInteger(indent))) {
|
|
14404
|
+
throw new Error("The `indent` option must be an integer from 0 and up");
|
|
14405
|
+
}
|
|
14406
|
+
this.#options.indent = indent;
|
|
14407
|
+
}
|
|
14408
|
+
get interval() {
|
|
14409
|
+
return this.#options.interval ?? this.#spinner.interval ?? 100;
|
|
14410
|
+
}
|
|
14411
|
+
get spinner() {
|
|
14412
|
+
return this.#spinner;
|
|
14413
|
+
}
|
|
14414
|
+
set spinner(spinner) {
|
|
14415
|
+
this.#frameIndex = -1;
|
|
14416
|
+
this.#options.interval = undefined;
|
|
14417
|
+
if (typeof spinner === "object") {
|
|
14418
|
+
if (!Array.isArray(spinner.frames) || spinner.frames.length === 0 || spinner.frames.some((frame) => typeof frame !== "string")) {
|
|
14419
|
+
throw new Error("The given spinner must have a non-empty `frames` array of strings");
|
|
14420
|
+
}
|
|
14421
|
+
if (spinner.interval !== undefined && !(Number.isInteger(spinner.interval) && spinner.interval > 0)) {
|
|
14422
|
+
throw new Error("`spinner.interval` must be a positive integer if provided");
|
|
14423
|
+
}
|
|
14424
|
+
this.#spinner = spinner;
|
|
14425
|
+
} else if (!isUnicodeSupported2()) {
|
|
14426
|
+
this.#spinner = cli_spinners_default.line;
|
|
14427
|
+
} else if (spinner === undefined) {
|
|
14428
|
+
this.#spinner = cli_spinners_default.dots;
|
|
14429
|
+
} else if (spinner !== "default" && cli_spinners_default[spinner]) {
|
|
14430
|
+
this.#spinner = cli_spinners_default[spinner];
|
|
14431
|
+
} else {
|
|
14432
|
+
throw new Error(`There is no built-in spinner named '${spinner}'. See https://github.com/sindresorhus/cli-spinners/blob/main/spinners.json for a full list.`);
|
|
14433
|
+
}
|
|
14434
|
+
}
|
|
14435
|
+
get text() {
|
|
14436
|
+
return this.#options.text;
|
|
14437
|
+
}
|
|
14438
|
+
set text(value = "") {
|
|
14439
|
+
this.#options.text = value;
|
|
14440
|
+
}
|
|
14441
|
+
get prefixText() {
|
|
14442
|
+
return this.#options.prefixText;
|
|
14532
14443
|
}
|
|
14533
|
-
|
|
14534
|
-
|
|
14535
|
-
|
|
14536
|
-
|
|
14537
|
-
|
|
14538
|
-
|
|
14539
|
-
|
|
14540
|
-
|
|
14541
|
-
|
|
14542
|
-
|
|
14543
|
-
|
|
14544
|
-
|
|
14545
|
-
|
|
14546
|
-
|
|
14547
|
-
|
|
14548
|
-
|
|
14549
|
-
if (segment.length > 1) {
|
|
14550
|
-
for (const char of segment.slice(1)) {
|
|
14551
|
-
if (char >= "" && char <= "") {
|
|
14552
|
-
extra += eastAsianWidth2(char.codePointAt(0), eastAsianWidthOptions);
|
|
14553
|
-
}
|
|
14444
|
+
set prefixText(value = "") {
|
|
14445
|
+
this.#options.prefixText = value;
|
|
14446
|
+
}
|
|
14447
|
+
get suffixText() {
|
|
14448
|
+
return this.#options.suffixText;
|
|
14449
|
+
}
|
|
14450
|
+
set suffixText(value = "") {
|
|
14451
|
+
this.#options.suffixText = value;
|
|
14452
|
+
}
|
|
14453
|
+
get isSpinning() {
|
|
14454
|
+
return this.#id !== undefined;
|
|
14455
|
+
}
|
|
14456
|
+
#formatAffix(value, separator, placeBefore = false) {
|
|
14457
|
+
const resolved = typeof value === "function" ? value() : value;
|
|
14458
|
+
if (typeof resolved === "string" && resolved !== "") {
|
|
14459
|
+
return placeBefore ? separator + resolved : resolved + separator;
|
|
14554
14460
|
}
|
|
14461
|
+
return "";
|
|
14555
14462
|
}
|
|
14556
|
-
|
|
14557
|
-
|
|
14558
|
-
function stringWidth2(input, options = {}) {
|
|
14559
|
-
if (typeof input !== "string" || input.length === 0) {
|
|
14560
|
-
return 0;
|
|
14463
|
+
#getFullPrefixText(prefixText = this.#options.prefixText, postfix = " ") {
|
|
14464
|
+
return this.#formatAffix(prefixText, postfix, false);
|
|
14561
14465
|
}
|
|
14562
|
-
|
|
14563
|
-
|
|
14564
|
-
countAnsiEscapeCodes = false
|
|
14565
|
-
} = options;
|
|
14566
|
-
let string = input;
|
|
14567
|
-
if (!countAnsiEscapeCodes) {
|
|
14568
|
-
string = stripAnsi3(string);
|
|
14466
|
+
#getFullSuffixText(suffixText = this.#options.suffixText, prefix = " ") {
|
|
14467
|
+
return this.#formatAffix(suffixText, prefix, true);
|
|
14569
14468
|
}
|
|
14570
|
-
|
|
14571
|
-
|
|
14469
|
+
#computeLineCountFrom(text, columns) {
|
|
14470
|
+
let count = 0;
|
|
14471
|
+
for (const line of stripVTControlCharacters(text).split(`
|
|
14472
|
+
`)) {
|
|
14473
|
+
count += Math.max(1, Math.ceil(stringWidth2(line) / columns));
|
|
14474
|
+
}
|
|
14475
|
+
return count;
|
|
14572
14476
|
}
|
|
14573
|
-
|
|
14574
|
-
|
|
14575
|
-
|
|
14576
|
-
|
|
14577
|
-
|
|
14477
|
+
get isEnabled() {
|
|
14478
|
+
return this.#options.isEnabled && !this.#options.isSilent;
|
|
14479
|
+
}
|
|
14480
|
+
set isEnabled(value) {
|
|
14481
|
+
if (typeof value !== "boolean") {
|
|
14482
|
+
throw new TypeError("The `isEnabled` option must be a boolean");
|
|
14578
14483
|
}
|
|
14579
|
-
|
|
14580
|
-
|
|
14581
|
-
|
|
14484
|
+
this.#options.isEnabled = value;
|
|
14485
|
+
}
|
|
14486
|
+
get isSilent() {
|
|
14487
|
+
return this.#options.isSilent;
|
|
14488
|
+
}
|
|
14489
|
+
set isSilent(value) {
|
|
14490
|
+
if (typeof value !== "boolean") {
|
|
14491
|
+
throw new TypeError("The `isSilent` option must be a boolean");
|
|
14582
14492
|
}
|
|
14583
|
-
|
|
14584
|
-
width += eastAsianWidth2(codePoint, eastAsianWidthOptions);
|
|
14585
|
-
width += trailingHalfwidthWidth(segment, eastAsianWidthOptions);
|
|
14493
|
+
this.#options.isSilent = value;
|
|
14586
14494
|
}
|
|
14587
|
-
|
|
14588
|
-
|
|
14589
|
-
|
|
14590
|
-
|
|
14591
|
-
|
|
14592
|
-
return Boolean(stream && stream.isTTY && process.env.TERM !== "dumb" && !("CI" in process.env));
|
|
14593
|
-
}
|
|
14594
|
-
|
|
14595
|
-
// ../../node_modules/stdin-discarder/index.js
|
|
14596
|
-
import process7 from "node:process";
|
|
14597
|
-
var ASCII_ETX_CODE = 3;
|
|
14598
|
-
|
|
14599
|
-
class StdinDiscarder {
|
|
14600
|
-
#activeCount = 0;
|
|
14601
|
-
#stdin;
|
|
14602
|
-
#stdinWasPaused = false;
|
|
14603
|
-
#stdinWasRaw = false;
|
|
14604
|
-
#handleInputBound = (chunk) => {
|
|
14605
|
-
if (!chunk?.length) {
|
|
14606
|
-
return;
|
|
14495
|
+
frame() {
|
|
14496
|
+
const now = Date.now();
|
|
14497
|
+
if (this.#frameIndex === -1 || now - this.#lastFrameTime >= this.interval) {
|
|
14498
|
+
this.#frameIndex = (this.#frameIndex + 1) % this.#spinner.frames.length;
|
|
14499
|
+
this.#lastFrameTime = now;
|
|
14607
14500
|
}
|
|
14608
|
-
const
|
|
14609
|
-
|
|
14610
|
-
|
|
14611
|
-
|
|
14612
|
-
} else {
|
|
14613
|
-
process7.kill(process7.pid, "SIGINT");
|
|
14614
|
-
}
|
|
14501
|
+
const { frames } = this.#spinner;
|
|
14502
|
+
let frame = frames[this.#frameIndex];
|
|
14503
|
+
if (this.color) {
|
|
14504
|
+
frame = source_default[this.color](frame);
|
|
14615
14505
|
}
|
|
14616
|
-
|
|
14617
|
-
|
|
14618
|
-
this.#
|
|
14619
|
-
|
|
14620
|
-
|
|
14506
|
+
const fullPrefixText = this.#getFullPrefixText(this.#options.prefixText, " ");
|
|
14507
|
+
const fullText = typeof this.text === "string" ? " " + this.text : "";
|
|
14508
|
+
const fullSuffixText = this.#getFullSuffixText(this.#options.suffixText, " ");
|
|
14509
|
+
return fullPrefixText + frame + fullText + fullSuffixText;
|
|
14510
|
+
}
|
|
14511
|
+
clear() {
|
|
14512
|
+
if (!this.isEnabled || !this.#stream.isTTY) {
|
|
14513
|
+
return this;
|
|
14621
14514
|
}
|
|
14515
|
+
this.#internalWrite(() => {
|
|
14516
|
+
this.#stream.cursorTo(0);
|
|
14517
|
+
for (let index = 0;index < this.#linesToClear; index++) {
|
|
14518
|
+
if (index > 0) {
|
|
14519
|
+
this.#stream.moveCursor(0, -1);
|
|
14520
|
+
}
|
|
14521
|
+
this.#stream.clearLine(1);
|
|
14522
|
+
}
|
|
14523
|
+
if (this.#options.indent) {
|
|
14524
|
+
this.#stream.cursorTo(this.#options.indent);
|
|
14525
|
+
}
|
|
14526
|
+
});
|
|
14527
|
+
this.#linesToClear = 0;
|
|
14528
|
+
return this;
|
|
14622
14529
|
}
|
|
14623
|
-
|
|
14624
|
-
if (this.#
|
|
14530
|
+
#hookStream(stream) {
|
|
14531
|
+
if (!stream || this.#hookedStreams.has(stream) || !stream.isTTY || typeof stream.write !== "function") {
|
|
14625
14532
|
return;
|
|
14626
14533
|
}
|
|
14627
|
-
if (
|
|
14628
|
-
|
|
14534
|
+
if (activeHooksPerStream.has(stream)) {
|
|
14535
|
+
console.warn("[ora] Multiple concurrent spinners detected. This may cause visual corruption. Use one spinner at a time.");
|
|
14629
14536
|
}
|
|
14537
|
+
const originalWrite = stream.write;
|
|
14538
|
+
this.#hookedStreams.set(stream, originalWrite);
|
|
14539
|
+
activeHooksPerStream.set(stream, this);
|
|
14540
|
+
stream.write = (chunk, encoding, callback) => this.#hookedWrite(stream, originalWrite, chunk, encoding, callback);
|
|
14630
14541
|
}
|
|
14631
|
-
#
|
|
14632
|
-
|
|
14633
|
-
if (process7.platform === "win32" || !stdin2?.isTTY || typeof stdin2.setRawMode !== "function") {
|
|
14634
|
-
this.#stdin = undefined;
|
|
14542
|
+
#installHook() {
|
|
14543
|
+
if (!this.isEnabled || this.#hookedStreams.size > 0) {
|
|
14635
14544
|
return;
|
|
14636
14545
|
}
|
|
14637
|
-
this.#
|
|
14638
|
-
|
|
14639
|
-
|
|
14640
|
-
stdin2.setRawMode(true);
|
|
14641
|
-
stdin2.prependListener("data", this.#handleInputBound);
|
|
14642
|
-
if (this.#stdinWasPaused) {
|
|
14643
|
-
stdin2.resume();
|
|
14546
|
+
const streamsToHook = new Set([this.#stream, process8.stdout, process8.stderr]);
|
|
14547
|
+
for (const stream of streamsToHook) {
|
|
14548
|
+
this.#hookStream(stream);
|
|
14644
14549
|
}
|
|
14645
14550
|
}
|
|
14646
|
-
#
|
|
14647
|
-
|
|
14648
|
-
|
|
14551
|
+
#uninstallHook() {
|
|
14552
|
+
for (const [stream, originalWrite] of this.#hookedStreams) {
|
|
14553
|
+
stream.write = originalWrite;
|
|
14554
|
+
if (activeHooksPerStream.get(stream) === this) {
|
|
14555
|
+
activeHooksPerStream.delete(stream);
|
|
14556
|
+
}
|
|
14649
14557
|
}
|
|
14650
|
-
|
|
14651
|
-
|
|
14652
|
-
|
|
14653
|
-
|
|
14558
|
+
this.#hookedStreams.clear();
|
|
14559
|
+
}
|
|
14560
|
+
#hookedWrite(stream, originalWrite, chunk, encoding, callback) {
|
|
14561
|
+
if (typeof encoding === "function") {
|
|
14562
|
+
callback = encoding;
|
|
14563
|
+
encoding = undefined;
|
|
14654
14564
|
}
|
|
14655
|
-
if (this.#
|
|
14656
|
-
|
|
14565
|
+
if (this.#isInternalWrite) {
|
|
14566
|
+
return originalWrite.call(stream, chunk, encoding, callback);
|
|
14657
14567
|
}
|
|
14658
|
-
this
|
|
14659
|
-
this.#
|
|
14660
|
-
|
|
14568
|
+
this.clear();
|
|
14569
|
+
const chunkString = this.#stringifyChunk(chunk, encoding);
|
|
14570
|
+
const chunkTerminatesLine = this.#chunkTerminatesLine(chunkString);
|
|
14571
|
+
const writeResult = originalWrite.call(stream, chunk, encoding, callback);
|
|
14572
|
+
if (chunkTerminatesLine) {
|
|
14573
|
+
this.#clearRenderDeferral();
|
|
14574
|
+
} else if (chunkString.length > 0) {
|
|
14575
|
+
this.#scheduleRenderDeferral();
|
|
14576
|
+
}
|
|
14577
|
+
if (this.isSpinning && !this.#deferRenderTimer) {
|
|
14578
|
+
this.render();
|
|
14579
|
+
}
|
|
14580
|
+
return writeResult;
|
|
14661
14581
|
}
|
|
14662
|
-
|
|
14663
|
-
|
|
14664
|
-
|
|
14665
|
-
|
|
14666
|
-
|
|
14667
|
-
|
|
14668
|
-
var SYNCHRONIZED_OUTPUT_ENABLE = "\x1B[?2026h";
|
|
14669
|
-
var SYNCHRONIZED_OUTPUT_DISABLE = "\x1B[?2026l";
|
|
14670
|
-
var activeHooksPerStream = new Map;
|
|
14671
|
-
|
|
14672
|
-
class Ora {
|
|
14673
|
-
#linesToClear = 0;
|
|
14674
|
-
#frameIndex = -1;
|
|
14675
|
-
#lastFrameTime = 0;
|
|
14676
|
-
#options;
|
|
14677
|
-
#spinner;
|
|
14678
|
-
#stream;
|
|
14679
|
-
#id;
|
|
14680
|
-
#hookedStreams = new Map;
|
|
14681
|
-
#isInternalWrite = false;
|
|
14682
|
-
#drainHandler;
|
|
14683
|
-
#deferRenderTimer;
|
|
14684
|
-
#isDiscardingStdin = false;
|
|
14685
|
-
color;
|
|
14686
|
-
#internalWrite(fn) {
|
|
14687
|
-
this.#isInternalWrite = true;
|
|
14582
|
+
render() {
|
|
14583
|
+
if (!this.isEnabled || this.#drainHandler || this.#deferRenderTimer) {
|
|
14584
|
+
return this;
|
|
14585
|
+
}
|
|
14586
|
+
const useSynchronizedOutput = this.#stream.isTTY;
|
|
14587
|
+
let shouldDisableSynchronizedOutput = false;
|
|
14688
14588
|
try {
|
|
14689
|
-
|
|
14589
|
+
if (useSynchronizedOutput) {
|
|
14590
|
+
this.#internalWrite(() => this.#stream.write(SYNCHRONIZED_OUTPUT_ENABLE));
|
|
14591
|
+
shouldDisableSynchronizedOutput = true;
|
|
14592
|
+
}
|
|
14593
|
+
this.clear();
|
|
14594
|
+
let frameContent = this.frame();
|
|
14595
|
+
const columns = this.#stream.columns ?? 80;
|
|
14596
|
+
const actualLineCount = this.#computeLineCountFrom(frameContent, columns);
|
|
14597
|
+
const consoleHeight = this.#stream.rows;
|
|
14598
|
+
if (consoleHeight && consoleHeight > 1 && actualLineCount > consoleHeight) {
|
|
14599
|
+
const lines = frameContent.split(`
|
|
14600
|
+
`);
|
|
14601
|
+
const maxLines = consoleHeight - 1;
|
|
14602
|
+
frameContent = [...lines.slice(0, maxLines), "... (content truncated to fit terminal)"].join(`
|
|
14603
|
+
`);
|
|
14604
|
+
}
|
|
14605
|
+
const canContinue = this.#internalWrite(() => this.#stream.write(frameContent));
|
|
14606
|
+
if (canContinue === false && this.#stream.isTTY) {
|
|
14607
|
+
this.#drainHandler = () => {
|
|
14608
|
+
this.#drainHandler = undefined;
|
|
14609
|
+
this.#tryRender();
|
|
14610
|
+
};
|
|
14611
|
+
this.#stream.once("drain", this.#drainHandler);
|
|
14612
|
+
}
|
|
14613
|
+
this.#linesToClear = this.#computeLineCountFrom(frameContent, columns);
|
|
14690
14614
|
} finally {
|
|
14691
|
-
|
|
14615
|
+
if (shouldDisableSynchronizedOutput) {
|
|
14616
|
+
this.#internalWrite(() => this.#stream.write(SYNCHRONIZED_OUTPUT_DISABLE));
|
|
14617
|
+
}
|
|
14692
14618
|
}
|
|
14619
|
+
return this;
|
|
14693
14620
|
}
|
|
14694
|
-
|
|
14695
|
-
if (
|
|
14696
|
-
this.
|
|
14621
|
+
start(text) {
|
|
14622
|
+
if (text) {
|
|
14623
|
+
this.text = text;
|
|
14697
14624
|
}
|
|
14698
|
-
|
|
14699
|
-
|
|
14700
|
-
if (chunk === undefined || chunk === null) {
|
|
14701
|
-
return "";
|
|
14625
|
+
if (this.isSilent) {
|
|
14626
|
+
return this;
|
|
14702
14627
|
}
|
|
14703
|
-
if (
|
|
14704
|
-
|
|
14628
|
+
if (!this.isEnabled) {
|
|
14629
|
+
const symbol = this.text ? "-" : "";
|
|
14630
|
+
const line = " ".repeat(this.#options.indent) + this.#buildOutputLine(symbol, this.text, this.#options.prefixText, this.#options.suffixText);
|
|
14631
|
+
if (line.trim() !== "") {
|
|
14632
|
+
this.#internalWrite(() => this.#stream.write(line + `
|
|
14633
|
+
`));
|
|
14634
|
+
}
|
|
14635
|
+
return this;
|
|
14705
14636
|
}
|
|
14706
|
-
if (
|
|
14707
|
-
|
|
14708
|
-
return Buffer.from(chunk).toString(normalizedEncoding);
|
|
14637
|
+
if (this.isSpinning) {
|
|
14638
|
+
return this;
|
|
14709
14639
|
}
|
|
14710
|
-
|
|
14711
|
-
|
|
14712
|
-
#chunkTerminatesLine(chunkString) {
|
|
14713
|
-
if (!chunkString) {
|
|
14714
|
-
return false;
|
|
14640
|
+
if (this.#options.hideCursor) {
|
|
14641
|
+
cli_cursor_default.hide(this.#stream);
|
|
14715
14642
|
}
|
|
14716
|
-
|
|
14717
|
-
|
|
14718
|
-
|
|
14643
|
+
if (this.#options.discardStdin && process8.stdin.isTTY) {
|
|
14644
|
+
stdin_discarder_default.start();
|
|
14645
|
+
this.#isDiscardingStdin = true;
|
|
14646
|
+
}
|
|
14647
|
+
this.#installHook();
|
|
14648
|
+
this.render();
|
|
14649
|
+
this.#id = setInterval(this.render.bind(this), this.interval);
|
|
14650
|
+
return this;
|
|
14719
14651
|
}
|
|
14720
|
-
|
|
14721
|
-
|
|
14722
|
-
|
|
14652
|
+
stop() {
|
|
14653
|
+
clearInterval(this.#id);
|
|
14654
|
+
this.#id = undefined;
|
|
14655
|
+
this.#frameIndex = -1;
|
|
14656
|
+
this.#lastFrameTime = 0;
|
|
14657
|
+
this.#clearRenderDeferral();
|
|
14658
|
+
this.#uninstallHook();
|
|
14659
|
+
if (this.#drainHandler) {
|
|
14660
|
+
this.#stream.removeListener("drain", this.#drainHandler);
|
|
14661
|
+
this.#drainHandler = undefined;
|
|
14723
14662
|
}
|
|
14724
|
-
|
|
14725
|
-
this
|
|
14726
|
-
if (this.
|
|
14727
|
-
this.#
|
|
14663
|
+
if (this.isEnabled) {
|
|
14664
|
+
this.clear();
|
|
14665
|
+
if (this.#options.hideCursor) {
|
|
14666
|
+
cli_cursor_default.show(this.#stream);
|
|
14728
14667
|
}
|
|
14729
|
-
}, RENDER_DEFERRAL_TIMEOUT);
|
|
14730
|
-
if (typeof this.#deferRenderTimer?.unref === "function") {
|
|
14731
|
-
this.#deferRenderTimer.unref();
|
|
14732
14668
|
}
|
|
14733
|
-
|
|
14734
|
-
|
|
14735
|
-
|
|
14736
|
-
clearTimeout(this.#deferRenderTimer);
|
|
14737
|
-
this.#deferRenderTimer = undefined;
|
|
14669
|
+
if (this.#isDiscardingStdin) {
|
|
14670
|
+
this.#isDiscardingStdin = false;
|
|
14671
|
+
stdin_discarder_default.stop();
|
|
14738
14672
|
}
|
|
14673
|
+
return this;
|
|
14739
14674
|
}
|
|
14740
|
-
|
|
14741
|
-
|
|
14742
|
-
const separatorText = symbol ? " " : "";
|
|
14743
|
-
const fullText = typeof text === "string" ? separatorText + text : "";
|
|
14744
|
-
const fullSuffixText = this.#getFullSuffixText(suffixText, " ");
|
|
14745
|
-
return fullPrefixText + symbol + fullText + fullSuffixText;
|
|
14675
|
+
succeed(text) {
|
|
14676
|
+
return this.stopAndPersist({ symbol: exports_symbols.success, text });
|
|
14746
14677
|
}
|
|
14747
|
-
|
|
14748
|
-
|
|
14749
|
-
options = {
|
|
14750
|
-
text: options
|
|
14751
|
-
};
|
|
14752
|
-
}
|
|
14753
|
-
this.#options = {
|
|
14754
|
-
color: "cyan",
|
|
14755
|
-
stream: process8.stderr,
|
|
14756
|
-
discardStdin: true,
|
|
14757
|
-
hideCursor: true,
|
|
14758
|
-
...options
|
|
14759
|
-
};
|
|
14760
|
-
this.color = this.#options.color;
|
|
14761
|
-
this.#stream = this.#options.stream;
|
|
14762
|
-
if (typeof this.#options.isEnabled !== "boolean") {
|
|
14763
|
-
this.#options.isEnabled = isInteractive({ stream: this.#stream });
|
|
14764
|
-
}
|
|
14765
|
-
if (typeof this.#options.isSilent !== "boolean") {
|
|
14766
|
-
this.#options.isSilent = false;
|
|
14767
|
-
}
|
|
14768
|
-
const userInterval = this.#options.interval;
|
|
14769
|
-
this.spinner = this.#options.spinner;
|
|
14770
|
-
this.#options.interval = userInterval;
|
|
14771
|
-
this.text = this.#options.text;
|
|
14772
|
-
this.prefixText = this.#options.prefixText;
|
|
14773
|
-
this.suffixText = this.#options.suffixText;
|
|
14774
|
-
this.indent = this.#options.indent;
|
|
14775
|
-
if (process8.env.NODE_ENV === "test") {
|
|
14776
|
-
this._stream = this.#stream;
|
|
14777
|
-
this._isEnabled = this.#options.isEnabled;
|
|
14778
|
-
Object.defineProperty(this, "_linesToClear", {
|
|
14779
|
-
get() {
|
|
14780
|
-
return this.#linesToClear;
|
|
14781
|
-
},
|
|
14782
|
-
set(newValue) {
|
|
14783
|
-
this.#linesToClear = newValue;
|
|
14784
|
-
}
|
|
14785
|
-
});
|
|
14786
|
-
Object.defineProperty(this, "_frameIndex", {
|
|
14787
|
-
get() {
|
|
14788
|
-
return this.#frameIndex;
|
|
14789
|
-
}
|
|
14790
|
-
});
|
|
14791
|
-
Object.defineProperty(this, "_lineCount", {
|
|
14792
|
-
get() {
|
|
14793
|
-
const columns = this.#stream.columns ?? 80;
|
|
14794
|
-
const prefixText = typeof this.#options.prefixText === "function" ? "" : this.#options.prefixText;
|
|
14795
|
-
const suffixText = typeof this.#options.suffixText === "function" ? "" : this.#options.suffixText;
|
|
14796
|
-
const fullPrefixText = typeof prefixText === "string" && prefixText !== "" ? prefixText + " " : "";
|
|
14797
|
-
const fullSuffixText = typeof suffixText === "string" && suffixText !== "" ? " " + suffixText : "";
|
|
14798
|
-
const spinnerChar = "-";
|
|
14799
|
-
const fullText = " ".repeat(this.#options.indent) + fullPrefixText + spinnerChar + (typeof this.#options.text === "string" ? " " + this.#options.text : "") + fullSuffixText;
|
|
14800
|
-
return this.#computeLineCountFrom(fullText, columns);
|
|
14801
|
-
}
|
|
14802
|
-
});
|
|
14803
|
-
}
|
|
14678
|
+
fail(text) {
|
|
14679
|
+
return this.stopAndPersist({ symbol: exports_symbols.error, text });
|
|
14804
14680
|
}
|
|
14805
|
-
|
|
14806
|
-
return this
|
|
14681
|
+
warn(text) {
|
|
14682
|
+
return this.stopAndPersist({ symbol: exports_symbols.warning, text });
|
|
14807
14683
|
}
|
|
14808
|
-
|
|
14809
|
-
|
|
14810
|
-
|
|
14684
|
+
info(text) {
|
|
14685
|
+
return this.stopAndPersist({ symbol: exports_symbols.info, text });
|
|
14686
|
+
}
|
|
14687
|
+
stopAndPersist(options = {}) {
|
|
14688
|
+
if (this.isSilent) {
|
|
14689
|
+
return this;
|
|
14690
|
+
}
|
|
14691
|
+
const symbol = options.symbol ?? " ";
|
|
14692
|
+
const text = options.text ?? this.text;
|
|
14693
|
+
const prefixText = options.prefixText ?? this.#options.prefixText;
|
|
14694
|
+
const suffixText = options.suffixText ?? this.#options.suffixText;
|
|
14695
|
+
const textToWrite = this.#buildOutputLine(symbol, text, prefixText, suffixText) + `
|
|
14696
|
+
`;
|
|
14697
|
+
this.stop();
|
|
14698
|
+
this.#internalWrite(() => this.#stream.write(textToWrite));
|
|
14699
|
+
return this;
|
|
14700
|
+
}
|
|
14701
|
+
}
|
|
14702
|
+
function ora(options) {
|
|
14703
|
+
return new Ora(options);
|
|
14704
|
+
}
|
|
14705
|
+
|
|
14706
|
+
// src/lib/ui.ts
|
|
14707
|
+
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
14708
|
+
import * as readline from "readline";
|
|
14709
|
+
var colors2 = {
|
|
14710
|
+
primary: import_picocolors.default.cyan,
|
|
14711
|
+
secondary: import_picocolors.default.blue,
|
|
14712
|
+
accent: import_picocolors.default.magenta,
|
|
14713
|
+
success: import_picocolors.default.green,
|
|
14714
|
+
warning: import_picocolors.default.yellow,
|
|
14715
|
+
error: import_picocolors.default.red,
|
|
14716
|
+
info: import_picocolors.default.blue,
|
|
14717
|
+
dim: import_picocolors.default.dim,
|
|
14718
|
+
bold: import_picocolors.default.bold,
|
|
14719
|
+
italic: import_picocolors.default.italic,
|
|
14720
|
+
excellent: import_picocolors.default.green,
|
|
14721
|
+
good: import_picocolors.default.cyan,
|
|
14722
|
+
moderate: import_picocolors.default.yellow,
|
|
14723
|
+
poor: import_picocolors.default.red,
|
|
14724
|
+
highlight: (text) => import_picocolors.default.bold(import_picocolors.default.cyan(text)),
|
|
14725
|
+
muted: (text) => import_picocolors.default.dim(import_picocolors.default.gray(text)),
|
|
14726
|
+
link: (text) => import_picocolors.default.underline(import_picocolors.default.blue(text))
|
|
14727
|
+
};
|
|
14728
|
+
function createSpinner(text) {
|
|
14729
|
+
return ora({
|
|
14730
|
+
text,
|
|
14731
|
+
spinner: "dots",
|
|
14732
|
+
color: "cyan"
|
|
14733
|
+
});
|
|
14734
|
+
}
|
|
14735
|
+
function formatTier(tier) {
|
|
14736
|
+
const tierColors = {
|
|
14737
|
+
elite: (s2) => import_picocolors.default.bold(import_picocolors.default.magenta(s2)),
|
|
14738
|
+
expert: (s2) => import_picocolors.default.bold(import_picocolors.default.cyan(s2)),
|
|
14739
|
+
advanced: (s2) => import_picocolors.default.bold(import_picocolors.default.green(s2)),
|
|
14740
|
+
proficient: (s2) => import_picocolors.default.blue(s2),
|
|
14741
|
+
intermediate: (s2) => import_picocolors.default.yellow(s2),
|
|
14742
|
+
developing: (s2) => import_picocolors.default.dim(s2)
|
|
14743
|
+
};
|
|
14744
|
+
const colorFn = tierColors[tier.toLowerCase()] ?? colors2.dim;
|
|
14745
|
+
return colorFn(tier.charAt(0).toUpperCase() + tier.slice(1));
|
|
14746
|
+
}
|
|
14747
|
+
var icons = {
|
|
14748
|
+
success: colors2.success("✔"),
|
|
14749
|
+
error: colors2.error("✖"),
|
|
14750
|
+
warning: colors2.warning("⚠"),
|
|
14751
|
+
info: colors2.info("ℹ"),
|
|
14752
|
+
arrow: colors2.primary("→"),
|
|
14753
|
+
bullet: colors2.dim("•"),
|
|
14754
|
+
star: colors2.warning("★"),
|
|
14755
|
+
check: colors2.success("✓"),
|
|
14756
|
+
cross: colors2.error("✗"),
|
|
14757
|
+
pending: colors2.dim("○"),
|
|
14758
|
+
lightning: "⚡",
|
|
14759
|
+
fire: "\uD83D\uDD25",
|
|
14760
|
+
rocket: "\uD83D\uDE80",
|
|
14761
|
+
chart: "\uD83D\uDCCA",
|
|
14762
|
+
money: "\uD83D\uDCB0",
|
|
14763
|
+
brain: "\uD83E\uDDE0",
|
|
14764
|
+
target: "\uD83C\uDFAF"
|
|
14765
|
+
};
|
|
14766
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
14767
|
+
function clearLine2() {
|
|
14768
|
+
readline.clearLine(process.stdout, 0);
|
|
14769
|
+
readline.cursorTo(process.stdout, 0);
|
|
14770
|
+
}
|
|
14771
|
+
function write(text) {
|
|
14772
|
+
process.stdout.write(text);
|
|
14773
|
+
}
|
|
14774
|
+
async function animateProgressBar(label, score, options = {}) {
|
|
14775
|
+
const { width = 20, charDelay = 40, labelWidth = 20 } = options;
|
|
14776
|
+
const filled = Math.round(score / 100 * width);
|
|
14777
|
+
let barColor = colors2.excellent;
|
|
14778
|
+
if (score < 40)
|
|
14779
|
+
barColor = colors2.poor;
|
|
14780
|
+
else if (score < 60)
|
|
14781
|
+
barColor = colors2.moderate;
|
|
14782
|
+
else if (score < 75)
|
|
14783
|
+
barColor = colors2.good;
|
|
14784
|
+
const paddedLabel = label.padEnd(labelWidth);
|
|
14785
|
+
const scoreStr = `${score}/100`.padStart(7);
|
|
14786
|
+
write(` ${colors2.dim(paddedLabel)} ${colors2.dim(scoreStr)} `);
|
|
14787
|
+
for (let i3 = 0;i3 < width; i3++) {
|
|
14788
|
+
if (i3 < filled) {
|
|
14789
|
+
write(barColor("█"));
|
|
14790
|
+
} else {
|
|
14791
|
+
write(colors2.dim("░"));
|
|
14811
14792
|
}
|
|
14812
|
-
|
|
14813
|
-
}
|
|
14814
|
-
get interval() {
|
|
14815
|
-
return this.#options.interval ?? this.#spinner.interval ?? 100;
|
|
14793
|
+
await sleep(charDelay);
|
|
14816
14794
|
}
|
|
14817
|
-
|
|
14818
|
-
|
|
14795
|
+
console.log();
|
|
14796
|
+
}
|
|
14797
|
+
async function thinkingStep(thinkingText, duration = 800, successText) {
|
|
14798
|
+
const spinner = createSpinner(thinkingText);
|
|
14799
|
+
spinner.start();
|
|
14800
|
+
await sleep(duration);
|
|
14801
|
+
spinner.succeed(successText ?? thinkingText);
|
|
14802
|
+
}
|
|
14803
|
+
async function revealDiscovery(icon, text, delay2 = 300) {
|
|
14804
|
+
await sleep(delay2);
|
|
14805
|
+
console.log(` ${icon} ${text}`);
|
|
14806
|
+
}
|
|
14807
|
+
async function showPhaseHeader(phase, total, title, delay2 = 400) {
|
|
14808
|
+
await sleep(delay2);
|
|
14809
|
+
console.log();
|
|
14810
|
+
console.log(` ${colors2.dim(`Phase ${phase}/${total}:`)} ${colors2.bold(colors2.primary(title))}`);
|
|
14811
|
+
console.log(colors2.dim(" " + "─".repeat(40)));
|
|
14812
|
+
}
|
|
14813
|
+
async function animateScoreReveal(score, tier, options = {}) {
|
|
14814
|
+
const { countDuration = 1000, barDelay = 50 } = options;
|
|
14815
|
+
const scoreColor = score >= 80 ? colors2.excellent : score >= 60 ? colors2.good : score >= 40 ? colors2.moderate : colors2.poor;
|
|
14816
|
+
console.log();
|
|
14817
|
+
console.log(colors2.dim(" " + "═".repeat(45)));
|
|
14818
|
+
console.log();
|
|
14819
|
+
const steps = 30;
|
|
14820
|
+
const stepDuration = countDuration / steps;
|
|
14821
|
+
for (let i3 = 1;i3 <= steps; i3++) {
|
|
14822
|
+
const current = Math.round(i3 / steps * score);
|
|
14823
|
+
clearLine2();
|
|
14824
|
+
write(` ${colors2.bold("Your Score:")} ${scoreColor(colors2.bold(current.toString()))}/100`);
|
|
14825
|
+
await sleep(stepDuration);
|
|
14819
14826
|
}
|
|
14820
|
-
|
|
14821
|
-
|
|
14822
|
-
|
|
14823
|
-
|
|
14824
|
-
|
|
14825
|
-
|
|
14826
|
-
|
|
14827
|
-
|
|
14828
|
-
|
|
14829
|
-
}
|
|
14830
|
-
this.#spinner = spinner;
|
|
14831
|
-
} else if (!isUnicodeSupported2()) {
|
|
14832
|
-
this.#spinner = cli_spinners_default.line;
|
|
14833
|
-
} else if (spinner === undefined) {
|
|
14834
|
-
this.#spinner = cli_spinners_default.dots;
|
|
14835
|
-
} else if (spinner !== "default" && cli_spinners_default[spinner]) {
|
|
14836
|
-
this.#spinner = cli_spinners_default[spinner];
|
|
14827
|
+
write(` ${colors2.dim("(")}${formatTier(tier)}${colors2.dim(")")}`);
|
|
14828
|
+
console.log();
|
|
14829
|
+
console.log();
|
|
14830
|
+
const barWidth = 30;
|
|
14831
|
+
const filled = Math.round(score / 100 * barWidth);
|
|
14832
|
+
write(" ");
|
|
14833
|
+
for (let i3 = 0;i3 < barWidth; i3++) {
|
|
14834
|
+
if (i3 < filled) {
|
|
14835
|
+
write(scoreColor("█"));
|
|
14837
14836
|
} else {
|
|
14838
|
-
|
|
14837
|
+
write(colors2.dim("░"));
|
|
14839
14838
|
}
|
|
14839
|
+
await sleep(barDelay);
|
|
14840
14840
|
}
|
|
14841
|
-
|
|
14842
|
-
|
|
14843
|
-
|
|
14844
|
-
|
|
14845
|
-
|
|
14846
|
-
|
|
14847
|
-
|
|
14848
|
-
|
|
14849
|
-
|
|
14850
|
-
|
|
14851
|
-
|
|
14852
|
-
}
|
|
14853
|
-
|
|
14854
|
-
|
|
14855
|
-
|
|
14856
|
-
|
|
14857
|
-
|
|
14858
|
-
}
|
|
14859
|
-
|
|
14860
|
-
|
|
14861
|
-
}
|
|
14862
|
-
|
|
14863
|
-
|
|
14864
|
-
|
|
14865
|
-
|
|
14841
|
+
console.log();
|
|
14842
|
+
console.log();
|
|
14843
|
+
console.log(colors2.dim(" " + "═".repeat(45)));
|
|
14844
|
+
}
|
|
14845
|
+
async function showFinding(type, label, value, unit = "", delay2 = 250) {
|
|
14846
|
+
await sleep(delay2);
|
|
14847
|
+
const iconMap = {
|
|
14848
|
+
warning: icons.warning,
|
|
14849
|
+
error: icons.error,
|
|
14850
|
+
info: icons.info,
|
|
14851
|
+
success: icons.success
|
|
14852
|
+
};
|
|
14853
|
+
const colorMap = {
|
|
14854
|
+
warning: colors2.warning,
|
|
14855
|
+
error: colors2.error,
|
|
14856
|
+
info: colors2.info,
|
|
14857
|
+
success: colors2.success
|
|
14858
|
+
};
|
|
14859
|
+
const icon = iconMap[type];
|
|
14860
|
+
const valueColor = colorMap[type];
|
|
14861
|
+
console.log(` ${icon} ${label}: ${valueColor(value.toString())}${unit}`);
|
|
14862
|
+
}
|
|
14863
|
+
|
|
14864
|
+
// src/lib/frustration-detector.ts
|
|
14865
|
+
var ROOT_CAUSE_PATTERNS = {
|
|
14866
|
+
hallucination: {
|
|
14867
|
+
patterns: [
|
|
14868
|
+
/doesn'?t exist/i,
|
|
14869
|
+
/not a valid/i,
|
|
14870
|
+
/no such (file|method|function|class|property|module)/i,
|
|
14871
|
+
/wrong api/i,
|
|
14872
|
+
/outdated/i,
|
|
14873
|
+
/deprecated/i,
|
|
14874
|
+
/that'?s not (how|the)/i,
|
|
14875
|
+
/method doesn'?t/i,
|
|
14876
|
+
/property doesn'?t/i,
|
|
14877
|
+
/hallucinating/i,
|
|
14878
|
+
/made up/i,
|
|
14879
|
+
/invented/i,
|
|
14880
|
+
/that method/i,
|
|
14881
|
+
/wrong syntax/i
|
|
14882
|
+
],
|
|
14883
|
+
description: "AI hallucinated non-existent API/method/syntax",
|
|
14884
|
+
fix: {
|
|
14885
|
+
tool: "Context7",
|
|
14886
|
+
description: "Provides up-to-date library documentation to prevent hallucinations",
|
|
14887
|
+
installCommand: "claude mcp add context7 https://mcp.context7.com/mcp --transport http",
|
|
14888
|
+
estimatedImprovementPercent: 70
|
|
14866
14889
|
}
|
|
14867
|
-
|
|
14868
|
-
|
|
14869
|
-
|
|
14870
|
-
|
|
14871
|
-
|
|
14872
|
-
|
|
14873
|
-
|
|
14874
|
-
|
|
14875
|
-
|
|
14876
|
-
|
|
14877
|
-
|
|
14878
|
-
|
|
14879
|
-
|
|
14890
|
+
},
|
|
14891
|
+
missing_docs: {
|
|
14892
|
+
patterns: [
|
|
14893
|
+
/how do (i|you)/i,
|
|
14894
|
+
/what'?s the (syntax|api|method|way)/i,
|
|
14895
|
+
/documentation/i,
|
|
14896
|
+
/check the docs/i,
|
|
14897
|
+
/look up/i,
|
|
14898
|
+
/find the right/i,
|
|
14899
|
+
/correct (api|method|syntax)/i,
|
|
14900
|
+
/which (api|method|function)/i
|
|
14901
|
+
],
|
|
14902
|
+
description: "Needed documentation that AI didn't have access to",
|
|
14903
|
+
fix: {
|
|
14904
|
+
tool: "Context7",
|
|
14905
|
+
description: "Live documentation lookup prevents outdated information",
|
|
14906
|
+
installCommand: "claude mcp add context7 https://mcp.context7.com/mcp --transport http",
|
|
14907
|
+
estimatedImprovementPercent: 65
|
|
14908
|
+
}
|
|
14909
|
+
},
|
|
14910
|
+
context_loss: {
|
|
14911
|
+
patterns: [
|
|
14912
|
+
/i already told you/i,
|
|
14913
|
+
/as i (said|mentioned)/i,
|
|
14914
|
+
/we discussed/i,
|
|
14915
|
+
/you forgot/i,
|
|
14916
|
+
/remember/i,
|
|
14917
|
+
/i explained/i,
|
|
14918
|
+
/sessions ago/i,
|
|
14919
|
+
/previously/i,
|
|
14920
|
+
/earlier/i,
|
|
14921
|
+
/context/i,
|
|
14922
|
+
/last time/i,
|
|
14923
|
+
/before/i
|
|
14924
|
+
],
|
|
14925
|
+
description: "AI forgot previously established context",
|
|
14926
|
+
fix: {
|
|
14927
|
+
tool: "Supermemory",
|
|
14928
|
+
description: "Persistent memory across sessions prevents context loss",
|
|
14929
|
+
installCommand: "claude mcp add supermemory -- npx -y @supermemory/mcp@latest",
|
|
14930
|
+
estimatedImprovementPercent: 80
|
|
14931
|
+
}
|
|
14932
|
+
},
|
|
14933
|
+
unclear_prompt: {
|
|
14934
|
+
patterns: [
|
|
14935
|
+
/what do you mean/i,
|
|
14936
|
+
/clarify/i,
|
|
14937
|
+
/specify/i,
|
|
14938
|
+
/more (details|context|information)/i,
|
|
14939
|
+
/not sure what/i,
|
|
14940
|
+
/which (file|one|version)/i,
|
|
14941
|
+
/be more specific/i
|
|
14942
|
+
],
|
|
14943
|
+
description: "Prompt was unclear, leading to misunderstanding",
|
|
14944
|
+
fix: {
|
|
14945
|
+
tool: "Writing Plans Skill",
|
|
14946
|
+
description: "Helps write clearer, more structured prompts",
|
|
14947
|
+
installCommand: "npx skills add obra/superpowers@writing-plans --yes",
|
|
14948
|
+
estimatedImprovementPercent: 50
|
|
14949
|
+
}
|
|
14950
|
+
},
|
|
14951
|
+
tool_failure: {
|
|
14952
|
+
patterns: [
|
|
14953
|
+
/tool failed/i,
|
|
14954
|
+
/mcp error/i,
|
|
14955
|
+
/error executing/i,
|
|
14956
|
+
/command failed/i,
|
|
14957
|
+
/couldn'?t run/i,
|
|
14958
|
+
/failed to/i,
|
|
14959
|
+
/error:/i,
|
|
14960
|
+
/exception/i
|
|
14961
|
+
],
|
|
14962
|
+
description: "Tool or MCP server failed to execute",
|
|
14963
|
+
fix: {
|
|
14964
|
+
tool: "MCP Doctor",
|
|
14965
|
+
description: "Fix MCP configuration issues",
|
|
14966
|
+
installCommand: "claude doctor && claude mcp list",
|
|
14967
|
+
estimatedImprovementPercent: 40
|
|
14968
|
+
}
|
|
14969
|
+
},
|
|
14970
|
+
undo_loop: {
|
|
14971
|
+
patterns: [
|
|
14972
|
+
/undo/i,
|
|
14973
|
+
/revert/i,
|
|
14974
|
+
/go back/i,
|
|
14975
|
+
/try again/i,
|
|
14976
|
+
/start over/i,
|
|
14977
|
+
/that'?s wrong/i,
|
|
14978
|
+
/not what i wanted/i,
|
|
14979
|
+
/roll back/i,
|
|
14980
|
+
/put it back/i,
|
|
14981
|
+
/restore/i,
|
|
14982
|
+
/wrong/i
|
|
14983
|
+
],
|
|
14984
|
+
description: "Got stuck in undo/redo loop from incorrect changes",
|
|
14985
|
+
fix: {
|
|
14986
|
+
tool: "Systematic Debugging Skill",
|
|
14987
|
+
description: "Structured approach to fixing issues without loops",
|
|
14988
|
+
installCommand: "npx skills add obra/superpowers@systematic-debugging --yes",
|
|
14989
|
+
estimatedImprovementPercent: 55
|
|
14880
14990
|
}
|
|
14881
|
-
return count;
|
|
14882
|
-
}
|
|
14883
|
-
get isEnabled() {
|
|
14884
|
-
return this.#options.isEnabled && !this.#options.isSilent;
|
|
14885
14991
|
}
|
|
14886
|
-
|
|
14887
|
-
|
|
14888
|
-
|
|
14992
|
+
};
|
|
14993
|
+
function detectFrustrations(sessions) {
|
|
14994
|
+
const frustrations = [];
|
|
14995
|
+
for (const session of sessions) {
|
|
14996
|
+
const frustrationPatterns = session.patterns.filter((p) => p.type !== "smooth_flow" && p.type !== "long_back_forth");
|
|
14997
|
+
if (frustrationPatterns.length === 0)
|
|
14998
|
+
continue;
|
|
14999
|
+
const sessionPath = findSessionPath(session.sessionId, session.agent);
|
|
15000
|
+
const exactPrompts = sessionPath ? extractFrustrationPrompts(sessionPath, frustrationPatterns) : [];
|
|
15001
|
+
for (let i3 = 0;i3 < frustrationPatterns.length; i3++) {
|
|
15002
|
+
const pattern = frustrationPatterns[i3];
|
|
15003
|
+
const exactPrompt = exactPrompts[i3] || "(Unable to extract prompt from session file)";
|
|
15004
|
+
const rootCause = analyzeRootCause(exactPrompt, pattern.type);
|
|
15005
|
+
const timeWasted = Math.round(pattern.estimatedWastedTokens / 1000);
|
|
15006
|
+
const costWasted = pattern.estimatedWastedTokens * 0.000015;
|
|
15007
|
+
frustrations.push({
|
|
15008
|
+
sessionId: session.sessionId,
|
|
15009
|
+
sessionPath: sessionPath || `${session.agent}/${session.sessionId}`,
|
|
15010
|
+
agent: session.agent,
|
|
15011
|
+
timestamp: session.startedAt,
|
|
15012
|
+
exactPrompt: exactPrompt.slice(0, 500),
|
|
15013
|
+
promptTruncated: exactPrompt.length > 500,
|
|
15014
|
+
patternType: pattern.type,
|
|
15015
|
+
patternDescription: getPatternDescription(pattern.type),
|
|
15016
|
+
rootCause,
|
|
15017
|
+
estimatedTimeWastedMinutes: timeWasted,
|
|
15018
|
+
estimatedTokensWasted: pattern.estimatedWastedTokens,
|
|
15019
|
+
estimatedCostWasted: Math.round(costWasted * 100) / 100,
|
|
15020
|
+
recommendedFix: getRecommendedFix(rootCause.category)
|
|
15021
|
+
});
|
|
14889
15022
|
}
|
|
14890
|
-
this.#options.isEnabled = value;
|
|
14891
15023
|
}
|
|
14892
|
-
|
|
14893
|
-
|
|
15024
|
+
frustrations.sort((a2, b2) => b2.estimatedTimeWastedMinutes - a2.estimatedTimeWastedMinutes);
|
|
15025
|
+
const totalTimeWasted = frustrations.reduce((a2, f3) => a2 + f3.estimatedTimeWastedMinutes, 0);
|
|
15026
|
+
const totalTokensWasted = frustrations.reduce((a2, f3) => a2 + f3.estimatedTokensWasted, 0);
|
|
15027
|
+
const totalCostWasted = frustrations.reduce((a2, f3) => a2 + f3.estimatedCostWasted, 0);
|
|
15028
|
+
const byRootCause = {};
|
|
15029
|
+
for (const f3 of frustrations) {
|
|
15030
|
+
byRootCause[f3.rootCause.category] = (byRootCause[f3.rootCause.category] || 0) + 1;
|
|
14894
15031
|
}
|
|
14895
|
-
|
|
14896
|
-
|
|
14897
|
-
|
|
15032
|
+
const recommendations = aggregateRecommendations(frustrations);
|
|
15033
|
+
return {
|
|
15034
|
+
totalFrustrations: frustrations.length,
|
|
15035
|
+
totalTimeWastedMinutes: totalTimeWasted,
|
|
15036
|
+
totalTokensWasted,
|
|
15037
|
+
totalCostWasted: Math.round(totalCostWasted * 100) / 100,
|
|
15038
|
+
byRootCause,
|
|
15039
|
+
topFrustrations: frustrations.slice(0, 5),
|
|
15040
|
+
recommendations
|
|
15041
|
+
};
|
|
15042
|
+
}
|
|
15043
|
+
function findSessionPath(sessionId, agent) {
|
|
15044
|
+
const home = homedir6();
|
|
15045
|
+
if (agent === "claude") {
|
|
15046
|
+
const projectsDir = join7(home, ".claude", "projects");
|
|
15047
|
+
if (!existsSync7(projectsDir))
|
|
15048
|
+
return null;
|
|
15049
|
+
try {
|
|
15050
|
+
const projectDirs = fsReaddirSync(projectsDir, { withFileTypes: true }).filter((d2) => d2.isDirectory()).map((d2) => join7(projectsDir, d2.name));
|
|
15051
|
+
for (const projectDir of projectDirs) {
|
|
15052
|
+
const sessionFile = join7(projectDir, `${sessionId}.jsonl`);
|
|
15053
|
+
if (existsSync7(sessionFile)) {
|
|
15054
|
+
return sessionFile;
|
|
15055
|
+
}
|
|
15056
|
+
}
|
|
15057
|
+
} catch {
|
|
15058
|
+
return null;
|
|
14898
15059
|
}
|
|
14899
|
-
this.#options.isSilent = value;
|
|
14900
15060
|
}
|
|
14901
|
-
|
|
14902
|
-
const
|
|
14903
|
-
if (
|
|
14904
|
-
|
|
14905
|
-
|
|
14906
|
-
|
|
14907
|
-
|
|
14908
|
-
|
|
14909
|
-
|
|
14910
|
-
|
|
15061
|
+
if (agent === "opencode") {
|
|
15062
|
+
const baseDir = join7(home, ".local", "share", "opencode", "storage", "session");
|
|
15063
|
+
if (!existsSync7(baseDir))
|
|
15064
|
+
return null;
|
|
15065
|
+
try {
|
|
15066
|
+
const projectDirs = fsReaddirSync(baseDir, { withFileTypes: true }).filter((d2) => d2.isDirectory()).map((d2) => join7(baseDir, d2.name));
|
|
15067
|
+
for (const projectDir of projectDirs) {
|
|
15068
|
+
const sessionFile = join7(projectDir, `${sessionId}.json`);
|
|
15069
|
+
if (existsSync7(sessionFile)) {
|
|
15070
|
+
return sessionFile;
|
|
15071
|
+
}
|
|
15072
|
+
}
|
|
15073
|
+
} catch {
|
|
15074
|
+
return null;
|
|
14911
15075
|
}
|
|
14912
|
-
const fullPrefixText = this.#getFullPrefixText(this.#options.prefixText, " ");
|
|
14913
|
-
const fullText = typeof this.text === "string" ? " " + this.text : "";
|
|
14914
|
-
const fullSuffixText = this.#getFullSuffixText(this.#options.suffixText, " ");
|
|
14915
|
-
return fullPrefixText + frame + fullText + fullSuffixText;
|
|
14916
15076
|
}
|
|
14917
|
-
|
|
14918
|
-
|
|
14919
|
-
|
|
14920
|
-
|
|
14921
|
-
|
|
14922
|
-
|
|
14923
|
-
|
|
14924
|
-
|
|
14925
|
-
|
|
15077
|
+
return null;
|
|
15078
|
+
}
|
|
15079
|
+
function extractFrustrationPrompts(sessionPath, patterns) {
|
|
15080
|
+
try {
|
|
15081
|
+
const content = readFileSync7(sessionPath, "utf-8");
|
|
15082
|
+
const prompts = [];
|
|
15083
|
+
if (sessionPath.endsWith(".jsonl")) {
|
|
15084
|
+
const lines = content.trim().split(`
|
|
15085
|
+
`);
|
|
15086
|
+
const messages = [];
|
|
15087
|
+
for (const line of lines) {
|
|
15088
|
+
try {
|
|
15089
|
+
messages.push(JSON.parse(line));
|
|
15090
|
+
} catch {}
|
|
15091
|
+
}
|
|
15092
|
+
const userMessages = messages.map((m2, i3) => ({ msg: m2, index: i3 })).filter((m2) => {
|
|
15093
|
+
const role = m2.msg.role ?? m2.msg.message?.role;
|
|
15094
|
+
return role === "user";
|
|
15095
|
+
});
|
|
15096
|
+
for (const pattern of patterns) {
|
|
15097
|
+
if (pattern.messageIndices && pattern.messageIndices.length > 0) {
|
|
15098
|
+
const idx = pattern.messageIndices[0];
|
|
15099
|
+
const userMsg = userMessages.find((m2) => m2.index === idx);
|
|
15100
|
+
if (userMsg) {
|
|
15101
|
+
const text = extractMessageText(userMsg.msg);
|
|
15102
|
+
prompts.push(text);
|
|
15103
|
+
} else {
|
|
15104
|
+
const frustrationMsg = findFrustrationMessage(userMessages.map((m2) => extractMessageText(m2.msg)));
|
|
15105
|
+
prompts.push(frustrationMsg || "");
|
|
15106
|
+
}
|
|
15107
|
+
} else {
|
|
15108
|
+
const frustrationMsg = findFrustrationMessage(userMessages.map((m2) => extractMessageText(m2.msg)));
|
|
15109
|
+
prompts.push(frustrationMsg || "");
|
|
14926
15110
|
}
|
|
14927
|
-
this.#stream.clearLine(1);
|
|
14928
15111
|
}
|
|
14929
|
-
|
|
14930
|
-
|
|
15112
|
+
} else if (sessionPath.endsWith(".json")) {
|
|
15113
|
+
for (const _3 of patterns) {
|
|
15114
|
+
prompts.push("");
|
|
14931
15115
|
}
|
|
14932
|
-
});
|
|
14933
|
-
this.#linesToClear = 0;
|
|
14934
|
-
return this;
|
|
14935
|
-
}
|
|
14936
|
-
#hookStream(stream) {
|
|
14937
|
-
if (!stream || this.#hookedStreams.has(stream) || !stream.isTTY || typeof stream.write !== "function") {
|
|
14938
|
-
return;
|
|
14939
15116
|
}
|
|
14940
|
-
|
|
14941
|
-
|
|
14942
|
-
|
|
14943
|
-
const originalWrite = stream.write;
|
|
14944
|
-
this.#hookedStreams.set(stream, originalWrite);
|
|
14945
|
-
activeHooksPerStream.set(stream, this);
|
|
14946
|
-
stream.write = (chunk, encoding, callback) => this.#hookedWrite(stream, originalWrite, chunk, encoding, callback);
|
|
15117
|
+
return prompts;
|
|
15118
|
+
} catch {
|
|
15119
|
+
return [];
|
|
14947
15120
|
}
|
|
14948
|
-
|
|
14949
|
-
|
|
14950
|
-
|
|
14951
|
-
|
|
14952
|
-
|
|
14953
|
-
|
|
14954
|
-
|
|
15121
|
+
}
|
|
15122
|
+
function extractMessageText(msg) {
|
|
15123
|
+
if (typeof msg.content === "string")
|
|
15124
|
+
return msg.content;
|
|
15125
|
+
if (Array.isArray(msg.content)) {
|
|
15126
|
+
return msg.content.filter((c3) => c3.type === "text" && c3.text).map((c3) => c3.text).join(" ");
|
|
15127
|
+
}
|
|
15128
|
+
return "";
|
|
15129
|
+
}
|
|
15130
|
+
function findFrustrationMessage(messages) {
|
|
15131
|
+
const frustrationIndicators = [
|
|
15132
|
+
/[A-Z]{5,}/,
|
|
15133
|
+
/!{2,}/,
|
|
15134
|
+
/\?{2,}/,
|
|
15135
|
+
/\b(ugh|argh|wtf|wrong|no|stop|don't|undo|revert)\b/i
|
|
15136
|
+
];
|
|
15137
|
+
for (const msg of messages) {
|
|
15138
|
+
for (const indicator of frustrationIndicators) {
|
|
15139
|
+
if (indicator.test(msg)) {
|
|
15140
|
+
return msg;
|
|
15141
|
+
}
|
|
14955
15142
|
}
|
|
14956
15143
|
}
|
|
14957
|
-
|
|
14958
|
-
|
|
14959
|
-
|
|
14960
|
-
|
|
14961
|
-
|
|
15144
|
+
return null;
|
|
15145
|
+
}
|
|
15146
|
+
function analyzeRootCause(prompt2, patternType) {
|
|
15147
|
+
if (patternType === "memory_loss") {
|
|
15148
|
+
return {
|
|
15149
|
+
category: "context_loss",
|
|
15150
|
+
description: ROOT_CAUSE_PATTERNS.context_loss.description,
|
|
15151
|
+
confidence: "high"
|
|
15152
|
+
};
|
|
15153
|
+
}
|
|
15154
|
+
if (patternType === "undo_loop") {
|
|
15155
|
+
for (const pattern of ROOT_CAUSE_PATTERNS.hallucination.patterns) {
|
|
15156
|
+
if (pattern.test(prompt2)) {
|
|
15157
|
+
return {
|
|
15158
|
+
category: "hallucination",
|
|
15159
|
+
description: ROOT_CAUSE_PATTERNS.hallucination.description,
|
|
15160
|
+
confidence: "medium"
|
|
15161
|
+
};
|
|
14962
15162
|
}
|
|
14963
15163
|
}
|
|
14964
|
-
|
|
15164
|
+
return {
|
|
15165
|
+
category: "undo_loop",
|
|
15166
|
+
description: ROOT_CAUSE_PATTERNS.undo_loop.description,
|
|
15167
|
+
confidence: "high"
|
|
15168
|
+
};
|
|
14965
15169
|
}
|
|
14966
|
-
|
|
14967
|
-
|
|
14968
|
-
|
|
14969
|
-
|
|
15170
|
+
if (patternType === "tool_failure") {
|
|
15171
|
+
return {
|
|
15172
|
+
category: "tool_failure",
|
|
15173
|
+
description: ROOT_CAUSE_PATTERNS.tool_failure.description,
|
|
15174
|
+
confidence: "high"
|
|
15175
|
+
};
|
|
15176
|
+
}
|
|
15177
|
+
for (const [category, config] of Object.entries(ROOT_CAUSE_PATTERNS)) {
|
|
15178
|
+
for (const pattern of config.patterns) {
|
|
15179
|
+
if (pattern.test(prompt2)) {
|
|
15180
|
+
return {
|
|
15181
|
+
category,
|
|
15182
|
+
description: config.description,
|
|
15183
|
+
confidence: "medium"
|
|
15184
|
+
};
|
|
15185
|
+
}
|
|
14970
15186
|
}
|
|
14971
|
-
|
|
14972
|
-
|
|
15187
|
+
}
|
|
15188
|
+
return {
|
|
15189
|
+
category: "unknown",
|
|
15190
|
+
description: "Unable to determine specific root cause",
|
|
15191
|
+
confidence: "low"
|
|
15192
|
+
};
|
|
15193
|
+
}
|
|
15194
|
+
function getRecommendedFix(category) {
|
|
15195
|
+
const fixes = {
|
|
15196
|
+
hallucination: ROOT_CAUSE_PATTERNS.hallucination.fix,
|
|
15197
|
+
missing_docs: ROOT_CAUSE_PATTERNS.missing_docs.fix,
|
|
15198
|
+
context_loss: ROOT_CAUSE_PATTERNS.context_loss.fix,
|
|
15199
|
+
unclear_prompt: ROOT_CAUSE_PATTERNS.unclear_prompt.fix,
|
|
15200
|
+
tool_failure: ROOT_CAUSE_PATTERNS.tool_failure.fix,
|
|
15201
|
+
undo_loop: ROOT_CAUSE_PATTERNS.undo_loop.fix,
|
|
15202
|
+
unknown: {
|
|
15203
|
+
tool: "CLAUDE.md",
|
|
15204
|
+
description: "Create project instructions to prevent common issues",
|
|
15205
|
+
installCommand: `echo '# Project Instructions
|
|
15206
|
+
' > CLAUDE.md`,
|
|
15207
|
+
estimatedImprovementPercent: 30
|
|
14973
15208
|
}
|
|
14974
|
-
|
|
14975
|
-
|
|
14976
|
-
|
|
14977
|
-
|
|
14978
|
-
|
|
14979
|
-
|
|
14980
|
-
|
|
14981
|
-
|
|
15209
|
+
};
|
|
15210
|
+
return fixes[category];
|
|
15211
|
+
}
|
|
15212
|
+
function getPatternDescription(patternType) {
|
|
15213
|
+
const descriptions = {
|
|
15214
|
+
undo_loop: "Got stuck in undo/redo cycle",
|
|
15215
|
+
memory_loss: "Had to re-explain context",
|
|
15216
|
+
frustration_caps: "Expressed frustration (ALL CAPS)",
|
|
15217
|
+
repeated_rephrasing: "Had to rephrase multiple times",
|
|
15218
|
+
context_compaction: "Lost context due to compaction",
|
|
15219
|
+
tool_failure: "Tool or MCP failed",
|
|
15220
|
+
long_back_forth: "Excessive back-and-forth"
|
|
15221
|
+
};
|
|
15222
|
+
return descriptions[patternType] || patternType;
|
|
15223
|
+
}
|
|
15224
|
+
function aggregateRecommendations(frustrations) {
|
|
15225
|
+
const byTool = {};
|
|
15226
|
+
for (const f3 of frustrations) {
|
|
15227
|
+
const key = f3.recommendedFix.tool;
|
|
15228
|
+
if (!byTool[key]) {
|
|
15229
|
+
byTool[key] = { count: 0, timeSaved: 0, costSaved: 0, fix: f3.recommendedFix, frustrations: [] };
|
|
14982
15230
|
}
|
|
14983
|
-
|
|
14984
|
-
|
|
15231
|
+
byTool[key].count++;
|
|
15232
|
+
byTool[key].timeSaved += f3.estimatedTimeWastedMinutes * (f3.recommendedFix.estimatedImprovementPercent / 100);
|
|
15233
|
+
byTool[key].costSaved += f3.estimatedCostWasted * (f3.recommendedFix.estimatedImprovementPercent / 100);
|
|
15234
|
+
byTool[key].frustrations.push(f3);
|
|
15235
|
+
}
|
|
15236
|
+
const recommendations = [];
|
|
15237
|
+
for (const [tool, data] of Object.entries(byTool)) {
|
|
15238
|
+
const preventedFrustrations = data.frustrations.sort((a2, b2) => b2.estimatedTimeWastedMinutes - a2.estimatedTimeWastedMinutes).slice(0, 3).map((f3) => ({
|
|
15239
|
+
patternType: f3.patternDescription,
|
|
15240
|
+
promptSnippet: f3.exactPrompt.slice(0, 80) + (f3.exactPrompt.length > 80 ? "..." : ""),
|
|
15241
|
+
timeWasted: f3.estimatedTimeWastedMinutes
|
|
15242
|
+
}));
|
|
15243
|
+
recommendations.push({
|
|
15244
|
+
tool,
|
|
15245
|
+
description: data.fix.description,
|
|
15246
|
+
installCommand: data.fix.installCommand,
|
|
15247
|
+
wouldHavePreventedCount: data.count,
|
|
15248
|
+
estimatedTimeSavedMinutes: Math.round(data.timeSaved),
|
|
15249
|
+
estimatedCostSaved: Math.round(data.costSaved * 100) / 100,
|
|
15250
|
+
preventedFrustrations
|
|
15251
|
+
});
|
|
15252
|
+
}
|
|
15253
|
+
recommendations.sort((a2, b2) => b2.estimatedTimeSavedMinutes - a2.estimatedTimeSavedMinutes);
|
|
15254
|
+
return recommendations;
|
|
15255
|
+
}
|
|
15256
|
+
function formatFrustrationSummary(summary) {
|
|
15257
|
+
const lines = [];
|
|
15258
|
+
if (summary.totalFrustrations === 0) {
|
|
15259
|
+
lines.push(` ${icons.success} ${colors2.success("No frustration events detected!")}`);
|
|
15260
|
+
return lines;
|
|
15261
|
+
}
|
|
15262
|
+
lines.push("");
|
|
15263
|
+
lines.push(colors2.dim(" " + "═".repeat(50)));
|
|
15264
|
+
lines.push(` ${colors2.error("!")} ${colors2.bold("Frustration Analysis")}`);
|
|
15265
|
+
lines.push(colors2.dim(" " + "═".repeat(50)));
|
|
15266
|
+
lines.push("");
|
|
15267
|
+
lines.push(` ${colors2.bold("Summary:")}`);
|
|
15268
|
+
lines.push(` ${icons.warning} ${summary.totalFrustrations} frustration events detected`);
|
|
15269
|
+
lines.push(` ${colors2.dim(">")} ~${summary.totalTimeWastedMinutes} min wasted`);
|
|
15270
|
+
lines.push(` ${icons.money} ~$${summary.totalCostWasted.toFixed(2)} in tokens`);
|
|
15271
|
+
lines.push("");
|
|
15272
|
+
if (Object.keys(summary.byRootCause).length > 0) {
|
|
15273
|
+
lines.push(` ${colors2.bold("Root Causes:")}`);
|
|
15274
|
+
for (const [cause, count] of Object.entries(summary.byRootCause)) {
|
|
15275
|
+
const label = formatCauseLabel(cause);
|
|
15276
|
+
lines.push(` ${colors2.dim("•")} ${label}: ${count}x`);
|
|
14985
15277
|
}
|
|
14986
|
-
|
|
15278
|
+
lines.push("");
|
|
14987
15279
|
}
|
|
14988
|
-
|
|
14989
|
-
|
|
14990
|
-
|
|
15280
|
+
if (summary.topFrustrations.length > 0) {
|
|
15281
|
+
lines.push(` ${colors2.bold("Top Frustrations:")}`);
|
|
15282
|
+
lines.push("");
|
|
15283
|
+
for (let i3 = 0;i3 < Math.min(3, summary.topFrustrations.length); i3++) {
|
|
15284
|
+
const f3 = summary.topFrustrations[i3];
|
|
15285
|
+
lines.push(...formatFrustrationEvent(f3, i3 + 1));
|
|
15286
|
+
lines.push("");
|
|
14991
15287
|
}
|
|
14992
|
-
|
|
14993
|
-
|
|
14994
|
-
|
|
14995
|
-
|
|
14996
|
-
|
|
14997
|
-
|
|
14998
|
-
|
|
14999
|
-
|
|
15000
|
-
|
|
15001
|
-
const
|
|
15002
|
-
|
|
15003
|
-
|
|
15004
|
-
|
|
15005
|
-
|
|
15006
|
-
`);
|
|
15007
|
-
const
|
|
15008
|
-
|
|
15009
|
-
|
|
15010
|
-
}
|
|
15011
|
-
const canContinue = this.#internalWrite(() => this.#stream.write(frameContent));
|
|
15012
|
-
if (canContinue === false && this.#stream.isTTY) {
|
|
15013
|
-
this.#drainHandler = () => {
|
|
15014
|
-
this.#drainHandler = undefined;
|
|
15015
|
-
this.#tryRender();
|
|
15016
|
-
};
|
|
15017
|
-
this.#stream.once("drain", this.#drainHandler);
|
|
15018
|
-
}
|
|
15019
|
-
this.#linesToClear = this.#computeLineCountFrom(frameContent, columns);
|
|
15020
|
-
} finally {
|
|
15021
|
-
if (shouldDisableSynchronizedOutput) {
|
|
15022
|
-
this.#internalWrite(() => this.#stream.write(SYNCHRONIZED_OUTPUT_DISABLE));
|
|
15288
|
+
}
|
|
15289
|
+
if (summary.recommendations.length > 0) {
|
|
15290
|
+
lines.push(` ${colors2.bold(colors2.primary("Contextual Recommendations:"))}`);
|
|
15291
|
+
lines.push("");
|
|
15292
|
+
const totalTimeSavings = summary.recommendations.reduce((a2, r3) => a2 + r3.estimatedTimeSavedMinutes, 0);
|
|
15293
|
+
const totalCostSavings = summary.recommendations.reduce((a2, r3) => a2 + r3.estimatedCostSaved, 0);
|
|
15294
|
+
lines.push(` ${colors2.dim("Total potential savings:")} ${colors2.success(`~${totalTimeSavings} min`)} | ${colors2.success(`$${totalCostSavings.toFixed(2)}`)}`);
|
|
15295
|
+
lines.push("");
|
|
15296
|
+
for (let i3 = 0;i3 < Math.min(3, summary.recommendations.length); i3++) {
|
|
15297
|
+
const rec = summary.recommendations[i3];
|
|
15298
|
+
lines.push(` ${colors2.success(`${i3 + 1}.`)} ${colors2.bold(rec.tool)}`);
|
|
15299
|
+
lines.push(` ${rec.description}`);
|
|
15300
|
+
lines.push(` ${colors2.dim("Prevented:")} ${rec.wouldHavePreventedCount} issue${rec.wouldHavePreventedCount > 1 ? "s" : ""} ${colors2.dim("|")} ${colors2.success(`~${rec.estimatedTimeSavedMinutes} min saved`)}`);
|
|
15301
|
+
if (rec.preventedFrustrations.length > 0) {
|
|
15302
|
+
lines.push(` ${colors2.dim("Would have fixed:")}`);
|
|
15303
|
+
for (const pf of rec.preventedFrustrations.slice(0, 2)) {
|
|
15304
|
+
lines.push(` ${colors2.dim("•")} ${pf.patternType} ${colors2.dim(`(${pf.timeWasted} min)`)}`);
|
|
15305
|
+
}
|
|
15023
15306
|
}
|
|
15307
|
+
lines.push(` ${colors2.dim("Install:")} ${colors2.primary(rec.installCommand)}`);
|
|
15308
|
+
lines.push("");
|
|
15024
15309
|
}
|
|
15025
|
-
return this;
|
|
15026
15310
|
}
|
|
15027
|
-
|
|
15028
|
-
|
|
15029
|
-
|
|
15311
|
+
lines.push(colors2.dim(" " + "═".repeat(50)));
|
|
15312
|
+
return lines;
|
|
15313
|
+
}
|
|
15314
|
+
function formatFrustrationEvent(f3, index) {
|
|
15315
|
+
const lines = [];
|
|
15316
|
+
lines.push(` ${colors2.warning(`${index}.`)} ${colors2.bold(f3.patternDescription)} ${colors2.dim(`(${f3.agent})`)}`);
|
|
15317
|
+
lines.push(` ${colors2.dim("Session:")} ${f3.sessionId.slice(0, 12)}...`);
|
|
15318
|
+
lines.push(` ${colors2.dim("Time wasted:")} ~${f3.estimatedTimeWastedMinutes} min`);
|
|
15319
|
+
lines.push(` ${colors2.dim("Cause:")} ${formatCauseLabel(f3.rootCause.category)}`);
|
|
15320
|
+
if (f3.exactPrompt && f3.exactPrompt.length > 0 && !f3.exactPrompt.startsWith("(Unable")) {
|
|
15321
|
+
lines.push("");
|
|
15322
|
+
lines.push(` ${colors2.dim("┌" + "─".repeat(40))}`);
|
|
15323
|
+
const promptLines = wrapText(f3.exactPrompt, 38);
|
|
15324
|
+
for (const line of promptLines.slice(0, 4)) {
|
|
15325
|
+
lines.push(` ${colors2.dim("│")} ${line}`);
|
|
15030
15326
|
}
|
|
15031
|
-
if (
|
|
15032
|
-
|
|
15327
|
+
if (promptLines.length > 4) {
|
|
15328
|
+
lines.push(` ${colors2.dim("│")} ${colors2.dim("...")}`);
|
|
15033
15329
|
}
|
|
15034
|
-
|
|
15035
|
-
|
|
15036
|
-
|
|
15037
|
-
|
|
15038
|
-
|
|
15039
|
-
|
|
15040
|
-
|
|
15041
|
-
|
|
15330
|
+
lines.push(` ${colors2.dim("└" + "─".repeat(40))}`);
|
|
15331
|
+
}
|
|
15332
|
+
lines.push("");
|
|
15333
|
+
lines.push(` ${colors2.success("Fix:")} ${f3.recommendedFix.tool}`);
|
|
15334
|
+
lines.push(` ${colors2.dim("$")} ${colors2.primary(f3.recommendedFix.installCommand)}`);
|
|
15335
|
+
return lines;
|
|
15336
|
+
}
|
|
15337
|
+
function formatCauseLabel(cause) {
|
|
15338
|
+
const labels = {
|
|
15339
|
+
hallucination: colors2.error("API Hallucination"),
|
|
15340
|
+
missing_docs: colors2.warning("Missing Docs"),
|
|
15341
|
+
context_loss: colors2.warning("Context Loss"),
|
|
15342
|
+
unclear_prompt: colors2.dim("Unclear Prompt"),
|
|
15343
|
+
tool_failure: colors2.error("Tool Failure"),
|
|
15344
|
+
undo_loop: colors2.warning("Undo Loop"),
|
|
15345
|
+
unknown: colors2.dim("Unknown")
|
|
15346
|
+
};
|
|
15347
|
+
return labels[cause] || cause;
|
|
15348
|
+
}
|
|
15349
|
+
function wrapText(text, width) {
|
|
15350
|
+
const words = text.split(/\s+/);
|
|
15351
|
+
const lines = [];
|
|
15352
|
+
let currentLine = "";
|
|
15353
|
+
for (const word of words) {
|
|
15354
|
+
if (currentLine.length + word.length + 1 <= width) {
|
|
15355
|
+
currentLine += (currentLine ? " " : "") + word;
|
|
15356
|
+
} else {
|
|
15357
|
+
if (currentLine)
|
|
15358
|
+
lines.push(currentLine);
|
|
15359
|
+
currentLine = word.slice(0, width);
|
|
15042
15360
|
}
|
|
15043
|
-
|
|
15044
|
-
|
|
15361
|
+
}
|
|
15362
|
+
if (currentLine)
|
|
15363
|
+
lines.push(currentLine);
|
|
15364
|
+
return lines;
|
|
15365
|
+
}
|
|
15366
|
+
|
|
15367
|
+
// src/lib/optimization-installer.ts
|
|
15368
|
+
import { execSync as execSync2, spawnSync } from "node:child_process";
|
|
15369
|
+
import { existsSync as existsSync8, writeFileSync as writeFileSync3, readFileSync as readFileSync8, mkdirSync as mkdirSync3, readdirSync as readdirSync4 } from "node:fs";
|
|
15370
|
+
import { join as join8 } from "node:path";
|
|
15371
|
+
import { homedir as homedir7 } from "node:os";
|
|
15372
|
+
async function installOptimizations(optimizations, projectDir, options = {}) {
|
|
15373
|
+
const results = [];
|
|
15374
|
+
for (const opt of optimizations) {
|
|
15375
|
+
if (!opt.selected)
|
|
15376
|
+
continue;
|
|
15377
|
+
try {
|
|
15378
|
+
const result = await installSingleOptimization(opt, projectDir, options);
|
|
15379
|
+
results.push(result);
|
|
15380
|
+
} catch (err) {
|
|
15381
|
+
results.push({
|
|
15382
|
+
id: opt.id,
|
|
15383
|
+
name: opt.name,
|
|
15384
|
+
success: false,
|
|
15385
|
+
message: "Installation failed",
|
|
15386
|
+
error: err instanceof Error ? err.message : String(err)
|
|
15387
|
+
});
|
|
15045
15388
|
}
|
|
15046
|
-
|
|
15047
|
-
|
|
15389
|
+
}
|
|
15390
|
+
return results;
|
|
15391
|
+
}
|
|
15392
|
+
async function installSingleOptimization(opt, projectDir, options) {
|
|
15393
|
+
if (options.dryRun) {
|
|
15394
|
+
return {
|
|
15395
|
+
id: opt.id,
|
|
15396
|
+
name: opt.name,
|
|
15397
|
+
success: true,
|
|
15398
|
+
message: `[DRY RUN] Would install: ${opt.installCommand || opt.configPath || "unknown"}`
|
|
15399
|
+
};
|
|
15400
|
+
}
|
|
15401
|
+
switch (opt.type) {
|
|
15402
|
+
case "mcp":
|
|
15403
|
+
return installMCP(opt, projectDir, options.agent);
|
|
15404
|
+
case "skill":
|
|
15405
|
+
return installSkill(opt);
|
|
15406
|
+
case "config":
|
|
15407
|
+
return installConfig(opt, projectDir);
|
|
15408
|
+
case "hook":
|
|
15409
|
+
return installHook(opt, projectDir);
|
|
15410
|
+
default:
|
|
15411
|
+
return {
|
|
15412
|
+
id: opt.id,
|
|
15413
|
+
name: opt.name,
|
|
15414
|
+
success: false,
|
|
15415
|
+
message: "Unknown optimization type"
|
|
15416
|
+
};
|
|
15417
|
+
}
|
|
15418
|
+
}
|
|
15419
|
+
function installMCP(opt, projectDir, agent) {
|
|
15420
|
+
if (opt.installCommand?.startsWith("claude mcp add")) {
|
|
15421
|
+
try {
|
|
15422
|
+
execSync2(opt.installCommand, {
|
|
15423
|
+
encoding: "utf-8",
|
|
15424
|
+
stdio: "pipe",
|
|
15425
|
+
timeout: 60000
|
|
15426
|
+
});
|
|
15427
|
+
return {
|
|
15428
|
+
id: opt.id,
|
|
15429
|
+
name: opt.name,
|
|
15430
|
+
success: true,
|
|
15431
|
+
message: `Installed via: ${opt.installCommand}`
|
|
15432
|
+
};
|
|
15433
|
+
} catch (err) {}
|
|
15434
|
+
}
|
|
15435
|
+
if (opt.id === "beads" || opt.name.toLowerCase().includes("beads")) {
|
|
15436
|
+
try {
|
|
15437
|
+
execSync2("bun add -g beads", { encoding: "utf-8", stdio: "pipe", timeout: 60000 });
|
|
15438
|
+
execSync2("bd init", { cwd: projectDir, encoding: "utf-8", stdio: "pipe", timeout: 30000 });
|
|
15439
|
+
return {
|
|
15440
|
+
id: opt.id,
|
|
15441
|
+
name: opt.name,
|
|
15442
|
+
success: true,
|
|
15443
|
+
message: "Installed Beads globally and initialized in project"
|
|
15444
|
+
};
|
|
15445
|
+
} catch (err) {
|
|
15446
|
+
return {
|
|
15447
|
+
id: opt.id,
|
|
15448
|
+
name: opt.name,
|
|
15449
|
+
success: false,
|
|
15450
|
+
message: "Failed to install Beads",
|
|
15451
|
+
error: err instanceof Error ? err.message : String(err)
|
|
15452
|
+
};
|
|
15048
15453
|
}
|
|
15049
|
-
|
|
15050
|
-
|
|
15051
|
-
|
|
15454
|
+
}
|
|
15455
|
+
if (opt.installCommand) {
|
|
15456
|
+
try {
|
|
15457
|
+
execSync2(opt.installCommand, {
|
|
15458
|
+
encoding: "utf-8",
|
|
15459
|
+
stdio: "pipe",
|
|
15460
|
+
timeout: 60000
|
|
15461
|
+
});
|
|
15462
|
+
return {
|
|
15463
|
+
id: opt.id,
|
|
15464
|
+
name: opt.name,
|
|
15465
|
+
success: true,
|
|
15466
|
+
message: `Installed via: ${opt.installCommand}`
|
|
15467
|
+
};
|
|
15468
|
+
} catch (err) {
|
|
15469
|
+
return {
|
|
15470
|
+
id: opt.id,
|
|
15471
|
+
name: opt.name,
|
|
15472
|
+
success: false,
|
|
15473
|
+
message: "Failed to install MCP",
|
|
15474
|
+
error: err instanceof Error ? err.message : String(err)
|
|
15475
|
+
};
|
|
15052
15476
|
}
|
|
15053
|
-
this.#installHook();
|
|
15054
|
-
this.render();
|
|
15055
|
-
this.#id = setInterval(this.render.bind(this), this.interval);
|
|
15056
|
-
return this;
|
|
15057
15477
|
}
|
|
15058
|
-
|
|
15059
|
-
|
|
15060
|
-
|
|
15061
|
-
|
|
15062
|
-
|
|
15063
|
-
|
|
15064
|
-
|
|
15065
|
-
|
|
15066
|
-
|
|
15067
|
-
|
|
15478
|
+
return {
|
|
15479
|
+
id: opt.id,
|
|
15480
|
+
name: opt.name,
|
|
15481
|
+
success: false,
|
|
15482
|
+
message: "No install command available"
|
|
15483
|
+
};
|
|
15484
|
+
}
|
|
15485
|
+
function installSkill(opt) {
|
|
15486
|
+
if (!opt.installCommand) {
|
|
15487
|
+
return {
|
|
15488
|
+
id: opt.id,
|
|
15489
|
+
name: opt.name,
|
|
15490
|
+
success: false,
|
|
15491
|
+
message: "No install command for skill"
|
|
15492
|
+
};
|
|
15493
|
+
}
|
|
15494
|
+
try {
|
|
15495
|
+
const skillPath = opt.installCommand.replace(/^npx\s+/, "").replace(/^bunx\s+/, "").replace(/^skills\s+add\s+/, "").trim();
|
|
15496
|
+
let result = spawnSync("bunx", ["--bun", "skills", "add", skillPath], {
|
|
15497
|
+
encoding: "utf-8",
|
|
15498
|
+
stdio: "pipe",
|
|
15499
|
+
timeout: 120000
|
|
15500
|
+
});
|
|
15501
|
+
if (result.status !== 0) {
|
|
15502
|
+
result = spawnSync("npx", ["-y", "skills", "add", skillPath], {
|
|
15503
|
+
encoding: "utf-8",
|
|
15504
|
+
stdio: "pipe",
|
|
15505
|
+
timeout: 120000
|
|
15506
|
+
});
|
|
15068
15507
|
}
|
|
15069
|
-
if (
|
|
15070
|
-
|
|
15071
|
-
|
|
15072
|
-
|
|
15508
|
+
if (result.status === 0) {
|
|
15509
|
+
return {
|
|
15510
|
+
id: opt.id,
|
|
15511
|
+
name: opt.name,
|
|
15512
|
+
success: true,
|
|
15513
|
+
message: `Skill installed successfully`
|
|
15514
|
+
};
|
|
15515
|
+
} else {
|
|
15516
|
+
const output = (result.stderr || result.stdout || "").toLowerCase();
|
|
15517
|
+
if (output.includes("already exists") || output.includes("already installed")) {
|
|
15518
|
+
return {
|
|
15519
|
+
id: opt.id,
|
|
15520
|
+
name: opt.name,
|
|
15521
|
+
success: true,
|
|
15522
|
+
message: `Skill already installed`
|
|
15523
|
+
};
|
|
15073
15524
|
}
|
|
15525
|
+
return {
|
|
15526
|
+
id: opt.id,
|
|
15527
|
+
name: opt.name,
|
|
15528
|
+
success: false,
|
|
15529
|
+
message: "Skill installation failed",
|
|
15530
|
+
error: result.stderr || result.stdout || "Unknown error"
|
|
15531
|
+
};
|
|
15074
15532
|
}
|
|
15075
|
-
|
|
15076
|
-
|
|
15077
|
-
|
|
15078
|
-
|
|
15079
|
-
|
|
15080
|
-
|
|
15081
|
-
|
|
15082
|
-
|
|
15083
|
-
}
|
|
15084
|
-
fail(text) {
|
|
15085
|
-
return this.stopAndPersist({ symbol: exports_symbols.error, text });
|
|
15086
|
-
}
|
|
15087
|
-
warn(text) {
|
|
15088
|
-
return this.stopAndPersist({ symbol: exports_symbols.warning, text });
|
|
15533
|
+
} catch (err) {
|
|
15534
|
+
return {
|
|
15535
|
+
id: opt.id,
|
|
15536
|
+
name: opt.name,
|
|
15537
|
+
success: false,
|
|
15538
|
+
message: "Failed to install skill",
|
|
15539
|
+
error: err instanceof Error ? err.message : String(err)
|
|
15540
|
+
};
|
|
15089
15541
|
}
|
|
15090
|
-
|
|
15091
|
-
|
|
15542
|
+
}
|
|
15543
|
+
function installConfig(opt, projectDir) {
|
|
15544
|
+
if (!opt.configPath || !opt.configContent) {
|
|
15545
|
+
return {
|
|
15546
|
+
id: opt.id,
|
|
15547
|
+
name: opt.name,
|
|
15548
|
+
success: false,
|
|
15549
|
+
message: "No config path or content provided"
|
|
15550
|
+
};
|
|
15092
15551
|
}
|
|
15093
|
-
|
|
15094
|
-
|
|
15095
|
-
|
|
15552
|
+
try {
|
|
15553
|
+
const fullPath = opt.configPath.startsWith("/") || opt.configPath.startsWith("~") ? opt.configPath.replace("~", homedir7()) : join8(projectDir, opt.configPath);
|
|
15554
|
+
if (existsSync8(fullPath)) {
|
|
15555
|
+
return {
|
|
15556
|
+
id: opt.id,
|
|
15557
|
+
name: opt.name,
|
|
15558
|
+
success: true,
|
|
15559
|
+
message: `Config already exists: ${opt.configPath}`
|
|
15560
|
+
};
|
|
15096
15561
|
}
|
|
15097
|
-
const
|
|
15098
|
-
|
|
15099
|
-
|
|
15100
|
-
|
|
15101
|
-
|
|
15102
|
-
|
|
15103
|
-
|
|
15104
|
-
|
|
15105
|
-
|
|
15106
|
-
|
|
15107
|
-
}
|
|
15108
|
-
|
|
15109
|
-
|
|
15110
|
-
|
|
15111
|
-
|
|
15112
|
-
|
|
15113
|
-
|
|
15114
|
-
|
|
15115
|
-
|
|
15116
|
-
|
|
15117
|
-
|
|
15118
|
-
|
|
15119
|
-
|
|
15120
|
-
|
|
15121
|
-
|
|
15122
|
-
|
|
15123
|
-
|
|
15124
|
-
bold: import_picocolors.default.bold,
|
|
15125
|
-
italic: import_picocolors.default.italic,
|
|
15126
|
-
excellent: import_picocolors.default.green,
|
|
15127
|
-
good: import_picocolors.default.cyan,
|
|
15128
|
-
moderate: import_picocolors.default.yellow,
|
|
15129
|
-
poor: import_picocolors.default.red,
|
|
15130
|
-
highlight: (text) => import_picocolors.default.bold(import_picocolors.default.cyan(text)),
|
|
15131
|
-
muted: (text) => import_picocolors.default.dim(import_picocolors.default.gray(text)),
|
|
15132
|
-
link: (text) => import_picocolors.default.underline(import_picocolors.default.blue(text))
|
|
15133
|
-
};
|
|
15134
|
-
function createSpinner(text) {
|
|
15135
|
-
return ora({
|
|
15136
|
-
text,
|
|
15137
|
-
spinner: "dots",
|
|
15138
|
-
color: "cyan"
|
|
15139
|
-
});
|
|
15140
|
-
}
|
|
15141
|
-
function formatTier(tier) {
|
|
15142
|
-
const tierColors = {
|
|
15143
|
-
elite: (s2) => import_picocolors.default.bold(import_picocolors.default.magenta(s2)),
|
|
15144
|
-
expert: (s2) => import_picocolors.default.bold(import_picocolors.default.cyan(s2)),
|
|
15145
|
-
advanced: (s2) => import_picocolors.default.bold(import_picocolors.default.green(s2)),
|
|
15146
|
-
proficient: (s2) => import_picocolors.default.blue(s2),
|
|
15147
|
-
intermediate: (s2) => import_picocolors.default.yellow(s2),
|
|
15148
|
-
developing: (s2) => import_picocolors.default.dim(s2)
|
|
15149
|
-
};
|
|
15150
|
-
const colorFn = tierColors[tier.toLowerCase()] ?? colors2.dim;
|
|
15151
|
-
return colorFn(tier.charAt(0).toUpperCase() + tier.slice(1));
|
|
15152
|
-
}
|
|
15153
|
-
var icons = {
|
|
15154
|
-
success: colors2.success("✔"),
|
|
15155
|
-
error: colors2.error("✖"),
|
|
15156
|
-
warning: colors2.warning("⚠"),
|
|
15157
|
-
info: colors2.info("ℹ"),
|
|
15158
|
-
arrow: colors2.primary("→"),
|
|
15159
|
-
bullet: colors2.dim("•"),
|
|
15160
|
-
star: colors2.warning("★"),
|
|
15161
|
-
check: colors2.success("✓"),
|
|
15162
|
-
cross: colors2.error("✗"),
|
|
15163
|
-
pending: colors2.dim("○"),
|
|
15164
|
-
lightning: "⚡",
|
|
15165
|
-
fire: "\uD83D\uDD25",
|
|
15166
|
-
rocket: "\uD83D\uDE80",
|
|
15167
|
-
chart: "\uD83D\uDCCA",
|
|
15168
|
-
money: "\uD83D\uDCB0",
|
|
15169
|
-
brain: "\uD83E\uDDE0",
|
|
15170
|
-
target: "\uD83C\uDFAF"
|
|
15171
|
-
};
|
|
15172
|
-
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
15173
|
-
function clearLine2() {
|
|
15174
|
-
readline.clearLine(process.stdout, 0);
|
|
15175
|
-
readline.cursorTo(process.stdout, 0);
|
|
15176
|
-
}
|
|
15177
|
-
function write(text) {
|
|
15178
|
-
process.stdout.write(text);
|
|
15179
|
-
}
|
|
15180
|
-
async function animateProgressBar(label, score, options = {}) {
|
|
15181
|
-
const { width = 20, charDelay = 40, labelWidth = 20 } = options;
|
|
15182
|
-
const filled = Math.round(score / 100 * width);
|
|
15183
|
-
let barColor = colors2.excellent;
|
|
15184
|
-
if (score < 40)
|
|
15185
|
-
barColor = colors2.poor;
|
|
15186
|
-
else if (score < 60)
|
|
15187
|
-
barColor = colors2.moderate;
|
|
15188
|
-
else if (score < 75)
|
|
15189
|
-
barColor = colors2.good;
|
|
15190
|
-
const paddedLabel = label.padEnd(labelWidth);
|
|
15191
|
-
const scoreStr = `${score}/100`.padStart(7);
|
|
15192
|
-
write(` ${colors2.dim(paddedLabel)} ${colors2.dim(scoreStr)} `);
|
|
15193
|
-
for (let i3 = 0;i3 < width; i3++) {
|
|
15194
|
-
if (i3 < filled) {
|
|
15195
|
-
write(barColor("█"));
|
|
15562
|
+
const parentDir = fullPath.substring(0, fullPath.lastIndexOf("/"));
|
|
15563
|
+
if (parentDir && !existsSync8(parentDir)) {
|
|
15564
|
+
mkdirSync3(parentDir, { recursive: true });
|
|
15565
|
+
}
|
|
15566
|
+
writeFileSync3(fullPath, opt.configContent);
|
|
15567
|
+
return {
|
|
15568
|
+
id: opt.id,
|
|
15569
|
+
name: opt.name,
|
|
15570
|
+
success: true,
|
|
15571
|
+
message: `Created: ${opt.configPath}`
|
|
15572
|
+
};
|
|
15573
|
+
} catch (err) {
|
|
15574
|
+
return {
|
|
15575
|
+
id: opt.id,
|
|
15576
|
+
name: opt.name,
|
|
15577
|
+
success: false,
|
|
15578
|
+
message: "Failed to create config",
|
|
15579
|
+
error: err instanceof Error ? err.message : String(err)
|
|
15580
|
+
};
|
|
15581
|
+
}
|
|
15582
|
+
}
|
|
15583
|
+
function installHook(opt, projectDir) {
|
|
15584
|
+
const agentsMdPath = join8(projectDir, "AGENTS.md");
|
|
15585
|
+
try {
|
|
15586
|
+
let content = "";
|
|
15587
|
+
if (existsSync8(agentsMdPath)) {
|
|
15588
|
+
content = readFileSync8(agentsMdPath, "utf-8");
|
|
15196
15589
|
} else {
|
|
15197
|
-
|
|
15590
|
+
content = `# Agent Instructions
|
|
15591
|
+
|
|
15592
|
+
`;
|
|
15198
15593
|
}
|
|
15199
|
-
|
|
15594
|
+
const hookName = opt.name.toLowerCase();
|
|
15595
|
+
if (content.toLowerCase().includes(hookName)) {
|
|
15596
|
+
return {
|
|
15597
|
+
id: opt.id,
|
|
15598
|
+
name: opt.name,
|
|
15599
|
+
success: true,
|
|
15600
|
+
message: "Hook already configured in AGENTS.md"
|
|
15601
|
+
};
|
|
15602
|
+
}
|
|
15603
|
+
const hookSection = opt.configContent || `
|
|
15604
|
+
## ${opt.name}
|
|
15605
|
+
${opt.description}
|
|
15606
|
+
`;
|
|
15607
|
+
content += `
|
|
15608
|
+
` + hookSection;
|
|
15609
|
+
writeFileSync3(agentsMdPath, content);
|
|
15610
|
+
return {
|
|
15611
|
+
id: opt.id,
|
|
15612
|
+
name: opt.name,
|
|
15613
|
+
success: true,
|
|
15614
|
+
message: "Added hook to AGENTS.md"
|
|
15615
|
+
};
|
|
15616
|
+
} catch (err) {
|
|
15617
|
+
return {
|
|
15618
|
+
id: opt.id,
|
|
15619
|
+
name: opt.name,
|
|
15620
|
+
success: false,
|
|
15621
|
+
message: "Failed to add hook",
|
|
15622
|
+
error: err instanceof Error ? err.message : String(err)
|
|
15623
|
+
};
|
|
15200
15624
|
}
|
|
15201
|
-
console.log();
|
|
15202
|
-
}
|
|
15203
|
-
async function thinkingStep(thinkingText, duration = 800, successText) {
|
|
15204
|
-
const spinner = createSpinner(thinkingText);
|
|
15205
|
-
spinner.start();
|
|
15206
|
-
await sleep(duration);
|
|
15207
|
-
spinner.succeed(successText ?? thinkingText);
|
|
15208
15625
|
}
|
|
15209
|
-
|
|
15210
|
-
|
|
15211
|
-
|
|
15212
|
-
|
|
15213
|
-
|
|
15214
|
-
|
|
15215
|
-
|
|
15216
|
-
|
|
15217
|
-
|
|
15626
|
+
function phaseRecToInstallable(rec) {
|
|
15627
|
+
return {
|
|
15628
|
+
id: rec.title.toLowerCase().replace(/\s+/g, "-"),
|
|
15629
|
+
name: rec.title,
|
|
15630
|
+
type: rec.type,
|
|
15631
|
+
description: rec.description,
|
|
15632
|
+
installCommand: rec.installCommand,
|
|
15633
|
+
selected: false
|
|
15634
|
+
};
|
|
15218
15635
|
}
|
|
15219
|
-
|
|
15220
|
-
const
|
|
15221
|
-
const
|
|
15222
|
-
|
|
15223
|
-
|
|
15224
|
-
|
|
15225
|
-
|
|
15226
|
-
|
|
15227
|
-
|
|
15228
|
-
|
|
15229
|
-
|
|
15230
|
-
|
|
15231
|
-
|
|
15636
|
+
function checkInstalledStatus(projectDir) {
|
|
15637
|
+
const home = homedir7();
|
|
15638
|
+
const status = {
|
|
15639
|
+
context7: false,
|
|
15640
|
+
supermemory: false,
|
|
15641
|
+
nia: false,
|
|
15642
|
+
beads: false,
|
|
15643
|
+
skills: []
|
|
15644
|
+
};
|
|
15645
|
+
const mcpConfigPaths = [
|
|
15646
|
+
join8(home, ".claude.json"),
|
|
15647
|
+
join8(home, ".claude", "claude_desktop_config.json"),
|
|
15648
|
+
join8(home, ".claude", "settings.json"),
|
|
15649
|
+
join8(home, ".claude", "settings.local.json"),
|
|
15650
|
+
join8(projectDir, ".mcp.json"),
|
|
15651
|
+
join8(projectDir, ".claude", "settings.local.json")
|
|
15652
|
+
];
|
|
15653
|
+
for (const configPath of mcpConfigPaths) {
|
|
15654
|
+
if (existsSync8(configPath)) {
|
|
15655
|
+
try {
|
|
15656
|
+
const config = JSON.parse(readFileSync8(configPath, "utf-8"));
|
|
15657
|
+
const mcpServers = config.mcpServers || config.mcp_servers || {};
|
|
15658
|
+
for (const name of Object.keys(mcpServers)) {
|
|
15659
|
+
const mcpName = name.toLowerCase();
|
|
15660
|
+
if (mcpName.includes("context7") || mcpName === "c7") {
|
|
15661
|
+
status.context7 = true;
|
|
15662
|
+
}
|
|
15663
|
+
if (mcpName.includes("supermemory") || mcpName.includes("memory")) {
|
|
15664
|
+
status.supermemory = true;
|
|
15665
|
+
}
|
|
15666
|
+
if (mcpName.includes("nia")) {
|
|
15667
|
+
status.nia = true;
|
|
15668
|
+
}
|
|
15669
|
+
}
|
|
15670
|
+
} catch {}
|
|
15671
|
+
}
|
|
15232
15672
|
}
|
|
15233
|
-
|
|
15234
|
-
|
|
15235
|
-
|
|
15236
|
-
|
|
15237
|
-
|
|
15238
|
-
|
|
15239
|
-
|
|
15240
|
-
|
|
15241
|
-
|
|
15242
|
-
|
|
15243
|
-
|
|
15673
|
+
status.beads = existsSync8(join8(projectDir, ".beads"));
|
|
15674
|
+
const skillsDirs = [
|
|
15675
|
+
join8(home, ".claude", "skills"),
|
|
15676
|
+
join8(home, ".config", "opencode", "skills"),
|
|
15677
|
+
join8(home, ".agents", "skills"),
|
|
15678
|
+
join8(projectDir, ".opencode", "skill")
|
|
15679
|
+
];
|
|
15680
|
+
for (const dir of skillsDirs) {
|
|
15681
|
+
if (existsSync8(dir)) {
|
|
15682
|
+
try {
|
|
15683
|
+
const skills = readdirSync4(dir);
|
|
15684
|
+
for (const skill of skills) {
|
|
15685
|
+
if (!status.skills.includes(skill.toLowerCase())) {
|
|
15686
|
+
status.skills.push(skill.toLowerCase());
|
|
15687
|
+
}
|
|
15688
|
+
}
|
|
15689
|
+
} catch {}
|
|
15244
15690
|
}
|
|
15245
|
-
await sleep(barDelay);
|
|
15246
15691
|
}
|
|
15247
|
-
|
|
15248
|
-
console.log();
|
|
15249
|
-
console.log(colors2.dim(" " + "═".repeat(45)));
|
|
15692
|
+
return status;
|
|
15250
15693
|
}
|
|
15251
|
-
|
|
15252
|
-
|
|
15253
|
-
|
|
15254
|
-
|
|
15255
|
-
|
|
15256
|
-
|
|
15257
|
-
|
|
15258
|
-
|
|
15259
|
-
|
|
15260
|
-
|
|
15261
|
-
|
|
15262
|
-
|
|
15263
|
-
|
|
15264
|
-
|
|
15265
|
-
|
|
15266
|
-
|
|
15267
|
-
|
|
15694
|
+
function filterAlreadyInstalled(optimizations, status) {
|
|
15695
|
+
return optimizations.filter((opt) => {
|
|
15696
|
+
const id = opt.id.toLowerCase();
|
|
15697
|
+
if (id === "context7" && status.context7)
|
|
15698
|
+
return false;
|
|
15699
|
+
if (id === "supermemory" && status.supermemory)
|
|
15700
|
+
return false;
|
|
15701
|
+
if (id === "nia" && status.nia)
|
|
15702
|
+
return false;
|
|
15703
|
+
if (id === "beads" && status.beads)
|
|
15704
|
+
return false;
|
|
15705
|
+
if (opt.type === "skill") {
|
|
15706
|
+
const skillName = opt.name.toLowerCase().replace(/\s+/g, "-");
|
|
15707
|
+
if (status.skills.some((s2) => s2.includes(skillName) || skillName.includes(s2) || s2.includes("tdd") && id.includes("tdd") || s2.includes("debug") && id.includes("debug") || s2.includes("plan") && id.includes("plan"))) {
|
|
15708
|
+
return false;
|
|
15709
|
+
}
|
|
15710
|
+
}
|
|
15711
|
+
return true;
|
|
15712
|
+
});
|
|
15268
15713
|
}
|
|
15714
|
+
var QUICK_INSTALL_PRESETS = {
|
|
15715
|
+
essential: [
|
|
15716
|
+
{
|
|
15717
|
+
id: "context7",
|
|
15718
|
+
name: "Context7 MCP",
|
|
15719
|
+
type: "mcp",
|
|
15720
|
+
description: "Up-to-date library documentation",
|
|
15721
|
+
installCommand: "claude mcp add context7 https://mcp.context7.com/mcp --transport http",
|
|
15722
|
+
selected: true
|
|
15723
|
+
},
|
|
15724
|
+
{
|
|
15725
|
+
id: "supermemory",
|
|
15726
|
+
name: "Supermemory MCP",
|
|
15727
|
+
type: "mcp",
|
|
15728
|
+
description: "Persistent memory across sessions",
|
|
15729
|
+
installCommand: "claude mcp add supermemory -- npx -y @supermemory/mcp@latest",
|
|
15730
|
+
selected: true
|
|
15731
|
+
},
|
|
15732
|
+
{
|
|
15733
|
+
id: "beads",
|
|
15734
|
+
name: "Beads Task Manager",
|
|
15735
|
+
type: "mcp",
|
|
15736
|
+
description: "Persistent task tracking",
|
|
15737
|
+
installCommand: "bun add -g beads && bd init",
|
|
15738
|
+
selected: true
|
|
15739
|
+
}
|
|
15740
|
+
],
|
|
15741
|
+
productivity: [
|
|
15742
|
+
{
|
|
15743
|
+
id: "claude-md",
|
|
15744
|
+
name: "CLAUDE.md",
|
|
15745
|
+
type: "config",
|
|
15746
|
+
description: "Project context file",
|
|
15747
|
+
configPath: "CLAUDE.md",
|
|
15748
|
+
configContent: `# Project Instructions
|
|
15749
|
+
|
|
15750
|
+
## Build & Test Commands
|
|
15751
|
+
\`\`\`bash
|
|
15752
|
+
bun test # Run tests
|
|
15753
|
+
bun run build # Build project
|
|
15754
|
+
bun run lint # Run linter
|
|
15755
|
+
\`\`\`
|
|
15756
|
+
|
|
15757
|
+
## Architecture
|
|
15758
|
+
Describe your project structure here.
|
|
15759
|
+
|
|
15760
|
+
## Conventions
|
|
15761
|
+
- Use TypeScript
|
|
15762
|
+
- Write tests for new features
|
|
15763
|
+
- Use conventional commits
|
|
15764
|
+
`,
|
|
15765
|
+
selected: true
|
|
15766
|
+
},
|
|
15767
|
+
{
|
|
15768
|
+
id: "vitest",
|
|
15769
|
+
name: "Vitest",
|
|
15770
|
+
type: "library",
|
|
15771
|
+
description: "Fast unit testing framework",
|
|
15772
|
+
installCommand: "bun add -D vitest",
|
|
15773
|
+
selected: true
|
|
15774
|
+
}
|
|
15775
|
+
]
|
|
15776
|
+
};
|
|
15269
15777
|
|
|
15270
15778
|
// src/commands/scan.ts
|
|
15271
15779
|
var scanCommand = defineCommand2({
|
|
@@ -15489,10 +15997,19 @@ var scanCommand = defineCommand2({
|
|
|
15489
15997
|
console.log(colors2.dim(" " + "═".repeat(45)));
|
|
15490
15998
|
console.log();
|
|
15491
15999
|
if (!args["no-report"]) {
|
|
15492
|
-
const reportDir =
|
|
16000
|
+
const reportDir = join9(projectDir, args["report-dir"]);
|
|
15493
16001
|
const reportPath = generateReport(reportDir, score, git, agents, tests, args.since, sdlcAnalysis, scanCost, analysis);
|
|
15494
16002
|
console.log(` ${icons.success} Report saved: ${colors2.dim(reportPath)}`);
|
|
15495
16003
|
}
|
|
16004
|
+
if (agents && agents.sessions.length > 0 && !args.brief) {
|
|
16005
|
+
const frustrationSummary = detectFrustrations(agents.sessions);
|
|
16006
|
+
if (frustrationSummary.totalFrustrations > 0) {
|
|
16007
|
+
const frustrationLines = formatFrustrationSummary(frustrationSummary);
|
|
16008
|
+
for (const line of frustrationLines) {
|
|
16009
|
+
console.log(line);
|
|
16010
|
+
}
|
|
16011
|
+
}
|
|
16012
|
+
}
|
|
15496
16013
|
if (!args.brief) {
|
|
15497
16014
|
const installedStatus = checkInstalledStatus(projectDir);
|
|
15498
16015
|
const projectContext = loadProjectContext(projectDir);
|
|
@@ -15754,12 +16271,12 @@ var scanCommand = defineCommand2({
|
|
|
15754
16271
|
}
|
|
15755
16272
|
});
|
|
15756
16273
|
function loadProjectContext(projectDir) {
|
|
15757
|
-
const contextPath =
|
|
15758
|
-
if (!
|
|
16274
|
+
const contextPath = join9(projectDir, ".nairon", "context.json");
|
|
16275
|
+
if (!existsSync9(contextPath)) {
|
|
15759
16276
|
return null;
|
|
15760
16277
|
}
|
|
15761
16278
|
try {
|
|
15762
|
-
const raw =
|
|
16279
|
+
const raw = readFileSync9(contextPath, "utf-8");
|
|
15763
16280
|
const data = JSON.parse(raw);
|
|
15764
16281
|
const context = {
|
|
15765
16282
|
painPoints: data.painPoints || [],
|
|
@@ -15812,12 +16329,12 @@ function parseSince(since) {
|
|
|
15812
16329
|
return new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
|
|
15813
16330
|
}
|
|
15814
16331
|
function generateReport(reportDir, score, git, agents, tests, since, sdlcAnalysis, scanCost, analysis) {
|
|
15815
|
-
if (!
|
|
16332
|
+
if (!existsSync9(reportDir)) {
|
|
15816
16333
|
mkdirSync4(reportDir, { recursive: true });
|
|
15817
16334
|
}
|
|
15818
16335
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
15819
16336
|
const filename = `scan-${timestamp}.md`;
|
|
15820
|
-
const filepath =
|
|
16337
|
+
const filepath = join9(reportDir, filename);
|
|
15821
16338
|
const lines = [];
|
|
15822
16339
|
lines.push(`# NaironAI Scan Report`);
|
|
15823
16340
|
lines.push("");
|
|
@@ -15958,11 +16475,11 @@ init_dist();
|
|
|
15958
16475
|
init_client();
|
|
15959
16476
|
|
|
15960
16477
|
// src/collectors/report-data.ts
|
|
15961
|
-
import { existsSync as
|
|
15962
|
-
import { homedir as
|
|
15963
|
-
import { join as
|
|
16478
|
+
import { existsSync as existsSync10, readdirSync as readdirSync5, readFileSync as readFileSync10, statSync as statSync2 } from "node:fs";
|
|
16479
|
+
import { homedir as homedir8 } from "node:os";
|
|
16480
|
+
import { join as join10, basename as basename3 } from "node:path";
|
|
15964
16481
|
async function collectReportData(projectDir, since, until = new Date, harness) {
|
|
15965
|
-
const projectName =
|
|
16482
|
+
const projectName = basename3(projectDir);
|
|
15966
16483
|
const [commits, allSessions, mcpConfigs] = await Promise.all([
|
|
15967
16484
|
collectGitCommits(projectDir, since, until),
|
|
15968
16485
|
collectAllSessions(since, until, projectDir),
|
|
@@ -16043,12 +16560,12 @@ function detectAIAssistedCommit(message) {
|
|
|
16043
16560
|
}
|
|
16044
16561
|
async function collectAllSessions(since, until, projectDir) {
|
|
16045
16562
|
const sessions = [];
|
|
16046
|
-
const claudeDir =
|
|
16047
|
-
if (
|
|
16563
|
+
const claudeDir = join10(homedir8(), ".claude");
|
|
16564
|
+
if (existsSync10(claudeDir)) {
|
|
16048
16565
|
sessions.push(...collectClaudeCodeSessions(claudeDir, since, until, projectDir));
|
|
16049
16566
|
}
|
|
16050
|
-
const openCodeDir =
|
|
16051
|
-
if (
|
|
16567
|
+
const openCodeDir = join10(homedir8(), ".local", "share", "opencode");
|
|
16568
|
+
if (existsSync10(openCodeDir)) {
|
|
16052
16569
|
sessions.push(...collectOpenCodeSessions2(openCodeDir, since, until));
|
|
16053
16570
|
}
|
|
16054
16571
|
sessions.sort((a2, b2) => a2.startTime.getTime() - b2.startTime.getTime());
|
|
@@ -16056,15 +16573,15 @@ async function collectAllSessions(since, until, projectDir) {
|
|
|
16056
16573
|
}
|
|
16057
16574
|
function collectClaudeCodeSessions(claudeDir, since, until, projectDir) {
|
|
16058
16575
|
const sessions = [];
|
|
16059
|
-
const transcriptsDir =
|
|
16060
|
-
if (!
|
|
16576
|
+
const transcriptsDir = join10(claudeDir, "transcripts");
|
|
16577
|
+
if (!existsSync10(transcriptsDir))
|
|
16061
16578
|
return sessions;
|
|
16062
16579
|
const projectHash = projectDir ? hashPath(projectDir) : null;
|
|
16063
|
-
const projectsDir =
|
|
16580
|
+
const projectsDir = join10(claudeDir, "projects");
|
|
16064
16581
|
try {
|
|
16065
16582
|
const transcriptFiles = readdirSync5(transcriptsDir).filter((f3) => f3.endsWith(".jsonl"));
|
|
16066
16583
|
for (const file of transcriptFiles) {
|
|
16067
|
-
const filePath =
|
|
16584
|
+
const filePath = join10(transcriptsDir, file);
|
|
16068
16585
|
const stat = statSync2(filePath);
|
|
16069
16586
|
if (stat.mtime < since || stat.mtime > until)
|
|
16070
16587
|
continue;
|
|
@@ -16075,12 +16592,12 @@ function collectClaudeCodeSessions(claudeDir, since, until, projectDir) {
|
|
|
16075
16592
|
}
|
|
16076
16593
|
} catch {}
|
|
16077
16594
|
}
|
|
16078
|
-
if (projectHash &&
|
|
16079
|
-
const projectSessionDir =
|
|
16080
|
-
if (
|
|
16595
|
+
if (projectHash && existsSync10(projectsDir)) {
|
|
16596
|
+
const projectSessionDir = join10(projectsDir, projectHash);
|
|
16597
|
+
if (existsSync10(projectSessionDir)) {
|
|
16081
16598
|
const projectFiles = readdirSync5(projectSessionDir).filter((f3) => f3.endsWith(".jsonl"));
|
|
16082
16599
|
for (const file of projectFiles) {
|
|
16083
|
-
const filePath =
|
|
16600
|
+
const filePath = join10(projectSessionDir, file);
|
|
16084
16601
|
const stat = statSync2(filePath);
|
|
16085
16602
|
if (stat.mtime < since || stat.mtime > until)
|
|
16086
16603
|
continue;
|
|
@@ -16099,7 +16616,7 @@ function collectClaudeCodeSessions(claudeDir, since, until, projectDir) {
|
|
|
16099
16616
|
return sessions;
|
|
16100
16617
|
}
|
|
16101
16618
|
function parseClaudeTranscript(filePath, fileName) {
|
|
16102
|
-
const content =
|
|
16619
|
+
const content = readFileSync10(filePath, "utf-8");
|
|
16103
16620
|
const lines = content.trim().split(`
|
|
16104
16621
|
`).filter((l2) => l2.trim());
|
|
16105
16622
|
if (lines.length === 0)
|
|
@@ -16189,25 +16706,25 @@ function parseClaudeTranscript(filePath, fileName) {
|
|
|
16189
16706
|
}
|
|
16190
16707
|
function collectOpenCodeSessions2(openCodeDir, since, until) {
|
|
16191
16708
|
const sessions = [];
|
|
16192
|
-
const sessionDir =
|
|
16193
|
-
const messageDir =
|
|
16194
|
-
const partDir =
|
|
16195
|
-
if (!
|
|
16709
|
+
const sessionDir = join10(openCodeDir, "storage", "session");
|
|
16710
|
+
const messageDir = join10(openCodeDir, "storage", "message");
|
|
16711
|
+
const partDir = join10(openCodeDir, "storage", "part");
|
|
16712
|
+
if (!existsSync10(sessionDir))
|
|
16196
16713
|
return sessions;
|
|
16197
16714
|
try {
|
|
16198
|
-
const projectDirs = readdirSync5(sessionDir, { withFileTypes: true }).filter((d2) => d2.isDirectory()).map((d2) =>
|
|
16715
|
+
const projectDirs = readdirSync5(sessionDir, { withFileTypes: true }).filter((d2) => d2.isDirectory()).map((d2) => join10(sessionDir, d2.name));
|
|
16199
16716
|
for (const projectDir of projectDirs) {
|
|
16200
16717
|
const sessionFiles = readdirSync5(projectDir).filter((f3) => f3.endsWith(".json"));
|
|
16201
16718
|
for (const sessionFile of sessionFiles) {
|
|
16202
16719
|
try {
|
|
16203
|
-
const sessionPath =
|
|
16204
|
-
const sessionData = JSON.parse(
|
|
16720
|
+
const sessionPath = join10(projectDir, sessionFile);
|
|
16721
|
+
const sessionData = JSON.parse(readFileSync10(sessionPath, "utf-8"));
|
|
16205
16722
|
const createdAt = new Date(sessionData.time?.created || 0);
|
|
16206
16723
|
const updatedAt = new Date(sessionData.time?.updated || sessionData.time?.created || 0);
|
|
16207
16724
|
if (updatedAt < since || createdAt > until)
|
|
16208
16725
|
continue;
|
|
16209
16726
|
const sessionId = sessionData.id;
|
|
16210
|
-
const sessionMsgDir =
|
|
16727
|
+
const sessionMsgDir = join10(messageDir, sessionId);
|
|
16211
16728
|
const prompts = [];
|
|
16212
16729
|
const responses = [];
|
|
16213
16730
|
const toolsUsed = new Set;
|
|
@@ -16218,12 +16735,12 @@ function collectOpenCodeSessions2(openCodeDir, since, until) {
|
|
|
16218
16735
|
let model = "unknown";
|
|
16219
16736
|
let startTime = createdAt;
|
|
16220
16737
|
let endTime = updatedAt;
|
|
16221
|
-
if (
|
|
16738
|
+
if (existsSync10(sessionMsgDir)) {
|
|
16222
16739
|
const msgFiles = readdirSync5(sessionMsgDir).filter((f3) => f3.endsWith(".json")).sort();
|
|
16223
16740
|
for (const msgFile of msgFiles) {
|
|
16224
16741
|
try {
|
|
16225
|
-
const msgPath =
|
|
16226
|
-
const msgData = JSON.parse(
|
|
16742
|
+
const msgPath = join10(sessionMsgDir, msgFile);
|
|
16743
|
+
const msgData = JSON.parse(readFileSync10(msgPath, "utf-8"));
|
|
16227
16744
|
const msgId = msgData.id;
|
|
16228
16745
|
if (msgData.model?.modelID) {
|
|
16229
16746
|
model = msgData.model.modelID;
|
|
@@ -16233,14 +16750,14 @@ function collectOpenCodeSessions2(openCodeDir, since, until) {
|
|
|
16233
16750
|
startTime = msgTime;
|
|
16234
16751
|
if (msgTime > endTime)
|
|
16235
16752
|
endTime = msgTime;
|
|
16236
|
-
const msgPartDir =
|
|
16753
|
+
const msgPartDir = join10(partDir, msgId);
|
|
16237
16754
|
let messageText = "";
|
|
16238
|
-
if (
|
|
16755
|
+
if (existsSync10(msgPartDir)) {
|
|
16239
16756
|
const partFiles = readdirSync5(msgPartDir).filter((f3) => f3.endsWith(".json")).sort();
|
|
16240
16757
|
for (const partFile of partFiles) {
|
|
16241
16758
|
try {
|
|
16242
|
-
const partPath =
|
|
16243
|
-
const partData = JSON.parse(
|
|
16759
|
+
const partPath = join10(msgPartDir, partFile);
|
|
16760
|
+
const partData = JSON.parse(readFileSync10(partPath, "utf-8"));
|
|
16244
16761
|
if (partData.type === "text" && partData.text && !partData.synthetic) {
|
|
16245
16762
|
messageText += partData.text + `
|
|
16246
16763
|
`;
|
|
@@ -16414,10 +16931,10 @@ function analyzeResponse(text, sessionId, index, promptId, timestamp) {
|
|
|
16414
16931
|
}
|
|
16415
16932
|
function collectMCPConfigs() {
|
|
16416
16933
|
const configs = [];
|
|
16417
|
-
const claudeConfig =
|
|
16418
|
-
if (
|
|
16934
|
+
const claudeConfig = join10(homedir8(), ".claude.json");
|
|
16935
|
+
if (existsSync10(claudeConfig)) {
|
|
16419
16936
|
try {
|
|
16420
|
-
const data = JSON.parse(
|
|
16937
|
+
const data = JSON.parse(readFileSync10(claudeConfig, "utf-8"));
|
|
16421
16938
|
const mcpServers = data.mcpServers || {};
|
|
16422
16939
|
for (const [name, config] of Object.entries(mcpServers)) {
|
|
16423
16940
|
configs.push({
|
|
@@ -16430,13 +16947,13 @@ function collectMCPConfigs() {
|
|
|
16430
16947
|
} catch {}
|
|
16431
16948
|
}
|
|
16432
16949
|
const openCodeConfigs = [
|
|
16433
|
-
|
|
16434
|
-
|
|
16950
|
+
join10(homedir8(), ".opencode.json"),
|
|
16951
|
+
join10(homedir8(), ".config", "opencode", "opencode.json")
|
|
16435
16952
|
];
|
|
16436
16953
|
for (const configPath of openCodeConfigs) {
|
|
16437
|
-
if (
|
|
16954
|
+
if (existsSync10(configPath)) {
|
|
16438
16955
|
try {
|
|
16439
|
-
const data = JSON.parse(
|
|
16956
|
+
const data = JSON.parse(readFileSync10(configPath, "utf-8"));
|
|
16440
16957
|
const mcpServers = data.mcp || {};
|
|
16441
16958
|
for (const [name, config] of Object.entries(mcpServers)) {
|
|
16442
16959
|
if (!configs.find((c3) => c3.name === name)) {
|
|
@@ -16451,10 +16968,10 @@ function collectMCPConfigs() {
|
|
|
16451
16968
|
} catch {}
|
|
16452
16969
|
}
|
|
16453
16970
|
}
|
|
16454
|
-
const cursorConfig =
|
|
16455
|
-
if (
|
|
16971
|
+
const cursorConfig = join10(homedir8(), ".cursor", "mcp.json");
|
|
16972
|
+
if (existsSync10(cursorConfig)) {
|
|
16456
16973
|
try {
|
|
16457
|
-
const data = JSON.parse(
|
|
16974
|
+
const data = JSON.parse(readFileSync10(cursorConfig, "utf-8"));
|
|
16458
16975
|
const mcpServers = data.mcpServers || {};
|
|
16459
16976
|
for (const [name, config] of Object.entries(mcpServers)) {
|
|
16460
16977
|
if (!configs.find((c3) => c3.name === name)) {
|
|
@@ -18655,9 +19172,9 @@ function getSeverityEmoji(severity) {
|
|
|
18655
19172
|
}
|
|
18656
19173
|
|
|
18657
19174
|
// src/lib/tool-analyzer.ts
|
|
18658
|
-
import { existsSync as
|
|
18659
|
-
import { homedir as
|
|
18660
|
-
import { join as
|
|
19175
|
+
import { existsSync as existsSync11, readdirSync as readdirSync6 } from "node:fs";
|
|
19176
|
+
import { homedir as homedir9 } from "node:os";
|
|
19177
|
+
import { join as join11 } from "node:path";
|
|
18661
19178
|
function analyzeToolUtilization(data) {
|
|
18662
19179
|
const mcpServers = analyzeMCPServers(data);
|
|
18663
19180
|
const mcpSummary = buildMCPSummary(mcpServers);
|
|
@@ -18807,24 +19324,24 @@ function categorizeTools(tools) {
|
|
|
18807
19324
|
}
|
|
18808
19325
|
function analyzeSkills() {
|
|
18809
19326
|
const skills = [];
|
|
18810
|
-
const home =
|
|
19327
|
+
const home = homedir9();
|
|
18811
19328
|
const skillsDirs = [
|
|
18812
|
-
|
|
18813
|
-
|
|
18814
|
-
|
|
19329
|
+
join11(home, ".claude", "skills"),
|
|
19330
|
+
join11(home, ".agents", "skills"),
|
|
19331
|
+
join11(home, ".config", "claude", "skills")
|
|
18815
19332
|
];
|
|
18816
19333
|
const projectSkillsDirs = [
|
|
18817
|
-
|
|
18818
|
-
|
|
19334
|
+
join11(process.cwd(), ".claude", "skills"),
|
|
19335
|
+
join11(process.cwd(), ".agents", "skills")
|
|
18819
19336
|
];
|
|
18820
19337
|
const openCodeSkillDirs = [
|
|
18821
|
-
|
|
18822
|
-
|
|
19338
|
+
join11(home, ".config", "opencode", "skills"),
|
|
19339
|
+
join11(home, ".local", "share", "opencode", "skills")
|
|
18823
19340
|
];
|
|
18824
19341
|
const allSkillDirs = [...skillsDirs, ...projectSkillsDirs, ...openCodeSkillDirs];
|
|
18825
19342
|
const seenSkills = new Set;
|
|
18826
19343
|
for (const skillsDir of allSkillDirs) {
|
|
18827
|
-
if (
|
|
19344
|
+
if (existsSync11(skillsDir)) {
|
|
18828
19345
|
try {
|
|
18829
19346
|
const entries = readdirSync6(skillsDir, { withFileTypes: true });
|
|
18830
19347
|
for (const entry of entries) {
|
|
@@ -18835,7 +19352,7 @@ function analyzeSkills() {
|
|
|
18835
19352
|
if (entry.isDirectory() || entry.isSymbolicLink() || entry.name.endsWith(".md")) {
|
|
18836
19353
|
skills.push({
|
|
18837
19354
|
name: skillName,
|
|
18838
|
-
path:
|
|
19355
|
+
path: join11(skillsDir, entry.name),
|
|
18839
19356
|
used: false,
|
|
18840
19357
|
usageCount: 0
|
|
18841
19358
|
});
|
|
@@ -19132,22 +19649,22 @@ function renderToolUtilizationMarkdown(analysis) {
|
|
|
19132
19649
|
}
|
|
19133
19650
|
|
|
19134
19651
|
// src/lib/coverage-parser.ts
|
|
19135
|
-
import { existsSync as
|
|
19136
|
-
import { join as
|
|
19652
|
+
import { existsSync as existsSync12, readFileSync as readFileSync12 } from "node:fs";
|
|
19653
|
+
import { join as join12 } from "node:path";
|
|
19137
19654
|
function parseCoverageReport(projectDir) {
|
|
19138
19655
|
const coveragePaths = [
|
|
19139
|
-
{ path:
|
|
19140
|
-
{ path:
|
|
19141
|
-
{ path:
|
|
19142
|
-
{ path:
|
|
19143
|
-
{ path:
|
|
19144
|
-
{ path:
|
|
19145
|
-
{ path:
|
|
19656
|
+
{ path: join12(projectDir, "coverage", "lcov.info"), parser: parseLcov },
|
|
19657
|
+
{ path: join12(projectDir, "coverage", "coverage-summary.json"), parser: parseIstanbulSummary },
|
|
19658
|
+
{ path: join12(projectDir, "coverage", "coverage-final.json"), parser: parseIstanbulFinal },
|
|
19659
|
+
{ path: join12(projectDir, "coverage", "cobertura-coverage.xml"), parser: parseCobertura },
|
|
19660
|
+
{ path: join12(projectDir, "coverage", "clover.xml"), parser: parseClover },
|
|
19661
|
+
{ path: join12(projectDir, "lcov.info"), parser: parseLcov },
|
|
19662
|
+
{ path: join12(projectDir, ".nyc_output", "coverage-summary.json"), parser: parseIstanbulSummary }
|
|
19146
19663
|
];
|
|
19147
19664
|
for (const { path, parser: parser4 } of coveragePaths) {
|
|
19148
|
-
if (
|
|
19665
|
+
if (existsSync12(path)) {
|
|
19149
19666
|
try {
|
|
19150
|
-
const content =
|
|
19667
|
+
const content = readFileSync12(path, "utf-8");
|
|
19151
19668
|
return parser4(content, path);
|
|
19152
19669
|
} catch {}
|
|
19153
19670
|
}
|
|
@@ -21357,9 +21874,9 @@ function renderBar4(value, width) {
|
|
|
21357
21874
|
}
|
|
21358
21875
|
|
|
21359
21876
|
// src/commands/doctor.ts
|
|
21360
|
-
import { existsSync as
|
|
21361
|
-
import { homedir as
|
|
21362
|
-
import { join as
|
|
21877
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
21878
|
+
import { homedir as homedir10 } from "node:os";
|
|
21879
|
+
import { join as join13 } from "node:path";
|
|
21363
21880
|
init_client();
|
|
21364
21881
|
|
|
21365
21882
|
// src/lib/recommendations-db.ts
|
|
@@ -22016,16 +22533,16 @@ var doctorCommand = defineCommand2({
|
|
|
22016
22533
|
results.push({ label: "OS", status: "info", value: `${process.platform} ${process.arch}` });
|
|
22017
22534
|
results.push({ label: "Bun", status: "info", value: typeof Bun !== "undefined" ? Bun.version : "N/A" });
|
|
22018
22535
|
results.push({ label: "Node", status: "info", value: process.version });
|
|
22019
|
-
results.push({ label: "Home", status: "info", value:
|
|
22020
|
-
const gitDir =
|
|
22021
|
-
if (
|
|
22536
|
+
results.push({ label: "Home", status: "info", value: homedir10() });
|
|
22537
|
+
const gitDir = join13(process.cwd(), ".git");
|
|
22538
|
+
if (existsSync13(gitDir)) {
|
|
22022
22539
|
results.push({ label: "Git", status: "success", value: "Repository detected" });
|
|
22023
22540
|
} else {
|
|
22024
22541
|
results.push({ label: "Git", status: "warn", value: "No repository in current directory" });
|
|
22025
22542
|
}
|
|
22026
22543
|
for (const [agent, pathTemplate] of Object.entries(AGENT_LOG_PATHS)) {
|
|
22027
|
-
const resolvedPath = pathTemplate.replace("~",
|
|
22028
|
-
if (
|
|
22544
|
+
const resolvedPath = pathTemplate.replace("~", homedir10());
|
|
22545
|
+
if (existsSync13(resolvedPath)) {
|
|
22029
22546
|
results.push({ label: agent, status: "success", value: `found at ${resolvedPath}` });
|
|
22030
22547
|
}
|
|
22031
22548
|
}
|
|
@@ -22079,9 +22596,9 @@ var doctorCommand = defineCommand2({
|
|
|
22079
22596
|
});
|
|
22080
22597
|
|
|
22081
22598
|
// src/commands/setup.ts
|
|
22082
|
-
import { existsSync as
|
|
22083
|
-
import { join as
|
|
22084
|
-
import { homedir as
|
|
22599
|
+
import { existsSync as existsSync14, readFileSync as readFileSync13, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, copyFileSync } from "node:fs";
|
|
22600
|
+
import { join as join14, dirname as dirname2 } from "node:path";
|
|
22601
|
+
import { homedir as homedir11, platform as platform2 } from "node:os";
|
|
22085
22602
|
import { execSync as execSync3 } from "node:child_process";
|
|
22086
22603
|
import { createInterface } from "node:readline";
|
|
22087
22604
|
var CONVEX_SITE_URL = "https://steady-bass-841.convex.site";
|
|
@@ -22100,7 +22617,7 @@ var FALLBACK_HARNESSES = [
|
|
|
22100
22617
|
id: "claude-code",
|
|
22101
22618
|
name: "Claude Code",
|
|
22102
22619
|
configPaths: [
|
|
22103
|
-
|
|
22620
|
+
join14(homedir11(), ".claude.json")
|
|
22104
22621
|
],
|
|
22105
22622
|
mcpConfigKey: "mcpServers",
|
|
22106
22623
|
detected: false
|
|
@@ -22109,8 +22626,8 @@ var FALLBACK_HARNESSES = [
|
|
|
22109
22626
|
id: "opencode",
|
|
22110
22627
|
name: "OpenCode",
|
|
22111
22628
|
configPaths: [
|
|
22112
|
-
|
|
22113
|
-
|
|
22629
|
+
join14(homedir11(), ".opencode.json"),
|
|
22630
|
+
join14(homedir11(), ".config", "opencode", "opencode.json")
|
|
22114
22631
|
],
|
|
22115
22632
|
mcpConfigKey: "mcp",
|
|
22116
22633
|
detected: false
|
|
@@ -22119,8 +22636,8 @@ var FALLBACK_HARNESSES = [
|
|
|
22119
22636
|
id: "cursor",
|
|
22120
22637
|
name: "Cursor",
|
|
22121
22638
|
configPaths: [
|
|
22122
|
-
|
|
22123
|
-
|
|
22639
|
+
join14(homedir11(), ".cursor", "mcp.json"),
|
|
22640
|
+
join14(homedir11(), "Library", "Application Support", "Cursor", "User", "globalStorage", "mcp.json")
|
|
22124
22641
|
],
|
|
22125
22642
|
mcpConfigKey: "mcpServers",
|
|
22126
22643
|
detected: false
|
|
@@ -22137,7 +22654,7 @@ function getConfigPathsForPlatform(harness) {
|
|
|
22137
22654
|
} else {
|
|
22138
22655
|
paths = pathMap.linux;
|
|
22139
22656
|
}
|
|
22140
|
-
return paths.map((p) => p.replace(/^~/,
|
|
22657
|
+
return paths.map((p) => p.replace(/^~/, homedir11()).replace(/%USERPROFILE%/gi, homedir11()).replace(/%APPDATA%/gi, join14(homedir11(), "AppData", "Roaming")));
|
|
22141
22658
|
}
|
|
22142
22659
|
function convertAPIHarnessToConfig(harness) {
|
|
22143
22660
|
return {
|
|
@@ -22152,7 +22669,7 @@ function detectHarnesses(harnesses) {
|
|
|
22152
22669
|
const detected = [];
|
|
22153
22670
|
for (const harness of harnesses) {
|
|
22154
22671
|
for (const configPath of harness.configPaths) {
|
|
22155
|
-
if (
|
|
22672
|
+
if (existsSync14(configPath)) {
|
|
22156
22673
|
detected.push({
|
|
22157
22674
|
...harness,
|
|
22158
22675
|
detected: true,
|
|
@@ -22165,19 +22682,19 @@ function detectHarnesses(harnesses) {
|
|
|
22165
22682
|
return detected;
|
|
22166
22683
|
}
|
|
22167
22684
|
function backupConfig(configPath) {
|
|
22168
|
-
const backupDir =
|
|
22169
|
-
if (!
|
|
22685
|
+
const backupDir = join14(homedir11(), ".nairon", "backups");
|
|
22686
|
+
if (!existsSync14(backupDir)) {
|
|
22170
22687
|
mkdirSync5(backupDir, { recursive: true });
|
|
22171
22688
|
}
|
|
22172
22689
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
22173
22690
|
const filename = configPath.replace(/[/\\]/g, "_").replace(/^_/, "");
|
|
22174
|
-
const backupPath =
|
|
22691
|
+
const backupPath = join14(backupDir, `${timestamp}_${filename}`);
|
|
22175
22692
|
copyFileSync(configPath, backupPath);
|
|
22176
22693
|
return backupPath;
|
|
22177
22694
|
}
|
|
22178
22695
|
function readJsonConfig(configPath) {
|
|
22179
22696
|
try {
|
|
22180
|
-
const content =
|
|
22697
|
+
const content = readFileSync13(configPath, "utf-8");
|
|
22181
22698
|
return JSON.parse(content);
|
|
22182
22699
|
} catch {
|
|
22183
22700
|
return {};
|
|
@@ -22185,7 +22702,7 @@ function readJsonConfig(configPath) {
|
|
|
22185
22702
|
}
|
|
22186
22703
|
function writeJsonConfig(configPath, config) {
|
|
22187
22704
|
const dir = dirname2(configPath);
|
|
22188
|
-
if (!
|
|
22705
|
+
if (!existsSync14(dir)) {
|
|
22189
22706
|
mkdirSync5(dir, { recursive: true });
|
|
22190
22707
|
}
|
|
22191
22708
|
writeFileSync6(configPath, JSON.stringify(config, null, 2));
|
|
@@ -22229,7 +22746,7 @@ function getInstalledMCPs(harnesses) {
|
|
|
22229
22746
|
const installed = new Set;
|
|
22230
22747
|
for (const harness of harnesses) {
|
|
22231
22748
|
for (const configPath of harness.configPaths) {
|
|
22232
|
-
if (!
|
|
22749
|
+
if (!existsSync14(configPath))
|
|
22233
22750
|
continue;
|
|
22234
22751
|
const config = readJsonConfig(configPath);
|
|
22235
22752
|
const mcpServers = config[harness.mcpConfigKey];
|
|
@@ -22253,7 +22770,7 @@ async function installMCPServer(serverName, instruction, harness) {
|
|
|
22253
22770
|
if (!harness.configPath || !instruction.mcpServerConfig)
|
|
22254
22771
|
return false;
|
|
22255
22772
|
try {
|
|
22256
|
-
if (
|
|
22773
|
+
if (existsSync14(harness.configPath)) {
|
|
22257
22774
|
backupConfig(harness.configPath);
|
|
22258
22775
|
}
|
|
22259
22776
|
const config = readJsonConfig(harness.configPath);
|
|
@@ -22298,8 +22815,8 @@ async function installBeads(projectDir) {
|
|
|
22298
22815
|
}
|
|
22299
22816
|
}
|
|
22300
22817
|
}
|
|
22301
|
-
const beadsDir =
|
|
22302
|
-
if (!
|
|
22818
|
+
const beadsDir = join14(projectDir, ".beads");
|
|
22819
|
+
if (!existsSync14(beadsDir)) {
|
|
22303
22820
|
const projectName = projectDir.split(/[/\\]/).pop() ?? "project";
|
|
22304
22821
|
const initSpinner = createSpinner(`Initializing Beads in ${projectName}...`);
|
|
22305
22822
|
initSpinner.start();
|
|
@@ -22318,9 +22835,9 @@ async function installBeads(projectDir) {
|
|
|
22318
22835
|
}
|
|
22319
22836
|
}
|
|
22320
22837
|
async function createClaudeRules(projectDir) {
|
|
22321
|
-
const claudeMdPath =
|
|
22322
|
-
const agentsMdPath =
|
|
22323
|
-
if (
|
|
22838
|
+
const claudeMdPath = join14(projectDir, "CLAUDE.md");
|
|
22839
|
+
const agentsMdPath = join14(projectDir, "AGENTS.md");
|
|
22840
|
+
if (existsSync14(claudeMdPath) || existsSync14(agentsMdPath)) {
|
|
22324
22841
|
console.log(` ${icons.info} CLAUDE.md or AGENTS.md already exists`);
|
|
22325
22842
|
return true;
|
|
22326
22843
|
}
|
|
@@ -22643,6 +23160,26 @@ var BOLD = "\x1B[1m";
|
|
|
22643
23160
|
var RESET = "\x1B[0m";
|
|
22644
23161
|
var MAGENTA = "\x1B[35m";
|
|
22645
23162
|
var CHANGELOG = [
|
|
23163
|
+
{
|
|
23164
|
+
version: "0.3.15",
|
|
23165
|
+
date: "2026-02-14",
|
|
23166
|
+
title: "Contextual Recommendations",
|
|
23167
|
+
highlights: [
|
|
23168
|
+
"Recommendations now linked to specific frustrations they prevent",
|
|
23169
|
+
"Total time and cost savings summary",
|
|
23170
|
+
"See exactly which issues each tool would have fixed"
|
|
23171
|
+
]
|
|
23172
|
+
},
|
|
23173
|
+
{
|
|
23174
|
+
version: "0.3.14",
|
|
23175
|
+
date: "2026-02-14",
|
|
23176
|
+
title: "Enhanced Frustration Detection",
|
|
23177
|
+
highlights: [
|
|
23178
|
+
"Scan now shows exact prompts that caused frustration",
|
|
23179
|
+
"Root cause analysis: hallucination, context loss, undo loops",
|
|
23180
|
+
"Each frustration linked to a specific fix with install command"
|
|
23181
|
+
]
|
|
23182
|
+
},
|
|
22646
23183
|
{
|
|
22647
23184
|
version: "0.3.13",
|
|
22648
23185
|
date: "2026-02-14",
|
|
@@ -23051,7 +23588,7 @@ function showFullChangelog() {
|
|
|
23051
23588
|
// package.json
|
|
23052
23589
|
var package_default = {
|
|
23053
23590
|
name: "nairon-bench",
|
|
23054
|
-
version: "0.3.
|
|
23591
|
+
version: "0.3.15",
|
|
23055
23592
|
description: "AI workflow benchmarking CLI",
|
|
23056
23593
|
type: "module",
|
|
23057
23594
|
bin: {
|
|
@@ -23110,9 +23647,9 @@ var versionCommand = defineCommand2({
|
|
|
23110
23647
|
|
|
23111
23648
|
// src/commands/init.ts
|
|
23112
23649
|
init_dist();
|
|
23113
|
-
import { existsSync as
|
|
23114
|
-
import { homedir as
|
|
23115
|
-
import { join as
|
|
23650
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
23651
|
+
import { homedir as homedir12, platform as platform3, arch } from "node:os";
|
|
23652
|
+
import { join as join15 } from "node:path";
|
|
23116
23653
|
init_client();
|
|
23117
23654
|
|
|
23118
23655
|
// src/lib/github-auth.ts
|
|
@@ -23282,8 +23819,8 @@ var initCommand = defineCommand2({
|
|
|
23282
23819
|
consola.start("Step 2/6: Detecting AI agents...");
|
|
23283
23820
|
const detectedAgents = [];
|
|
23284
23821
|
for (const [agent, pathTemplate] of Object.entries(AGENT_LOG_PATHS)) {
|
|
23285
|
-
const resolvedPath = pathTemplate.replace("~",
|
|
23286
|
-
if (
|
|
23822
|
+
const resolvedPath = pathTemplate.replace("~", homedir12());
|
|
23823
|
+
if (existsSync15(resolvedPath)) {
|
|
23287
23824
|
detectedAgents.push(agent);
|
|
23288
23825
|
consola.success(` Found: ${agent}`);
|
|
23289
23826
|
}
|
|
@@ -23386,7 +23923,7 @@ var initCommand = defineCommand2({
|
|
|
23386
23923
|
{ name: "playwright", configs: ["playwright.config.ts", "playwright.config.js"] }
|
|
23387
23924
|
];
|
|
23388
23925
|
for (const fw of testFrameworks) {
|
|
23389
|
-
if (fw.configs.some((c3) =>
|
|
23926
|
+
if (fw.configs.some((c3) => existsSync15(join15(process.cwd(), c3)))) {
|
|
23390
23927
|
toolStack.testing.push(fw.name);
|
|
23391
23928
|
}
|
|
23392
23929
|
}
|
|
@@ -23455,13 +23992,13 @@ var initCommand = defineCommand2({
|
|
|
23455
23992
|
});
|
|
23456
23993
|
function detectPackageManager() {
|
|
23457
23994
|
const cwd = process.cwd();
|
|
23458
|
-
if (
|
|
23995
|
+
if (existsSync15(join15(cwd, "bun.lock")) || existsSync15(join15(cwd, "bun.lockb")))
|
|
23459
23996
|
return "bun";
|
|
23460
|
-
if (
|
|
23997
|
+
if (existsSync15(join15(cwd, "pnpm-lock.yaml")))
|
|
23461
23998
|
return "pnpm";
|
|
23462
|
-
if (
|
|
23999
|
+
if (existsSync15(join15(cwd, "yarn.lock")))
|
|
23463
24000
|
return "yarn";
|
|
23464
|
-
if (
|
|
24001
|
+
if (existsSync15(join15(cwd, "package-lock.json")))
|
|
23465
24002
|
return "npm";
|
|
23466
24003
|
return;
|
|
23467
24004
|
}
|
|
@@ -23476,15 +24013,15 @@ var CLAUDE_CODE_SKILLS = [
|
|
|
23476
24013
|
];
|
|
23477
24014
|
function detectEasyWins(detectedAgents) {
|
|
23478
24015
|
const wins = [];
|
|
23479
|
-
const home =
|
|
24016
|
+
const home = homedir12();
|
|
23480
24017
|
const hasClaudeCode = detectedAgents.some((a2) => a2.toLowerCase().includes("claude") || a2.toLowerCase().includes("opencode"));
|
|
23481
|
-
const claudeConfigDir =
|
|
23482
|
-
const hasClaudeConfig =
|
|
24018
|
+
const claudeConfigDir = join15(home, ".claude");
|
|
24019
|
+
const hasClaudeConfig = existsSync15(claudeConfigDir);
|
|
23483
24020
|
if (hasClaudeCode || hasClaudeConfig) {
|
|
23484
|
-
const skillsDir =
|
|
24021
|
+
const skillsDir = join15(home, ".claude", "skills");
|
|
23485
24022
|
for (const skill of CLAUDE_CODE_SKILLS) {
|
|
23486
|
-
const skillPath =
|
|
23487
|
-
const isInstalled =
|
|
24023
|
+
const skillPath = join15(skillsDir, skill.id);
|
|
24024
|
+
const isInstalled = existsSync15(skillPath);
|
|
23488
24025
|
if (!isInstalled) {
|
|
23489
24026
|
wins.push({
|
|
23490
24027
|
icon: skill.icon,
|
|
@@ -23500,14 +24037,14 @@ function detectEasyWins(detectedAgents) {
|
|
|
23500
24037
|
// src/commands/onboard.ts
|
|
23501
24038
|
init_dist();
|
|
23502
24039
|
init_client();
|
|
23503
|
-
import { existsSync as
|
|
23504
|
-
import { join as
|
|
24040
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync6, readFileSync as readFileSync15, writeFileSync as writeFileSync7, readdirSync as readdirSync9 } from "node:fs";
|
|
24041
|
+
import { join as join17 } from "node:path";
|
|
23505
24042
|
|
|
23506
24043
|
// src/lib/project-context-detector.ts
|
|
23507
|
-
import { existsSync as
|
|
23508
|
-
import { join as
|
|
24044
|
+
import { existsSync as existsSync16, readFileSync as readFileSync14, readdirSync as readdirSync8 } from "node:fs";
|
|
24045
|
+
import { join as join16, basename as basename4 } from "node:path";
|
|
23509
24046
|
function detectProjectContext(projectDir) {
|
|
23510
|
-
const projectName =
|
|
24047
|
+
const projectName = basename4(projectDir);
|
|
23511
24048
|
const projectId = generateProjectId(projectDir);
|
|
23512
24049
|
const techStack = detectTechStack(projectDir);
|
|
23513
24050
|
const projectType = inferProjectType(projectDir, techStack);
|
|
@@ -23541,11 +24078,11 @@ function detectTechStack(projectDir) {
|
|
|
23541
24078
|
};
|
|
23542
24079
|
}
|
|
23543
24080
|
function readPackageJson(projectDir) {
|
|
23544
|
-
const pkgPath =
|
|
23545
|
-
if (!
|
|
24081
|
+
const pkgPath = join16(projectDir, "package.json");
|
|
24082
|
+
if (!existsSync16(pkgPath))
|
|
23546
24083
|
return {};
|
|
23547
24084
|
try {
|
|
23548
|
-
return JSON.parse(
|
|
24085
|
+
return JSON.parse(readFileSync14(pkgPath, "utf-8"));
|
|
23549
24086
|
} catch {
|
|
23550
24087
|
return {};
|
|
23551
24088
|
}
|
|
@@ -23566,34 +24103,34 @@ function detectFramework(deps) {
|
|
|
23566
24103
|
return null;
|
|
23567
24104
|
}
|
|
23568
24105
|
function detectMetaFramework(deps, projectDir) {
|
|
23569
|
-
if (deps.next ||
|
|
24106
|
+
if (deps.next || existsSync16(join16(projectDir, "next.config.js")) || existsSync16(join16(projectDir, "next.config.mjs")))
|
|
23570
24107
|
return "next";
|
|
23571
|
-
if (deps.nuxt ||
|
|
24108
|
+
if (deps.nuxt || existsSync16(join16(projectDir, "nuxt.config.ts")))
|
|
23572
24109
|
return "nuxt";
|
|
23573
24110
|
if (deps["@sveltejs/kit"])
|
|
23574
24111
|
return "sveltekit";
|
|
23575
|
-
if (deps.astro ||
|
|
24112
|
+
if (deps.astro || existsSync16(join16(projectDir, "astro.config.mjs")))
|
|
23576
24113
|
return "astro";
|
|
23577
24114
|
if (deps["@remix-run/react"])
|
|
23578
24115
|
return "remix";
|
|
23579
24116
|
if (deps.gatsby)
|
|
23580
24117
|
return "gatsby";
|
|
23581
|
-
if (deps.vite ||
|
|
24118
|
+
if (deps.vite || existsSync16(join16(projectDir, "vite.config.ts")))
|
|
23582
24119
|
return "vite";
|
|
23583
24120
|
return null;
|
|
23584
24121
|
}
|
|
23585
24122
|
function detectRuntime(projectDir) {
|
|
23586
|
-
if (
|
|
24123
|
+
if (existsSync16(join16(projectDir, "bun.lockb")) || existsSync16(join16(projectDir, "bun.lock")))
|
|
23587
24124
|
return "bun";
|
|
23588
|
-
if (
|
|
24125
|
+
if (existsSync16(join16(projectDir, "deno.json")) || existsSync16(join16(projectDir, "deno.lock")))
|
|
23589
24126
|
return "deno";
|
|
23590
24127
|
return "node";
|
|
23591
24128
|
}
|
|
23592
24129
|
function detectLanguage(projectDir) {
|
|
23593
|
-
if (
|
|
24130
|
+
if (existsSync16(join16(projectDir, "tsconfig.json")))
|
|
23594
24131
|
return "typescript";
|
|
23595
|
-
const srcDir =
|
|
23596
|
-
if (
|
|
24132
|
+
const srcDir = join16(projectDir, "src");
|
|
24133
|
+
if (existsSync16(srcDir)) {
|
|
23597
24134
|
try {
|
|
23598
24135
|
const files = readdirSync8(srcDir);
|
|
23599
24136
|
if (files.some((f3) => f3.endsWith(".ts") || f3.endsWith(".tsx")))
|
|
@@ -23604,7 +24141,7 @@ function detectLanguage(projectDir) {
|
|
|
23604
24141
|
}
|
|
23605
24142
|
function detectStyling(deps, projectDir) {
|
|
23606
24143
|
const tools = [];
|
|
23607
|
-
if (deps.tailwindcss ||
|
|
24144
|
+
if (deps.tailwindcss || existsSync16(join16(projectDir, "tailwind.config.js")) || existsSync16(join16(projectDir, "tailwind.config.ts")))
|
|
23608
24145
|
tools.push("tailwind");
|
|
23609
24146
|
if (deps["styled-components"])
|
|
23610
24147
|
tools.push("styled-components");
|
|
@@ -23649,13 +24186,13 @@ function detectORM(deps) {
|
|
|
23649
24186
|
}
|
|
23650
24187
|
function detectTesting(deps, projectDir) {
|
|
23651
24188
|
const tools = [];
|
|
23652
|
-
if (deps.vitest ||
|
|
24189
|
+
if (deps.vitest || existsSync16(join16(projectDir, "vitest.config.ts")))
|
|
23653
24190
|
tools.push("vitest");
|
|
23654
|
-
if (deps.jest ||
|
|
24191
|
+
if (deps.jest || existsSync16(join16(projectDir, "jest.config.js")))
|
|
23655
24192
|
tools.push("jest");
|
|
23656
|
-
if (deps["@playwright/test"] ||
|
|
24193
|
+
if (deps["@playwright/test"] || existsSync16(join16(projectDir, "playwright.config.ts")))
|
|
23657
24194
|
tools.push("playwright");
|
|
23658
|
-
if (deps.cypress ||
|
|
24195
|
+
if (deps.cypress || existsSync16(join16(projectDir, "cypress.config.ts")))
|
|
23659
24196
|
tools.push("cypress");
|
|
23660
24197
|
if (deps["@testing-library/react"] || deps["@testing-library/vue"])
|
|
23661
24198
|
tools.push("testing-library");
|
|
@@ -23687,7 +24224,7 @@ function detectBuildTools(deps, projectDir) {
|
|
|
23687
24224
|
tools.push("esbuild");
|
|
23688
24225
|
if (deps.webpack)
|
|
23689
24226
|
tools.push("webpack");
|
|
23690
|
-
if (deps.turbo ||
|
|
24227
|
+
if (deps.turbo || existsSync16(join16(projectDir, "turbo.json")))
|
|
23691
24228
|
tools.push("turborepo");
|
|
23692
24229
|
if (deps.tsup)
|
|
23693
24230
|
tools.push("tsup");
|
|
@@ -23697,17 +24234,17 @@ function detectBuildTools(deps, projectDir) {
|
|
|
23697
24234
|
}
|
|
23698
24235
|
function detectDeployment(projectDir) {
|
|
23699
24236
|
const tools = [];
|
|
23700
|
-
if (
|
|
24237
|
+
if (existsSync16(join16(projectDir, "vercel.json")) || existsSync16(join16(projectDir, ".vercel")))
|
|
23701
24238
|
tools.push("vercel");
|
|
23702
|
-
if (
|
|
24239
|
+
if (existsSync16(join16(projectDir, "netlify.toml")))
|
|
23703
24240
|
tools.push("netlify");
|
|
23704
|
-
if (
|
|
24241
|
+
if (existsSync16(join16(projectDir, "fly.toml")))
|
|
23705
24242
|
tools.push("fly");
|
|
23706
|
-
if (
|
|
24243
|
+
if (existsSync16(join16(projectDir, "railway.json")))
|
|
23707
24244
|
tools.push("railway");
|
|
23708
|
-
if (
|
|
24245
|
+
if (existsSync16(join16(projectDir, "Dockerfile")))
|
|
23709
24246
|
tools.push("docker");
|
|
23710
|
-
if (
|
|
24247
|
+
if (existsSync16(join16(projectDir, ".github", "workflows")))
|
|
23711
24248
|
tools.push("github-actions");
|
|
23712
24249
|
return tools;
|
|
23713
24250
|
}
|
|
@@ -23730,20 +24267,20 @@ function detectAIML(deps) {
|
|
|
23730
24267
|
return tools;
|
|
23731
24268
|
}
|
|
23732
24269
|
function inferProjectType(projectDir, techStack) {
|
|
23733
|
-
if (
|
|
24270
|
+
if (existsSync16(join16(projectDir, "packages")) || existsSync16(join16(projectDir, "apps"))) {
|
|
23734
24271
|
return "monorepo";
|
|
23735
24272
|
}
|
|
23736
24273
|
const pkg = readPackageJson(projectDir);
|
|
23737
|
-
if (pkg.bin ||
|
|
24274
|
+
if (pkg.bin || existsSync16(join16(projectDir, "src", "cli.ts")) || existsSync16(join16(projectDir, "src", "index.ts"))) {
|
|
23738
24275
|
const hasBin = !!pkg.bin;
|
|
23739
|
-
const hasCommands =
|
|
24276
|
+
const hasCommands = existsSync16(join16(projectDir, "src", "commands"));
|
|
23740
24277
|
if (hasBin || hasCommands)
|
|
23741
24278
|
return "cli";
|
|
23742
24279
|
}
|
|
23743
24280
|
if (!techStack.framework && !techStack.metaFramework && pkg.main) {
|
|
23744
24281
|
return "library";
|
|
23745
24282
|
}
|
|
23746
|
-
if (
|
|
24283
|
+
if (existsSync16(join16(projectDir, "app.json")) || existsSync16(join16(projectDir, "expo"))) {
|
|
23747
24284
|
return "mobile";
|
|
23748
24285
|
}
|
|
23749
24286
|
if (techStack.database.length > 0 && !techStack.framework) {
|
|
@@ -23760,10 +24297,10 @@ function extractDescription(projectDir) {
|
|
|
23760
24297
|
return pkg.description;
|
|
23761
24298
|
const readmePaths = ["README.md", "readme.md", "Readme.md"];
|
|
23762
24299
|
for (const readme of readmePaths) {
|
|
23763
|
-
const path =
|
|
23764
|
-
if (
|
|
24300
|
+
const path = join16(projectDir, readme);
|
|
24301
|
+
if (existsSync16(path)) {
|
|
23765
24302
|
try {
|
|
23766
|
-
const content =
|
|
24303
|
+
const content = readFileSync14(path, "utf-8");
|
|
23767
24304
|
const lines = content.split(`
|
|
23768
24305
|
`);
|
|
23769
24306
|
let foundTitle = false;
|
|
@@ -25181,9 +25718,9 @@ var onboardCommand = defineCommand2({
|
|
|
25181
25718
|
},
|
|
25182
25719
|
async run({ args }) {
|
|
25183
25720
|
const projectPath = process.cwd();
|
|
25184
|
-
const contextPath =
|
|
25185
|
-
if (
|
|
25186
|
-
const existing = JSON.parse(
|
|
25721
|
+
const contextPath = join17(projectPath, ".nairon", "context.json");
|
|
25722
|
+
if (existsSync17(contextPath) && !args.force) {
|
|
25723
|
+
const existing = JSON.parse(readFileSync15(contextPath, "utf-8"));
|
|
25187
25724
|
consola.info("Project already onboarded. Use --force to re-run.");
|
|
25188
25725
|
consola.info(`Business: ${existing.businessContext?.domain || existing.businessContext?.slice?.(0, 50) || "Not set"}...`);
|
|
25189
25726
|
consola.info(`Stack: ${formatTechStackSummary(existing)}`);
|
|
@@ -25331,8 +25868,8 @@ var onboardCommand = defineCommand2({
|
|
|
25331
25868
|
createdAt: new Date().toISOString(),
|
|
25332
25869
|
updatedAt: new Date().toISOString()
|
|
25333
25870
|
};
|
|
25334
|
-
const naironDir =
|
|
25335
|
-
if (!
|
|
25871
|
+
const naironDir = join17(projectPath, ".nairon");
|
|
25872
|
+
if (!existsSync17(naironDir)) {
|
|
25336
25873
|
mkdirSync6(naironDir, { recursive: true });
|
|
25337
25874
|
}
|
|
25338
25875
|
writeFileSync7(contextPath, JSON.stringify(fullContext, null, 2));
|
|
@@ -25423,51 +25960,51 @@ function formatTechStackSummary(context) {
|
|
|
25423
25960
|
function detectInstalledTools(projectPath) {
|
|
25424
25961
|
const tools = [];
|
|
25425
25962
|
const home = process.env.HOME || "";
|
|
25426
|
-
const userClaudeJson =
|
|
25427
|
-
if (
|
|
25963
|
+
const userClaudeJson = join17(home, ".claude.json");
|
|
25964
|
+
if (existsSync17(userClaudeJson)) {
|
|
25428
25965
|
try {
|
|
25429
|
-
const config = JSON.parse(
|
|
25966
|
+
const config = JSON.parse(readFileSync15(userClaudeJson, "utf-8"));
|
|
25430
25967
|
if (config.mcpServers) {
|
|
25431
25968
|
tools.push(...Object.keys(config.mcpServers));
|
|
25432
25969
|
}
|
|
25433
25970
|
} catch {}
|
|
25434
25971
|
}
|
|
25435
|
-
const claudeDesktopConfig =
|
|
25436
|
-
if (
|
|
25972
|
+
const claudeDesktopConfig = join17(home, ".claude", "claude_desktop_config.json");
|
|
25973
|
+
if (existsSync17(claudeDesktopConfig)) {
|
|
25437
25974
|
try {
|
|
25438
|
-
const config = JSON.parse(
|
|
25975
|
+
const config = JSON.parse(readFileSync15(claudeDesktopConfig, "utf-8"));
|
|
25439
25976
|
if (config.mcpServers) {
|
|
25440
25977
|
tools.push(...Object.keys(config.mcpServers));
|
|
25441
25978
|
}
|
|
25442
25979
|
} catch {}
|
|
25443
25980
|
}
|
|
25444
|
-
const projectMcpJson =
|
|
25445
|
-
if (
|
|
25981
|
+
const projectMcpJson = join17(projectPath, ".mcp.json");
|
|
25982
|
+
if (existsSync17(projectMcpJson)) {
|
|
25446
25983
|
try {
|
|
25447
|
-
const config = JSON.parse(
|
|
25984
|
+
const config = JSON.parse(readFileSync15(projectMcpJson, "utf-8"));
|
|
25448
25985
|
if (config.mcpServers) {
|
|
25449
25986
|
tools.push(...Object.keys(config.mcpServers));
|
|
25450
25987
|
}
|
|
25451
25988
|
} catch {}
|
|
25452
25989
|
}
|
|
25453
|
-
const projectClaudeConfig =
|
|
25454
|
-
if (
|
|
25990
|
+
const projectClaudeConfig = join17(projectPath, ".claude", "settings.json");
|
|
25991
|
+
if (existsSync17(projectClaudeConfig)) {
|
|
25455
25992
|
try {
|
|
25456
|
-
const config = JSON.parse(
|
|
25993
|
+
const config = JSON.parse(readFileSync15(projectClaudeConfig, "utf-8"));
|
|
25457
25994
|
if (config.mcpServers) {
|
|
25458
25995
|
tools.push(...Object.keys(config.mcpServers));
|
|
25459
25996
|
}
|
|
25460
25997
|
} catch {}
|
|
25461
25998
|
}
|
|
25462
|
-
const skillsDir =
|
|
25463
|
-
if (
|
|
25999
|
+
const skillsDir = join17(home, ".config", "opencode", "skills");
|
|
26000
|
+
if (existsSync17(skillsDir)) {
|
|
25464
26001
|
try {
|
|
25465
26002
|
const skills = readdirSync9(skillsDir);
|
|
25466
26003
|
tools.push(...skills.filter((s2) => !s2.startsWith(".")));
|
|
25467
26004
|
} catch {}
|
|
25468
26005
|
}
|
|
25469
|
-
const agentsSkillsDir =
|
|
25470
|
-
if (
|
|
26006
|
+
const agentsSkillsDir = join17(home, ".agents", "skills");
|
|
26007
|
+
if (existsSync17(agentsSkillsDir)) {
|
|
25471
26008
|
try {
|
|
25472
26009
|
const skills = readdirSync9(agentsSkillsDir);
|
|
25473
26010
|
tools.push(...skills.filter((s2) => !s2.startsWith(".")));
|
|
@@ -25477,11 +26014,11 @@ function detectInstalledTools(projectPath) {
|
|
|
25477
26014
|
}
|
|
25478
26015
|
function detectPrimaryAgent() {
|
|
25479
26016
|
const home = process.env.HOME || "";
|
|
25480
|
-
if (
|
|
26017
|
+
if (existsSync17(join17(home, ".claude")))
|
|
25481
26018
|
return "claude-code";
|
|
25482
|
-
if (
|
|
26019
|
+
if (existsSync17(join17(home, ".cursor")))
|
|
25483
26020
|
return "cursor";
|
|
25484
|
-
if (
|
|
26021
|
+
if (existsSync17(join17(home, ".config", "opencode")))
|
|
25485
26022
|
return "opencode";
|
|
25486
26023
|
return;
|
|
25487
26024
|
}
|
|
@@ -25576,7 +26113,7 @@ function formatBytes(bytes) {
|
|
|
25576
26113
|
// package.json
|
|
25577
26114
|
var package_default2 = {
|
|
25578
26115
|
name: "nairon-bench",
|
|
25579
|
-
version: "0.3.
|
|
26116
|
+
version: "0.3.15",
|
|
25580
26117
|
description: "AI workflow benchmarking CLI",
|
|
25581
26118
|
type: "module",
|
|
25582
26119
|
bin: {
|