nairon-bench 0.3.13 → 0.3.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +2166 -1657
  2. 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 existsSync8, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4, readFileSync as readFileSync8 } from "node:fs";
4451
- import { join as join8 } from "node:path";
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/optimization-installer.ts
11462
- import { execSync as execSync2, spawnSync } from "node:child_process";
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
- async function installOptimizations(optimizations, projectDir, options = {}) {
11467
- const results = [];
11468
- for (const opt of optimizations) {
11469
- if (!opt.selected)
11470
- continue;
11471
- try {
11472
- const result = await installSingleOptimization(opt, projectDir, options);
11473
- results.push(result);
11474
- } catch (err) {
11475
- results.push({
11476
- id: opt.id,
11477
- name: opt.name,
11478
- success: false,
11479
- message: "Installation failed",
11480
- error: err instanceof Error ? err.message : String(err)
11481
- });
11482
- }
11483
- }
11484
- return results;
11485
- }
11486
- async function installSingleOptimization(opt, projectDir, options) {
11487
- if (options.dryRun) {
11488
- return {
11489
- id: opt.id,
11490
- name: opt.name,
11491
- success: true,
11492
- message: `[DRY RUN] Would install: ${opt.installCommand || opt.configPath || "unknown"}`
11493
- };
11494
- }
11495
- switch (opt.type) {
11496
- case "mcp":
11497
- return installMCP(opt, projectDir, options.agent);
11498
- case "skill":
11499
- return installSkill(opt);
11500
- case "config":
11501
- return installConfig(opt, projectDir);
11502
- case "hook":
11503
- return installHook(opt, projectDir);
11504
- default:
11505
- return {
11506
- id: opt.id,
11507
- name: opt.name,
11508
- success: false,
11509
- message: "Unknown optimization type"
11510
- };
11511
- }
11512
- }
11513
- function installMCP(opt, projectDir, agent) {
11514
- if (opt.installCommand?.startsWith("claude mcp add")) {
11515
- try {
11516
- execSync2(opt.installCommand, {
11517
- encoding: "utf-8",
11518
- stdio: "pipe",
11519
- timeout: 60000
11520
- });
11521
- return {
11522
- id: opt.id,
11523
- name: opt.name,
11524
- success: true,
11525
- message: `Installed via: ${opt.installCommand}`
11526
- };
11527
- } catch (err) {}
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
- if (opt.installCommand) {
11550
- try {
11551
- execSync2(opt.installCommand, {
11552
- encoding: "utf-8",
11553
- stdio: "pipe",
11554
- timeout: 60000
11555
- });
11556
- return {
11557
- id: opt.id,
11558
- name: opt.name,
11559
- success: true,
11560
- message: `Installed via: ${opt.installCommand}`
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
- return {
11573
- id: opt.id,
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
- function installConfig(opt, projectDir) {
11638
- if (!opt.configPath || !opt.configContent) {
11639
- return {
11640
- id: opt.id,
11641
- name: opt.name,
11642
- success: false,
11643
- message: "No config path or content provided"
11644
- };
11645
- }
11646
- try {
11647
- const fullPath = opt.configPath.startsWith("/") || opt.configPath.startsWith("~") ? opt.configPath.replace("~", homedir6()) : join7(projectDir, opt.configPath);
11648
- if (existsSync7(fullPath)) {
11649
- return {
11650
- id: opt.id,
11651
- name: opt.name,
11652
- success: true,
11653
- message: `Config already exists: ${opt.configPath}`
11654
- };
11655
- }
11656
- const parentDir = fullPath.substring(0, fullPath.lastIndexOf("/"));
11657
- if (parentDir && !existsSync7(parentDir)) {
11658
- mkdirSync3(parentDir, { recursive: true });
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
- writeFileSync3(fullPath, opt.configContent);
11661
- return {
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
- function installHook(opt, projectDir) {
11678
- const agentsMdPath = join7(projectDir, "AGENTS.md");
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
- const hookName = opt.name.toLowerCase();
11689
- if (content.toLowerCase().includes(hookName)) {
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
- const hookSection = opt.configContent || `
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 phaseRecToInstallable(rec) {
11675
+ function translateLevel(level) {
11676
+ if (level === 0) {
11677
+ return false;
11678
+ }
11721
11679
  return {
11722
- id: rec.title.toLowerCase().replace(/\s+/g, "-"),
11723
- name: rec.title,
11724
- type: rec.type,
11725
- description: rec.description,
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 checkInstalledStatus(projectDir) {
11731
- const home = homedir6();
11732
- const status = {
11733
- context7: false,
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
- status.beads = existsSync7(join7(projectDir, ".beads"));
11768
- const skillsDirs = [
11769
- join7(home, ".claude", "skills"),
11770
- join7(home, ".config", "opencode", "skills"),
11771
- join7(home, ".agents", "skills"),
11772
- join7(projectDir, ".opencode", "skill")
11773
- ];
11774
- for (const dir of skillsDirs) {
11775
- if (existsSync7(dir)) {
11776
- try {
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
- return status;
11787
- }
11788
- function filterAlreadyInstalled(optimizations, status) {
11789
- return optimizations.filter((opt) => {
11790
- const id = opt.id.toLowerCase();
11791
- if (id === "context7" && status.context7)
11792
- return false;
11793
- if (id === "supermemory" && status.supermemory)
11794
- return false;
11795
- if (id === "nia" && status.nia)
11796
- return false;
11797
- if (id === "beads" && status.beads)
11798
- return false;
11799
- if (opt.type === "skill") {
11800
- const skillName = opt.name.toLowerCase().replace(/\s+/g, "-");
11801
- 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"))) {
11802
- return false;
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
- return true;
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 QUICK_INSTALL_PRESETS = {
11809
- essential: [
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/ora/index.js
11873
- import process8 from "node:process";
11874
- import { stripVTControlCharacters } from "node:util";
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/vendor/ansi-styles/index.js
11877
- var ANSI_BACKGROUND_OFFSET = 10;
11878
- var wrapAnsi16 = (offset = 0) => (code2) => `\x1B[${code2 + offset}m`;
11879
- var wrapAnsi256 = (offset = 0) => (code2) => `\x1B[${38 + offset};5;${code2}m`;
11880
- var wrapAnsi16m = (offset = 0) => (red, green, blue) => `\x1B[${38 + offset};2;${red};${green};${blue}m`;
11881
- var styles = {
11882
- modifier: {
11883
- reset: [0, 0],
11884
- bold: [1, 22],
11885
- dim: [2, 22],
11886
- italic: [3, 23],
11887
- underline: [4, 24],
11888
- overline: [53, 55],
11889
- inverse: [7, 27],
11890
- hidden: [8, 28],
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 modifierNames = Object.keys(styles.modifier);
11935
- var foregroundColorNames = Object.keys(styles.color);
11936
- var backgroundColorNames = Object.keys(styles.bgColor);
11937
- var colorNames = [...foregroundColorNames, ...backgroundColorNames];
11938
- function assembleStyles() {
11939
- const codes = new Map;
11940
- for (const [groupName, group] of Object.entries(styles)) {
11941
- for (const [styleName, style] of Object.entries(group)) {
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
- function envForceColor() {
12071
- if ("FORCE_COLOR" in env2) {
12072
- if (env2.FORCE_COLOR === "true") {
12073
- return 1;
12074
- }
12075
- if (env2.FORCE_COLOR === "false") {
12076
- return 0;
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
- function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
12093
- const noFlagForceColor = envForceColor();
12094
- if (noFlagForceColor !== undefined) {
12095
- flagForceColor = noFlagForceColor;
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
- if (sniffFlags) {
12102
- if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
12103
- return 3;
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 (hasFlag("color=256")) {
12106
- return 2;
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 ("TF_BUILD" in env2 && "AGENT_NAME" in env2) {
12110
- return 1;
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
- if (process2.platform === "win32") {
12120
- const osRelease = os.release().split(".");
12121
- if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
12122
- return Number(osRelease[2]) >= 14931 ? 3 : 2;
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
- return 1;
12125
- }
12126
- if ("CI" in env2) {
12127
- if (["GITHUB_ACTIONS", "GITEA_ACTIONS", "CIRCLECI"].some((key) => (key in env2))) {
12128
- return 3;
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
- if (["TRAVIS", "APPVEYOR", "GITLAB_CI", "BUILDKITE", "DRONE"].some((sign) => (sign in env2)) || env2.CI_NAME === "codeship") {
12131
- return 1;
12132
- }
12133
- return min;
12134
- }
12135
- if ("TEAMCITY_VERSION" in env2) {
12136
- return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env2.TEAMCITY_VERSION) ? 1 : 0;
12137
- }
12138
- if (env2.COLORTERM === "truecolor") {
12139
- return 3;
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
  });
@@ -14505,767 +14099,1663 @@ function stripAnsi3(string) {
14505
14099
  if (typeof string !== "string") {
14506
14100
  throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
14507
14101
  }
14508
- return string.replace(regex2, "");
14509
- }
14510
-
14511
- // ../../node_modules/get-east-asian-width/lookup.js
14512
- function isAmbiguous2(x2) {
14513
- return x2 === 161 || x2 === 164 || x2 === 167 || x2 === 168 || x2 === 170 || x2 === 173 || x2 === 174 || x2 >= 176 && x2 <= 180 || x2 >= 182 && x2 <= 186 || x2 >= 188 && x2 <= 191 || x2 === 198 || x2 === 208 || x2 === 215 || x2 === 216 || x2 >= 222 && x2 <= 225 || x2 === 230 || x2 >= 232 && x2 <= 234 || x2 === 236 || x2 === 237 || x2 === 240 || x2 === 242 || x2 === 243 || x2 >= 247 && x2 <= 250 || x2 === 252 || x2 === 254 || x2 === 257 || x2 === 273 || x2 === 275 || x2 === 283 || x2 === 294 || x2 === 295 || x2 === 299 || x2 >= 305 && x2 <= 307 || x2 === 312 || x2 >= 319 && x2 <= 322 || x2 === 324 || x2 >= 328 && x2 <= 331 || x2 === 333 || x2 === 338 || x2 === 339 || x2 === 358 || x2 === 359 || x2 === 363 || x2 === 462 || x2 === 464 || x2 === 466 || x2 === 468 || x2 === 470 || x2 === 472 || x2 === 474 || x2 === 476 || x2 === 593 || x2 === 609 || x2 === 708 || x2 === 711 || x2 >= 713 && x2 <= 715 || x2 === 717 || x2 === 720 || x2 >= 728 && x2 <= 731 || x2 === 733 || x2 === 735 || x2 >= 768 && x2 <= 879 || x2 >= 913 && x2 <= 929 || x2 >= 931 && x2 <= 937 || x2 >= 945 && x2 <= 961 || x2 >= 963 && x2 <= 969 || x2 === 1025 || x2 >= 1040 && x2 <= 1103 || x2 === 1105 || x2 === 8208 || x2 >= 8211 && x2 <= 8214 || x2 === 8216 || x2 === 8217 || x2 === 8220 || x2 === 8221 || x2 >= 8224 && x2 <= 8226 || x2 >= 8228 && x2 <= 8231 || x2 === 8240 || x2 === 8242 || x2 === 8243 || x2 === 8245 || x2 === 8251 || x2 === 8254 || x2 === 8308 || x2 === 8319 || x2 >= 8321 && x2 <= 8324 || x2 === 8364 || x2 === 8451 || x2 === 8453 || x2 === 8457 || x2 === 8467 || x2 === 8470 || x2 === 8481 || x2 === 8482 || x2 === 8486 || x2 === 8491 || x2 === 8531 || x2 === 8532 || x2 >= 8539 && x2 <= 8542 || x2 >= 8544 && x2 <= 8555 || x2 >= 8560 && x2 <= 8569 || x2 === 8585 || x2 >= 8592 && x2 <= 8601 || x2 === 8632 || x2 === 8633 || x2 === 8658 || x2 === 8660 || x2 === 8679 || x2 === 8704 || x2 === 8706 || x2 === 8707 || x2 === 8711 || x2 === 8712 || x2 === 8715 || x2 === 8719 || x2 === 8721 || x2 === 8725 || x2 === 8730 || x2 >= 8733 && x2 <= 8736 || x2 === 8739 || x2 === 8741 || x2 >= 8743 && x2 <= 8748 || x2 === 8750 || x2 >= 8756 && x2 <= 8759 || x2 === 8764 || x2 === 8765 || x2 === 8776 || x2 === 8780 || x2 === 8786 || x2 === 8800 || x2 === 8801 || x2 >= 8804 && x2 <= 8807 || x2 === 8810 || x2 === 8811 || x2 === 8814 || x2 === 8815 || x2 === 8834 || x2 === 8835 || x2 === 8838 || x2 === 8839 || x2 === 8853 || x2 === 8857 || x2 === 8869 || x2 === 8895 || x2 === 8978 || x2 >= 9312 && x2 <= 9449 || x2 >= 9451 && x2 <= 9547 || x2 >= 9552 && x2 <= 9587 || x2 >= 9600 && x2 <= 9615 || x2 >= 9618 && x2 <= 9621 || x2 === 9632 || x2 === 9633 || x2 >= 9635 && x2 <= 9641 || x2 === 9650 || x2 === 9651 || x2 === 9654 || x2 === 9655 || x2 === 9660 || x2 === 9661 || x2 === 9664 || x2 === 9665 || x2 >= 9670 && x2 <= 9672 || x2 === 9675 || x2 >= 9678 && x2 <= 9681 || x2 >= 9698 && x2 <= 9701 || x2 === 9711 || x2 === 9733 || x2 === 9734 || x2 === 9737 || x2 === 9742 || x2 === 9743 || x2 === 9756 || x2 === 9758 || x2 === 9792 || x2 === 9794 || x2 === 9824 || x2 === 9825 || x2 >= 9827 && x2 <= 9829 || x2 >= 9831 && x2 <= 9834 || x2 === 9836 || x2 === 9837 || x2 === 9839 || x2 === 9886 || x2 === 9887 || x2 === 9919 || x2 >= 9926 && x2 <= 9933 || x2 >= 9935 && x2 <= 9939 || x2 >= 9941 && x2 <= 9953 || x2 === 9955 || x2 === 9960 || x2 === 9961 || x2 >= 9963 && x2 <= 9969 || x2 === 9972 || x2 >= 9974 && x2 <= 9977 || x2 === 9979 || x2 === 9980 || x2 === 9982 || x2 === 9983 || x2 === 10045 || x2 >= 10102 && x2 <= 10111 || x2 >= 11094 && x2 <= 11097 || x2 >= 12872 && x2 <= 12879 || x2 >= 57344 && x2 <= 63743 || x2 >= 65024 && x2 <= 65039 || x2 === 65533 || x2 >= 127232 && x2 <= 127242 || x2 >= 127248 && x2 <= 127277 || x2 >= 127280 && x2 <= 127337 || x2 >= 127344 && x2 <= 127373 || x2 === 127375 || x2 === 127376 || x2 >= 127387 && x2 <= 127404 || x2 >= 917760 && x2 <= 917999 || x2 >= 983040 && x2 <= 1048573 || x2 >= 1048576 && x2 <= 1114109;
14514
- }
14515
- function isFullWidth2(x2) {
14516
- return x2 === 12288 || x2 >= 65281 && x2 <= 65376 || x2 >= 65504 && x2 <= 65510;
14517
- }
14518
- function isWide2(x2) {
14519
- return x2 >= 4352 && x2 <= 4447 || x2 === 8986 || x2 === 8987 || x2 === 9001 || x2 === 9002 || x2 >= 9193 && x2 <= 9196 || x2 === 9200 || x2 === 9203 || x2 === 9725 || x2 === 9726 || x2 === 9748 || x2 === 9749 || x2 >= 9776 && x2 <= 9783 || x2 >= 9800 && x2 <= 9811 || x2 === 9855 || x2 >= 9866 && x2 <= 9871 || x2 === 9875 || x2 === 9889 || x2 === 9898 || x2 === 9899 || x2 === 9917 || x2 === 9918 || x2 === 9924 || x2 === 9925 || x2 === 9934 || x2 === 9940 || x2 === 9962 || x2 === 9970 || x2 === 9971 || x2 === 9973 || x2 === 9978 || x2 === 9981 || x2 === 9989 || x2 === 9994 || x2 === 9995 || x2 === 10024 || x2 === 10060 || x2 === 10062 || x2 >= 10067 && x2 <= 10069 || x2 === 10071 || x2 >= 10133 && x2 <= 10135 || x2 === 10160 || x2 === 10175 || x2 === 11035 || x2 === 11036 || x2 === 11088 || x2 === 11093 || x2 >= 11904 && x2 <= 11929 || x2 >= 11931 && x2 <= 12019 || x2 >= 12032 && x2 <= 12245 || x2 >= 12272 && x2 <= 12287 || x2 >= 12289 && x2 <= 12350 || x2 >= 12353 && x2 <= 12438 || x2 >= 12441 && x2 <= 12543 || x2 >= 12549 && x2 <= 12591 || x2 >= 12593 && x2 <= 12686 || x2 >= 12688 && x2 <= 12773 || x2 >= 12783 && x2 <= 12830 || x2 >= 12832 && x2 <= 12871 || x2 >= 12880 && x2 <= 42124 || x2 >= 42128 && x2 <= 42182 || x2 >= 43360 && x2 <= 43388 || x2 >= 44032 && x2 <= 55203 || x2 >= 63744 && x2 <= 64255 || x2 >= 65040 && x2 <= 65049 || x2 >= 65072 && x2 <= 65106 || x2 >= 65108 && x2 <= 65126 || x2 >= 65128 && x2 <= 65131 || x2 >= 94176 && x2 <= 94180 || x2 >= 94192 && x2 <= 94198 || x2 >= 94208 && x2 <= 101589 || x2 >= 101631 && x2 <= 101662 || x2 >= 101760 && x2 <= 101874 || x2 >= 110576 && x2 <= 110579 || x2 >= 110581 && x2 <= 110587 || x2 === 110589 || x2 === 110590 || x2 >= 110592 && x2 <= 110882 || x2 === 110898 || x2 >= 110928 && x2 <= 110930 || x2 === 110933 || x2 >= 110948 && x2 <= 110951 || x2 >= 110960 && x2 <= 111355 || x2 >= 119552 && x2 <= 119638 || x2 >= 119648 && x2 <= 119670 || x2 === 126980 || x2 === 127183 || x2 === 127374 || x2 >= 127377 && x2 <= 127386 || x2 >= 127488 && x2 <= 127490 || x2 >= 127504 && x2 <= 127547 || x2 >= 127552 && x2 <= 127560 || x2 === 127568 || x2 === 127569 || x2 >= 127584 && x2 <= 127589 || x2 >= 127744 && x2 <= 127776 || x2 >= 127789 && x2 <= 127797 || x2 >= 127799 && x2 <= 127868 || x2 >= 127870 && x2 <= 127891 || x2 >= 127904 && x2 <= 127946 || x2 >= 127951 && x2 <= 127955 || x2 >= 127968 && x2 <= 127984 || x2 === 127988 || x2 >= 127992 && x2 <= 128062 || x2 === 128064 || x2 >= 128066 && x2 <= 128252 || x2 >= 128255 && x2 <= 128317 || x2 >= 128331 && x2 <= 128334 || x2 >= 128336 && x2 <= 128359 || x2 === 128378 || x2 === 128405 || x2 === 128406 || x2 === 128420 || x2 >= 128507 && x2 <= 128591 || x2 >= 128640 && x2 <= 128709 || x2 === 128716 || x2 >= 128720 && x2 <= 128722 || x2 >= 128725 && x2 <= 128728 || x2 >= 128732 && x2 <= 128735 || x2 === 128747 || x2 === 128748 || x2 >= 128756 && x2 <= 128764 || x2 >= 128992 && x2 <= 129003 || x2 === 129008 || x2 >= 129292 && x2 <= 129338 || x2 >= 129340 && x2 <= 129349 || x2 >= 129351 && x2 <= 129535 || x2 >= 129648 && x2 <= 129660 || x2 >= 129664 && x2 <= 129674 || x2 >= 129678 && x2 <= 129734 || x2 === 129736 || x2 >= 129741 && x2 <= 129756 || x2 >= 129759 && x2 <= 129770 || x2 >= 129775 && x2 <= 129784 || x2 >= 131072 && x2 <= 196605 || x2 >= 196608 && x2 <= 262141;
14520
- }
14521
-
14522
- // ../../node_modules/get-east-asian-width/index.js
14523
- function validate2(codePoint) {
14524
- if (!Number.isSafeInteger(codePoint)) {
14525
- throw new TypeError(`Expected a code point, got \`${typeof codePoint}\`.`);
14102
+ return string.replace(regex2, "");
14103
+ }
14104
+
14105
+ // ../../node_modules/get-east-asian-width/lookup.js
14106
+ function isAmbiguous2(x2) {
14107
+ return x2 === 161 || x2 === 164 || x2 === 167 || x2 === 168 || x2 === 170 || x2 === 173 || x2 === 174 || x2 >= 176 && x2 <= 180 || x2 >= 182 && x2 <= 186 || x2 >= 188 && x2 <= 191 || x2 === 198 || x2 === 208 || x2 === 215 || x2 === 216 || x2 >= 222 && x2 <= 225 || x2 === 230 || x2 >= 232 && x2 <= 234 || x2 === 236 || x2 === 237 || x2 === 240 || x2 === 242 || x2 === 243 || x2 >= 247 && x2 <= 250 || x2 === 252 || x2 === 254 || x2 === 257 || x2 === 273 || x2 === 275 || x2 === 283 || x2 === 294 || x2 === 295 || x2 === 299 || x2 >= 305 && x2 <= 307 || x2 === 312 || x2 >= 319 && x2 <= 322 || x2 === 324 || x2 >= 328 && x2 <= 331 || x2 === 333 || x2 === 338 || x2 === 339 || x2 === 358 || x2 === 359 || x2 === 363 || x2 === 462 || x2 === 464 || x2 === 466 || x2 === 468 || x2 === 470 || x2 === 472 || x2 === 474 || x2 === 476 || x2 === 593 || x2 === 609 || x2 === 708 || x2 === 711 || x2 >= 713 && x2 <= 715 || x2 === 717 || x2 === 720 || x2 >= 728 && x2 <= 731 || x2 === 733 || x2 === 735 || x2 >= 768 && x2 <= 879 || x2 >= 913 && x2 <= 929 || x2 >= 931 && x2 <= 937 || x2 >= 945 && x2 <= 961 || x2 >= 963 && x2 <= 969 || x2 === 1025 || x2 >= 1040 && x2 <= 1103 || x2 === 1105 || x2 === 8208 || x2 >= 8211 && x2 <= 8214 || x2 === 8216 || x2 === 8217 || x2 === 8220 || x2 === 8221 || x2 >= 8224 && x2 <= 8226 || x2 >= 8228 && x2 <= 8231 || x2 === 8240 || x2 === 8242 || x2 === 8243 || x2 === 8245 || x2 === 8251 || x2 === 8254 || x2 === 8308 || x2 === 8319 || x2 >= 8321 && x2 <= 8324 || x2 === 8364 || x2 === 8451 || x2 === 8453 || x2 === 8457 || x2 === 8467 || x2 === 8470 || x2 === 8481 || x2 === 8482 || x2 === 8486 || x2 === 8491 || x2 === 8531 || x2 === 8532 || x2 >= 8539 && x2 <= 8542 || x2 >= 8544 && x2 <= 8555 || x2 >= 8560 && x2 <= 8569 || x2 === 8585 || x2 >= 8592 && x2 <= 8601 || x2 === 8632 || x2 === 8633 || x2 === 8658 || x2 === 8660 || x2 === 8679 || x2 === 8704 || x2 === 8706 || x2 === 8707 || x2 === 8711 || x2 === 8712 || x2 === 8715 || x2 === 8719 || x2 === 8721 || x2 === 8725 || x2 === 8730 || x2 >= 8733 && x2 <= 8736 || x2 === 8739 || x2 === 8741 || x2 >= 8743 && x2 <= 8748 || x2 === 8750 || x2 >= 8756 && x2 <= 8759 || x2 === 8764 || x2 === 8765 || x2 === 8776 || x2 === 8780 || x2 === 8786 || x2 === 8800 || x2 === 8801 || x2 >= 8804 && x2 <= 8807 || x2 === 8810 || x2 === 8811 || x2 === 8814 || x2 === 8815 || x2 === 8834 || x2 === 8835 || x2 === 8838 || x2 === 8839 || x2 === 8853 || x2 === 8857 || x2 === 8869 || x2 === 8895 || x2 === 8978 || x2 >= 9312 && x2 <= 9449 || x2 >= 9451 && x2 <= 9547 || x2 >= 9552 && x2 <= 9587 || x2 >= 9600 && x2 <= 9615 || x2 >= 9618 && x2 <= 9621 || x2 === 9632 || x2 === 9633 || x2 >= 9635 && x2 <= 9641 || x2 === 9650 || x2 === 9651 || x2 === 9654 || x2 === 9655 || x2 === 9660 || x2 === 9661 || x2 === 9664 || x2 === 9665 || x2 >= 9670 && x2 <= 9672 || x2 === 9675 || x2 >= 9678 && x2 <= 9681 || x2 >= 9698 && x2 <= 9701 || x2 === 9711 || x2 === 9733 || x2 === 9734 || x2 === 9737 || x2 === 9742 || x2 === 9743 || x2 === 9756 || x2 === 9758 || x2 === 9792 || x2 === 9794 || x2 === 9824 || x2 === 9825 || x2 >= 9827 && x2 <= 9829 || x2 >= 9831 && x2 <= 9834 || x2 === 9836 || x2 === 9837 || x2 === 9839 || x2 === 9886 || x2 === 9887 || x2 === 9919 || x2 >= 9926 && x2 <= 9933 || x2 >= 9935 && x2 <= 9939 || x2 >= 9941 && x2 <= 9953 || x2 === 9955 || x2 === 9960 || x2 === 9961 || x2 >= 9963 && x2 <= 9969 || x2 === 9972 || x2 >= 9974 && x2 <= 9977 || x2 === 9979 || x2 === 9980 || x2 === 9982 || x2 === 9983 || x2 === 10045 || x2 >= 10102 && x2 <= 10111 || x2 >= 11094 && x2 <= 11097 || x2 >= 12872 && x2 <= 12879 || x2 >= 57344 && x2 <= 63743 || x2 >= 65024 && x2 <= 65039 || x2 === 65533 || x2 >= 127232 && x2 <= 127242 || x2 >= 127248 && x2 <= 127277 || x2 >= 127280 && x2 <= 127337 || x2 >= 127344 && x2 <= 127373 || x2 === 127375 || x2 === 127376 || x2 >= 127387 && x2 <= 127404 || x2 >= 917760 && x2 <= 917999 || x2 >= 983040 && x2 <= 1048573 || x2 >= 1048576 && x2 <= 1114109;
14108
+ }
14109
+ function isFullWidth2(x2) {
14110
+ return x2 === 12288 || x2 >= 65281 && x2 <= 65376 || x2 >= 65504 && x2 <= 65510;
14111
+ }
14112
+ function isWide2(x2) {
14113
+ return x2 >= 4352 && x2 <= 4447 || x2 === 8986 || x2 === 8987 || x2 === 9001 || x2 === 9002 || x2 >= 9193 && x2 <= 9196 || x2 === 9200 || x2 === 9203 || x2 === 9725 || x2 === 9726 || x2 === 9748 || x2 === 9749 || x2 >= 9776 && x2 <= 9783 || x2 >= 9800 && x2 <= 9811 || x2 === 9855 || x2 >= 9866 && x2 <= 9871 || x2 === 9875 || x2 === 9889 || x2 === 9898 || x2 === 9899 || x2 === 9917 || x2 === 9918 || x2 === 9924 || x2 === 9925 || x2 === 9934 || x2 === 9940 || x2 === 9962 || x2 === 9970 || x2 === 9971 || x2 === 9973 || x2 === 9978 || x2 === 9981 || x2 === 9989 || x2 === 9994 || x2 === 9995 || x2 === 10024 || x2 === 10060 || x2 === 10062 || x2 >= 10067 && x2 <= 10069 || x2 === 10071 || x2 >= 10133 && x2 <= 10135 || x2 === 10160 || x2 === 10175 || x2 === 11035 || x2 === 11036 || x2 === 11088 || x2 === 11093 || x2 >= 11904 && x2 <= 11929 || x2 >= 11931 && x2 <= 12019 || x2 >= 12032 && x2 <= 12245 || x2 >= 12272 && x2 <= 12287 || x2 >= 12289 && x2 <= 12350 || x2 >= 12353 && x2 <= 12438 || x2 >= 12441 && x2 <= 12543 || x2 >= 12549 && x2 <= 12591 || x2 >= 12593 && x2 <= 12686 || x2 >= 12688 && x2 <= 12773 || x2 >= 12783 && x2 <= 12830 || x2 >= 12832 && x2 <= 12871 || x2 >= 12880 && x2 <= 42124 || x2 >= 42128 && x2 <= 42182 || x2 >= 43360 && x2 <= 43388 || x2 >= 44032 && x2 <= 55203 || x2 >= 63744 && x2 <= 64255 || x2 >= 65040 && x2 <= 65049 || x2 >= 65072 && x2 <= 65106 || x2 >= 65108 && x2 <= 65126 || x2 >= 65128 && x2 <= 65131 || x2 >= 94176 && x2 <= 94180 || x2 >= 94192 && x2 <= 94198 || x2 >= 94208 && x2 <= 101589 || x2 >= 101631 && x2 <= 101662 || x2 >= 101760 && x2 <= 101874 || x2 >= 110576 && x2 <= 110579 || x2 >= 110581 && x2 <= 110587 || x2 === 110589 || x2 === 110590 || x2 >= 110592 && x2 <= 110882 || x2 === 110898 || x2 >= 110928 && x2 <= 110930 || x2 === 110933 || x2 >= 110948 && x2 <= 110951 || x2 >= 110960 && x2 <= 111355 || x2 >= 119552 && x2 <= 119638 || x2 >= 119648 && x2 <= 119670 || x2 === 126980 || x2 === 127183 || x2 === 127374 || x2 >= 127377 && x2 <= 127386 || x2 >= 127488 && x2 <= 127490 || x2 >= 127504 && x2 <= 127547 || x2 >= 127552 && x2 <= 127560 || x2 === 127568 || x2 === 127569 || x2 >= 127584 && x2 <= 127589 || x2 >= 127744 && x2 <= 127776 || x2 >= 127789 && x2 <= 127797 || x2 >= 127799 && x2 <= 127868 || x2 >= 127870 && x2 <= 127891 || x2 >= 127904 && x2 <= 127946 || x2 >= 127951 && x2 <= 127955 || x2 >= 127968 && x2 <= 127984 || x2 === 127988 || x2 >= 127992 && x2 <= 128062 || x2 === 128064 || x2 >= 128066 && x2 <= 128252 || x2 >= 128255 && x2 <= 128317 || x2 >= 128331 && x2 <= 128334 || x2 >= 128336 && x2 <= 128359 || x2 === 128378 || x2 === 128405 || x2 === 128406 || x2 === 128420 || x2 >= 128507 && x2 <= 128591 || x2 >= 128640 && x2 <= 128709 || x2 === 128716 || x2 >= 128720 && x2 <= 128722 || x2 >= 128725 && x2 <= 128728 || x2 >= 128732 && x2 <= 128735 || x2 === 128747 || x2 === 128748 || x2 >= 128756 && x2 <= 128764 || x2 >= 128992 && x2 <= 129003 || x2 === 129008 || x2 >= 129292 && x2 <= 129338 || x2 >= 129340 && x2 <= 129349 || x2 >= 129351 && x2 <= 129535 || x2 >= 129648 && x2 <= 129660 || x2 >= 129664 && x2 <= 129674 || x2 >= 129678 && x2 <= 129734 || x2 === 129736 || x2 >= 129741 && x2 <= 129756 || x2 >= 129759 && x2 <= 129770 || x2 >= 129775 && x2 <= 129784 || x2 >= 131072 && x2 <= 196605 || x2 >= 196608 && x2 <= 262141;
14114
+ }
14115
+
14116
+ // ../../node_modules/get-east-asian-width/index.js
14117
+ function validate2(codePoint) {
14118
+ if (!Number.isSafeInteger(codePoint)) {
14119
+ throw new TypeError(`Expected a code point, got \`${typeof codePoint}\`.`);
14120
+ }
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;
14443
+ }
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;
14460
+ }
14461
+ return "";
14462
+ }
14463
+ #getFullPrefixText(prefixText = this.#options.prefixText, postfix = " ") {
14464
+ return this.#formatAffix(prefixText, postfix, false);
14526
14465
  }
14527
- }
14528
- function eastAsianWidth2(codePoint, { ambiguousAsWide = false } = {}) {
14529
- validate2(codePoint);
14530
- if (isFullWidth2(codePoint) || isWide2(codePoint) || ambiguousAsWide && isAmbiguous2(codePoint)) {
14531
- return 2;
14466
+ #getFullSuffixText(suffixText = this.#options.suffixText, prefix = " ") {
14467
+ return this.#formatAffix(suffixText, prefix, true);
14532
14468
  }
14533
- return 1;
14534
- }
14535
-
14536
- // ../../node_modules/string-width/index.js
14537
- var segmenter2 = new Intl.Segmenter;
14538
- var zeroWidthClusterRegex = /^(?:\p{Default_Ignorable_Code_Point}|\p{Control}|\p{Format}|\p{Mark}|\p{Surrogate})+$/v;
14539
- var leadingNonPrintingRegex = /^[\p{Default_Ignorable_Code_Point}\p{Control}\p{Format}\p{Mark}\p{Surrogate}]+/v;
14540
- var rgiEmojiRegex = /^\p{RGI_Emoji}$/v;
14541
- function baseVisible(segment) {
14542
- return segment.replace(leadingNonPrintingRegex, "");
14543
- }
14544
- function isZeroWidthCluster(segment) {
14545
- return zeroWidthClusterRegex.test(segment);
14546
- }
14547
- function trailingHalfwidthWidth(segment, eastAsianWidthOptions) {
14548
- let extra = 0;
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
- }
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));
14554
14474
  }
14475
+ return count;
14555
14476
  }
14556
- return extra;
14557
- }
14558
- function stringWidth2(input, options = {}) {
14559
- if (typeof input !== "string" || input.length === 0) {
14560
- return 0;
14477
+ get isEnabled() {
14478
+ return this.#options.isEnabled && !this.#options.isSilent;
14561
14479
  }
14562
- const {
14563
- ambiguousIsNarrow = true,
14564
- countAnsiEscapeCodes = false
14565
- } = options;
14566
- let string = input;
14567
- if (!countAnsiEscapeCodes) {
14568
- string = stripAnsi3(string);
14480
+ set isEnabled(value) {
14481
+ if (typeof value !== "boolean") {
14482
+ throw new TypeError("The `isEnabled` option must be a boolean");
14483
+ }
14484
+ this.#options.isEnabled = value;
14569
14485
  }
14570
- if (string.length === 0) {
14571
- return 0;
14486
+ get isSilent() {
14487
+ return this.#options.isSilent;
14572
14488
  }
14573
- let width = 0;
14574
- const eastAsianWidthOptions = { ambiguousAsWide: !ambiguousIsNarrow };
14575
- for (const { segment } of segmenter2.segment(string)) {
14576
- if (isZeroWidthCluster(segment)) {
14577
- continue;
14489
+ set isSilent(value) {
14490
+ if (typeof value !== "boolean") {
14491
+ throw new TypeError("The `isSilent` option must be a boolean");
14578
14492
  }
14579
- if (rgiEmojiRegex.test(segment)) {
14580
- width += 2;
14581
- continue;
14493
+ this.#options.isSilent = value;
14494
+ }
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;
14582
14500
  }
14583
- const codePoint = baseVisible(segment).codePointAt(0);
14584
- width += eastAsianWidth2(codePoint, eastAsianWidthOptions);
14585
- width += trailingHalfwidthWidth(segment, eastAsianWidthOptions);
14501
+ const { frames } = this.#spinner;
14502
+ let frame = frames[this.#frameIndex];
14503
+ if (this.color) {
14504
+ frame = source_default[this.color](frame);
14505
+ }
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;
14586
14510
  }
14587
- return width;
14588
- }
14589
-
14590
- // ../../node_modules/is-interactive/index.js
14591
- function isInteractive({ stream = process.stdout } = {}) {
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;
14511
+ clear() {
14512
+ if (!this.isEnabled || !this.#stream.isTTY) {
14513
+ return this;
14607
14514
  }
14608
- const code2 = typeof chunk === "string" ? chunk.codePointAt(0) : chunk[0];
14609
- if (code2 === ASCII_ETX_CODE) {
14610
- if (process7.listenerCount("SIGINT") > 0) {
14611
- process7.emit("SIGINT");
14612
- } else {
14613
- process7.kill(process7.pid, "SIGINT");
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);
14614
14525
  }
14526
+ });
14527
+ this.#linesToClear = 0;
14528
+ return this;
14529
+ }
14530
+ #hookStream(stream) {
14531
+ if (!stream || this.#hookedStreams.has(stream) || !stream.isTTY || typeof stream.write !== "function") {
14532
+ return;
14615
14533
  }
14616
- };
14617
- start() {
14618
- this.#activeCount++;
14619
- if (this.#activeCount === 1) {
14620
- this.#realStart();
14534
+ if (activeHooksPerStream.has(stream)) {
14535
+ console.warn("[ora] Multiple concurrent spinners detected. This may cause visual corruption. Use one spinner at a time.");
14621
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);
14622
14541
  }
14623
- stop() {
14624
- if (this.#activeCount === 0) {
14542
+ #installHook() {
14543
+ if (!this.isEnabled || this.#hookedStreams.size > 0) {
14625
14544
  return;
14626
14545
  }
14627
- if (--this.#activeCount === 0) {
14628
- this.#realStop();
14546
+ const streamsToHook = new Set([this.#stream, process8.stdout, process8.stderr]);
14547
+ for (const stream of streamsToHook) {
14548
+ this.#hookStream(stream);
14549
+ }
14550
+ }
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
+ }
14557
+ }
14558
+ this.#hookedStreams.clear();
14559
+ }
14560
+ #hookedWrite(stream, originalWrite, chunk, encoding, callback) {
14561
+ if (typeof encoding === "function") {
14562
+ callback = encoding;
14563
+ encoding = undefined;
14564
+ }
14565
+ if (this.#isInternalWrite) {
14566
+ return originalWrite.call(stream, chunk, encoding, callback);
14567
+ }
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;
14581
+ }
14582
+ render() {
14583
+ if (!this.isEnabled || this.#drainHandler || this.#deferRenderTimer) {
14584
+ return this;
14585
+ }
14586
+ const useSynchronizedOutput = this.#stream.isTTY;
14587
+ let shouldDisableSynchronizedOutput = false;
14588
+ try {
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);
14614
+ } finally {
14615
+ if (shouldDisableSynchronizedOutput) {
14616
+ this.#internalWrite(() => this.#stream.write(SYNCHRONIZED_OUTPUT_DISABLE));
14617
+ }
14618
+ }
14619
+ return this;
14620
+ }
14621
+ start(text) {
14622
+ if (text) {
14623
+ this.text = text;
14624
+ }
14625
+ if (this.isSilent) {
14626
+ return this;
14627
+ }
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;
14636
+ }
14637
+ if (this.isSpinning) {
14638
+ return this;
14629
14639
  }
14630
- }
14631
- #realStart() {
14632
- const { stdin: stdin2 } = process7;
14633
- if (process7.platform === "win32" || !stdin2?.isTTY || typeof stdin2.setRawMode !== "function") {
14634
- this.#stdin = undefined;
14635
- return;
14640
+ if (this.#options.hideCursor) {
14641
+ cli_cursor_default.hide(this.#stream);
14636
14642
  }
14637
- this.#stdin = stdin2;
14638
- this.#stdinWasPaused = stdin2.isPaused();
14639
- this.#stdinWasRaw = Boolean(stdin2.isRaw);
14640
- stdin2.setRawMode(true);
14641
- stdin2.prependListener("data", this.#handleInputBound);
14642
- if (this.#stdinWasPaused) {
14643
- stdin2.resume();
14643
+ if (this.#options.discardStdin && process8.stdin.isTTY) {
14644
+ stdin_discarder_default.start();
14645
+ this.#isDiscardingStdin = true;
14644
14646
  }
14647
+ this.#installHook();
14648
+ this.render();
14649
+ this.#id = setInterval(this.render.bind(this), this.interval);
14650
+ return this;
14645
14651
  }
14646
- #realStop() {
14647
- if (!this.#stdin) {
14648
- return;
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;
14649
14662
  }
14650
- const stdin2 = this.#stdin;
14651
- stdin2.off("data", this.#handleInputBound);
14652
- if (stdin2.isTTY) {
14653
- stdin2.setRawMode?.(this.#stdinWasRaw);
14663
+ if (this.isEnabled) {
14664
+ this.clear();
14665
+ if (this.#options.hideCursor) {
14666
+ cli_cursor_default.show(this.#stream);
14667
+ }
14654
14668
  }
14655
- if (this.#stdinWasPaused) {
14656
- stdin2.pause();
14669
+ if (this.#isDiscardingStdin) {
14670
+ this.#isDiscardingStdin = false;
14671
+ stdin_discarder_default.stop();
14657
14672
  }
14658
- this.#stdin = undefined;
14659
- this.#stdinWasPaused = false;
14660
- this.#stdinWasRaw = false;
14673
+ return this;
14661
14674
  }
14662
- }
14663
- var stdinDiscarder = new StdinDiscarder;
14664
- var stdin_discarder_default = Object.freeze(stdinDiscarder);
14665
-
14666
- // ../../node_modules/ora/index.js
14667
- var RENDER_DEFERRAL_TIMEOUT = 200;
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;
14688
- try {
14689
- return fn();
14690
- } finally {
14691
- this.#isInternalWrite = false;
14692
- }
14675
+ succeed(text) {
14676
+ return this.stopAndPersist({ symbol: exports_symbols.success, text });
14693
14677
  }
14694
- #tryRender() {
14695
- if (this.isSpinning) {
14696
- this.render();
14697
- }
14678
+ fail(text) {
14679
+ return this.stopAndPersist({ symbol: exports_symbols.error, text });
14698
14680
  }
14699
- #stringifyChunk(chunk, encoding) {
14700
- if (chunk === undefined || chunk === null) {
14701
- return "";
14702
- }
14703
- if (typeof chunk === "string") {
14704
- return chunk;
14681
+ warn(text) {
14682
+ return this.stopAndPersist({ symbol: exports_symbols.warning, text });
14683
+ }
14684
+ info(text) {
14685
+ return this.stopAndPersist({ symbol: exports_symbols.info, text });
14686
+ }
14687
+ stopAndPersist(options = {}) {
14688
+ if (this.isSilent) {
14689
+ return this;
14705
14690
  }
14706
- if (Buffer.isBuffer(chunk) || ArrayBuffer.isView(chunk)) {
14707
- const normalizedEncoding = typeof encoding === "string" && encoding && encoding !== "buffer" ? encoding : "utf8";
14708
- return Buffer.from(chunk).toString(normalizedEncoding);
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("░"));
14709
14792
  }
14710
- return String(chunk);
14793
+ await sleep(charDelay);
14711
14794
  }
14712
- #chunkTerminatesLine(chunkString) {
14713
- if (!chunkString) {
14714
- return false;
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);
14826
+ }
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("█"));
14836
+ } else {
14837
+ write(colors2.dim("░"));
14715
14838
  }
14716
- const lastCharacter = chunkString.at(-1);
14717
- return lastCharacter === `
14718
- ` || lastCharacter === "\r";
14839
+ await sleep(barDelay);
14719
14840
  }
14720
- #scheduleRenderDeferral() {
14721
- if (this.#deferRenderTimer) {
14722
- return;
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
14723
14889
  }
14724
- this.#deferRenderTimer = setTimeout(() => {
14725
- this.#deferRenderTimer = undefined;
14726
- if (this.isSpinning) {
14727
- this.#tryRender();
14728
- }
14729
- }, RENDER_DEFERRAL_TIMEOUT);
14730
- if (typeof this.#deferRenderTimer?.unref === "function") {
14731
- this.#deferRenderTimer.unref();
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
14732
14908
  }
14733
- }
14734
- #clearRenderDeferral() {
14735
- if (this.#deferRenderTimer) {
14736
- clearTimeout(this.#deferRenderTimer);
14737
- this.#deferRenderTimer = undefined;
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
14738
14931
  }
14739
- }
14740
- #buildOutputLine(symbol, text, prefixText, suffixText) {
14741
- const fullPrefixText = this.#getFullPrefixText(prefixText, " ");
14742
- const separatorText = symbol ? " " : "";
14743
- const fullText = typeof text === "string" ? separatorText + text : "";
14744
- const fullSuffixText = this.#getFullSuffixText(suffixText, " ");
14745
- return fullPrefixText + symbol + fullText + fullSuffixText;
14746
- }
14747
- constructor(options) {
14748
- if (typeof options === "string") {
14749
- options = {
14750
- text: options
14751
- };
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
14752
14949
  }
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 });
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
14764
14968
  }
14765
- if (typeof this.#options.isSilent !== "boolean") {
14766
- this.#options.isSilent = false;
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
14767
14990
  }
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
- }
14991
+ }
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)
14802
15021
  });
