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.
- package/dist/index.js +345 -75
- 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(/^
|
|
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(
|
|
13994
|
-
|
|
13995
|
-
|
|
13996
|
-
|
|
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
|
-
|
|
13999
|
-
|
|
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
|
-
|
|
14002
|
-
|
|
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
|
-
|
|
14005
|
-
|
|
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
|
-
|
|
14019
|
-
|
|
14020
|
-
await
|
|
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
|
-
|
|
14123
|
+
await showFinding("warning", "Memory loss events", analysis.sessionPatterns.memoryLossCount, " times/week", 300);
|
|
14031
14124
|
}
|
|
14032
14125
|
if (analysis.sessionPatterns.undoLoops > 0) {
|
|
14033
|
-
|
|
14126
|
+
await showFinding("warning", "Undo loop occurrences", analysis.sessionPatterns.undoLoops, "", 300);
|
|
14034
14127
|
}
|
|
14035
14128
|
if (analysis.sessionPatterns.frustrationCount > 0) {
|
|
14036
|
-
|
|
14129
|
+
await showFinding("error", "High frustration sessions", analysis.sessionPatterns.frustrationCount, "", 300);
|
|
14037
14130
|
}
|
|
14038
|
-
if (
|
|
14039
|
-
|
|
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
|
-
|
|
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
|
-
|
|
14048
|
-
|
|
14049
|
-
|
|
14050
|
-
|
|
14140
|
+
await animateScoreReveal(score.overall, score.tier, {
|
|
14141
|
+
countDuration: 1200,
|
|
14142
|
+
barDelay: 35
|
|
14143
|
+
});
|
|
14051
14144
|
console.log();
|
|
14052
|
-
console.log(colors2.
|
|
14145
|
+
console.log(` ${colors2.bold("Phase Breakdown")}`);
|
|
14053
14146
|
console.log();
|
|
14054
14147
|
for (const phase of score.phases) {
|
|
14055
|
-
|
|
14056
|
-
|
|
14057
|
-
|
|
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(
|
|
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}
|
|
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("
|
|
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();
|