nairon-bench 0.0.16 → 0.0.18

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 +345 -75
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -9921,7 +9921,7 @@ function detectEnvironment(projectDir, agents) {
9921
9921
  if (session.toolNames) {
9922
9922
  for (const toolName of session.toolNames) {
9923
9923
  const name = toolName.toLowerCase();
9924
- const mcpMatch = name.match(/^mcp__(\w+)__/);
9924
+ const mcpMatch = name.match(/^mcp[_]{1,2}([a-z0-9-]+)[_]{1,2}/);
9925
9925
  if (mcpMatch) {
9926
9926
  const serverName = mcpMatch[1];
9927
9927
  if (!detectedMcps.includes(serverName)) {
@@ -9938,24 +9938,50 @@ function detectEnvironment(projectDir, agents) {
9938
9938
  hasNia = true;
9939
9939
  }
9940
9940
  }
9941
- if (name.includes("context7")) {
9941
+ if (name.includes("context7") || name.includes("context-7")) {
9942
9942
  hasContext7 = true;
9943
9943
  if (!detectedMcps.includes("context7")) {
9944
9944
  detectedMcps.push("context7");
9945
9945
  mcpCount++;
9946
9946
  }
9947
9947
  }
9948
- if (name.includes("supermemory")) {
9948
+ if (name.includes("supermemory") || name === "supermemory") {
9949
9949
  hasSupermemory = true;
9950
9950
  if (!detectedMcps.includes("supermemory")) {
9951
9951
  detectedMcps.push("supermemory");
9952
9952
  mcpCount++;
9953
9953
  }
9954
9954
  }
9955
+ if (name.includes("nia") && name.startsWith("mcp")) {
9956
+ hasNia = true;
9957
+ if (!detectedMcps.includes("nia")) {
9958
+ detectedMcps.push("nia");
9959
+ mcpCount++;
9960
+ }
9961
+ }
9955
9962
  }
9956
9963
  }
9957
9964
  }
9958
9965
  }
9966
+ const transcriptsDir = join4(home, ".claude", "transcripts");
9967
+ if (!hasSupermemory && existsSync4(transcriptsDir)) {
9968
+ try {
9969
+ const transcriptFiles = readdirSync2(transcriptsDir).filter((f3) => f3.endsWith(".jsonl")).slice(-20);
9970
+ for (const file of transcriptFiles) {
9971
+ try {
9972
+ const content = readFileSync4(join4(transcriptsDir, file), "utf-8");
9973
+ if (content.includes('"tool_name":"supermemory"') || content.includes('"name":"supermemory"') || content.includes("supermemory")) {
9974
+ hasSupermemory = true;
9975
+ if (!detectedMcps.includes("supermemory")) {
9976
+ detectedMcps.push("supermemory");
9977
+ mcpCount++;
9978
+ }
9979
+ break;
9980
+ }
9981
+ } catch {}
9982
+ }
9983
+ } catch {}
9984
+ }
9959
9985
  const claudeSettingsLocal = join4(home, ".claude", "settings.local.json");
9960
9986
  const claudeProjectSettings = join4(projectDir, ".claude", "settings.local.json");
9961
9987
  const mcpConfigPaths = [
@@ -13863,6 +13889,7 @@ function ora(options) {
13863
13889
 
13864
13890
  // src/lib/ui.ts
13865
13891
  var import_picocolors = __toESM(require_picocolors(), 1);
13892
+ import * as readline from "readline";
13866
13893
  var colors2 = {
13867
13894
  primary: import_picocolors.default.cyan,
13868
13895
  secondary: import_picocolors.default.blue,
@@ -13889,23 +13916,6 @@ function createSpinner(text) {
13889
13916
  color: "cyan"
13890
13917
  });
13891
13918
  }
13892
- function progressBar(value, max = 100, width = 20) {
13893
- const percentage = Math.min(100, Math.max(0, value / max * 100));
13894
- const filled = Math.round(percentage / 100 * width);
13895
- const empty = width - filled;
13896
- let barColor = colors2.excellent;
13897
- if (percentage < 40)
13898
- barColor = colors2.poor;
13899
- else if (percentage < 60)
13900
- barColor = colors2.moderate;
13901
- else if (percentage < 75)
13902
- barColor = colors2.good;
13903
- const bar = barColor("█".repeat(filled)) + colors2.dim("░".repeat(empty));
13904
- return bar;
13905
- }
13906
- function scoreBar(score, width = 20) {
13907
- return progressBar(score, 100, width);
13908
- }
13909
13919
  function formatTier(tier) {
13910
13920
  const tierColors = {
13911
13921
  elite: (s2) => import_picocolors.default.bold(import_picocolors.default.magenta(s2)),
@@ -13947,6 +13957,102 @@ var icons = {
13947
13957
  target: "\uD83C\uDFAF"
13948
13958
  };
13949
13959
  var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
13960
+ function clearLine2() {
13961
+ readline.clearLine(process.stdout, 0);
13962
+ readline.cursorTo(process.stdout, 0);
13963
+ }
13964
+ function write(text) {
13965
+ process.stdout.write(text);
13966
+ }
13967
+ async function animateProgressBar(label, score, options = {}) {
13968
+ const { width = 20, charDelay = 40, labelWidth = 20 } = options;
13969
+ const filled = Math.round(score / 100 * width);
13970
+ let barColor = colors2.excellent;
13971
+ if (score < 40)
13972
+ barColor = colors2.poor;
13973
+ else if (score < 60)
13974
+ barColor = colors2.moderate;
13975
+ else if (score < 75)
13976
+ barColor = colors2.good;
13977
+ const paddedLabel = label.padEnd(labelWidth);
13978
+ const scoreStr = `${score}/100`.padStart(7);
13979
+ write(` ${colors2.dim(paddedLabel)} ${colors2.dim(scoreStr)} `);
13980
+ for (let i4 = 0;i4 < width; i4++) {
13981
+ if (i4 < filled) {
13982
+ write(barColor("█"));
13983
+ } else {
13984
+ write(colors2.dim("░"));
13985
+ }
13986
+ await sleep(charDelay);
13987
+ }
13988
+ console.log();
13989
+ }
13990
+ async function thinkingStep(thinkingText, duration = 800, successText) {
13991
+ const spinner = createSpinner(thinkingText);
13992
+ spinner.start();
13993
+ await sleep(duration);
13994
+ spinner.succeed(successText ?? thinkingText);
13995
+ }
13996
+ async function revealDiscovery(icon, text, delay2 = 300) {
13997
+ await sleep(delay2);
13998
+ console.log(` ${icon} ${text}`);
13999
+ }
14000
+ async function showPhaseHeader(phase, total, title, delay2 = 400) {
14001
+ await sleep(delay2);
14002
+ console.log();
14003
+ console.log(` ${colors2.dim(`Phase ${phase}/${total}:`)} ${colors2.bold(colors2.primary(title))}`);
14004
+ console.log(colors2.dim(" " + "─".repeat(40)));
14005
+ }
14006
+ async function animateScoreReveal(score, tier, options = {}) {
14007
+ const { countDuration = 1000, barDelay = 50 } = options;
14008
+ const scoreColor = score >= 80 ? colors2.excellent : score >= 60 ? colors2.good : score >= 40 ? colors2.moderate : colors2.poor;
14009
+ console.log();
14010
+ console.log(colors2.dim(" " + "═".repeat(45)));
14011
+ console.log();
14012
+ const steps = 30;
14013
+ const stepDuration = countDuration / steps;
14014
+ for (let i4 = 1;i4 <= steps; i4++) {
14015
+ const current = Math.round(i4 / steps * score);
14016
+ clearLine2();
14017
+ write(` ${colors2.bold("Your Score:")} ${scoreColor(colors2.bold(current.toString()))}/100`);
14018
+ await sleep(stepDuration);
14019
+ }
14020
+ write(` ${colors2.dim("(")}${formatTier(tier)}${colors2.dim(")")}`);
14021
+ console.log();
14022
+ console.log();
14023
+ const barWidth = 30;
14024
+ const filled = Math.round(score / 100 * barWidth);
14025
+ write(" ");
14026
+ for (let i4 = 0;i4 < barWidth; i4++) {
14027
+ if (i4 < filled) {
14028
+ write(scoreColor("█"));
14029
+ } else {
14030
+ write(colors2.dim("░"));
14031
+ }
14032
+ await sleep(barDelay);
14033
+ }
14034
+ console.log();
14035
+ console.log();
14036
+ console.log(colors2.dim(" " + "═".repeat(45)));
14037
+ }
14038
+ async function showFinding(type, label, value, unit = "", delay2 = 250) {
14039
+ await sleep(delay2);
14040
+ const iconMap = {
14041
+ warning: icons.warning,
14042
+ error: icons.error,
14043
+ info: icons.info,
14044
+ success: icons.success
14045
+ };
14046
+ const colorMap = {
14047
+ warning: colors2.warning,
14048
+ error: colors2.error,
14049
+ info: colors2.info,
14050
+ success: colors2.success
14051
+ };
14052
+ const icon = iconMap[type];
14053
+ const valueColor = colorMap[type];
14054
+ console.log(` ${icon} ${label}: ${valueColor(value.toString())}${unit}`);
14055
+ }
13950
14056
 
13951
14057
  // src/commands/scan.ts
13952
14058
  var scanCommand = defineCommand2({
@@ -13990,99 +14096,100 @@ var scanCommand = defineCommand2({
13990
14096
  const since = parseSince(args.since);
13991
14097
  console.log();
13992
14098
  console.log(colors2.bold(colors2.primary(" NaironAI Workflow Scanner")));
13993
- console.log(colors2.dim(` Analyzing last ${args.since}...
13994
- `));
13995
- const collectSpinner = createSpinner("Collecting data sources...");
13996
- collectSpinner.start();
14099
+ console.log(colors2.dim(" " + "─".repeat(40)));
14100
+ await sleep(300);
14101
+ await showPhaseHeader(1, 3, "Data Collection", 200);
14102
+ await thinkingStep("Connecting to git repository...", 400);
13997
14103
  const git = await collectGit(projectDir, since);
13998
- collectSpinner.text = "Scanning git history...";
13999
- await sleep(150);
14104
+ if (git) {
14105
+ await revealDiscovery(icons.success, `Git: ${colors2.primary(git.commitCount.toString())} commits found`, 200);
14106
+ }
14107
+ await thinkingStep("Scanning AI session logs...", 600);
14000
14108
  const agents = await collectAgentSessions(since);
14001
- collectSpinner.text = "Reading AI session logs...";
14002
- await sleep(150);
14109
+ if (agents) {
14110
+ await revealDiscovery(icons.success, `Sessions: ${colors2.primary(agents.totalSessions.toString())} sessions loaded`, 200);
14111
+ }
14112
+ await thinkingStep("Checking test results...", 400);
14003
14113
  const tests = await collectTestResults(projectDir);
14004
- collectSpinner.text = "Checking test results...";
14005
- await sleep(100);
14006
- collectSpinner.succeed("Data collection complete");
14007
- const summaryParts = [];
14008
- if (git)
14009
- summaryParts.push(`${colors2.primary(git.commitCount.toString())} commits`);
14010
- if (agents)
14011
- summaryParts.push(`${colors2.primary(agents.totalSessions.toString())} sessions`);
14012
- if (tests)
14013
- summaryParts.push(`${colors2.primary(tests.totalTests.toString())} tests`);
14014
- if (summaryParts.length > 0) {
14015
- console.log(colors2.dim(` Found: ${summaryParts.join(", ")}
14016
- `));
14114
+ if (tests) {
14115
+ await revealDiscovery(icons.success, `Tests: ${colors2.primary(tests.totalTests.toString())} tests found`, 200);
14017
14116
  }
14018
- const analyzeSpinner = createSpinner("Analyzing workflow patterns...");
14019
- analyzeSpinner.start();
14020
- await sleep(200);
14117
+ await showPhaseHeader(2, 3, "Pattern Analysis", 400);
14118
+ await thinkingStep("Analyzing commit patterns...", 500);
14119
+ await thinkingStep("Detecting workflow inefficiencies...", 600);
14021
14120
  const analysis = analyzeWorkflow(agents, projectDir);
14022
- analyzeSpinner.text = "Detecting inefficiencies...";
14023
- await sleep(150);
14024
14121
  const sdlcAnalysis = analyzeSDLCPhases(agents, git, tests, projectDir);
14025
- analyzeSpinner.text = "Evaluating SDLC phases...";
14026
- await sleep(150);
14027
- analyzeSpinner.succeed("Analysis complete");
14028
- const issues = [];
14029
14122
  if (analysis.sessionPatterns.memoryLossCount > 0) {
14030
- issues.push(`${icons.warning} Memory loss: ${colors2.warning(analysis.sessionPatterns.memoryLossCount.toString())} times/week`);
14123
+ await showFinding("warning", "Memory loss events", analysis.sessionPatterns.memoryLossCount, " times/week", 300);
14031
14124
  }
14032
14125
  if (analysis.sessionPatterns.undoLoops > 0) {
14033
- issues.push(`${icons.warning} Undo loops: ${colors2.warning(analysis.sessionPatterns.undoLoops.toString())} occurrences`);
14126
+ await showFinding("warning", "Undo loop occurrences", analysis.sessionPatterns.undoLoops, "", 300);
14034
14127
  }
14035
14128
  if (analysis.sessionPatterns.frustrationCount > 0) {
14036
- issues.push(`${icons.error} High frustration: ${colors2.error(analysis.sessionPatterns.frustrationCount.toString())} sessions`);
14129
+ await showFinding("error", "High frustration sessions", analysis.sessionPatterns.frustrationCount, "", 300);
14037
14130
  }
14038
- if (issues.length > 0) {
14039
- console.log();
14040
- for (const issue of issues) {
14041
- console.log(` ${issue}`);
14042
- }
14131
+ if (analysis.sessionPatterns.memoryLossCount === 0 && analysis.sessionPatterns.undoLoops === 0 && analysis.sessionPatterns.frustrationCount === 0) {
14132
+ await revealDiscovery(icons.success, colors2.success("No significant issues detected"), 300);
14043
14133
  }
14044
- console.log();
14134
+ await showPhaseHeader(3, 3, "Computing Score", 400);
14135
+ await thinkingStep("Evaluating SDLC phases...", 500);
14136
+ await thinkingStep("Calculating token efficiency...", 400);
14137
+ await thinkingStep("Computing final score...", 600);
14045
14138
  const score = computeNaironScore(git ?? undefined, agents ?? undefined, tests ?? undefined);
14046
14139
  const scanCost = calculateScanCost(agents, git);
14047
- const scoreColor = score.overall >= 80 ? colors2.success : score.overall >= 60 ? colors2.primary : score.overall >= 40 ? colors2.warning : colors2.error;
14048
- console.log(colors2.dim(" ─".repeat(22)));
14049
- console.log();
14050
- console.log(` ${colors2.bold("Your Score:")} ${scoreColor(colors2.bold(score.overall.toString()))}/100 ${colors2.dim("(")}${formatTier(score.tier)}${colors2.dim(")")}`);
14140
+ await animateScoreReveal(score.overall, score.tier, {
14141
+ countDuration: 1200,
14142
+ barDelay: 35
14143
+ });
14051
14144
  console.log();
14052
- console.log(colors2.dim("".repeat(22)));
14145
+ console.log(` ${colors2.bold("Phase Breakdown")}`);
14053
14146
  console.log();
14054
14147
  for (const phase of score.phases) {
14055
- const bar = scoreBar(phase.score, 20);
14056
- const phaseScore = phase.score >= 70 ? colors2.success(phase.score.toString()) : phase.score >= 50 ? colors2.warning(phase.score.toString()) : colors2.error(phase.score.toString());
14057
- console.log(` ${colors2.dim(phase.phase.padEnd(16))} ${phaseScore.padStart(10)}/100 ${bar}`);
14148
+ await animateProgressBar(phase.phase, phase.score, {
14149
+ width: 20,
14150
+ charDelay: 25,
14151
+ labelWidth: 18
14152
+ });
14153
+ await sleep(150);
14058
14154
  }
14059
14155
  console.log();
14060
14156
  const wasteColor = score.tokenEfficiency.wastePercentage <= 5 ? colors2.success : score.tokenEfficiency.wastePercentage <= 15 ? colors2.warning : colors2.error;
14061
14157
  console.log(` ${colors2.dim("Token Efficiency:")} ${colors2.primary(score.tokenEfficiency.modifier.toString())}x ${colors2.dim("(")}${wasteColor(score.tokenEfficiency.wastePercentage.toString())}% waste${colors2.dim(")")}`);
14062
- console.log();
14063
14158
  if (!args.brief && analysis.recommendations.length > 0) {
14064
- console.log(` ${colors2.bold("Recommendations")}`);
14065
14159
  console.log();
14160
+ console.log(` ${colors2.bold("Recommendations")}`);
14161
+ console.log(colors2.dim(" " + "─".repeat(40)));
14066
14162
  const topRecs = analysis.recommendations.slice(0, 3);
14067
14163
  for (let i4 = 0;i4 < topRecs.length; i4++) {
14068
14164
  const rec = topRecs[i4];
14165
+ await sleep(400);
14166
+ console.log();
14069
14167
  console.log(` ${colors2.success(`${i4 + 1}.`)} ${colors2.bold(rec.title)}`);
14168
+ await sleep(150);
14070
14169
  console.log(` ${colors2.dim(rec.description)}`);
14071
- console.log();
14072
14170
  }
14171
+ console.log();
14172
+ await sleep(300);
14073
14173
  console.log(` ${colors2.dim("Estimated impact:")}`);
14174
+ await sleep(200);
14074
14175
  console.log(` ${icons.arrow} Score: ${colors2.success(`+${analysis.estimatedImpact.scoreImprovement}`)} points`);
14176
+ await sleep(150);
14075
14177
  console.log(` ${icons.arrow} Tokens: ${colors2.success(`-${formatTokens2(analysis.estimatedImpact.tokenssSavedWeekly)}`)}/week`);
14076
- console.log();
14077
14178
  }
14078
- console.log(colors2.dim(" ─".repeat(22)));
14179
+ console.log();
14180
+ console.log(colors2.dim(" " + "═".repeat(45)));
14181
+ await sleep(300);
14079
14182
  const wastedPct = scanCost.sessionsCostUsd > 0 ? Math.round(scanCost.wastedCostUsd / scanCost.sessionsCostUsd * 100) : 0;
14080
- console.log(` ${icons.money} Period cost: ${colors2.bold(colors2.success(`$${scanCost.sessionsCostUsd.toFixed(2)}`))}`);
14183
+ console.log(` ${icons.money} ${colors2.bold("Cost Summary")}`);
14184
+ await sleep(200);
14185
+ console.log(` Period cost: ${colors2.bold(colors2.success(`$${scanCost.sessionsCostUsd.toFixed(2)}`))}`);
14081
14186
  if (scanCost.wastedCostUsd > 0) {
14187
+ await sleep(150);
14082
14188
  console.log(` Wasted: ${colors2.error(`$${scanCost.wastedCostUsd.toFixed(2)}`)} ${colors2.dim(`(${wastedPct}%)`)}`);
14083
14189
  }
14190
+ await sleep(150);
14084
14191
  console.log(` Projected monthly: ${colors2.primary(`$${scanCost.projectedMonthlyCostUsd.toFixed(2)}`)}`);
14085
- console.log(colors2.dim(" ".repeat(22)));
14192
+ console.log(colors2.dim(" " + "═".repeat(45)));
14086
14193
  console.log();
14087
14194
  if (!args["no-report"]) {
14088
14195
  const reportDir = join5(projectDir, args["report-dir"]);
@@ -15186,7 +15293,8 @@ var toolsCommand = defineCommand2({
15186
15293
  discover: discoverCommand(),
15187
15294
  search: searchCommand(),
15188
15295
  info: infoCommand(),
15189
- compare: compareCommand()
15296
+ compare: compareCommand(),
15297
+ admin: adminCommand()
15190
15298
  }
15191
15299
  });
15192
15300
  function discoverCommand() {
@@ -15419,6 +15527,168 @@ function renderToolList(tools) {
15419
15527
  }
15420
15528
  consola.info(`Use \`nb tools info <slug>\` for setup instructions.`);
15421
15529
  }
15530
+ function adminCommand() {
15531
+ return defineCommand2({
15532
+ meta: {
15533
+ name: "admin",
15534
+ description: "Admin tools for reviewing discovered tools"
15535
+ },
15536
+ subCommands: {
15537
+ pending: pendingCommand(),
15538
+ approve: approveCommand(),
15539
+ reject: rejectCommand(),
15540
+ stats: statsCommand()
15541
+ }
15542
+ });
15543
+ }
15544
+ function pendingCommand() {
15545
+ return defineCommand2({
15546
+ meta: {
15547
+ name: "pending",
15548
+ description: "List tools pending review"
15549
+ },
15550
+ args: {
15551
+ limit: {
15552
+ type: "string",
15553
+ description: "Max results",
15554
+ default: "20"
15555
+ }
15556
+ },
15557
+ async run({ args }) {
15558
+ const client = getClient();
15559
+ if (!client) {
15560
+ console.log(` ${icons.error} Not connected. Run ${colors2.primary("nb init")} first.`);
15561
+ return;
15562
+ }
15563
+ const spinner = createSpinner("Fetching pending tools...");
15564
+ spinner.start();
15565
+ const tools = await client.query(api.tools.listPending, {
15566
+ limit: parseInt(args.limit, 10)
15567
+ });
15568
+ spinner.succeed(`Found ${tools.length} pending tools`);
15569
+ console.log();
15570
+ if (tools.length === 0) {
15571
+ console.log(` ${icons.success} No tools pending review!`);
15572
+ return;
15573
+ }
15574
+ for (const tool of tools) {
15575
+ const phases = tool.sdlcPhases.join(", ");
15576
+ const source = tool.mentions?.[0]?.source ?? "unknown";
15577
+ console.log(` ${colors2.bold(tool.name)}`);
15578
+ console.log(` ${colors2.dim("Slug:")} ${colors2.primary(tool.slug)}`);
15579
+ console.log(` ${colors2.dim("URL:")} ${tool.url}`);
15580
+ console.log(` ${colors2.dim("Source:")} ${source}`);
15581
+ console.log(` ${colors2.dim("Phases:")} ${phases}`);
15582
+ console.log(` ${colors2.dim(tool.description.slice(0, 100))}${tool.description.length > 100 ? "..." : ""}`);
15583
+ console.log();
15584
+ }
15585
+ console.log(colors2.dim(" Commands:"));
15586
+ console.log(` ${colors2.primary("nb tools admin approve <slug>")} - Approve a tool`);
15587
+ console.log(` ${colors2.primary("nb tools admin reject <slug>")} - Reject a tool`);
15588
+ }
15589
+ });
15590
+ }
15591
+ function approveCommand() {
15592
+ return defineCommand2({
15593
+ meta: {
15594
+ name: "approve",
15595
+ description: "Approve a pending tool"
15596
+ },
15597
+ args: {
15598
+ slug: {
15599
+ type: "positional",
15600
+ description: "Tool slug to approve",
15601
+ required: true
15602
+ },
15603
+ phases: {
15604
+ type: "string",
15605
+ description: "SDLC phases (comma-separated: requirements,planning,implementation,testing,review)"
15606
+ }
15607
+ },
15608
+ async run({ args }) {
15609
+ const client = getClient();
15610
+ if (!client) {
15611
+ console.log(` ${icons.error} Not connected. Run ${colors2.primary("nb init")} first.`);
15612
+ return;
15613
+ }
15614
+ const spinner = createSpinner(`Approving ${args.slug}...`);
15615
+ spinner.start();
15616
+ try {
15617
+ const result = args.phases ? await client.mutation(api.tools.approveTool, {
15618
+ slug: args.slug,
15619
+ sdlcPhases: args.phases.split(",").map((p) => p.trim())
15620
+ }) : await client.mutation(api.tools.approveTool, {
15621
+ slug: args.slug
15622
+ });
15623
+ spinner.succeed(`Approved: ${colors2.success(result.name)}`);
15624
+ } catch (error2) {
15625
+ spinner.fail(`Failed to approve: ${error2 instanceof Error ? error2.message : String(error2)}`);
15626
+ }
15627
+ }
15628
+ });
15629
+ }
15630
+ function rejectCommand() {
15631
+ return defineCommand2({
15632
+ meta: {
15633
+ name: "reject",
15634
+ description: "Reject a pending tool"
15635
+ },
15636
+ args: {
15637
+ slug: {
15638
+ type: "positional",
15639
+ description: "Tool slug to reject",
15640
+ required: true
15641
+ },
15642
+ reason: {
15643
+ type: "string",
15644
+ description: "Reason for rejection"
15645
+ }
15646
+ },
15647
+ async run({ args }) {
15648
+ const client = getClient();
15649
+ if (!client) {
15650
+ console.log(` ${icons.error} Not connected. Run ${colors2.primary("nb init")} first.`);
15651
+ return;
15652
+ }
15653
+ const spinner = createSpinner(`Rejecting ${args.slug}...`);
15654
+ spinner.start();
15655
+ try {
15656
+ const result = await client.mutation(api.tools.rejectTool, {
15657
+ slug: args.slug,
15658
+ reason: args.reason
15659
+ });
15660
+ spinner.succeed(`Rejected: ${colors2.warning(result.name)}`);
15661
+ } catch (error2) {
15662
+ spinner.fail(`Failed to reject: ${error2 instanceof Error ? error2.message : String(error2)}`);
15663
+ }
15664
+ }
15665
+ });
15666
+ }
15667
+ function statsCommand() {
15668
+ return defineCommand2({
15669
+ meta: {
15670
+ name: "stats",
15671
+ description: "Show tool database statistics"
15672
+ },
15673
+ async run() {
15674
+ const client = getClient();
15675
+ if (!client) {
15676
+ console.log(` ${icons.error} Not connected. Run ${colors2.primary("nb init")} first.`);
15677
+ return;
15678
+ }
15679
+ const spinner = createSpinner("Fetching stats...");
15680
+ spinner.start();
15681
+ const stats = await client.query(api.tools.getStats, {});
15682
+ spinner.succeed("Tool Database Stats");
15683
+ console.log();
15684
+ console.log(` ${icons.pending} Pending: ${colors2.warning(stats.pending.toString())}`);
15685
+ console.log(` ${icons.success} Approved: ${colors2.success(stats.approved.toString())}`);
15686
+ console.log(` ${icons.error} Rejected: ${colors2.error(stats.rejected.toString())}`);
15687
+ console.log(` ${colors2.dim("─".repeat(25))}`);
15688
+ console.log(` ${icons.info} Total: ${colors2.primary(stats.total.toString())}`);
15689
+ }
15690
+ });
15691
+ }
15422
15692
 
15423
15693
  // src/commands/dashboard.ts
15424
15694
  init_dist();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nairon-bench",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "description": "AI workflow benchmarking CLI",
5
5
  "type": "module",
6
6
  "bin": {