14803
15022
  }
14804
15023
  }
14805
- get indent() {
14806
- return this.#options.indent;
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;
14807
15031
  }
14808
- set indent(indent = 0) {
14809
- if (!(indent >= 0 && Number.isInteger(indent))) {
14810
- throw new Error("The `indent` option must be an integer from 0 and up");
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;
14811
15059
  }
14812
- this.#options.indent = indent;
14813
- }
14814
- get interval() {
14815
- return this.#options.interval ?? this.#spinner.interval ?? 100;
14816
15060
  }
14817
- get spinner() {
14818
- return this.#spinner;
14819
- }
14820
- set spinner(spinner) {
14821
- this.#frameIndex = -1;
14822
- this.#options.interval = undefined;
14823
- if (typeof spinner === "object") {
14824
- if (!Array.isArray(spinner.frames) || spinner.frames.length === 0 || spinner.frames.some((frame) => typeof frame !== "string")) {
14825
- throw new Error("The given spinner must have a non-empty `frames` array of strings");
14826
- }
14827
- if (spinner.interval !== undefined && !(Number.isInteger(spinner.interval) && spinner.interval > 0)) {
14828
- throw new Error("`spinner.interval` must be a positive integer if provided");
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
+ }
14829
15072
  }
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];
14837
- } else {
14838
- 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.`);
15073
+ } catch {
15074
+ return null;
14839
15075
  }
14840
15076
  }
14841
- get text() {
14842
- return this.#options.text;
14843
- }
14844
- set text(value = "") {
14845
- this.#options.text = value;
14846
- }
14847
- get prefixText() {
14848
- return this.#options.prefixText;
14849
- }
14850
- set prefixText(value = "") {
14851
- this.#options.prefixText = value;
14852
- }
14853
- get suffixText() {
14854
- return this.#options.suffixText;
14855
- }
14856
- set suffixText(value = "") {
14857
- this.#options.suffixText = value;
14858
- }
14859
- get isSpinning() {
14860
- return this.#id !== undefined;
14861
- }
14862
- #formatAffix(value, separator, placeBefore = false) {
14863
- const resolved = typeof value === "function" ? value() : value;
14864
- if (typeof resolved === "string" && resolved !== "") {
14865
- return placeBefore ? separator + resolved : resolved + separator;
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 || "");
15110
+ }
15111
+ }
15112
+ } else if (sessionPath.endsWith(".json")) {
15113
+ for (const _3 of patterns) {
15114
+ prompts.push("");
15115
+ }
14866
15116
  }
14867
- return "";
14868
- }
14869
- #getFullPrefixText(prefixText = this.#options.prefixText, postfix = " ") {
14870
- return this.#formatAffix(prefixText, postfix, false);
15117
+ return prompts;
15118
+ } catch {
15119
+ return [];
14871
15120
  }
14872
- #getFullSuffixText(suffixText = this.#options.suffixText, prefix = " ") {
14873
- return this.#formatAffix(suffixText, prefix, true);
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(" ");
14874
15127
  }
14875
- #computeLineCountFrom(text, columns) {
14876
- let count = 0;
14877
- for (const line of stripVTControlCharacters(text).split(`
14878
- `)) {
14879
- count += Math.max(1, Math.ceil(stringWidth2(line) / columns));
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
+ }
14880
15142
  }
14881
- return count;
14882
15143
  }
14883
- get isEnabled() {
14884
- return this.#options.isEnabled && !this.#options.isSilent;
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
+ };
14885
15153
  }
14886
- set isEnabled(value) {
14887
- if (typeof value !== "boolean") {
14888
- throw new TypeError("The `isEnabled` option must be a boolean");
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
+ };
15162
+ }
14889
15163
  }
14890
- this.#options.isEnabled = value;
15164
+ return {
15165
+ category: "undo_loop",
15166
+ description: ROOT_CAUSE_PATTERNS.undo_loop.description,
15167
+ confidence: "high"
15168
+ };
14891
15169
  }
14892
- get isSilent() {
14893
- return this.#options.isSilent;
15170
+ if (patternType === "tool_failure") {
15171
+ return {
15172
+ category: "tool_failure",
15173
+ description: ROOT_CAUSE_PATTERNS.tool_failure.description,
15174
+ confidence: "high"
15175
+ };
14894
15176
  }
14895
- set isSilent(value) {
14896
- if (typeof value !== "boolean") {
14897
- throw new TypeError("The `isSilent` option must be a boolean");
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
+ }
14898
15186
  }
14899
- this.#options.isSilent = value;
14900
15187
  }
14901
- frame() {
14902
- const now = Date.now();
14903
- if (this.#frameIndex === -1 || now - this.#lastFrameTime >= this.interval) {
14904
- this.#frameIndex = (this.#frameIndex + 1) % this.#spinner.frames.length;
14905
- this.#lastFrameTime = now;
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
14906
15208
  }
14907
- const { frames } = this.#spinner;
14908
- let frame = frames[this.#frameIndex];
14909
- if (this.color) {
14910
- frame = source_default[this.color](frame);
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 };
14911
15230
  }
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;
15231
+ byTool[key].count++;
15232
+ byTool[key].timeSaved += f3.estimatedTimeWastedMinutes * (f3.recommendedFix.estimatedImprovementPercent / 100);
15233
+ byTool[key].costSaved += f3.estimatedCostWasted * (f3.recommendedFix.estimatedImprovementPercent / 100);
14916
15234
  }
14917
- clear() {
14918
- if (!this.isEnabled || !this.#stream.isTTY) {
14919
- return this;
14920
- }
14921
- this.#internalWrite(() => {
14922
- this.#stream.cursorTo(0);
14923
- for (let index = 0;index < this.#linesToClear; index++) {
14924
- if (index > 0) {
14925
- this.#stream.moveCursor(0, -1);
14926
- }
14927
- this.#stream.clearLine(1);
14928
- }
14929
- if (this.#options.indent) {
14930
- this.#stream.cursorTo(this.#options.indent);
14931
- }
15235
+ const recommendations = [];
15236
+ for (const [tool, data] of Object.entries(byTool)) {
15237
+ recommendations.push({
15238
+ tool,
15239
+ description: data.fix.description,
15240
+ installCommand: data.fix.installCommand,
15241
+ wouldHavePreventedCount: data.count,
15242
+ estimatedTimeSavedMinutes: Math.round(data.timeSaved),
15243
+ estimatedCostSaved: Math.round(data.costSaved * 100) / 100
14932
15244
  });
14933
- this.#linesToClear = 0;
14934
- return this;
14935
15245
  }
14936
- #hookStream(stream) {
14937
- if (!stream || this.#hookedStreams.has(stream) || !stream.isTTY || typeof stream.write !== "function") {
14938
- return;
14939
- }
14940
- if (activeHooksPerStream.has(stream)) {
14941
- console.warn("[ora] Multiple concurrent spinners detected. This may cause visual corruption. Use one spinner at a time.");
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);
15246
+ recommendations.sort((a2, b2) => b2.estimatedTimeSavedMinutes - a2.estimatedTimeSavedMinutes);
15247
+ return recommendations;
15248
+ }
15249
+ function formatFrustrationSummary(summary) {
15250
+ const lines = [];
15251
+ if (summary.totalFrustrations === 0) {
15252
+ lines.push(` ${icons.success} ${colors2.success("No frustration events detected!")}`);
15253
+ return lines;
14947
15254
  }
14948
- #installHook() {
14949
- if (!this.isEnabled || this.#hookedStreams.size > 0) {
14950
- return;
14951
- }
14952
- const streamsToHook = new Set([this.#stream, process8.stdout, process8.stderr]);
14953
- for (const stream of streamsToHook) {
14954
- this.#hookStream(stream);
15255
+ lines.push("");
15256
+ lines.push(colors2.dim(" " + "═".repeat(50)));
15257
+ lines.push(` ${colors2.error("!")} ${colors2.bold("Frustration Analysis")}`);
15258
+ lines.push(colors2.dim(" " + "═".repeat(50)));
15259
+ lines.push("");
15260
+ lines.push(` ${colors2.bold("Summary:")}`);
15261
+ lines.push(` ${icons.warning} ${summary.totalFrustrations} frustration events detected`);
15262
+ lines.push(` ${colors2.dim(">")} ~${summary.totalTimeWastedMinutes} min wasted`);
15263
+ lines.push(` ${icons.money} ~$${summary.totalCostWasted.toFixed(2)} in tokens`);
15264
+ lines.push("");
15265
+ if (Object.keys(summary.byRootCause).length > 0) {
15266
+ lines.push(` ${colors2.bold("Root Causes:")}`);
15267
+ for (const [cause, count] of Object.entries(summary.byRootCause)) {
15268
+ const label = formatCauseLabel(cause);
15269
+ lines.push(` ${colors2.dim("•")} ${label}: ${count}x`);
14955
15270
  }
15271
+ lines.push("");
14956
15272
  }
14957
- #uninstallHook() {
14958
- for (const [stream, originalWrite] of this.#hookedStreams) {
14959
- stream.write = originalWrite;
14960
- if (activeHooksPerStream.get(stream) === this) {
14961
- activeHooksPerStream.delete(stream);
14962
- }
15273
+ if (summary.topFrustrations.length > 0) {
15274
+ lines.push(` ${colors2.bold("Top Frustrations:")}`);
15275
+ lines.push("");
15276
+ for (let i3 = 0;i3 < Math.min(3, summary.topFrustrations.length); i3++) {
15277
+ const f3 = summary.topFrustrations[i3];
15278
+ lines.push(...formatFrustrationEvent(f3, i3 + 1));
15279
+ lines.push("");
14963
15280
  }
14964
- this.#hookedStreams.clear();
14965
15281
  }
14966
- #hookedWrite(stream, originalWrite, chunk, encoding, callback) {
14967
- if (typeof encoding === "function") {
14968
- callback = encoding;
14969
- encoding = undefined;
14970
- }
14971
- if (this.#isInternalWrite) {
14972
- return originalWrite.call(stream, chunk, encoding, callback);
15282
+ if (summary.recommendations.length > 0) {
15283
+ lines.push(` ${colors2.bold(colors2.primary("Recommended Fixes:"))}`);
15284
+ lines.push("");
15285
+ for (const rec of summary.recommendations.slice(0, 3)) {
15286
+ lines.push(` ${colors2.success("+")} ${colors2.bold(rec.tool)}`);
15287
+ lines.push(` Would have prevented ${rec.wouldHavePreventedCount} issue${rec.wouldHavePreventedCount > 1 ? "s" : ""}`);
15288
+ lines.push(` Est. time saved: ${colors2.success(`~${rec.estimatedTimeSavedMinutes} min`)}`);
15289
+ lines.push(` ${colors2.dim("$")} ${colors2.primary(rec.installCommand)}`);
15290
+ lines.push("");
14973
15291
  }
14974
- this.clear();
14975
- const chunkString = this.#stringifyChunk(chunk, encoding);
14976
- const chunkTerminatesLine = this.#chunkTerminatesLine(chunkString);
14977
- const writeResult = originalWrite.call(stream, chunk, encoding, callback);
14978
- if (chunkTerminatesLine) {
14979
- this.#clearRenderDeferral();
14980
- } else if (chunkString.length > 0) {
14981
- this.#scheduleRenderDeferral();
15292
+ }
15293
+ lines.push(colors2.dim(" " + "═".repeat(50)));
15294
+ return lines;
15295
+ }
15296
+ function formatFrustrationEvent(f3, index) {
15297
+ const lines = [];
15298
+ lines.push(` ${colors2.warning(`${index}.`)} ${colors2.bold(f3.patternDescription)} ${colors2.dim(`(${f3.agent})`)}`);
15299
+ lines.push(` ${colors2.dim("Session:")} ${f3.sessionId.slice(0, 12)}...`);
15300
+ lines.push(` ${colors2.dim("Time wasted:")} ~${f3.estimatedTimeWastedMinutes} min`);
15301
+ lines.push(` ${colors2.dim("Cause:")} ${formatCauseLabel(f3.rootCause.category)}`);
15302
+ if (f3.exactPrompt && f3.exactPrompt.length > 0 && !f3.exactPrompt.startsWith("(Unable")) {
15303
+ lines.push("");
15304
+ lines.push(` ${colors2.dim("┌" + "─".repeat(40))}`);
15305
+ const promptLines = wrapText(f3.exactPrompt, 38);
15306
+ for (const line of promptLines.slice(0, 4)) {
15307
+ lines.push(` ${colors2.dim("│")} ${line}`);
14982
15308
  }
14983
- if (this.isSpinning && !this.#deferRenderTimer) {
14984
- this.render();
15309
+ if (promptLines.length > 4) {
15310
+ lines.push(` ${colors2.dim("│")} ${colors2.dim("...")}`);
14985
15311
  }
14986
- return writeResult;
15312
+ lines.push(` ${colors2.dim("└" + "─".repeat(40))}`);
14987
15313
  }
14988
- render() {
14989
- if (!this.isEnabled || this.#drainHandler || this.#deferRenderTimer) {
14990
- return this;
15314
+ lines.push("");
15315
+ lines.push(` ${colors2.success("Fix:")} ${f3.recommendedFix.tool}`);
15316
+ lines.push(` ${colors2.dim("$")} ${colors2.primary(f3.recommendedFix.installCommand)}`);
15317
+ return lines;
15318
+ }
15319
+ function formatCauseLabel(cause) {
15320
+ const labels = {
15321
+ hallucination: colors2.error("API Hallucination"),
15322
+ missing_docs: colors2.warning("Missing Docs"),
15323
+ context_loss: colors2.warning("Context Loss"),
15324
+ unclear_prompt: colors2.dim("Unclear Prompt"),
15325
+ tool_failure: colors2.error("Tool Failure"),
15326
+ undo_loop: colors2.warning("Undo Loop"),
15327
+ unknown: colors2.dim("Unknown")
15328
+ };
15329
+ return labels[cause] || cause;
15330
+ }
15331
+ function wrapText(text, width) {
15332
+ const words = text.split(/\s+/);
15333
+ const lines = [];
15334
+ let currentLine = "";
15335
+ for (const word of words) {
15336
+ if (currentLine.length + word.length + 1 <= width) {
15337
+ currentLine += (currentLine ? " " : "") + word;
15338
+ } else {
15339
+ if (currentLine)
15340
+ lines.push(currentLine);
15341
+ currentLine = word.slice(0, width);
14991
15342
  }
14992
- const useSynchronizedOutput = this.#stream.isTTY;
14993
- let shouldDisableSynchronizedOutput = false;
15343
+ }
15344
+ if (currentLine)
15345
+ lines.push(currentLine);
15346
+ return lines;
15347
+ }
15348
+
15349
+ // src/lib/optimization-installer.ts
15350
+ import { execSync as execSync2, spawnSync } from "node:child_process";
15351
+ import { existsSync as existsSync8, writeFileSync as writeFileSync3, readFileSync as readFileSync8, mkdirSync as mkdirSync3, readdirSync as readdirSync4 } from "node:fs";
15352
+ import { join as join8 } from "node:path";
15353
+ import { homedir as homedir7 } from "node:os";
15354
+ async function installOptimizations(optimizations, projectDir, options = {}) {
15355
+ const results = [];
15356
+ for (const opt of optimizations) {
15357
+ if (!opt.selected)
15358
+ continue;
14994
15359
  try {
14995
- if (useSynchronizedOutput) {
14996
- this.#internalWrite(() => this.#stream.write(SYNCHRONIZED_OUTPUT_ENABLE));
14997
- shouldDisableSynchronizedOutput = true;
14998
- }
14999
- this.clear();
15000
- let frameContent = this.frame();
15001
- const columns = this.#stream.columns ?? 80;
15002
- const actualLineCount = this.#computeLineCountFrom(frameContent, columns);
15003
- const consoleHeight = this.#stream.rows;
15004
- if (consoleHeight && consoleHeight > 1 && actualLineCount > consoleHeight) {
15005
- const lines = frameContent.split(`
15006
- `);
15007
- const maxLines = consoleHeight - 1;
15008
- frameContent = [...lines.slice(0, maxLines), "... (content truncated to fit terminal)"].join(`
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));
15023
- }
15360
+ const result = await installSingleOptimization(opt, projectDir, options);
15361
+ results.push(result);
15362
+ } catch (err) {
15363
+ results.push({
15364
+ id: opt.id,
15365
+ name: opt.name,
15366
+ success: false,
15367
+ message: "Installation failed",
15368
+ error: err instanceof Error ? err.message : String(err)
15369
+ });
15024
15370
  }
15025
- return this;
15026
15371
  }
15027
- start(text) {
15028
- if (text) {
15029
- this.text = text;
15030
- }
15031
- if (this.isSilent) {
15032
- return this;
15033
- }
15034
- if (!this.isEnabled) {
15035
- const symbol = this.text ? "-" : "";
15036
- const line = " ".repeat(this.#options.indent) + this.#buildOutputLine(symbol, this.text, this.#options.prefixText, this.#options.suffixText);
15037
- if (line.trim() !== "") {
15038
- this.#internalWrite(() => this.#stream.write(line + `
15039
- `));
15040
- }
15041
- return this;
15042
- }
15043
- if (this.isSpinning) {
15044
- return this;
15045
- }
15046
- if (this.#options.hideCursor) {
15047
- cli_cursor_default.hide(this.#stream);
15372
+ return results;
15373
+ }
15374
+ async function installSingleOptimization(opt, projectDir, options) {
15375
+ if (options.dryRun) {
15376
+ return {
15377
+ id: opt.id,
15378
+ name: opt.name,
15379
+ success: true,
15380
+ message: `[DRY RUN] Would install: ${opt.installCommand || opt.configPath || "unknown"}`
15381
+ };
15382
+ }
15383
+ switch (opt.type) {
15384
+ case "mcp":
15385
+ return installMCP(opt, projectDir, options.agent);
15386
+ case "skill":
15387
+ return installSkill(opt);
15388
+ case "config":
15389
+ return installConfig(opt, projectDir);
15390
+ case "hook":
15391
+ return installHook(opt, projectDir);
15392
+ default:
15393
+ return {
15394
+ id: opt.id,
15395
+ name: opt.name,
15396
+ success: false,
15397
+ message: "Unknown optimization type"
15398
+ };
15399
+ }
15400
+ }
15401
+ function installMCP(opt, projectDir, agent) {
15402
+ if (opt.installCommand?.startsWith("claude mcp add")) {
15403
+ try {
15404
+ execSync2(opt.installCommand, {
15405
+ encoding: "utf-8",
15406
+ stdio: "pipe",
15407
+ timeout: 60000
15408
+ });
15409
+ return {
15410
+ id: opt.id,
15411
+ name: opt.name,
15412
+ success: true,
15413
+ message: `Installed via: ${opt.installCommand}`
15414
+ };
15415
+ } catch (err) {}
15416
+ }
15417
+ if (opt.id === "beads" || opt.name.toLowerCase().includes("beads")) {
15418
+ try {
15419
+ execSync2("bun add -g beads", { encoding: "utf-8", stdio: "pipe", timeout: 60000 });
15420
+ execSync2("bd init", { cwd: projectDir, encoding: "utf-8", stdio: "pipe", timeout: 30000 });
15421
+ return {
15422
+ id: opt.id,
15423
+ name: opt.name,
15424
+ success: true,
15425
+ message: "Installed Beads globally and initialized in project"
15426
+ };
15427
+ } catch (err) {
15428
+ return {
15429
+ id: opt.id,
15430
+ name: opt.name,
15431
+ success: false,
15432
+ message: "Failed to install Beads",
15433
+ error: err instanceof Error ? err.message : String(err)
15434
+ };
15048
15435
  }
15049
- if (this.#options.discardStdin && process8.stdin.isTTY) {
15050
- stdin_discarder_default.start();
15051
- this.#isDiscardingStdin = true;
15436
+ }
15437
+ if (opt.installCommand) {
15438
+ try {
15439
+ execSync2(opt.installCommand, {
15440
+ encoding: "utf-8",
15441
+ stdio: "pipe",
15442
+ timeout: 60000
15443
+ });
15444
+ return {
15445
+ id: opt.id,
15446
+ name: opt.name,
15447
+ success: true,
15448
+ message: `Installed via: ${opt.installCommand}`
15449
+ };
15450
+ } catch (err) {
15451
+ return {
15452
+ id: opt.id,
15453
+ name: opt.name,
15454
+ success: false,
15455
+ message: "Failed to install MCP",
15456
+ error: err instanceof Error ? err.message : String(err)
15457
+ };
15052
15458
  }
15053
- this.#installHook();
15054
- this.render();
15055
- this.#id = setInterval(this.render.bind(this), this.interval);
15056
- return this;
15057
15459
  }
15058
- stop() {
15059
- clearInterval(this.#id);
15060
- this.#id = undefined;
15061
- this.#frameIndex = -1;
15062
- this.#lastFrameTime = 0;
15063
- this.#clearRenderDeferral();
15064
- this.#uninstallHook();
15065
- if (this.#drainHandler) {
15066
- this.#stream.removeListener("drain", this.#drainHandler);
15067
- this.#drainHandler = undefined;
15460
+ return {
15461
+ id: opt.id,
15462
+ name: opt.name,
15463
+ success: false,
15464
+ message: "No install command available"
15465
+ };
15466
+ }
15467
+ function installSkill(opt) {
15468
+ if (!opt.installCommand) {
15469
+ return {
15470
+ id: opt.id,
15471
+ name: opt.name,
15472
+ success: false,
15473
+ message: "No install command for skill"
15474
+ };
15475
+ }
15476
+ try {
15477
+ const skillPath = opt.installCommand.replace(/^npx\s+/, "").replace(/^bunx\s+/, "").replace(/^skills\s+add\s+/, "").trim();
15478
+ let result = spawnSync("bunx", ["--bun", "skills", "add", skillPath], {
15479
+ encoding: "utf-8",
15480
+ stdio: "pipe",
15481
+ timeout: 120000
15482
+ });
15483
+ if (result.status !== 0) {
15484
+ result = spawnSync("npx", ["-y", "skills", "add", skillPath], {
15485
+ encoding: "utf-8",
15486
+ stdio: "pipe",
15487
+ timeout: 120000
15488
+ });
15068
15489
  }
15069
- if (this.isEnabled) {
15070
- this.clear();
15071
- if (this.#options.hideCursor) {
15072
- cli_cursor_default.show(this.#stream);
15490
+ if (result.status === 0) {
15491
+ return {
15492
+ id: opt.id,
15493
+ name: opt.name,
15494
+ success: true,
15495
+ message: `Skill installed successfully`
15496
+ };
15497
+ } else {
15498
+ const output = (result.stderr || result.stdout || "").toLowerCase();
15499
+ if (output.includes("already exists") || output.includes("already installed")) {
15500
+ return {
15501
+ id: opt.id,
15502
+ name: opt.name,
15503
+ success: true,
15504
+ message: `Skill already installed`
15505
+ };
15073
15506
  }
15507
+ return {
15508
+ id: opt.id,
15509
+ name: opt.name,
15510
+ success: false,
15511
+ message: "Skill installation failed",
15512
+ error: result.stderr || result.stdout || "Unknown error"
15513
+ };
15074
15514
  }
15075
- if (this.#isDiscardingStdin) {
15076
- this.#isDiscardingStdin = false;
15077
- stdin_discarder_default.stop();
15078
- }
15079
- return this;
15080
- }
15081
- succeed(text) {
15082
- return this.stopAndPersist({ symbol: exports_symbols.success, text });
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 });
15515
+ } catch (err) {
15516
+ return {
15517
+ id: opt.id,
15518
+ name: opt.name,
15519
+ success: false,
15520
+ message: "Failed to install skill",
15521
+ error: err instanceof Error ? err.message : String(err)
15522
+ };
15089
15523
  }
15090
- info(text) {
15091
- return this.stopAndPersist({ symbol: exports_symbols.info, text });
15524
+ }
15525
+ function installConfig(opt, projectDir) {
15526
+ if (!opt.configPath || !opt.configContent) {
15527
+ return {
15528
+ id: opt.id,
15529
+ name: opt.name,
15530
+ success: false,
15531
+ message: "No config path or content provided"
15532
+ };
15092
15533
  }
15093
- stopAndPersist(options = {}) {
15094
- if (this.isSilent) {
15095
- return this;
15534
+ try {
15535
+ const fullPath = opt.configPath.startsWith("/") || opt.configPath.startsWith("~") ? opt.configPath.replace("~", homedir7()) : join8(projectDir, opt.configPath);
15536
+ if (existsSync8(fullPath)) {
15537
+ return {
15538
+ id: opt.id,
15539
+ name: opt.name,
15540
+ success: true,
15541
+ message: `Config already exists: ${opt.configPath}`
15542
+ };
15096
15543
  }
15097
- const symbol = options.symbol ?? " ";
15098
- const text = options.text ?? this.text;
15099
- const prefixText = options.prefixText ?? this.#options.prefixText;
15100
- const suffixText = options.suffixText ?? this.#options.suffixText;
15101
- const textToWrite = this.#buildOutputLine(symbol, text, prefixText, suffixText) + `
15102
- `;
15103
- this.stop();
15104
- this.#internalWrite(() => this.#stream.write(textToWrite));
15105
- return this;
15106
- }
15107
- }
15108
- function ora(options) {
15109
- return new Ora(options);
15110
- }
15111
-
15112
- // src/lib/ui.ts
15113
- var import_picocolors = __toESM(require_picocolors(), 1);
15114
- import * as readline from "readline";
15115
- var colors2 = {
15116
- primary: import_picocolors.default.cyan,
15117
- secondary: import_picocolors.default.blue,
15118
- accent: import_picocolors.default.magenta,
15119
- success: import_picocolors.default.green,
15120
- warning: import_picocolors.default.yellow,
15121
- error: import_picocolors.default.red,
15122
- info: import_picocolors.default.blue,
15123
- dim: import_picocolors.default.dim,
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("█"));
15544
+ const parentDir = fullPath.substring(0, fullPath.lastIndexOf("/"));
15545
+ if (parentDir && !existsSync8(parentDir)) {
15546
+ mkdirSync3(parentDir, { recursive: true });
15547
+ }
15548
+ writeFileSync3(fullPath, opt.configContent);
15549
+ return {
15550
+ id: opt.id,
15551
+ name: opt.name,
15552
+ success: true,
15553
+ message: `Created: ${opt.configPath}`
15554
+ };
15555
+ } catch (err) {
15556
+ return {
15557
+ id: opt.id,
15558
+ name: opt.name,
15559
+ success: false,
15560
+ message: "Failed to create config",
15561
+ error: err instanceof Error ? err.message : String(err)
15562
+ };
15563
+ }
15564
+ }
15565
+ function installHook(opt, projectDir) {
15566
+ const agentsMdPath = join8(projectDir, "AGENTS.md");
15567
+ try {
15568
+ let content = "";
15569
+ if (existsSync8(agentsMdPath)) {
15570
+ content = readFileSync8(agentsMdPath, "utf-8");
15196
15571
  } else {
15197
- write(colors2.dim("░"));
15572
+ content = `# Agent Instructions
15573
+
15574
+ `;
15198
15575
  }
15199
- await sleep(charDelay);
15576
+ const hookName = opt.name.toLowerCase();
15577
+ if (content.toLowerCase().includes(hookName)) {
15578
+ return {
15579
+ id: opt.id,
15580
+ name: opt.name,
15581
+ success: true,
15582
+ message: "Hook already configured in AGENTS.md"
15583
+ };
15584
+ }
15585
+ const hookSection = opt.configContent || `
15586
+ ## ${opt.name}
15587
+ ${opt.description}
15588
+ `;
15589
+ content += `
15590
+ ` + hookSection;
15591
+ writeFileSync3(agentsMdPath, content);
15592
+ return {
15593
+ id: opt.id,
15594
+ name: opt.name,
15595
+ success: true,
15596
+ message: "Added hook to AGENTS.md"
15597
+ };
15598
+ } catch (err) {
15599
+ return {
15600
+ id: opt.id,
15601
+ name: opt.name,
15602
+ success: false,
15603
+ message: "Failed to add hook",
15604
+ error: err instanceof Error ? err.message : String(err)
15605
+ };
15200
15606
  }
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
- }
15209
- async function revealDiscovery(icon, text, delay2 = 300) {
15210
- await sleep(delay2);
15211
- console.log(` ${icon} ${text}`);
15212
15607
  }
15213
- async function showPhaseHeader(phase, total, title, delay2 = 400) {
15214
- await sleep(delay2);
15215
- console.log();
15216
- console.log(` ${colors2.dim(`Phase ${phase}/${total}:`)} ${colors2.bold(colors2.primary(title))}`);
15217
- console.log(colors2.dim(" " + "─".repeat(40)));
15608
+ function phaseRecToInstallable(rec) {
15609
+ return {
15610
+ id: rec.title.toLowerCase().replace(/\s+/g, "-"),
15611
+ name: rec.title,
15612
+ type: rec.type,
15613
+ description: rec.description,
15614
+ installCommand: rec.installCommand,
15615
+ selected: false
15616
+ };
15218
15617
  }
15219
- async function animateScoreReveal(score, tier, options = {}) {
15220
- const { countDuration = 1000, barDelay = 50 } = options;
15221
- const scoreColor = score >= 80 ? colors2.excellent : score >= 60 ? colors2.good : score >= 40 ? colors2.moderate : colors2.poor;
15222
- console.log();
15223
- console.log(colors2.dim(" " + "═".repeat(45)));
15224
- console.log();
15225
- const steps = 30;
15226
- const stepDuration = countDuration / steps;
15227
- for (let i3 = 1;i3 <= steps; i3++) {
15228
- const current = Math.round(i3 / steps * score);
15229
- clearLine2();
15230
- write(` ${colors2.bold("Your Score:")} ${scoreColor(colors2.bold(current.toString()))}/100`);
15231
- await sleep(stepDuration);
15618
+ function checkInstalledStatus(projectDir) {
15619
+ const home = homedir7();
15620
+ const status = {
15621
+ context7: false,
15622
+ supermemory: false,
15623
+ nia: false,
15624
+ beads: false,
15625
+ skills: []
15626
+ };
15627
+ const mcpConfigPaths = [
15628
+ join8(home, ".claude.json"),
15629
+ join8(home, ".claude", "claude_desktop_config.json"),
15630
+ join8(home, ".claude", "settings.json"),
15631
+ join8(home, ".claude", "settings.local.json"),
15632
+ join8(projectDir, ".mcp.json"),
15633
+ join8(projectDir, ".claude", "settings.local.json")
15634
+ ];
15635
+ for (const configPath of mcpConfigPaths) {
15636
+ if (existsSync8(configPath)) {
15637
+ try {
15638
+ const config = JSON.parse(readFileSync8(configPath, "utf-8"));
15639
+ const mcpServers = config.mcpServers || config.mcp_servers || {};
15640
+ for (const name of Object.keys(mcpServers)) {
15641
+ const mcpName = name.toLowerCase();
15642
+ if (mcpName.includes("context7") || mcpName === "c7") {
15643
+ status.context7 = true;
15644
+ }
15645
+ if (mcpName.includes("supermemory") || mcpName.includes("memory")) {
15646
+ status.supermemory = true;
15647
+ }
15648
+ if (mcpName.includes("nia")) {
15649
+ status.nia = true;
15650
+ }
15651
+ }
15652
+ } catch {}
15653
+ }
15232
15654
  }
15233
- write(` ${colors2.dim("(")}${formatTier(tier)}${colors2.dim(")")}`);
15234
- console.log();
15235
- console.log();
15236
- const barWidth = 30;
15237
- const filled = Math.round(score / 100 * barWidth);
15238
- write(" ");
15239
- for (let i3 = 0;i3 < barWidth; i3++) {
15240
- if (i3 < filled) {
15241
- write(scoreColor("█"));
15242
- } else {
15243
- write(colors2.dim("░"));
15655
+ status.beads = existsSync8(join8(projectDir, ".beads"));
15656
+ const skillsDirs = [
15657
+ join8(home, ".claude", "skills"),
15658
+ join8(home, ".config", "opencode", "skills"),
15659
+ join8(home, ".agents", "skills"),
15660
+ join8(projectDir, ".opencode", "skill")
15661
+ ];
15662
+ for (const dir of skillsDirs) {
15663
+ if (existsSync8(dir)) {
15664
+ try {
15665
+ const skills = readdirSync4(dir);
15666
+ for (const skill of skills) {
15667
+ if (!status.skills.includes(skill.toLowerCase())) {
15668
+ status.skills.push(skill.toLowerCase());
15669
+ }
15670
+ }
15671
+ } catch {}
15244
15672
  }
15245
- await sleep(barDelay);
15246
15673
  }
15247
- console.log();
15248
- console.log();
15249
- console.log(colors2.dim(" " + "═".repeat(45)));
15674
+ return status;
15250
15675
  }
15251
- async function showFinding(type, label, value, unit = "", delay2 = 250) {
15252
- await sleep(delay2);
15253
- const iconMap = {
15254
- warning: icons.warning,
15255
- error: icons.error,
15256
- info: icons.info,
15257
- success: icons.success
15258
- };
15259
- const colorMap = {
15260
- warning: colors2.warning,
15261
- error: colors2.error,
15262
- info: colors2.info,
15263
- success: colors2.success
15264
- };
15265
- const icon = iconMap[type];
15266
- const valueColor = colorMap[type];
15267
- console.log(` ${icon} ${label}: ${valueColor(value.toString())}${unit}`);
15676
+ function filterAlreadyInstalled(optimizations, status) {
15677
+ return optimizations.filter((opt) => {
15678
+ const id = opt.id.toLowerCase();
15679
+ if (id === "context7" && status.context7)
15680
+ return false;
15681
+ if (id === "supermemory" && status.supermemory)
15682
+ return false;
15683
+ if (id === "nia" && status.nia)
15684
+ return false;
15685
+ if (id === "beads" && status.beads)
15686
+ return false;
15687
+ if (opt.type === "skill") {
15688
+ const skillName = opt.name.toLowerCase().replace(/\s+/g, "-");
15689
+ 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"))) {
15690
+ return false;
15691
+ }
15692
+ }
15693
+ return true;
15694
+ });
15268
15695
  }
15696
+ var QUICK_INSTALL_PRESETS = {
15697
+ essential: [
15698
+ {
15699
+ id: "context7",
15700
+ name: "Context7 MCP",
15701
+ type: "mcp",
15702
+ description: "Up-to-date library documentation",
15703
+ installCommand: "claude mcp add context7 https://mcp.context7.com/mcp --transport http",
15704
+ selected: true
15705
+ },
15706
+ {
15707
+ id: "supermemory",
15708
+ name: "Supermemory MCP",
15709
+ type: "mcp",
15710
+ description: "Persistent memory across sessions",
15711
+ installCommand: "claude mcp add supermemory -- npx -y @supermemory/mcp@latest",
15712
+ selected: true
15713
+ },
15714
+ {
15715
+ id: "beads",
15716
+ name: "Beads Task Manager",
15717
+ type: "mcp",
15718
+ description: "Persistent task tracking",
15719
+ installCommand: "bun add -g beads && bd init",
15720
+ selected: true
15721
+ }
15722
+ ],
15723
+ productivity: [
15724
+ {
15725
+ id: "claude-md",
15726
+ name: "CLAUDE.md",
15727
+ type: "config",
15728
+ description: "Project context file",
15729
+ configPath: "CLAUDE.md",
15730
+ configContent: `# Project Instructions
15731
+
15732
+ ## Build & Test Commands
15733
+ \`\`\`bash
15734
+ bun test # Run tests
15735
+ bun run build # Build project
15736
+ bun run lint # Run linter
15737
+ \`\`\`
15738
+
15739
+ ## Architecture
15740
+ Describe your project structure here.
15741
+
15742
+ ## Conventions
15743
+ - Use TypeScript
15744
+ - Write tests for new features
15745
+ - Use conventional commits
15746
+ `,
15747
+ selected: true
15748
+ },
15749
+ {
15750
+ id: "vitest",
15751
+ name: "Vitest",
15752
+ type: "library",
15753
+ description: "Fast unit testing framework",
15754
+ installCommand: "bun add -D vitest",
15755
+ selected: true
15756
+ }
15757
+ ]
15758
+ };
15269
15759
 
15270
15760
  // src/commands/scan.ts
15271
15761
  var scanCommand = defineCommand2({
@@ -15489,10 +15979,19 @@ var scanCommand = defineCommand2({
15489
15979
  console.log(colors2.dim(" " + "═".repeat(45)));
15490
15980
  console.log();
15491
15981
  if (!args["no-report"]) {
15492
- const reportDir = join8(projectDir, args["report-dir"]);
15982
+ const reportDir = join9(projectDir, args["report-dir"]);
15493
15983
  const reportPath = generateReport(reportDir, score, git, agents, tests, args.since, sdlcAnalysis, scanCost, analysis);
15494
15984
  console.log(` ${icons.success} Report saved: ${colors2.dim(reportPath)}`);
15495
15985
  }
15986
+ if (agents && agents.sessions.length > 0 && !args.brief) {
15987
+ const frustrationSummary = detectFrustrations(agents.sessions);
15988
+ if (frustrationSummary.totalFrustrations > 0) {
15989
+ const frustrationLines = formatFrustrationSummary(frustrationSummary);
15990
+ for (const line of frustrationLines) {
15991
+ console.log(line);
15992
+ }
15993
+ }
15994
+ }
15496
15995
  if (!args.brief) {
15497
15996
  const installedStatus = checkInstalledStatus(projectDir);
15498
15997
  const projectContext = loadProjectContext(projectDir);
@@ -15754,12 +16253,12 @@ var scanCommand = defineCommand2({
15754
16253
  }
15755
16254
  });
15756
16255
  function loadProjectContext(projectDir) {
15757
- const contextPath = join8(projectDir, ".nairon", "context.json");
15758
- if (!existsSync8(contextPath)) {
16256
+ const contextPath = join9(projectDir, ".nairon", "context.json");
16257
+ if (!existsSync9(contextPath)) {
15759
16258
  return null;
15760
16259
  }
15761
16260
  try {
15762
- const raw = readFileSync8(contextPath, "utf-8");
16261
+ const raw = readFileSync9(contextPath, "utf-8");
15763
16262
  const data = JSON.parse(raw);
15764
16263
  const context = {
15765
16264
  painPoints: data.painPoints || [],
@@ -15812,12 +16311,12 @@ function parseSince(since) {
15812
16311
  return new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
15813
16312
  }
15814
16313
  function generateReport(reportDir, score, git, agents, tests, since, sdlcAnalysis, scanCost, analysis) {
15815
- if (!existsSync8(reportDir)) {
16314
+ if (!existsSync9(reportDir)) {
15816
16315
  mkdirSync4(reportDir, { recursive: true });
15817
16316
  }
15818
16317
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
15819
16318
  const filename = `scan-${timestamp}.md`;
15820
- const filepath = join8(reportDir, filename);
16319
+ const filepath = join9(reportDir, filename);
15821
16320
  const lines = [];
15822
16321
  lines.push(`# NaironAI Scan Report`);
15823
16322
  lines.push("");
@@ -15958,11 +16457,11 @@ init_dist();
15958
16457
  init_client();
15959
16458
 
15960
16459
  // src/collectors/report-data.ts
15961
- import { existsSync as existsSync9, readdirSync as readdirSync5, readFileSync as readFileSync9, statSync as statSync2 } from "node:fs";
15962
- import { homedir as homedir7 } from "node:os";
15963
- import { join as join9, basename as basename2 } from "node:path";
16460
+ import { existsSync as existsSync10, readdirSync as readdirSync5, readFileSync as readFileSync10, statSync as statSync2 } from "node:fs";
16461
+ import { homedir as homedir8 } from "node:os";
16462
+ import { join as join10, basename as basename3 } from "node:path";
15964
16463
  async function collectReportData(projectDir, since, until = new Date, harness) {
15965
- const projectName = basename2(projectDir);
16464
+ const projectName = basename3(projectDir);
15966
16465
  const [commits, allSessions, mcpConfigs] = await Promise.all([
15967
16466
  collectGitCommits(projectDir, since, until),
15968
16467
  collectAllSessions(since, until, projectDir),
@@ -16043,12 +16542,12 @@ function detectAIAssistedCommit(message) {
16043
16542
  }
16044
16543
  async function collectAllSessions(since, until, projectDir) {
16045
16544
  const sessions = [];
16046
- const claudeDir = join9(homedir7(), ".claude");
16047
- if (existsSync9(claudeDir)) {
16545
+ const claudeDir = join10(homedir8(), ".claude");
16546
+ if (existsSync10(claudeDir)) {
16048
16547
  sessions.push(...collectClaudeCodeSessions(claudeDir, since, until, projectDir));
16049
16548
  }
16050
- const openCodeDir = join9(homedir7(), ".local", "share", "opencode");
16051
- if (existsSync9(openCodeDir)) {
16549
+ const openCodeDir = join10(homedir8(), ".local", "share", "opencode");
16550
+ if (existsSync10(openCodeDir)) {
16052
16551
  sessions.push(...collectOpenCodeSessions2(openCodeDir, since, until));
16053
16552
  }
16054
16553
  sessions.sort((a2, b2) => a2.startTime.getTime() - b2.startTime.getTime());
@@ -16056,15 +16555,15 @@ async function collectAllSessions(since, until, projectDir) {
16056
16555
  }
16057
16556
  function collectClaudeCodeSessions(claudeDir, since, until, projectDir) {
16058
16557
  const sessions = [];
16059
- const transcriptsDir = join9(claudeDir, "transcripts");
16060
- if (!existsSync9(transcriptsDir))
16558
+ const transcriptsDir = join10(claudeDir, "transcripts");
16559
+ if (!existsSync10(transcriptsDir))
16061
16560
  return sessions;
16062
16561
  const projectHash = projectDir ? hashPath(projectDir) : null;
16063
- const projectsDir = join9(claudeDir, "projects");
16562
+ const projectsDir = join10(claudeDir, "projects");
16064
16563
  try {
16065
16564
  const transcriptFiles = readdirSync5(transcriptsDir).filter((f3) => f3.endsWith(".jsonl"));
16066
16565
  for (const file of transcriptFiles) {
16067
- const filePath = join9(transcriptsDir, file);
16566
+ const filePath = join10(transcriptsDir, file);
16068
16567
  const stat = statSync2(filePath);
16069
16568
  if (stat.mtime < since || stat.mtime > until)
16070
16569
  continue;
@@ -16075,12 +16574,12 @@ function collectClaudeCodeSessions(claudeDir, since, until, projectDir) {
16075
16574
  }
16076
16575
  } catch {}
16077
16576
  }
16078
- if (projectHash && existsSync9(projectsDir)) {
16079
- const projectSessionDir = join9(projectsDir, projectHash);
16080
- if (existsSync9(projectSessionDir)) {
16577
+ if (projectHash && existsSync10(projectsDir)) {
16578
+ const projectSessionDir = join10(projectsDir, projectHash);
16579
+ if (existsSync10(projectSessionDir)) {
16081
16580
  const projectFiles = readdirSync5(projectSessionDir).filter((f3) => f3.endsWith(".jsonl"));
16082
16581
  for (const file of projectFiles) {
16083
- const filePath = join9(projectSessionDir, file);
16582
+ const filePath = join10(projectSessionDir, file);
16084
16583
  const stat = statSync2(filePath);
16085
16584
  if (stat.mtime < since || stat.mtime > until)
16086
16585
  continue;
@@ -16099,7 +16598,7 @@ function collectClaudeCodeSessions(claudeDir, since, until, projectDir) {
16099
16598
  return sessions;
16100
16599
  }
16101
16600
  function parseClaudeTranscript(filePath, fileName) {
16102
- const content = readFileSync9(filePath, "utf-8");
16601
+ const content = readFileSync10(filePath, "utf-8");
16103
16602
  const lines = content.trim().split(`
16104
16603
  `).filter((l2) => l2.trim());
16105
16604
  if (lines.length === 0)
@@ -16189,25 +16688,25 @@ function parseClaudeTranscript(filePath, fileName) {
16189
16688
  }
16190
16689
  function collectOpenCodeSessions2(openCodeDir, since, until) {
16191
16690
  const sessions = [];
16192
- const sessionDir = join9(openCodeDir, "storage", "session");
16193
- const messageDir = join9(openCodeDir, "storage", "message");
16194
- const partDir = join9(openCodeDir, "storage", "part");
16195
- if (!existsSync9(sessionDir))
16691
+ const sessionDir = join10(openCodeDir, "storage", "session");
16692
+ const messageDir = join10(openCodeDir, "storage", "message");
16693
+ const partDir = join10(openCodeDir, "storage", "part");
16694
+ if (!existsSync10(sessionDir))
16196
16695
  return sessions;
16197
16696
  try {
16198
- const projectDirs = readdirSync5(sessionDir, { withFileTypes: true }).filter((d2) => d2.isDirectory()).map((d2) => join9(sessionDir, d2.name));
16697
+ const projectDirs = readdirSync5(sessionDir, { withFileTypes: true }).filter((d2) => d2.isDirectory()).map((d2) => join10(sessionDir, d2.name));
16199
16698
  for (const projectDir of projectDirs) {
16200
16699
  const sessionFiles = readdirSync5(projectDir).filter((f3) => f3.endsWith(".json"));
16201
16700
  for (const sessionFile of sessionFiles) {
16202
16701
  try {
16203
- const sessionPath = join9(projectDir, sessionFile);
16204
- const sessionData = JSON.parse(readFileSync9(sessionPath, "utf-8"));
16702
+ const sessionPath = join10(projectDir, sessionFile);
16703
+ const sessionData = JSON.parse(readFileSync10(sessionPath, "utf-8"));
16205
16704
  const createdAt = new Date(sessionData.time?.created || 0);
16206
16705
  const updatedAt = new Date(sessionData.time?.updated || sessionData.time?.created || 0);
16207
16706
  if (updatedAt < since || createdAt > until)
16208
16707
  continue;
16209
16708
  const sessionId = sessionData.id;
16210
- const sessionMsgDir = join9(messageDir, sessionId);
16709
+ const sessionMsgDir = join10(messageDir, sessionId);
16211
16710
  const prompts = [];
16212
16711
  const responses = [];
16213
16712
  const toolsUsed = new Set;
@@ -16218,12 +16717,12 @@ function collectOpenCodeSessions2(openCodeDir, since, until) {
16218
16717
  let model = "unknown";
16219
16718
  let startTime = createdAt;
16220
16719
  let endTime = updatedAt;
16221
- if (existsSync9(sessionMsgDir)) {
16720
+ if (existsSync10(sessionMsgDir)) {
16222
16721
  const msgFiles = readdirSync5(sessionMsgDir).filter((f3) => f3.endsWith(".json")).sort();
16223
16722
  for (const msgFile of msgFiles) {
16224
16723
  try {
16225
- const msgPath = join9(sessionMsgDir, msgFile);
16226
- const msgData = JSON.parse(readFileSync9(msgPath, "utf-8"));
16724
+ const msgPath = join10(sessionMsgDir, msgFile);
16725
+ const msgData = JSON.parse(readFileSync10(msgPath, "utf-8"));
16227
16726
  const msgId = msgData.id;
16228
16727
  if (msgData.model?.modelID) {
16229
16728
  model = msgData.model.modelID;
@@ -16233,14 +16732,14 @@ function collectOpenCodeSessions2(openCodeDir, since, until) {
16233
16732
  startTime = msgTime;
16234
16733
  if (msgTime > endTime)
16235
16734
  endTime = msgTime;
16236
- const msgPartDir = join9(partDir, msgId);
16735
+ const msgPartDir = join10(partDir, msgId);
16237
16736
  let messageText = "";
16238
- if (existsSync9(msgPartDir)) {
16737
+ if (existsSync10(msgPartDir)) {
16239
16738
  const partFiles = readdirSync5(msgPartDir).filter((f3) => f3.endsWith(".json")).sort();
16240
16739
  for (const partFile of partFiles) {
16241
16740
  try {
16242
- const partPath = join9(msgPartDir, partFile);
16243
- const partData = JSON.parse(readFileSync9(partPath, "utf-8"));
16741
+ const partPath = join10(msgPartDir, partFile);
16742
+ const partData = JSON.parse(readFileSync10(partPath, "utf-8"));
16244
16743
  if (partData.type === "text" && partData.text && !partData.synthetic) {
16245
16744
  messageText += partData.text + `
16246
16745
  `;
@@ -16414,10 +16913,10 @@ function analyzeResponse(text, sessionId, index, promptId, timestamp) {
16414
16913
  }
16415
16914
  function collectMCPConfigs() {
16416
16915
  const configs = [];
16417
- const claudeConfig = join9(homedir7(), ".claude.json");
16418
- if (existsSync9(claudeConfig)) {
16916
+ const claudeConfig = join10(homedir8(), ".claude.json");
16917
+ if (existsSync10(claudeConfig)) {
16419
16918
  try {
16420
- const data = JSON.parse(readFileSync9(claudeConfig, "utf-8"));
16919
+ const data = JSON.parse(readFileSync10(claudeConfig, "utf-8"));
16421
16920
  const mcpServers = data.mcpServers || {};
16422
16921
  for (const [name, config] of Object.entries(mcpServers)) {
16423
16922
  configs.push({
@@ -16430,13 +16929,13 @@ function collectMCPConfigs() {
16430
16929
  } catch {}
16431
16930
  }
16432
16931
  const openCodeConfigs = [
16433
- join9(homedir7(), ".opencode.json"),
16434
- join9(homedir7(), ".config", "opencode", "opencode.json")
16932
+ join10(homedir8(), ".opencode.json"),
16933
+ join10(homedir8(), ".config", "opencode", "opencode.json")
16435
16934
  ];
16436
16935
  for (const configPath of openCodeConfigs) {
16437
- if (existsSync9(configPath)) {
16936
+ if (existsSync10(configPath)) {
16438
16937
  try {
16439
- const data = JSON.parse(readFileSync9(configPath, "utf-8"));
16938
+ const data = JSON.parse(readFileSync10(configPath, "utf-8"));
16440
16939
  const mcpServers = data.mcp || {};
16441
16940
  for (const [name, config] of Object.entries(mcpServers)) {
16442
16941
  if (!configs.find((c3) => c3.name === name)) {
@@ -16451,10 +16950,10 @@ function collectMCPConfigs() {
16451
16950
  } catch {}
16452
16951
  }
16453
16952
  }
16454
- const cursorConfig = join9(homedir7(), ".cursor", "mcp.json");
16455
- if (existsSync9(cursorConfig)) {
16953
+ const cursorConfig = join10(homedir8(), ".cursor", "mcp.json");
16954
+ if (existsSync10(cursorConfig)) {
16456
16955
  try {
16457
- const data = JSON.parse(readFileSync9(cursorConfig, "utf-8"));
16956
+ const data = JSON.parse(readFileSync10(cursorConfig, "utf-8"));
16458
16957
  const mcpServers = data.mcpServers || {};
16459
16958
  for (const [name, config] of Object.entries(mcpServers)) {
16460
16959
  if (!configs.find((c3) => c3.name === name)) {
@@ -18655,9 +19154,9 @@ function getSeverityEmoji(severity) {
18655
19154
  }
18656
19155
 
18657
19156
  // src/lib/tool-analyzer.ts
18658
- import { existsSync as existsSync10, readdirSync as readdirSync6 } from "node:fs";
18659
- import { homedir as homedir8 } from "node:os";
18660
- import { join as join10 } from "node:path";
19157
+ import { existsSync as existsSync11, readdirSync as readdirSync6 } from "node:fs";
19158
+ import { homedir as homedir9 } from "node:os";
19159
+ import { join as join11 } from "node:path";
18661
19160
  function analyzeToolUtilization(data) {
18662
19161
  const mcpServers = analyzeMCPServers(data);
18663
19162
  const mcpSummary = buildMCPSummary(mcpServers);
@@ -18807,24 +19306,24 @@ function categorizeTools(tools) {
18807
19306
  }
18808
19307
  function analyzeSkills() {
18809
19308
  const skills = [];
18810
- const home = homedir8();
19309
+ const home = homedir9();
18811
19310
  const skillsDirs = [
18812
- join10(home, ".claude", "skills"),
18813
- join10(home, ".agents", "skills"),
18814
- join10(home, ".config", "claude", "skills")
19311
+ join11(home, ".claude", "skills"),
19312
+ join11(home, ".agents", "skills"),
19313
+ join11(home, ".config", "claude", "skills")
18815
19314
  ];
18816
19315
  const projectSkillsDirs = [
18817
- join10(process.cwd(), ".claude", "skills"),
18818
- join10(process.cwd(), ".agents", "skills")
19316
+ join11(process.cwd(), ".claude", "skills"),
19317
+ join11(process.cwd(), ".agents", "skills")
18819
19318
  ];
18820
19319
  const openCodeSkillDirs = [
18821
- join10(home, ".config", "opencode", "skills"),
18822
- join10(home, ".local", "share", "opencode", "skills")
19320
+ join11(home, ".config", "opencode", "skills"),
19321
+ join11(home, ".local", "share", "opencode", "skills")
18823
19322
  ];
18824
19323
  const allSkillDirs = [...skillsDirs, ...projectSkillsDirs, ...openCodeSkillDirs];
18825
19324
  const seenSkills = new Set;
18826
19325
  for (const skillsDir of allSkillDirs) {
18827
- if (existsSync10(skillsDir)) {
19326
+ if (existsSync11(skillsDir)) {
18828
19327
  try {
18829
19328
  const entries = readdirSync6(skillsDir, { withFileTypes: true });
18830
19329
  for (const entry of entries) {
@@ -18835,7 +19334,7 @@ function analyzeSkills() {
18835
19334
  if (entry.isDirectory() || entry.isSymbolicLink() || entry.name.endsWith(".md")) {
18836
19335
  skills.push({
18837
19336
  name: skillName,
18838
- path: join10(skillsDir, entry.name),
19337
+ path: join11(skillsDir, entry.name),
18839
19338
  used: false,
18840
19339
  usageCount: 0
18841
19340
  });
@@ -19132,22 +19631,22 @@ function renderToolUtilizationMarkdown(analysis) {
19132
19631
  }
19133
19632
 
19134
19633
  // src/lib/coverage-parser.ts
19135
- import { existsSync as existsSync11, readFileSync as readFileSync11 } from "node:fs";
19136
- import { join as join11 } from "node:path";
19634
+ import { existsSync as existsSync12, readFileSync as readFileSync12 } from "node:fs";
19635
+ import { join as join12 } from "node:path";
19137
19636
  function parseCoverageReport(projectDir) {
19138
19637
  const coveragePaths = [
19139
- { path: join11(projectDir, "coverage", "lcov.info"), parser: parseLcov },
19140
- { path: join11(projectDir, "coverage", "coverage-summary.json"), parser: parseIstanbulSummary },
19141
- { path: join11(projectDir, "coverage", "coverage-final.json"), parser: parseIstanbulFinal },
19142
- { path: join11(projectDir, "coverage", "cobertura-coverage.xml"), parser: parseCobertura },
19143
- { path: join11(projectDir, "coverage", "clover.xml"), parser: parseClover },
19144
- { path: join11(projectDir, "lcov.info"), parser: parseLcov },
19145
- { path: join11(projectDir, ".nyc_output", "coverage-summary.json"), parser: parseIstanbulSummary }
19638
+ { path: join12(projectDir, "coverage", "lcov.info"), parser: parseLcov },
19639
+ { path: join12(projectDir, "coverage", "coverage-summary.json"), parser: parseIstanbulSummary },
19640
+ { path: join12(projectDir, "coverage", "coverage-final.json"), parser: parseIstanbulFinal },
19641
+ { path: join12(projectDir, "coverage", "cobertura-coverage.xml"), parser: parseCobertura },
19642
+ { path: join12(projectDir, "coverage", "clover.xml"), parser: parseClover },
19643
+ { path: join12(projectDir, "lcov.info"), parser: parseLcov },
19644
+ { path: join12(projectDir, ".nyc_output", "coverage-summary.json"), parser: parseIstanbulSummary }
19146
19645
  ];
19147
19646
  for (const { path, parser: parser4 } of coveragePaths) {
19148
- if (existsSync11(path)) {
19647
+ if (existsSync12(path)) {
19149
19648
  try {
19150
- const content = readFileSync11(path, "utf-8");
19649
+ const content = readFileSync12(path, "utf-8");
19151
19650
  return parser4(content, path);
19152
19651
  } catch {}
19153
19652
  }
@@ -21357,9 +21856,9 @@ function renderBar4(value, width) {
21357
21856
  }
21358
21857
 
21359
21858
  // src/commands/doctor.ts
21360
- import { existsSync as existsSync12 } from "node:fs";
21361
- import { homedir as homedir9 } from "node:os";
21362
- import { join as join12 } from "node:path";
21859
+ import { existsSync as existsSync13 } from "node:fs";
21860
+ import { homedir as homedir10 } from "node:os";
21861
+ import { join as join13 } from "node:path";
21363
21862
  init_client();
21364
21863
 
21365
21864
  // src/lib/recommendations-db.ts
@@ -22016,16 +22515,16 @@ var doctorCommand = defineCommand2({
22016
22515
  results.push({ label: "OS", status: "info", value: `${process.platform} ${process.arch}` });
22017
22516
  results.push({ label: "Bun", status: "info", value: typeof Bun !== "undefined" ? Bun.version : "N/A" });
22018
22517
  results.push({ label: "Node", status: "info", value: process.version });
22019
- results.push({ label: "Home", status: "info", value: homedir9() });
22020
- const gitDir = join12(process.cwd(), ".git");
22021
- if (existsSync12(gitDir)) {
22518
+ results.push({ label: "Home", status: "info", value: homedir10() });
22519
+ const gitDir = join13(process.cwd(), ".git");
22520
+ if (existsSync13(gitDir)) {
22022
22521
  results.push({ label: "Git", status: "success", value: "Repository detected" });
22023
22522
  } else {
22024
22523
  results.push({ label: "Git", status: "warn", value: "No repository in current directory" });
22025
22524
  }
22026
22525
  for (const [agent, pathTemplate] of Object.entries(AGENT_LOG_PATHS)) {
22027
- const resolvedPath = pathTemplate.replace("~", homedir9());
22028
- if (existsSync12(resolvedPath)) {
22526
+ const resolvedPath = pathTemplate.replace("~", homedir10());
22527
+ if (existsSync13(resolvedPath)) {
22029
22528
  results.push({ label: agent, status: "success", value: `found at ${resolvedPath}` });
22030
22529
  }
22031
22530
  }
@@ -22079,9 +22578,9 @@ var doctorCommand = defineCommand2({
22079
22578
  });
22080
22579
 
22081
22580
  // src/commands/setup.ts
22082
- import { existsSync as existsSync13, readFileSync as readFileSync12, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, copyFileSync } from "node:fs";
22083
- import { join as join13, dirname as dirname2 } from "node:path";
22084
- import { homedir as homedir10, platform as platform2 } from "node:os";
22581
+ import { existsSync as existsSync14, readFileSync as readFileSync13, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, copyFileSync } from "node:fs";
22582
+ import { join as join14, dirname as dirname2 } from "node:path";
22583
+ import { homedir as homedir11, platform as platform2 } from "node:os";
22085
22584
  import { execSync as execSync3 } from "node:child_process";
22086
22585
  import { createInterface } from "node:readline";
22087
22586
  var CONVEX_SITE_URL = "https://steady-bass-841.convex.site";
@@ -22100,7 +22599,7 @@ var FALLBACK_HARNESSES = [
22100
22599
  id: "claude-code",
22101
22600
  name: "Claude Code",
22102
22601
  configPaths: [
22103
- join13(homedir10(), ".claude.json")
22602
+ join14(homedir11(), ".claude.json")
22104
22603
  ],
22105
22604
  mcpConfigKey: "mcpServers",
22106
22605
  detected: false
@@ -22109,8 +22608,8 @@ var FALLBACK_HARNESSES = [
22109
22608
  id: "opencode",
22110
22609
  name: "OpenCode",
22111
22610
  configPaths: [
22112
- join13(homedir10(), ".opencode.json"),
22113
- join13(homedir10(), ".config", "opencode", "opencode.json")
22611
+ join14(homedir11(), ".opencode.json"),
22612
+ join14(homedir11(), ".config", "opencode", "opencode.json")
22114
22613
  ],
22115
22614
  mcpConfigKey: "mcp",
22116
22615
  detected: false
@@ -22119,8 +22618,8 @@ var FALLBACK_HARNESSES = [
22119
22618
  id: "cursor",
22120
22619
  name: "Cursor",
22121
22620
  configPaths: [
22122
- join13(homedir10(), ".cursor", "mcp.json"),
22123
- join13(homedir10(), "Library", "Application Support", "Cursor", "User", "globalStorage", "mcp.json")
22621
+ join14(homedir11(), ".cursor", "mcp.json"),
22622
+ join14(homedir11(), "Library", "Application Support", "Cursor", "User", "globalStorage", "mcp.json")
22124
22623
  ],
22125
22624
  mcpConfigKey: "mcpServers",
22126
22625
  detected: false
@@ -22137,7 +22636,7 @@ function getConfigPathsForPlatform(harness) {
22137
22636
  } else {
22138
22637
  paths = pathMap.linux;
22139
22638
  }
22140
- return paths.map((p) => p.replace(/^~/, homedir10()).replace(/%USERPROFILE%/gi, homedir10()).replace(/%APPDATA%/gi, join13(homedir10(), "AppData", "Roaming")));
22639
+ return paths.map((p) => p.replace(/^~/, homedir11()).replace(/%USERPROFILE%/gi, homedir11()).replace(/%APPDATA%/gi, join14(homedir11(), "AppData", "Roaming")));
22141
22640
  }
22142
22641
  function convertAPIHarnessToConfig(harness) {
22143
22642
  return {
@@ -22152,7 +22651,7 @@ function detectHarnesses(harnesses) {
22152
22651
  const detected = [];
22153
22652
  for (const harness of harnesses) {
22154
22653
  for (const configPath of harness.configPaths) {
22155
- if (existsSync13(configPath)) {
22654
+ if (existsSync14(configPath)) {
22156
22655
  detected.push({
22157
22656
  ...harness,
22158
22657
  detected: true,
@@ -22165,19 +22664,19 @@ function detectHarnesses(harnesses) {
22165
22664
  return detected;
22166
22665
  }
22167
22666
  function backupConfig(configPath) {
22168
- const backupDir = join13(homedir10(), ".nairon", "backups");
22169
- if (!existsSync13(backupDir)) {
22667
+ const backupDir = join14(homedir11(), ".nairon", "backups");
22668
+ if (!existsSync14(backupDir)) {
22170
22669
  mkdirSync5(backupDir, { recursive: true });
22171
22670
  }
22172
22671
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
22173
22672
  const filename = configPath.replace(/[/\\]/g, "_").replace(/^_/, "");
22174
- const backupPath = join13(backupDir, `${timestamp}_${filename}`);
22673
+ const backupPath = join14(backupDir, `${timestamp}_${filename}`);
22175
22674
  copyFileSync(configPath, backupPath);
22176
22675
  return backupPath;
22177
22676
  }
22178
22677
  function readJsonConfig(configPath) {
22179
22678
  try {
22180
- const content = readFileSync12(configPath, "utf-8");
22679
+ const content = readFileSync13(configPath, "utf-8");
22181
22680
  return JSON.parse(content);
22182
22681
  } catch {
22183
22682
  return {};
@@ -22185,7 +22684,7 @@ function readJsonConfig(configPath) {
22185
22684
  }
22186
22685
  function writeJsonConfig(configPath, config) {
22187
22686
  const dir = dirname2(configPath);
22188
- if (!existsSync13(dir)) {
22687
+ if (!existsSync14(dir)) {
22189
22688
  mkdirSync5(dir, { recursive: true });
22190
22689
  }
22191
22690
  writeFileSync6(configPath, JSON.stringify(config, null, 2));
@@ -22229,7 +22728,7 @@ function getInstalledMCPs(harnesses) {
22229
22728
  const installed = new Set;
22230
22729
  for (const harness of harnesses) {
22231
22730
  for (const configPath of harness.configPaths) {
22232
- if (!existsSync13(configPath))
22731
+ if (!existsSync14(configPath))
22233
22732
  continue;
22234
22733
  const config = readJsonConfig(configPath);
22235
22734
  const mcpServers = config[harness.mcpConfigKey];
@@ -22253,7 +22752,7 @@ async function installMCPServer(serverName, instruction, harness) {
22253
22752
  if (!harness.configPath || !instruction.mcpServerConfig)
22254
22753
  return false;
22255
22754
  try {
22256
- if (existsSync13(harness.configPath)) {
22755
+ if (existsSync14(harness.configPath)) {
22257
22756
  backupConfig(harness.configPath);
22258
22757
  }
22259
22758
  const config = readJsonConfig(harness.configPath);
@@ -22298,8 +22797,8 @@ async function installBeads(projectDir) {
22298
22797
  }
22299
22798
  }
22300
22799
  }
22301
- const beadsDir = join13(projectDir, ".beads");
22302
- if (!existsSync13(beadsDir)) {
22800
+ const beadsDir = join14(projectDir, ".beads");
22801
+ if (!existsSync14(beadsDir)) {
22303
22802
  const projectName = projectDir.split(/[/\\]/).pop() ?? "project";
22304
22803
  const initSpinner = createSpinner(`Initializing Beads in ${projectName}...`);
22305
22804
  initSpinner.start();
@@ -22318,9 +22817,9 @@ async function installBeads(projectDir) {
22318
22817
  }
22319
22818
  }
22320
22819
  async function createClaudeRules(projectDir) {
22321
- const claudeMdPath = join13(projectDir, "CLAUDE.md");
22322
- const agentsMdPath = join13(projectDir, "AGENTS.md");
22323
- if (existsSync13(claudeMdPath) || existsSync13(agentsMdPath)) {
22820
+ const claudeMdPath = join14(projectDir, "CLAUDE.md");
22821
+ const agentsMdPath = join14(projectDir, "AGENTS.md");
22822
+ if (existsSync14(claudeMdPath) || existsSync14(agentsMdPath)) {
22324
22823
  console.log(` ${icons.info} CLAUDE.md or AGENTS.md already exists`);
22325
22824
  return true;
22326
22825
  }
@@ -22643,6 +23142,16 @@ var BOLD = "\x1B[1m";
22643
23142
  var RESET = "\x1B[0m";
22644
23143
  var MAGENTA = "\x1B[35m";
22645
23144
  var CHANGELOG = [
23145
+ {
23146
+ version: "0.3.14",
23147
+ date: "2026-02-14",
23148
+ title: "Enhanced Frustration Detection",
23149
+ highlights: [
23150
+ "Scan now shows exact prompts that caused frustration",
23151
+ "Root cause analysis: hallucination, context loss, undo loops",
23152
+ "Each frustration linked to a specific fix with install command"
23153
+ ]
23154
+ },
22646
23155
  {
22647
23156
  version: "0.3.13",
22648
23157
  date: "2026-02-14",
@@ -23051,7 +23560,7 @@ function showFullChangelog() {
23051
23560
  // package.json
23052
23561
  var package_default = {
23053
23562
  name: "nairon-bench",
23054
- version: "0.3.13",
23563
+ version: "0.3.14",
23055
23564
  description: "AI workflow benchmarking CLI",
23056
23565
  type: "module",
23057
23566
  bin: {
@@ -23110,9 +23619,9 @@ var versionCommand = defineCommand2({
23110
23619
 
23111
23620
  // src/commands/init.ts
23112
23621
  init_dist();
23113
- import { existsSync as existsSync14 } from "node:fs";
23114
- import { homedir as homedir11, platform as platform3, arch } from "node:os";
23115
- import { join as join14 } from "node:path";
23622
+ import { existsSync as existsSync15 } from "node:fs";
23623
+ import { homedir as homedir12, platform as platform3, arch } from "node:os";
23624
+ import { join as join15 } from "node:path";
23116
23625
  init_client();
23117
23626
 
23118
23627
  // src/lib/github-auth.ts
@@ -23282,8 +23791,8 @@ var initCommand = defineCommand2({
23282
23791
  consola.start("Step 2/6: Detecting AI agents...");
23283
23792
  const detectedAgents = [];
23284
23793
  for (const [agent, pathTemplate] of Object.entries(AGENT_LOG_PATHS)) {
23285
- const resolvedPath = pathTemplate.replace("~", homedir11());
23286
- if (existsSync14(resolvedPath)) {
23794
+ const resolvedPath = pathTemplate.replace("~", homedir12());
23795
+ if (existsSync15(resolvedPath)) {
23287
23796
  detectedAgents.push(agent);
23288
23797
  consola.success(` Found: ${agent}`);
23289
23798
  }
@@ -23386,7 +23895,7 @@ var initCommand = defineCommand2({
23386
23895
  { name: "playwright", configs: ["playwright.config.ts", "playwright.config.js"] }
23387
23896
  ];
23388
23897
  for (const fw of testFrameworks) {
23389
- if (fw.configs.some((c3) => existsSync14(join14(process.cwd(), c3)))) {
23898
+ if (fw.configs.some((c3) => existsSync15(join15(process.cwd(), c3)))) {
23390
23899
  toolStack.testing.push(fw.name);
23391
23900
  }
23392
23901
  }
@@ -23455,13 +23964,13 @@ var initCommand = defineCommand2({
23455
23964
  });
23456
23965
  function detectPackageManager() {
23457
23966
  const cwd = process.cwd();
23458
- if (existsSync14(join14(cwd, "bun.lock")) || existsSync14(join14(cwd, "bun.lockb")))
23967
+ if (existsSync15(join15(cwd, "bun.lock")) || existsSync15(join15(cwd, "bun.lockb")))
23459
23968
  return "bun";
23460
- if (existsSync14(join14(cwd, "pnpm-lock.yaml")))
23969
+ if (existsSync15(join15(cwd, "pnpm-lock.yaml")))
23461
23970
  return "pnpm";
23462
- if (existsSync14(join14(cwd, "yarn.lock")))
23971
+ if (existsSync15(join15(cwd, "yarn.lock")))
23463
23972
  return "yarn";
23464
- if (existsSync14(join14(cwd, "package-lock.json")))
23973
+ if (existsSync15(join15(cwd, "package-lock.json")))
23465
23974
  return "npm";
23466
23975
  return;
23467
23976
  }
@@ -23476,15 +23985,15 @@ var CLAUDE_CODE_SKILLS = [
23476
23985
  ];
23477
23986
  function detectEasyWins(detectedAgents) {
23478
23987
  const wins = [];
23479
- const home = homedir11();
23988
+ const home = homedir12();
23480
23989
  const hasClaudeCode = detectedAgents.some((a2) => a2.toLowerCase().includes("claude") || a2.toLowerCase().includes("opencode"));
23481
- const claudeConfigDir = join14(home, ".claude");
23482
- const hasClaudeConfig = existsSync14(claudeConfigDir);
23990
+ const claudeConfigDir = join15(home, ".claude");
23991
+ const hasClaudeConfig = existsSync15(claudeConfigDir);
23483
23992
  if (hasClaudeCode || hasClaudeConfig) {
23484
- const skillsDir = join14(home, ".claude", "skills");
23993
+ const skillsDir = join15(home, ".claude", "skills");
23485
23994
  for (const skill of CLAUDE_CODE_SKILLS) {
23486
- const skillPath = join14(skillsDir, skill.id);
23487
- const isInstalled = existsSync14(skillPath);
23995
+ const skillPath = join15(skillsDir, skill.id);
23996
+ const isInstalled = existsSync15(skillPath);
23488
23997
  if (!isInstalled) {
23489
23998
  wins.push({
23490
23999
  icon: skill.icon,
@@ -23500,14 +24009,14 @@ function detectEasyWins(detectedAgents) {
23500
24009
  // src/commands/onboard.ts
23501
24010
  init_dist();
23502
24011
  init_client();
23503
- import { existsSync as existsSync16, mkdirSync as mkdirSync6, readFileSync as readFileSync14, writeFileSync as writeFileSync7, readdirSync as readdirSync9 } from "node:fs";
23504
- import { join as join16 } from "node:path";
24012
+ import { existsSync as existsSync17, mkdirSync as mkdirSync6, readFileSync as readFileSync15, writeFileSync as writeFileSync7, readdirSync as readdirSync9 } from "node:fs";
24013
+ import { join as join17 } from "node:path";
23505
24014
 
23506
24015
  // src/lib/project-context-detector.ts
23507
- import { existsSync as existsSync15, readFileSync as readFileSync13, readdirSync as readdirSync8 } from "node:fs";
23508
- import { join as join15, basename as basename3 } from "node:path";
24016
+ import { existsSync as existsSync16, readFileSync as readFileSync14, readdirSync as readdirSync8 } from "node:fs";
24017
+ import { join as join16, basename as basename4 } from "node:path";
23509
24018
  function detectProjectContext(projectDir) {
23510
- const projectName = basename3(projectDir);
24019
+ const projectName = basename4(projectDir);
23511
24020
  const projectId = generateProjectId(projectDir);
23512
24021
  const techStack = detectTechStack(projectDir);
23513
24022
  const projectType = inferProjectType(projectDir, techStack);
@@ -23541,11 +24050,11 @@ function detectTechStack(projectDir) {
23541
24050
  };
23542
24051
  }
23543
24052
  function readPackageJson(projectDir) {
23544
- const pkgPath = join15(projectDir, "package.json");
23545
- if (!existsSync15(pkgPath))
24053
+ const pkgPath = join16(projectDir, "package.json");
24054
+ if (!existsSync16(pkgPath))
23546
24055
  return {};
23547
24056
  try {
23548
- return JSON.parse(readFileSync13(pkgPath, "utf-8"));
24057
+ return JSON.parse(readFileSync14(pkgPath, "utf-8"));
23549
24058
  } catch {
23550
24059
  return {};
23551
24060
  }
@@ -23566,34 +24075,34 @@ function detectFramework(deps) {
23566
24075
  return null;
23567
24076
  }
23568
24077
  function detectMetaFramework(deps, projectDir) {
23569
- if (deps.next || existsSync15(join15(projectDir, "next.config.js")) || existsSync15(join15(projectDir, "next.config.mjs")))
24078
+ if (deps.next || existsSync16(join16(projectDir, "next.config.js")) || existsSync16(join16(projectDir, "next.config.mjs")))
23570
24079
  return "next";
23571
- if (deps.nuxt || existsSync15(join15(projectDir, "nuxt.config.ts")))
24080
+ if (deps.nuxt || existsSync16(join16(projectDir, "nuxt.config.ts")))
23572
24081
  return "nuxt";
23573
24082
  if (deps["@sveltejs/kit"])
23574
24083
  return "sveltekit";
23575
- if (deps.astro || existsSync15(join15(projectDir, "astro.config.mjs")))
24084
+ if (deps.astro || existsSync16(join16(projectDir, "astro.config.mjs")))
23576
24085
  return "astro";
23577
24086
  if (deps["@remix-run/react"])
23578
24087
  return "remix";
23579
24088
  if (deps.gatsby)
23580
24089
  return "gatsby";
23581
- if (deps.vite || existsSync15(join15(projectDir, "vite.config.ts")))
24090
+ if (deps.vite || existsSync16(join16(projectDir, "vite.config.ts")))
23582
24091
  return "vite";
23583
24092
  return null;
23584
24093
  }
23585
24094
  function detectRuntime(projectDir) {
23586
- if (existsSync15(join15(projectDir, "bun.lockb")) || existsSync15(join15(projectDir, "bun.lock")))
24095
+ if (existsSync16(join16(projectDir, "bun.lockb")) || existsSync16(join16(projectDir, "bun.lock")))
23587
24096
  return "bun";
23588
- if (existsSync15(join15(projectDir, "deno.json")) || existsSync15(join15(projectDir, "deno.lock")))
24097
+ if (existsSync16(join16(projectDir, "deno.json")) || existsSync16(join16(projectDir, "deno.lock")))
23589
24098
  return "deno";
23590
24099
  return "node";
23591
24100
  }
23592
24101
  function detectLanguage(projectDir) {
23593
- if (existsSync15(join15(projectDir, "tsconfig.json")))
24102
+ if (existsSync16(join16(projectDir, "tsconfig.json")))
23594
24103
  return "typescript";
23595
- const srcDir = join15(projectDir, "src");
23596
- if (existsSync15(srcDir)) {
24104
+ const srcDir = join16(projectDir, "src");
24105
+ if (existsSync16(srcDir)) {
23597
24106
  try {
23598
24107
  const files = readdirSync8(srcDir);
23599
24108
  if (files.some((f3) => f3.endsWith(".ts") || f3.endsWith(".tsx")))
@@ -23604,7 +24113,7 @@ function detectLanguage(projectDir) {
23604
24113
  }
23605
24114
  function detectStyling(deps, projectDir) {
23606
24115
  const tools = [];
23607
- if (deps.tailwindcss || existsSync15(join15(projectDir, "tailwind.config.js")) || existsSync15(join15(projectDir, "tailwind.config.ts")))
24116
+ if (deps.tailwindcss || existsSync16(join16(projectDir, "tailwind.config.js")) || existsSync16(join16(projectDir, "tailwind.config.ts")))
23608
24117
  tools.push("tailwind");
23609
24118
  if (deps["styled-components"])
23610
24119
  tools.push("styled-components");
@@ -23649,13 +24158,13 @@ function detectORM(deps) {
23649
24158
  }
23650
24159
  function detectTesting(deps, projectDir) {
23651
24160
  const tools = [];
23652
- if (deps.vitest || existsSync15(join15(projectDir, "vitest.config.ts")))
24161
+ if (deps.vitest || existsSync16(join16(projectDir, "vitest.config.ts")))
23653
24162
  tools.push("vitest");
23654
- if (deps.jest || existsSync15(join15(projectDir, "jest.config.js")))
24163
+ if (deps.jest || existsSync16(join16(projectDir, "jest.config.js")))
23655
24164
  tools.push("jest");
23656
- if (deps["@playwright/test"] || existsSync15(join15(projectDir, "playwright.config.ts")))
24165
+ if (deps["@playwright/test"] || existsSync16(join16(projectDir, "playwright.config.ts")))
23657
24166
  tools.push("playwright");
23658
- if (deps.cypress || existsSync15(join15(projectDir, "cypress.config.ts")))
24167
+ if (deps.cypress || existsSync16(join16(projectDir, "cypress.config.ts")))
23659
24168
  tools.push("cypress");
23660
24169
  if (deps["@testing-library/react"] || deps["@testing-library/vue"])
23661
24170
  tools.push("testing-library");
@@ -23687,7 +24196,7 @@ function detectBuildTools(deps, projectDir) {
23687
24196
  tools.push("esbuild");
23688
24197
  if (deps.webpack)
23689
24198
  tools.push("webpack");
23690
- if (deps.turbo || existsSync15(join15(projectDir, "turbo.json")))
24199
+ if (deps.turbo || existsSync16(join16(projectDir, "turbo.json")))
23691
24200
  tools.push("turborepo");
23692
24201
  if (deps.tsup)
23693
24202
  tools.push("tsup");
@@ -23697,17 +24206,17 @@ function detectBuildTools(deps, projectDir) {
23697
24206
  }
23698
24207
  function detectDeployment(projectDir) {
23699
24208
  const tools = [];
23700
- if (existsSync15(join15(projectDir, "vercel.json")) || existsSync15(join15(projectDir, ".vercel")))
24209
+ if (existsSync16(join16(projectDir, "vercel.json")) || existsSync16(join16(projectDir, ".vercel")))
23701
24210
  tools.push("vercel");
23702
- if (existsSync15(join15(projectDir, "netlify.toml")))
24211
+ if (existsSync16(join16(projectDir, "netlify.toml")))
23703
24212
  tools.push("netlify");
23704
- if (existsSync15(join15(projectDir, "fly.toml")))
24213
+ if (existsSync16(join16(projectDir, "fly.toml")))
23705
24214
  tools.push("fly");
23706
- if (existsSync15(join15(projectDir, "railway.json")))
24215
+ if (existsSync16(join16(projectDir, "railway.json")))
23707
24216
  tools.push("railway");
23708
- if (existsSync15(join15(projectDir, "Dockerfile")))
24217
+ if (existsSync16(join16(projectDir, "Dockerfile")))
23709
24218
  tools.push("docker");
23710
- if (existsSync15(join15(projectDir, ".github", "workflows")))
24219
+ if (existsSync16(join16(projectDir, ".github", "workflows")))
23711
24220
  tools.push("github-actions");
23712
24221
  return tools;
23713
24222
  }
@@ -23730,20 +24239,20 @@ function detectAIML(deps) {
23730
24239
  return tools;
23731
24240
  }
23732
24241
  function inferProjectType(projectDir, techStack) {
23733
- if (existsSync15(join15(projectDir, "packages")) || existsSync15(join15(projectDir, "apps"))) {
24242
+ if (existsSync16(join16(projectDir, "packages")) || existsSync16(join16(projectDir, "apps"))) {
23734
24243
  return "monorepo";
23735
24244
  }
23736
24245
  const pkg = readPackageJson(projectDir);
23737
- if (pkg.bin || existsSync15(join15(projectDir, "src", "cli.ts")) || existsSync15(join15(projectDir, "src", "index.ts"))) {
24246
+ if (pkg.bin || existsSync16(join16(projectDir, "src", "cli.ts")) || existsSync16(join16(projectDir, "src", "index.ts"))) {
23738
24247
  const hasBin = !!pkg.bin;
23739
- const hasCommands = existsSync15(join15(projectDir, "src", "commands"));
24248
+ const hasCommands = existsSync16(join16(projectDir, "src", "commands"));
23740
24249
  if (hasBin || hasCommands)
23741
24250
  return "cli";
23742
24251
  }
23743
24252
  if (!techStack.framework && !techStack.metaFramework && pkg.main) {
23744
24253
  return "library";
23745
24254
  }
23746
- if (existsSync15(join15(projectDir, "app.json")) || existsSync15(join15(projectDir, "expo"))) {
24255
+ if (existsSync16(join16(projectDir, "app.json")) || existsSync16(join16(projectDir, "expo"))) {
23747
24256
  return "mobile";
23748
24257
  }
23749
24258
  if (techStack.database.length > 0 && !techStack.framework) {
@@ -23760,10 +24269,10 @@ function extractDescription(projectDir) {
23760
24269
  return pkg.description;
23761
24270
  const readmePaths = ["README.md", "readme.md", "Readme.md"];
23762
24271
  for (const readme of readmePaths) {
23763
- const path = join15(projectDir, readme);
23764
- if (existsSync15(path)) {
24272
+ const path = join16(projectDir, readme);
24273
+ if (existsSync16(path)) {
23765
24274
  try {
23766
- const content = readFileSync13(path, "utf-8");
24275
+ const content = readFileSync14(path, "utf-8");
23767
24276
  const lines = content.split(`
23768
24277
  `);
23769
24278
  let foundTitle = false;
@@ -25181,9 +25690,9 @@ var onboardCommand = defineCommand2({
25181
25690
  },
25182
25691
  async run({ args }) {
25183
25692
  const projectPath = process.cwd();
25184
- const contextPath = join16(projectPath, ".nairon", "context.json");
25185
- if (existsSync16(contextPath) && !args.force) {
25186
- const existing = JSON.parse(readFileSync14(contextPath, "utf-8"));
25693
+ const contextPath = join17(projectPath, ".nairon", "context.json");
25694
+ if (existsSync17(contextPath) && !args.force) {
25695
+ const existing = JSON.parse(readFileSync15(contextPath, "utf-8"));
25187
25696
  consola.info("Project already onboarded. Use --force to re-run.");
25188
25697
  consola.info(`Business: ${existing.businessContext?.domain || existing.businessContext?.slice?.(0, 50) || "Not set"}...`);
25189
25698
  consola.info(`Stack: ${formatTechStackSummary(existing)}`);
@@ -25331,8 +25840,8 @@ var onboardCommand = defineCommand2({
25331
25840
  createdAt: new Date().toISOString(),
25332
25841
  updatedAt: new Date().toISOString()
25333
25842
  };
25334
- const naironDir = join16(projectPath, ".nairon");
25335
- if (!existsSync16(naironDir)) {
25843
+ const naironDir = join17(projectPath, ".nairon");
25844
+ if (!existsSync17(naironDir)) {
25336
25845
  mkdirSync6(naironDir, { recursive: true });
25337
25846
  }
25338
25847
  writeFileSync7(contextPath, JSON.stringify(fullContext, null, 2));
@@ -25423,51 +25932,51 @@ function formatTechStackSummary(context) {
25423
25932
  function detectInstalledTools(projectPath) {
25424
25933
  const tools = [];
25425
25934
  const home = process.env.HOME || "";
25426
- const userClaudeJson = join16(home, ".claude.json");
25427
- if (existsSync16(userClaudeJson)) {
25935
+ const userClaudeJson = join17(home, ".claude.json");
25936
+ if (existsSync17(userClaudeJson)) {
25428
25937
  try {
25429
- const config = JSON.parse(readFileSync14(userClaudeJson, "utf-8"));
25938
+ const config = JSON.parse(readFileSync15(userClaudeJson, "utf-8"));
25430
25939
  if (config.mcpServers) {
25431
25940
  tools.push(...Object.keys(config.mcpServers));
25432
25941
  }
25433
25942
  } catch {}
25434
25943
  }
25435
- const claudeDesktopConfig = join16(home, ".claude", "claude_desktop_config.json");
25436
- if (existsSync16(claudeDesktopConfig)) {
25944
+ const claudeDesktopConfig = join17(home, ".claude", "claude_desktop_config.json");
25945
+ if (existsSync17(claudeDesktopConfig)) {
25437
25946
  try {
25438
- const config = JSON.parse(readFileSync14(claudeDesktopConfig, "utf-8"));
25947
+ const config = JSON.parse(readFileSync15(claudeDesktopConfig, "utf-8"));
25439
25948
  if (config.mcpServers) {
25440
25949
  tools.push(...Object.keys(config.mcpServers));
25441
25950
  }
25442
25951
  } catch {}
25443
25952
  }
25444
- const projectMcpJson = join16(projectPath, ".mcp.json");
25445
- if (existsSync16(projectMcpJson)) {
25953
+ const projectMcpJson = join17(projectPath, ".mcp.json");
25954
+ if (existsSync17(projectMcpJson)) {
25446
25955
  try {
25447
- const config = JSON.parse(readFileSync14(projectMcpJson, "utf-8"));
25956
+ const config = JSON.parse(readFileSync15(projectMcpJson, "utf-8"));
25448
25957
  if (config.mcpServers) {
25449
25958
  tools.push(...Object.keys(config.mcpServers));
25450
25959
  }
25451
25960
  } catch {}
25452
25961
  }
25453
- const projectClaudeConfig = join16(projectPath, ".claude", "settings.json");
25454
- if (existsSync16(projectClaudeConfig)) {
25962
+ const projectClaudeConfig = join17(projectPath, ".claude", "settings.json");
25963
+ if (existsSync17(projectClaudeConfig)) {
25455
25964
  try {
25456
- const config = JSON.parse(readFileSync14(projectClaudeConfig, "utf-8"));
25965
+ const config = JSON.parse(readFileSync15(projectClaudeConfig, "utf-8"));
25457
25966
  if (config.mcpServers) {
25458
25967
  tools.push(...Object.keys(config.mcpServers));
25459
25968
  }
25460
25969
  } catch {}
25461
25970
  }
25462
- const skillsDir = join16(home, ".config", "opencode", "skills");
25463
- if (existsSync16(skillsDir)) {
25971
+ const skillsDir = join17(home, ".config", "opencode", "skills");
25972
+ if (existsSync17(skillsDir)) {
25464
25973
  try {
25465
25974
  const skills = readdirSync9(skillsDir);
25466
25975
  tools.push(...skills.filter((s2) => !s2.startsWith(".")));
25467
25976
  } catch {}
25468
25977
  }
25469
- const agentsSkillsDir = join16(home, ".agents", "skills");
25470
- if (existsSync16(agentsSkillsDir)) {
25978
+ const agentsSkillsDir = join17(home, ".agents", "skills");
25979
+ if (existsSync17(agentsSkillsDir)) {
25471
25980
  try {
25472
25981
  const skills = readdirSync9(agentsSkillsDir);
25473
25982
  tools.push(...skills.filter((s2) => !s2.startsWith(".")));
@@ -25477,11 +25986,11 @@ function detectInstalledTools(projectPath) {
25477
25986
  }
25478
25987
  function detectPrimaryAgent() {
25479
25988
  const home = process.env.HOME || "";
25480
- if (existsSync16(join16(home, ".claude")))
25989
+ if (existsSync17(join17(home, ".claude")))
25481
25990
  return "claude-code";
25482
- if (existsSync16(join16(home, ".cursor")))
25991
+ if (existsSync17(join17(home, ".cursor")))
25483
25992
  return "cursor";
25484
- if (existsSync16(join16(home, ".config", "opencode")))
25993
+ if (existsSync17(join17(home, ".config", "opencode")))
25485
25994
  return "opencode";
25486
25995
  return;
25487
25996
  }
@@ -25576,7 +26085,7 @@ function formatBytes(bytes) {
25576
26085
  // package.json
25577
26086
  var package_default2 = {
25578
26087
  name: "nairon-bench",
25579
- version: "0.3.13",
26088
+ version: "0.3.14",
25580
26089
  description: "AI workflow benchmarking CLI",
25581
26090
  type: "module",
25582
26091
  bin: {