@triedotdev/mcp 1.0.55 → 1.0.57
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.
|
@@ -2786,6 +2786,18 @@ var StreamingManager = class {
|
|
|
2786
2786
|
issuesBySeverity: { critical: 0, serious: 0, moderate: 0, low: 0 }
|
|
2787
2787
|
};
|
|
2788
2788
|
}
|
|
2789
|
+
/**
|
|
2790
|
+
* Report watch status (directories, debounce, last change)
|
|
2791
|
+
*/
|
|
2792
|
+
reportWatchStatus(status) {
|
|
2793
|
+
this.emit("watch_status", status);
|
|
2794
|
+
}
|
|
2795
|
+
/**
|
|
2796
|
+
* Report a specific file change when watching
|
|
2797
|
+
*/
|
|
2798
|
+
reportWatchChange(file) {
|
|
2799
|
+
this.emit("watch_change", { file });
|
|
2800
|
+
}
|
|
2789
2801
|
};
|
|
2790
2802
|
function formatConsoleUpdate(update) {
|
|
2791
2803
|
if (isInteractiveMode()) {
|
|
@@ -3146,6 +3158,40 @@ var IssueAnalyzer = class {
|
|
|
3146
3158
|
// src/cli/interactive-dashboard.ts
|
|
3147
3159
|
import { stdin as input, stdout as output } from "process";
|
|
3148
3160
|
import * as readline from "readline";
|
|
3161
|
+
import pc from "picocolors";
|
|
3162
|
+
var colors = {
|
|
3163
|
+
// UI elements
|
|
3164
|
+
border: (s) => pc.cyan(s),
|
|
3165
|
+
header: (s) => pc.bold(pc.cyan(s)),
|
|
3166
|
+
brand: (s) => pc.bold(pc.cyan(s)),
|
|
3167
|
+
dim: (s) => pc.dim(s),
|
|
3168
|
+
// Severity levels
|
|
3169
|
+
critical: (s) => pc.bold(pc.red(s)),
|
|
3170
|
+
serious: (s) => pc.yellow(s),
|
|
3171
|
+
moderate: (s) => pc.blue(s),
|
|
3172
|
+
low: (s) => pc.dim(s),
|
|
3173
|
+
// Status
|
|
3174
|
+
success: (s) => pc.green(s),
|
|
3175
|
+
running: (s) => pc.yellow(s),
|
|
3176
|
+
waiting: (s) => pc.dim(s),
|
|
3177
|
+
alert: (s) => pc.bold(pc.red(s)),
|
|
3178
|
+
// Interactive
|
|
3179
|
+
selected: (s) => pc.bold(pc.magenta(s)),
|
|
3180
|
+
highlight: (s) => pc.bold(pc.white(s))
|
|
3181
|
+
};
|
|
3182
|
+
var box = {
|
|
3183
|
+
topLeft: "\u250C",
|
|
3184
|
+
topRight: "\u2510",
|
|
3185
|
+
bottomLeft: "\u2514",
|
|
3186
|
+
bottomRight: "\u2518",
|
|
3187
|
+
horizontal: "\u2500",
|
|
3188
|
+
vertical: "\u2502",
|
|
3189
|
+
leftT: "\u251C",
|
|
3190
|
+
rightT: "\u2524",
|
|
3191
|
+
topT: "\u252C",
|
|
3192
|
+
bottomT: "\u2534",
|
|
3193
|
+
cross: "\u253C"
|
|
3194
|
+
};
|
|
3149
3195
|
var InteractiveDashboard = class {
|
|
3150
3196
|
rl;
|
|
3151
3197
|
state;
|
|
@@ -3169,11 +3215,23 @@ var InteractiveDashboard = class {
|
|
|
3169
3215
|
search: ""
|
|
3170
3216
|
},
|
|
3171
3217
|
view: "overview",
|
|
3218
|
+
previousView: null,
|
|
3172
3219
|
selectedIssue: 0,
|
|
3220
|
+
selectedAgent: 0,
|
|
3173
3221
|
lastUpdate: Date.now(),
|
|
3174
3222
|
scanComplete: false,
|
|
3175
3223
|
startTime: Date.now(),
|
|
3176
|
-
activityLog: []
|
|
3224
|
+
activityLog: [],
|
|
3225
|
+
activityPage: 0,
|
|
3226
|
+
agentPage: 0,
|
|
3227
|
+
quietMode: false,
|
|
3228
|
+
alerts: { hasCritical: false },
|
|
3229
|
+
watch: {
|
|
3230
|
+
watching: false,
|
|
3231
|
+
directories: 0,
|
|
3232
|
+
recentChanges: []
|
|
3233
|
+
},
|
|
3234
|
+
agents: {}
|
|
3177
3235
|
};
|
|
3178
3236
|
}
|
|
3179
3237
|
/**
|
|
@@ -3217,15 +3275,37 @@ var InteractiveDashboard = class {
|
|
|
3217
3275
|
case "progress":
|
|
3218
3276
|
const oldProgress = this.state.progress;
|
|
3219
3277
|
this.state.progress = update.data;
|
|
3278
|
+
if (update.data.issuesBySeverity?.critical > 0) {
|
|
3279
|
+
this.state.alerts = { hasCritical: true, lastCriticalAt: update.timestamp };
|
|
3280
|
+
}
|
|
3220
3281
|
if (update.data.currentFile && update.data.processedFiles % 10 === 0 && update.data.processedFiles !== oldProgress.processedFiles) {
|
|
3221
3282
|
this.addActivity(`Scanned ${update.data.processedFiles}/${update.data.totalFiles} files`);
|
|
3222
3283
|
}
|
|
3223
3284
|
break;
|
|
3224
3285
|
case "agent_start":
|
|
3225
|
-
this.addActivity(`[*]
|
|
3286
|
+
this.addActivity(`[*] Scout started: ${update.data.agent}`);
|
|
3287
|
+
this.state.agents[update.data.agent] = {
|
|
3288
|
+
...this.state.agents[update.data.agent] || { issues: 0, status: "queued" },
|
|
3289
|
+
status: "running",
|
|
3290
|
+
start: update.timestamp
|
|
3291
|
+
};
|
|
3226
3292
|
break;
|
|
3227
3293
|
case "agent_complete":
|
|
3228
|
-
this.addActivity(`[+]
|
|
3294
|
+
this.addActivity(`[+] Scout complete: ${update.data.agent} (${update.data.issueCount} issues)`);
|
|
3295
|
+
{
|
|
3296
|
+
const prev = this.state.agents[update.data.agent];
|
|
3297
|
+
const start = prev?.start;
|
|
3298
|
+
const issues = update.data.issueCount ?? prev?.issues ?? 0;
|
|
3299
|
+
const durationMs = start !== void 0 ? update.timestamp - start : void 0;
|
|
3300
|
+
this.state.agents[update.data.agent] = {
|
|
3301
|
+
...prev ?? { issues: 0, status: "queued" },
|
|
3302
|
+
status: "done",
|
|
3303
|
+
end: update.timestamp,
|
|
3304
|
+
...start !== void 0 ? { start } : {},
|
|
3305
|
+
...durationMs !== void 0 ? { durationMs } : {},
|
|
3306
|
+
issues
|
|
3307
|
+
};
|
|
3308
|
+
}
|
|
3229
3309
|
break;
|
|
3230
3310
|
case "issue_found":
|
|
3231
3311
|
this.state.issues.push(update.data);
|
|
@@ -3233,6 +3313,15 @@ var InteractiveDashboard = class {
|
|
|
3233
3313
|
const icon = update.data.severity === "critical" ? "[!]" : "[x]";
|
|
3234
3314
|
const fileName = update.data.file?.split("/").pop() || "unknown";
|
|
3235
3315
|
this.addActivity(`${icon} ${update.data.severity.toUpperCase()}: ${update.data.message?.slice(0, 40) || fileName}`);
|
|
3316
|
+
if (update.data.severity === "critical") {
|
|
3317
|
+
this.state.alerts = { hasCritical: true, lastCriticalAt: update.timestamp };
|
|
3318
|
+
}
|
|
3319
|
+
}
|
|
3320
|
+
if (update.data.agent) {
|
|
3321
|
+
const agentMeta = this.state.agents[update.data.agent];
|
|
3322
|
+
if (agentMeta) {
|
|
3323
|
+
agentMeta.issues += 1;
|
|
3324
|
+
}
|
|
3236
3325
|
}
|
|
3237
3326
|
break;
|
|
3238
3327
|
case "scan_complete":
|
|
@@ -3244,6 +3333,22 @@ var InteractiveDashboard = class {
|
|
|
3244
3333
|
const elapsed = ((Date.now() - this.state.startTime) / 1e3).toFixed(1);
|
|
3245
3334
|
this.addActivity(`=== Scan complete - ${this.state.progress.totalIssues} issues in ${elapsed}s ===`);
|
|
3246
3335
|
break;
|
|
3336
|
+
case "watch_status":
|
|
3337
|
+
this.state.watch = {
|
|
3338
|
+
watching: update.data.watching ?? this.state.watch.watching,
|
|
3339
|
+
directories: update.data.directories ?? this.state.watch.directories,
|
|
3340
|
+
debounceMs: update.data.debounceMs ?? this.state.watch.debounceMs,
|
|
3341
|
+
lastChange: update.data.lastChange ?? this.state.watch.lastChange,
|
|
3342
|
+
recentChanges: update.data.recentChanges ?? this.state.watch.recentChanges
|
|
3343
|
+
};
|
|
3344
|
+
break;
|
|
3345
|
+
case "watch_change":
|
|
3346
|
+
const entry = { file: update.data.file, time: new Date(update.timestamp).toLocaleTimeString("en-US", { hour12: false }) };
|
|
3347
|
+
this.state.watch.recentChanges.unshift(entry);
|
|
3348
|
+
this.state.watch.recentChanges = this.state.watch.recentChanges.slice(0, 5);
|
|
3349
|
+
this.state.watch.lastChange = entry.time;
|
|
3350
|
+
this.addActivity(`Change detected: ${update.data.file}`);
|
|
3351
|
+
break;
|
|
3247
3352
|
}
|
|
3248
3353
|
if (this.isActive) {
|
|
3249
3354
|
this.render();
|
|
@@ -3269,9 +3374,11 @@ var InteractiveDashboard = class {
|
|
|
3269
3374
|
this.switchView();
|
|
3270
3375
|
break;
|
|
3271
3376
|
case "up":
|
|
3377
|
+
case "k":
|
|
3272
3378
|
this.navigateUp();
|
|
3273
3379
|
break;
|
|
3274
3380
|
case "down":
|
|
3381
|
+
case "j":
|
|
3275
3382
|
this.navigateDown();
|
|
3276
3383
|
break;
|
|
3277
3384
|
case "enter":
|
|
@@ -3299,6 +3406,18 @@ var InteractiveDashboard = class {
|
|
|
3299
3406
|
case "f":
|
|
3300
3407
|
this.promptFilter();
|
|
3301
3408
|
break;
|
|
3409
|
+
case "n":
|
|
3410
|
+
this.nextPage();
|
|
3411
|
+
break;
|
|
3412
|
+
case "p":
|
|
3413
|
+
this.prevPage();
|
|
3414
|
+
break;
|
|
3415
|
+
case "s":
|
|
3416
|
+
this.promptAgentFilter();
|
|
3417
|
+
break;
|
|
3418
|
+
case "b":
|
|
3419
|
+
this.goBack();
|
|
3420
|
+
break;
|
|
3302
3421
|
case "h":
|
|
3303
3422
|
case "?":
|
|
3304
3423
|
this.showHelp();
|
|
@@ -3318,57 +3437,69 @@ var InteractiveDashboard = class {
|
|
|
3318
3437
|
}, 100);
|
|
3319
3438
|
}
|
|
3320
3439
|
/**
|
|
3321
|
-
* Create a horizontal line
|
|
3440
|
+
* Create a horizontal line (Unicode box-drawing)
|
|
3322
3441
|
*/
|
|
3323
3442
|
line(width = 78) {
|
|
3324
|
-
return
|
|
3443
|
+
return box.horizontal.repeat(width);
|
|
3325
3444
|
}
|
|
3326
3445
|
/**
|
|
3327
|
-
* Create progress bar
|
|
3446
|
+
* Create progress bar with color
|
|
3328
3447
|
*/
|
|
3329
3448
|
progressBar(current, total, width = 50) {
|
|
3330
|
-
if (total === 0) return "[" + "
|
|
3449
|
+
if (total === 0) return colors.dim("[" + "\u2588".repeat(width) + "]");
|
|
3331
3450
|
const progress = Math.min(1, current / total);
|
|
3332
3451
|
const filled = Math.round(width * progress);
|
|
3333
3452
|
const empty = width - filled;
|
|
3334
|
-
|
|
3453
|
+
const filledBar = colors.border("\u2588".repeat(filled));
|
|
3454
|
+
const emptyBar = colors.dim("\u2591".repeat(empty));
|
|
3455
|
+
return "[" + filledBar + emptyBar + "]";
|
|
3335
3456
|
}
|
|
3336
3457
|
/**
|
|
3337
|
-
* Get severity icon
|
|
3458
|
+
* Get severity icon with color
|
|
3338
3459
|
*/
|
|
3339
3460
|
severityIcon(severity) {
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3461
|
+
switch (severity) {
|
|
3462
|
+
case "critical":
|
|
3463
|
+
return colors.critical("[!]");
|
|
3464
|
+
case "serious":
|
|
3465
|
+
return colors.serious("[x]");
|
|
3466
|
+
case "moderate":
|
|
3467
|
+
return colors.moderate("[~]");
|
|
3468
|
+
case "low":
|
|
3469
|
+
return colors.low("[-]");
|
|
3470
|
+
default:
|
|
3471
|
+
return colors.dim("[-]");
|
|
3472
|
+
}
|
|
3347
3473
|
}
|
|
3348
3474
|
/**
|
|
3349
|
-
* Get agent status icon
|
|
3475
|
+
* Get agent status icon with color
|
|
3350
3476
|
*/
|
|
3351
3477
|
agentIcon(status) {
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3478
|
+
switch (status) {
|
|
3479
|
+
case "running":
|
|
3480
|
+
return colors.running("\u25CF");
|
|
3481
|
+
case "done":
|
|
3482
|
+
return colors.success("\u2713");
|
|
3483
|
+
case "waiting":
|
|
3484
|
+
return colors.waiting("\u25CB");
|
|
3485
|
+
default:
|
|
3486
|
+
return colors.dim("\u25CB");
|
|
3487
|
+
}
|
|
3358
3488
|
}
|
|
3359
3489
|
/**
|
|
3360
3490
|
* Main render function
|
|
3361
3491
|
*/
|
|
3362
3492
|
render() {
|
|
3363
|
-
process.stdout.write("\x1B[2J\x1B[H\x1B[?25l");
|
|
3493
|
+
process.stdout.write("\x1B[2J\x1B[3J\x1B[H\x1B[?25l");
|
|
3364
3494
|
const width = Math.min(80, process.stdout.columns || 80);
|
|
3495
|
+
const height = Math.max(24, process.stdout.rows || 40);
|
|
3365
3496
|
this.renderHeader(width);
|
|
3366
3497
|
if (!this.state.scanComplete) {
|
|
3367
|
-
this.renderScanningView(width);
|
|
3498
|
+
this.renderScanningView(width, height);
|
|
3368
3499
|
} else {
|
|
3369
3500
|
switch (this.state.view) {
|
|
3370
3501
|
case "overview":
|
|
3371
|
-
this.renderOverview(width);
|
|
3502
|
+
this.renderOverview(width, height);
|
|
3372
3503
|
break;
|
|
3373
3504
|
case "issues":
|
|
3374
3505
|
this.renderIssuesList(width);
|
|
@@ -3387,31 +3518,51 @@ var InteractiveDashboard = class {
|
|
|
3387
3518
|
* Render header with title and status
|
|
3388
3519
|
*/
|
|
3389
3520
|
renderHeader(width) {
|
|
3390
|
-
const time = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit" });
|
|
3391
|
-
|
|
3521
|
+
const time = colors.dim((/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit" }));
|
|
3522
|
+
const watchLabel = this.state.watch.watching ? colors.success("[WATCH ON]") : colors.dim("[WATCH OFF]");
|
|
3523
|
+
let statusText = "";
|
|
3392
3524
|
if (this.state.scanComplete) {
|
|
3393
|
-
|
|
3394
|
-
}
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3525
|
+
statusText = colors.success("COMPLETE") + " " + colors.success("[OK]");
|
|
3526
|
+
} else {
|
|
3527
|
+
statusText = colors.running("SCANNING") + " " + colors.dim("(...)");
|
|
3528
|
+
}
|
|
3529
|
+
let alertText = "";
|
|
3530
|
+
if (this.state.alerts.hasCritical) {
|
|
3531
|
+
alertText = " " + colors.alert("\u2502 ALERT: CRITICAL");
|
|
3532
|
+
}
|
|
3533
|
+
const borderColor = colors.border;
|
|
3534
|
+
const topBorder = borderColor(box.topLeft + this.line(width - 2) + box.topRight);
|
|
3535
|
+
const midBorder = borderColor(box.leftT + this.line(width - 2) + box.rightT);
|
|
3536
|
+
const brandRaw = "TRIE GUARDIAN";
|
|
3537
|
+
const brand = colors.brand("TRIE GUARDIAN");
|
|
3538
|
+
const contentPadding = width - 4 - brandRaw.length;
|
|
3539
|
+
console.log(topBorder);
|
|
3540
|
+
console.log(borderColor(box.vertical) + " " + brand + " ".repeat(Math.max(1, contentPadding - 30)) + statusText + " " + watchLabel + alertText + " " + time + " " + borderColor(box.vertical));
|
|
3541
|
+
console.log(midBorder);
|
|
3398
3542
|
}
|
|
3399
3543
|
/**
|
|
3400
3544
|
* Render scanning in progress view
|
|
3401
3545
|
*/
|
|
3402
|
-
renderScanningView(width) {
|
|
3546
|
+
renderScanningView(width, height) {
|
|
3403
3547
|
const { processedFiles, totalFiles, currentFile, activeAgents, completedAgents } = this.state.progress;
|
|
3404
3548
|
const { issuesBySeverity } = this.state.progress;
|
|
3549
|
+
const v = colors.border(box.vertical);
|
|
3550
|
+
const sectionBorder = colors.border(box.leftT + this.line(width - 2) + box.rightT);
|
|
3551
|
+
const baseTotal = 21;
|
|
3552
|
+
const variableBudget = Math.max(0, height - baseTotal);
|
|
3553
|
+
const agentRows = Math.max(1, Math.min(4, Math.floor(variableBudget / 2)));
|
|
3554
|
+
const remaining = Math.max(0, variableBudget - agentRows);
|
|
3555
|
+
const activityRows = Math.max(1, Math.min(10, remaining || 1));
|
|
3405
3556
|
const percent = totalFiles > 0 ? Math.round(processedFiles / totalFiles * 100) : 0;
|
|
3406
3557
|
const current = currentFile ? currentFile.split("/").pop() || "" : "";
|
|
3407
3558
|
const progressBar = this.progressBar(processedFiles, totalFiles, 50);
|
|
3408
|
-
console.log(
|
|
3409
|
-
console.log(
|
|
3410
|
-
console.log(
|
|
3411
|
-
console.log(
|
|
3412
|
-
console.log(
|
|
3413
|
-
console.log("
|
|
3414
|
-
console.log("
|
|
3559
|
+
console.log(v + " ".repeat(width - 2) + v);
|
|
3560
|
+
console.log(v + " " + colors.dim("Scanning:") + " " + colors.highlight(current.slice(0, 40).padEnd(40)) + " ".repeat(Math.max(0, width - 56)) + v);
|
|
3561
|
+
console.log(v + " " + progressBar + " " + colors.highlight(`${percent}%`) + " " + colors.dim(`(${processedFiles}/${totalFiles} files)`) + " ".repeat(Math.max(0, width - 75)) + v);
|
|
3562
|
+
console.log(v + " ".repeat(width - 2) + v);
|
|
3563
|
+
console.log(sectionBorder);
|
|
3564
|
+
console.log(v + " " + colors.header("SCOUTS") + " ".repeat(width - 11) + v);
|
|
3565
|
+
console.log(v + " " + colors.dim(this.line(width - 6)) + " " + v);
|
|
3415
3566
|
const allAgents = [.../* @__PURE__ */ new Set([...activeAgents, ...completedAgents])];
|
|
3416
3567
|
const waitingAgents = ["security", "privacy", "typecheck", "accessibility", "legal", "test", "moneybags", "production-ready"].filter((a) => !activeAgents.includes(a) && !completedAgents.includes(a));
|
|
3417
3568
|
const leftAgents = [];
|
|
@@ -3420,8 +3571,8 @@ var InteractiveDashboard = class {
|
|
|
3420
3571
|
const isActive = activeAgents.includes(agent);
|
|
3421
3572
|
const isDone = completedAgents.includes(agent);
|
|
3422
3573
|
const icon = isActive ? this.agentIcon("running") : isDone ? this.agentIcon("done") : this.agentIcon("waiting");
|
|
3423
|
-
const
|
|
3424
|
-
const entry = `${icon} ${agent.slice(0, 12).padEnd(12)}
|
|
3574
|
+
const statusText = isActive ? colors.running("analyzing") : isDone ? colors.success(`done (${this.getAgentIssueCount(agent)})`) : colors.waiting("waiting");
|
|
3575
|
+
const entry = `${icon} ${agent.slice(0, 12).padEnd(12)} ${colors.dim("...")} ${statusText}`;
|
|
3425
3576
|
if (i % 2 === 0) {
|
|
3426
3577
|
leftAgents.push(entry);
|
|
3427
3578
|
} else {
|
|
@@ -3429,38 +3580,73 @@ var InteractiveDashboard = class {
|
|
|
3429
3580
|
}
|
|
3430
3581
|
});
|
|
3431
3582
|
waitingAgents.slice(0, 4).forEach((agent, i) => {
|
|
3432
|
-
const entry = `${this.agentIcon("waiting")} ${agent.slice(0, 12).padEnd(12)} ... waiting
|
|
3583
|
+
const entry = `${this.agentIcon("waiting")} ${agent.slice(0, 12).padEnd(12)} ${colors.dim("...")} ${colors.waiting("waiting")}`;
|
|
3433
3584
|
if ((allAgents.length + i) % 2 === 0) {
|
|
3434
3585
|
leftAgents.push(entry);
|
|
3435
3586
|
} else {
|
|
3436
3587
|
rightAgents.push(entry);
|
|
3437
3588
|
}
|
|
3438
3589
|
});
|
|
3439
|
-
const maxRows = Math.max(leftAgents.length, rightAgents.length,
|
|
3440
|
-
for (let i = 0; i < maxRows && i <
|
|
3590
|
+
const maxRows = Math.max(leftAgents.length, rightAgents.length, agentRows);
|
|
3591
|
+
for (let i = 0; i < maxRows && i < agentRows; i++) {
|
|
3441
3592
|
const left = leftAgents[i] || " ".repeat(35);
|
|
3442
3593
|
const right = rightAgents[i] || " ".repeat(35);
|
|
3443
|
-
console.log(
|
|
3444
|
-
}
|
|
3445
|
-
console.log(
|
|
3446
|
-
console.log(
|
|
3447
|
-
console.log("
|
|
3448
|
-
console.log("
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
console.log("
|
|
3454
|
-
console.log("
|
|
3455
|
-
|
|
3594
|
+
console.log(v + " " + left + " " + right + " " + v);
|
|
3595
|
+
}
|
|
3596
|
+
console.log(v + " ".repeat(width - 2) + v);
|
|
3597
|
+
console.log(sectionBorder);
|
|
3598
|
+
console.log(v + " " + colors.header("ISSUES FOUND") + " ".repeat(width - 17) + v);
|
|
3599
|
+
console.log(v + " " + colors.dim(this.line(width - 6)) + " " + v);
|
|
3600
|
+
const criticalLine = `${colors.critical("[!]")} ${colors.critical("Critical")} ${colors.critical(issuesBySeverity.critical.toString().padStart(4))}`;
|
|
3601
|
+
const moderateLine = `${colors.moderate("[~]")} ${colors.moderate("Moderate")} ${colors.moderate(issuesBySeverity.moderate.toString().padStart(5))}`;
|
|
3602
|
+
const seriousLine = `${colors.serious("[x]")} ${colors.serious("Serious")} ${colors.serious(issuesBySeverity.serious.toString().padStart(4))}`;
|
|
3603
|
+
const lowLine = `${colors.low("[-]")} ${colors.low("Low")} ${colors.low(issuesBySeverity.low.toString().padStart(5))}`;
|
|
3604
|
+
console.log(v + " " + criticalLine + " " + moderateLine + " ".repeat(Math.max(0, width - 60)) + v);
|
|
3605
|
+
console.log(v + " " + seriousLine + " " + lowLine + " ".repeat(Math.max(0, width - 60)) + v);
|
|
3606
|
+
console.log(v + " ".repeat(width - 2) + v);
|
|
3607
|
+
console.log(sectionBorder);
|
|
3608
|
+
console.log(v + " " + colors.header("WATCH STATUS") + " ".repeat(width - 17) + v);
|
|
3609
|
+
console.log(v + " " + colors.dim(this.line(width - 6)) + " " + v);
|
|
3610
|
+
const watchLine = this.state.watch.watching ? colors.success(`Watching ${this.state.watch.directories} dirs`) + colors.dim(this.state.watch.debounceMs ? ` \u2022 debounce ${this.state.watch.debounceMs}ms` : "") : colors.dim("Watch idle");
|
|
3611
|
+
console.log(v + " " + watchLine + " ".repeat(Math.max(0, width - 40)) + v);
|
|
3612
|
+
const lastChange = this.state.watch.lastChange ? colors.dim("Last change: ") + colors.highlight(this.state.watch.lastChange) : colors.dim("Last change: --");
|
|
3613
|
+
console.log(v + " " + lastChange + " ".repeat(Math.max(0, width - 30)) + v);
|
|
3614
|
+
const recentChange = this.state.watch.recentChanges[0]?.file ? colors.dim("Recent: ") + this.state.watch.recentChanges[0].file : "";
|
|
3615
|
+
console.log(v + " " + recentChange + " ".repeat(Math.max(0, width - 30)) + v);
|
|
3616
|
+
console.log(sectionBorder);
|
|
3617
|
+
console.log(v + " " + colors.header("ACTIVITY LOG") + " ".repeat(width - 17) + v);
|
|
3618
|
+
console.log(v + " " + colors.dim(this.line(width - 6)) + " " + v);
|
|
3619
|
+
const startIdx = this.state.activityPage * activityRows;
|
|
3620
|
+
const recentActivity = this.state.activityLog.slice(startIdx, startIdx + activityRows);
|
|
3456
3621
|
for (const entry of recentActivity) {
|
|
3457
|
-
const
|
|
3458
|
-
console.log(
|
|
3622
|
+
const logLine = colors.dim(entry.time) + " " + this.colorizeActivityMessage(entry.message);
|
|
3623
|
+
console.log(v + " " + logLine + " ".repeat(Math.max(0, width - 50)) + v);
|
|
3459
3624
|
}
|
|
3460
|
-
for (let i = recentActivity.length; i <
|
|
3461
|
-
console.log(
|
|
3625
|
+
for (let i = recentActivity.length; i < activityRows; i++) {
|
|
3626
|
+
console.log(v + " ".repeat(width - 2) + v);
|
|
3462
3627
|
}
|
|
3463
3628
|
}
|
|
3629
|
+
/**
|
|
3630
|
+
* Colorize activity log messages based on content
|
|
3631
|
+
*/
|
|
3632
|
+
colorizeActivityMessage(message) {
|
|
3633
|
+
if (message.includes("[!]") || message.includes("CRITICAL")) {
|
|
3634
|
+
return colors.critical(message);
|
|
3635
|
+
}
|
|
3636
|
+
if (message.includes("[x]") || message.includes("SERIOUS")) {
|
|
3637
|
+
return colors.serious(message);
|
|
3638
|
+
}
|
|
3639
|
+
if (message.includes("[+]") || message.includes("complete")) {
|
|
3640
|
+
return colors.success(message);
|
|
3641
|
+
}
|
|
3642
|
+
if (message.includes("[*]") || message.includes("started")) {
|
|
3643
|
+
return colors.running(message);
|
|
3644
|
+
}
|
|
3645
|
+
if (message.includes("===")) {
|
|
3646
|
+
return colors.header(message);
|
|
3647
|
+
}
|
|
3648
|
+
return message;
|
|
3649
|
+
}
|
|
3464
3650
|
/**
|
|
3465
3651
|
* Get issue count for an agent
|
|
3466
3652
|
*/
|
|
@@ -3470,52 +3656,56 @@ var InteractiveDashboard = class {
|
|
|
3470
3656
|
/**
|
|
3471
3657
|
* Render overview with summary statistics
|
|
3472
3658
|
*/
|
|
3473
|
-
renderOverview(width) {
|
|
3659
|
+
renderOverview(width, height) {
|
|
3474
3660
|
const { issuesBySeverity, totalIssues, processedFiles } = this.state.progress;
|
|
3475
3661
|
const { completedAgents } = this.state.progress;
|
|
3476
3662
|
const elapsed = ((Date.now() - this.state.startTime) / 1e3).toFixed(1);
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
console.log(
|
|
3481
|
-
console.log(
|
|
3482
|
-
console.log("
|
|
3483
|
-
console.log(
|
|
3484
|
-
|
|
3485
|
-
console.log(
|
|
3486
|
-
console.log(
|
|
3487
|
-
|
|
3488
|
-
console.log(
|
|
3489
|
-
console.log("
|
|
3663
|
+
const activityRows = Math.max(2, Math.min(8, Math.max(0, height - 26)));
|
|
3664
|
+
const v = colors.border(box.vertical);
|
|
3665
|
+
const sectionBorder = colors.border(box.leftT + this.line(width - 2) + box.rightT);
|
|
3666
|
+
console.log(v + " ".repeat(width - 2) + v);
|
|
3667
|
+
console.log(v + " " + colors.highlight(`${processedFiles}`) + colors.dim(` files scanned in ${elapsed}s`) + " ".repeat(Math.max(0, width - 35)) + v);
|
|
3668
|
+
console.log(v + " " + colors.highlight(`${completedAgents.length}`) + colors.dim(" scouts activated") + " ".repeat(Math.max(0, width - 30)) + v);
|
|
3669
|
+
console.log(v + " ".repeat(width - 2) + v);
|
|
3670
|
+
console.log(sectionBorder);
|
|
3671
|
+
console.log(v + " " + colors.header("SUMMARY") + " ".repeat(width - 12) + v);
|
|
3672
|
+
console.log(v + " " + colors.dim(this.line(width - 6)) + " " + v);
|
|
3673
|
+
const criticalLabel = issuesBySeverity.critical > 0 ? colors.alert("<- FIX NOW") : "";
|
|
3674
|
+
console.log(v + " " + colors.critical("[!]") + " " + colors.critical(issuesBySeverity.critical.toString().padStart(4)) + " " + colors.critical("Critical issues") + " " + criticalLabel + " ".repeat(Math.max(0, width - 45)) + v);
|
|
3675
|
+
console.log(v + " " + colors.serious("[x]") + " " + colors.serious(issuesBySeverity.serious.toString().padStart(4)) + " " + colors.serious("Serious issues") + " ".repeat(Math.max(0, width - 30)) + v);
|
|
3676
|
+
console.log(v + " " + colors.moderate("[~]") + " " + colors.moderate(issuesBySeverity.moderate.toString().padStart(4)) + " " + colors.moderate("Moderate issues") + " ".repeat(Math.max(0, width - 30)) + v);
|
|
3677
|
+
console.log(v + " " + colors.low("[-]") + " " + colors.low(issuesBySeverity.low.toString().padStart(4)) + " " + colors.low("Low issues") + " ".repeat(Math.max(0, width - 30)) + v);
|
|
3678
|
+
console.log(v + " ".repeat(width - 2) + v);
|
|
3490
3679
|
const criticalIssues = this.state.issues.filter((i) => i.severity === "critical").slice(0, 3);
|
|
3491
3680
|
if (criticalIssues.length > 0) {
|
|
3492
|
-
console.log(
|
|
3493
|
-
console.log("
|
|
3494
|
-
console.log("
|
|
3681
|
+
console.log(sectionBorder);
|
|
3682
|
+
console.log(v + " " + colors.critical("TOP CRITICAL ISSUES") + " ".repeat(width - 24) + v);
|
|
3683
|
+
console.log(v + " " + colors.dim(this.line(width - 6)) + " " + v);
|
|
3495
3684
|
for (const issue of criticalIssues) {
|
|
3496
3685
|
const filename = issue.file.split("/").pop() || issue.file;
|
|
3497
|
-
const
|
|
3498
|
-
const location = `${filename}${
|
|
3686
|
+
const lineNum = issue.line ? `:${issue.line}` : "";
|
|
3687
|
+
const location = `${filename}${lineNum}`;
|
|
3499
3688
|
const description = issue.issue.slice(0, 40) + (issue.issue.length > 40 ? "..." : "");
|
|
3500
|
-
console.log(
|
|
3501
|
-
console.log(
|
|
3502
|
-
console.log(
|
|
3689
|
+
console.log(v + " " + colors.critical("\u25B8") + " " + colors.critical(description) + " ".repeat(Math.max(0, width - 50)) + v);
|
|
3690
|
+
console.log(v + " " + colors.dim(location) + " ".repeat(Math.max(0, width - 30)) + v);
|
|
3691
|
+
console.log(v + " ".repeat(width - 2) + v);
|
|
3503
3692
|
}
|
|
3504
3693
|
} else if (totalIssues === 0) {
|
|
3505
|
-
console.log(
|
|
3506
|
-
console.log("
|
|
3507
|
-
console.log(
|
|
3508
|
-
}
|
|
3509
|
-
console.log(
|
|
3510
|
-
console.log("
|
|
3511
|
-
console.log("
|
|
3512
|
-
const
|
|
3694
|
+
console.log(sectionBorder);
|
|
3695
|
+
console.log(v + " " + colors.success("\u2713 No issues found - code looks good!") + " ".repeat(Math.max(0, width - 45)) + v);
|
|
3696
|
+
console.log(v + " ".repeat(width - 2) + v);
|
|
3697
|
+
}
|
|
3698
|
+
console.log(sectionBorder);
|
|
3699
|
+
console.log(v + " " + colors.header("ACTIVITY LOG") + " ".repeat(width - 17) + v);
|
|
3700
|
+
console.log(v + " " + colors.dim(this.line(width - 6)) + " " + v);
|
|
3701
|
+
const startIdx = this.state.activityPage * activityRows;
|
|
3702
|
+
const recentActivity = this.state.activityLog.slice(startIdx, startIdx + activityRows);
|
|
3513
3703
|
for (const entry of recentActivity) {
|
|
3514
|
-
const
|
|
3515
|
-
console.log(
|
|
3704
|
+
const logLine = colors.dim(entry.time) + " " + this.colorizeActivityMessage(entry.message);
|
|
3705
|
+
console.log(v + " " + logLine + " ".repeat(Math.max(0, width - 50)) + v);
|
|
3516
3706
|
}
|
|
3517
|
-
for (let i = recentActivity.length; i <
|
|
3518
|
-
console.log(
|
|
3707
|
+
for (let i = recentActivity.length; i < activityRows; i++) {
|
|
3708
|
+
console.log(v + " ".repeat(width - 2) + v);
|
|
3519
3709
|
}
|
|
3520
3710
|
}
|
|
3521
3711
|
/**
|
|
@@ -3524,8 +3714,10 @@ var InteractiveDashboard = class {
|
|
|
3524
3714
|
renderIssuesList(width) {
|
|
3525
3715
|
const filteredIssues = this.getFilteredIssues();
|
|
3526
3716
|
const { selectedIssue } = this.state;
|
|
3527
|
-
|
|
3528
|
-
|
|
3717
|
+
const v = colors.border(box.vertical);
|
|
3718
|
+
const sectionBorder = colors.border(box.leftT + this.line(width - 2) + box.rightT);
|
|
3719
|
+
console.log(v + " " + colors.dim("Filter:") + " " + this.getFilterDescription() + " ".repeat(Math.max(0, width - 25)) + v);
|
|
3720
|
+
console.log(sectionBorder);
|
|
3529
3721
|
const pageSize = 10;
|
|
3530
3722
|
const startIndex = Math.floor(selectedIssue / pageSize) * pageSize;
|
|
3531
3723
|
const pageIssues = filteredIssues.slice(startIndex, startIndex + pageSize);
|
|
@@ -3533,29 +3725,29 @@ var InteractiveDashboard = class {
|
|
|
3533
3725
|
const issue = pageIssues[i];
|
|
3534
3726
|
const globalIndex = startIndex + i;
|
|
3535
3727
|
const isSelected = globalIndex === selectedIssue;
|
|
3536
|
-
const cursor = isSelected ? "
|
|
3728
|
+
const cursor = isSelected ? colors.selected("\u25B8") : " ";
|
|
3537
3729
|
const severityIcon = this.severityIcon(issue.severity);
|
|
3538
3730
|
const filename = issue.file.split("/").pop() || issue.file;
|
|
3539
|
-
const location = `${filename}:${issue.line || "?"}
|
|
3731
|
+
const location = colors.dim(`${filename}:${issue.line || "?"}`);
|
|
3540
3732
|
const description = issue.issue.slice(0, 35) + (issue.issue.length > 35 ? "..." : "");
|
|
3541
|
-
const
|
|
3542
|
-
console.log(
|
|
3733
|
+
const descText = isSelected ? colors.selected(description) : description;
|
|
3734
|
+
console.log(v + " " + severityIcon + " " + cursor + " " + descText + " " + location + " ".repeat(Math.max(0, width - 70)) + v);
|
|
3543
3735
|
}
|
|
3544
3736
|
for (let i = pageIssues.length; i < pageSize; i++) {
|
|
3545
|
-
console.log(
|
|
3737
|
+
console.log(v + " ".repeat(width - 2) + v);
|
|
3546
3738
|
}
|
|
3547
3739
|
if (filteredIssues[selectedIssue]) {
|
|
3548
3740
|
const selected = filteredIssues[selectedIssue];
|
|
3549
|
-
console.log(
|
|
3550
|
-
console.log("
|
|
3551
|
-
console.log("
|
|
3552
|
-
console.log(
|
|
3553
|
-
console.log(
|
|
3554
|
-
console.log(
|
|
3741
|
+
console.log(sectionBorder);
|
|
3742
|
+
console.log(v + " " + colors.header("SELECTED:") + " " + colors.highlight(selected.issue.slice(0, width - 20)) + " ".repeat(Math.max(0, width - 60)) + v);
|
|
3743
|
+
console.log(v + " " + colors.dim(this.line(width - 6)) + " " + v);
|
|
3744
|
+
console.log(v + " " + colors.dim("File:") + " " + selected.file.slice(0, width - 15) + " ".repeat(Math.max(0, width - 50)) + v);
|
|
3745
|
+
console.log(v + " " + colors.dim("Line:") + " " + (selected.line || "Unknown") + " " + colors.dim("Scout:") + " " + selected.agent + " ".repeat(Math.max(0, width - 40)) + v);
|
|
3746
|
+
console.log(v + " ".repeat(width - 2) + v);
|
|
3555
3747
|
const fixLines = this.wrapText(selected.fix, width - 8);
|
|
3556
|
-
console.log("
|
|
3748
|
+
console.log(v + " " + colors.success("Fix:") + " ".repeat(Math.max(0, width - 10)) + v);
|
|
3557
3749
|
for (const line of fixLines.slice(0, 2)) {
|
|
3558
|
-
console.log(
|
|
3750
|
+
console.log(v + " " + colors.success(line) + " ".repeat(Math.max(0, width - line.length - 10)) + v);
|
|
3559
3751
|
}
|
|
3560
3752
|
}
|
|
3561
3753
|
}
|
|
@@ -3563,28 +3755,55 @@ var InteractiveDashboard = class {
|
|
|
3563
3755
|
* Render agents view
|
|
3564
3756
|
*/
|
|
3565
3757
|
renderAgentsView(width) {
|
|
3566
|
-
const
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3758
|
+
const v = colors.border(box.vertical);
|
|
3759
|
+
const sectionBorder = colors.border(box.leftT + this.line(width - 2) + box.rightT);
|
|
3760
|
+
const sorted = this.getSortedAgents();
|
|
3761
|
+
const pageSize = 6;
|
|
3762
|
+
const startIdx = this.state.agentPage * pageSize;
|
|
3763
|
+
const slice = sorted.slice(startIdx, startIdx + pageSize);
|
|
3764
|
+
console.log(v + " " + colors.header("SCOUT STATUS") + " " + colors.dim("(Enter to view issues, j/k to navigate)") + " ".repeat(Math.max(0, width - 60)) + v);
|
|
3765
|
+
console.log(sectionBorder);
|
|
3766
|
+
console.log(v + " " + colors.dim(`Page ${this.state.agentPage + 1} / ${Math.max(1, Math.ceil(sorted.length / pageSize))}`) + " ".repeat(Math.max(0, width - 20)) + v);
|
|
3767
|
+
if (slice.length === 0) {
|
|
3768
|
+
console.log(v + " " + colors.dim("No scouts yet") + " ".repeat(Math.max(0, width - 20)) + v);
|
|
3769
|
+
return;
|
|
3575
3770
|
}
|
|
3576
|
-
console.log("
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
const
|
|
3580
|
-
|
|
3581
|
-
|
|
3771
|
+
console.log(v + " " + colors.dim("Name Status Issues Duration") + " ".repeat(Math.max(0, width - 58)) + v);
|
|
3772
|
+
console.log(v + " " + colors.dim(this.line(width - 6)) + " " + v);
|
|
3773
|
+
for (let i = 0; i < slice.length; i++) {
|
|
3774
|
+
const agent = slice[i];
|
|
3775
|
+
if (!agent) continue;
|
|
3776
|
+
const globalIdx = startIdx + i;
|
|
3777
|
+
const isSelected = globalIdx === this.state.selectedAgent;
|
|
3778
|
+
const cursor = isSelected ? colors.selected("\u25B8") : " ";
|
|
3779
|
+
const statusIcon = agent.status === "running" ? this.agentIcon("running") : agent.status === "done" ? this.agentIcon("done") : this.agentIcon("waiting");
|
|
3780
|
+
const statusText = agent.status === "running" ? colors.running(agent.status.padEnd(9)) : agent.status === "done" ? colors.success(agent.status.padEnd(9)) : colors.waiting(agent.status.padEnd(9));
|
|
3781
|
+
const issueCount = agent.issues > 0 ? colors.serious(agent.issues.toString().padStart(6)) : colors.dim(agent.issues.toString().padStart(6));
|
|
3782
|
+
const duration = colors.dim(agent.duration.padEnd(8));
|
|
3783
|
+
const nameText = isSelected ? colors.selected(agent.name.padEnd(18)) : agent.name.padEnd(18);
|
|
3784
|
+
console.log(v + " " + cursor + " " + statusIcon + " " + nameText + " " + statusText + " " + issueCount + " " + duration + " ".repeat(Math.max(0, width - 65)) + v);
|
|
3785
|
+
}
|
|
3786
|
+
for (let i = slice.length; i < pageSize; i++) {
|
|
3787
|
+
console.log(v + " ".repeat(width - 2) + v);
|
|
3788
|
+
}
|
|
3789
|
+
const selected = sorted[this.state.selectedAgent];
|
|
3790
|
+
if (selected) {
|
|
3791
|
+
const agentIssues = this.state.issues.filter((i) => i.agent === selected.name);
|
|
3792
|
+
const criticals = agentIssues.filter((i) => i.severity === "critical").length;
|
|
3793
|
+
const serious = agentIssues.filter((i) => i.severity === "serious").length;
|
|
3794
|
+
console.log(sectionBorder);
|
|
3795
|
+
console.log(v + " " + colors.header("SELECTED:") + " " + colors.highlight(selected.name) + " ".repeat(Math.max(0, width - 30)) + v);
|
|
3796
|
+
console.log(v + " " + colors.dim(this.line(width - 6)) + " " + v);
|
|
3797
|
+
console.log(v + " " + colors.dim("Issues:") + " " + colors.highlight(agentIssues.length.toString()) + " total (" + colors.critical(`[!] ${criticals} critical`) + ", " + colors.serious(`[x] ${serious} serious`) + ")" + " ".repeat(Math.max(0, width - 65)) + v);
|
|
3798
|
+
console.log(v + " " + colors.dim("Press Enter to view all issues from this scout") + " ".repeat(Math.max(0, width - 55)) + v);
|
|
3582
3799
|
}
|
|
3583
3800
|
}
|
|
3584
3801
|
/**
|
|
3585
3802
|
* Render files view
|
|
3586
3803
|
*/
|
|
3587
3804
|
renderFilesView(width) {
|
|
3805
|
+
const v = colors.border(box.vertical);
|
|
3806
|
+
const sectionBorder = colors.border(box.leftT + this.line(width - 2) + box.rightT);
|
|
3588
3807
|
const fileIssues = /* @__PURE__ */ new Map();
|
|
3589
3808
|
for (const issue of this.state.issues) {
|
|
3590
3809
|
if (!fileIssues.has(issue.file)) {
|
|
@@ -3593,25 +3812,38 @@ var InteractiveDashboard = class {
|
|
|
3593
3812
|
fileIssues.get(issue.file).push(issue);
|
|
3594
3813
|
}
|
|
3595
3814
|
const sortedFiles = Array.from(fileIssues.entries()).sort((a, b) => b[1].length - a[1].length).slice(0, 15);
|
|
3596
|
-
console.log("
|
|
3597
|
-
console.log(
|
|
3815
|
+
console.log(v + " " + colors.header("FILES WITH ISSUES") + " ".repeat(width - 22) + v);
|
|
3816
|
+
console.log(sectionBorder);
|
|
3598
3817
|
for (const [file, issues] of sortedFiles) {
|
|
3599
3818
|
const filename = file.split("/").pop() || file;
|
|
3600
3819
|
const criticalCount = issues.filter((i) => i.severity === "critical").length;
|
|
3601
3820
|
const totalCount = issues.length;
|
|
3602
|
-
const criticalText = criticalCount > 0 ? ` (${criticalCount} critical)` : "";
|
|
3603
|
-
|
|
3821
|
+
const criticalText = criticalCount > 0 ? colors.critical(` (${criticalCount} critical)`) : "";
|
|
3822
|
+
const countText = criticalCount > 0 ? colors.serious(`${totalCount} issues`) : colors.dim(`${totalCount} issues`);
|
|
3823
|
+
console.log(v + " " + filename.padEnd(35) + " " + countText + criticalText + " ".repeat(Math.max(0, width - 60)) + v);
|
|
3824
|
+
}
|
|
3825
|
+
for (let i = sortedFiles.length; i < 10; i++) {
|
|
3826
|
+
console.log(v + " ".repeat(width - 2) + v);
|
|
3604
3827
|
}
|
|
3605
3828
|
}
|
|
3606
3829
|
/**
|
|
3607
3830
|
* Render footer with controls
|
|
3608
3831
|
*/
|
|
3609
3832
|
renderFooter(width) {
|
|
3610
|
-
|
|
3833
|
+
const bottomBorder = colors.border(box.bottomLeft + this.line(width - 2) + box.bottomRight);
|
|
3834
|
+
console.log(bottomBorder);
|
|
3835
|
+
const key = (k) => colors.border("[") + colors.highlight(k) + colors.border("]");
|
|
3836
|
+
const hint = (k, desc) => key(k) + colors.dim(` ${desc}`);
|
|
3611
3837
|
if (!this.state.scanComplete) {
|
|
3612
|
-
console.log("
|
|
3838
|
+
console.log(" " + hint("q", "Quit") + " " + hint("?", "Help"));
|
|
3839
|
+
} else if (this.state.view === "agents") {
|
|
3840
|
+
console.log(" " + hint("j/k", "Select") + " " + hint("Enter", "View issues") + " " + hint("n/p", "Pages") + " " + hint("Tab", "Views") + " " + hint("?", "Help") + " " + hint("q", "Quit"));
|
|
3841
|
+
} else if (this.state.view === "issues" && this.state.previousView === "agents") {
|
|
3842
|
+
console.log(" " + hint("b", "Back") + " " + hint("j/k", "Nav") + " " + hint("Enter", "Details") + " " + hint("1-4", "Severity") + " " + hint("f", "Search") + " " + hint("?", "Help") + " " + hint("q", "Quit"));
|
|
3843
|
+
} else if (this.state.view === "issues") {
|
|
3844
|
+
console.log(" " + hint("j/k", "Nav") + " " + hint("Enter", "Details") + " " + hint("1-4", "Severity") + " " + hint("f", "Search") + " " + hint("s", "Scout") + " " + hint("c", "Clear") + " " + hint("Tab", "Views") + " " + hint("?", "Help") + " " + hint("q", "Quit"));
|
|
3613
3845
|
} else {
|
|
3614
|
-
console.log("
|
|
3846
|
+
console.log(" " + hint("Tab", "Views") + " " + hint("n/p", "Pages") + " " + hint("?", "Help") + " " + hint("q", "Quit"));
|
|
3615
3847
|
}
|
|
3616
3848
|
}
|
|
3617
3849
|
// Helper methods
|
|
@@ -3625,12 +3857,62 @@ var InteractiveDashboard = class {
|
|
|
3625
3857
|
navigateUp() {
|
|
3626
3858
|
if (this.state.view === "issues") {
|
|
3627
3859
|
this.state.selectedIssue = Math.max(0, this.state.selectedIssue - 1);
|
|
3860
|
+
} else if (this.state.view === "agents") {
|
|
3861
|
+
this.state.selectedAgent = Math.max(0, this.state.selectedAgent - 1);
|
|
3862
|
+
const pageSize = 6;
|
|
3863
|
+
const page = Math.floor(this.state.selectedAgent / pageSize);
|
|
3864
|
+
if (page !== this.state.agentPage) {
|
|
3865
|
+
this.state.agentPage = page;
|
|
3866
|
+
}
|
|
3628
3867
|
}
|
|
3629
3868
|
}
|
|
3630
3869
|
navigateDown() {
|
|
3631
3870
|
if (this.state.view === "issues") {
|
|
3632
3871
|
const filteredIssues = this.getFilteredIssues();
|
|
3633
3872
|
this.state.selectedIssue = Math.min(filteredIssues.length - 1, this.state.selectedIssue + 1);
|
|
3873
|
+
} else if (this.state.view === "agents") {
|
|
3874
|
+
const agents = this.getSortedAgents();
|
|
3875
|
+
this.state.selectedAgent = Math.min(agents.length - 1, this.state.selectedAgent + 1);
|
|
3876
|
+
const pageSize = 6;
|
|
3877
|
+
const page = Math.floor(this.state.selectedAgent / pageSize);
|
|
3878
|
+
if (page !== this.state.agentPage) {
|
|
3879
|
+
this.state.agentPage = page;
|
|
3880
|
+
}
|
|
3881
|
+
}
|
|
3882
|
+
}
|
|
3883
|
+
getSortedAgents() {
|
|
3884
|
+
const agentEntries = [];
|
|
3885
|
+
for (const [name, data] of Object.entries(this.state.agents)) {
|
|
3886
|
+
const duration = data.durationMs ? `${(data.durationMs / 1e3).toFixed(1)}s` : "\u2014";
|
|
3887
|
+
agentEntries.push({ name, status: data.status, issues: data.issues, duration });
|
|
3888
|
+
}
|
|
3889
|
+
for (const name of this.state.progress.activeAgents) {
|
|
3890
|
+
if (!this.state.agents[name]) {
|
|
3891
|
+
agentEntries.push({ name, status: "running", issues: 0, duration: "\u2014" });
|
|
3892
|
+
}
|
|
3893
|
+
}
|
|
3894
|
+
for (const name of this.state.progress.completedAgents) {
|
|
3895
|
+
if (!this.state.agents[name]) {
|
|
3896
|
+
agentEntries.push({ name, status: "done", issues: this.getAgentIssueCount(name), duration: "\u2014" });
|
|
3897
|
+
}
|
|
3898
|
+
}
|
|
3899
|
+
const order = { running: 0, queued: 1, done: 2 };
|
|
3900
|
+
return agentEntries.sort((a, b) => (order[a.status] ?? 2) - (order[b.status] ?? 2) || a.name.localeCompare(b.name));
|
|
3901
|
+
}
|
|
3902
|
+
nextPage() {
|
|
3903
|
+
if (this.state.view === "agents") {
|
|
3904
|
+
const total = Math.max(1, Math.ceil(Object.keys(this.state.agents).length / 6));
|
|
3905
|
+
this.state.agentPage = Math.min(total - 1, this.state.agentPage + 1);
|
|
3906
|
+
} else {
|
|
3907
|
+
const total = Math.max(1, Math.ceil(this.state.activityLog.length / 6));
|
|
3908
|
+
this.state.activityPage = Math.min(total - 1, this.state.activityPage + 1);
|
|
3909
|
+
}
|
|
3910
|
+
}
|
|
3911
|
+
prevPage() {
|
|
3912
|
+
if (this.state.view === "agents") {
|
|
3913
|
+
this.state.agentPage = Math.max(0, this.state.agentPage - 1);
|
|
3914
|
+
} else {
|
|
3915
|
+
this.state.activityPage = Math.max(0, this.state.activityPage - 1);
|
|
3634
3916
|
}
|
|
3635
3917
|
}
|
|
3636
3918
|
selectCurrent() {
|
|
@@ -3640,6 +3922,24 @@ var InteractiveDashboard = class {
|
|
|
3640
3922
|
if (selected) {
|
|
3641
3923
|
this.showIssueDetails(selected);
|
|
3642
3924
|
}
|
|
3925
|
+
} else if (this.state.view === "agents") {
|
|
3926
|
+
const agents = this.getSortedAgents();
|
|
3927
|
+
const selected = agents[this.state.selectedAgent];
|
|
3928
|
+
if (selected) {
|
|
3929
|
+
this.state.previousView = "agents";
|
|
3930
|
+
this.state.filter.agent = selected.name;
|
|
3931
|
+
this.state.selectedIssue = 0;
|
|
3932
|
+
this.state.view = "issues";
|
|
3933
|
+
}
|
|
3934
|
+
}
|
|
3935
|
+
}
|
|
3936
|
+
goBack() {
|
|
3937
|
+
if (this.state.previousView) {
|
|
3938
|
+
if (this.state.previousView === "agents" && this.state.filter.agent !== "all") {
|
|
3939
|
+
this.state.filter.agent = "all";
|
|
3940
|
+
}
|
|
3941
|
+
this.state.view = this.state.previousView;
|
|
3942
|
+
this.state.previousView = null;
|
|
3643
3943
|
}
|
|
3644
3944
|
}
|
|
3645
3945
|
setFilter(type, value) {
|
|
@@ -3671,7 +3971,7 @@ var InteractiveDashboard = class {
|
|
|
3671
3971
|
getFilterDescription() {
|
|
3672
3972
|
const parts = [];
|
|
3673
3973
|
if (this.state.filter.severity !== "all") parts.push(`Severity: ${this.state.filter.severity}`);
|
|
3674
|
-
if (this.state.filter.agent !== "all") parts.push(`
|
|
3974
|
+
if (this.state.filter.agent !== "all") parts.push(`Scout: ${this.state.filter.agent}`);
|
|
3675
3975
|
if (this.state.filter.search) parts.push(`Search: "${this.state.filter.search}"`);
|
|
3676
3976
|
return parts.length > 0 ? parts.join(", ") : "All issues";
|
|
3677
3977
|
}
|
|
@@ -3691,38 +3991,108 @@ var InteractiveDashboard = class {
|
|
|
3691
3991
|
return lines;
|
|
3692
3992
|
}
|
|
3693
3993
|
async promptFilter() {
|
|
3994
|
+
if (this.updateInterval) {
|
|
3995
|
+
clearInterval(this.updateInterval);
|
|
3996
|
+
this.updateInterval = void 0;
|
|
3997
|
+
}
|
|
3694
3998
|
if (input.isTTY) {
|
|
3695
3999
|
input.setRawMode(false);
|
|
3696
4000
|
}
|
|
3697
|
-
|
|
4001
|
+
const v = colors.border(box.vertical);
|
|
4002
|
+
const w = 62;
|
|
4003
|
+
process.stdout.write("\x1B[2J\x1B[H\x1B[?25h");
|
|
4004
|
+
console.log(colors.border(box.topLeft + this.line(w - 2) + box.topRight));
|
|
4005
|
+
console.log(v + " " + colors.header("FILTER ISSUES") + " ".repeat(w - 18) + v);
|
|
4006
|
+
console.log(colors.border(box.leftT + this.line(w - 2) + box.rightT));
|
|
4007
|
+
console.log(v + " " + colors.dim("Current filters:") + " ".repeat(w - 21) + v);
|
|
4008
|
+
console.log(v + " " + colors.dim("Severity:") + " " + colors.highlight(this.state.filter.severity) + " ".repeat(Math.max(0, w - 20)) + v);
|
|
4009
|
+
console.log(v + " " + colors.dim("Scout:") + " " + colors.highlight(this.state.filter.agent) + " ".repeat(Math.max(0, w - 18)) + v);
|
|
4010
|
+
console.log(v + " " + colors.dim("Search:") + " " + colors.highlight(this.state.filter.search || "(none)") + " ".repeat(Math.max(0, w - 20)) + v);
|
|
4011
|
+
console.log(colors.border(box.bottomLeft + this.line(w - 2) + box.bottomRight));
|
|
4012
|
+
console.log("");
|
|
4013
|
+
this.rl.question(colors.border("\u25B8 ") + "Enter search term (empty to clear): ", (answer) => {
|
|
3698
4014
|
this.state.filter.search = answer.trim();
|
|
3699
4015
|
this.state.selectedIssue = 0;
|
|
3700
4016
|
if (input.isTTY) {
|
|
3701
4017
|
input.setRawMode(true);
|
|
3702
4018
|
}
|
|
4019
|
+
this.startUpdateLoop();
|
|
4020
|
+
this.render();
|
|
4021
|
+
});
|
|
4022
|
+
}
|
|
4023
|
+
async promptAgentFilter() {
|
|
4024
|
+
if (this.updateInterval) {
|
|
4025
|
+
clearInterval(this.updateInterval);
|
|
4026
|
+
this.updateInterval = void 0;
|
|
4027
|
+
}
|
|
4028
|
+
if (input.isTTY) {
|
|
4029
|
+
input.setRawMode(false);
|
|
4030
|
+
}
|
|
4031
|
+
const agents = [.../* @__PURE__ */ new Set([
|
|
4032
|
+
...this.state.progress.completedAgents,
|
|
4033
|
+
...this.state.progress.activeAgents,
|
|
4034
|
+
...Object.keys(this.state.agents)
|
|
4035
|
+
])].sort();
|
|
4036
|
+
const v = colors.border(box.vertical);
|
|
4037
|
+
const w = 62;
|
|
4038
|
+
process.stdout.write("\x1B[2J\x1B[H\x1B[?25h");
|
|
4039
|
+
console.log(colors.border(box.topLeft + this.line(w - 2) + box.topRight));
|
|
4040
|
+
console.log(v + " " + colors.header("FILTER BY SCOUT") + " ".repeat(w - 20) + v);
|
|
4041
|
+
console.log(colors.border(box.leftT + this.line(w - 2) + box.rightT));
|
|
4042
|
+
console.log(v + " " + colors.dim("Current scout filter:") + " " + colors.highlight(this.state.filter.agent) + " ".repeat(Math.max(0, w - 30)) + v);
|
|
4043
|
+
console.log(colors.border(box.leftT + this.line(w - 2) + box.rightT));
|
|
4044
|
+
console.log(v + " " + colors.dim("Available scouts:") + " ".repeat(w - 22) + v);
|
|
4045
|
+
for (const agent of agents.slice(0, 10)) {
|
|
4046
|
+
console.log(v + " " + colors.success("\u2022") + " " + agent + " ".repeat(Math.max(0, w - agent.length - 8)) + v);
|
|
4047
|
+
}
|
|
4048
|
+
if (agents.length > 10) {
|
|
4049
|
+
console.log(v + " " + colors.dim(`... and ${agents.length - 10} more`) + " ".repeat(Math.max(0, w - 25)) + v);
|
|
4050
|
+
}
|
|
4051
|
+
console.log(colors.border(box.bottomLeft + this.line(w - 2) + box.bottomRight));
|
|
4052
|
+
console.log("");
|
|
4053
|
+
this.rl.question(colors.border("\u25B8 ") + "Enter scout name (empty for all): ", (answer) => {
|
|
4054
|
+
const trimmed = answer.trim();
|
|
4055
|
+
if (trimmed === "" || trimmed.toLowerCase() === "all") {
|
|
4056
|
+
this.state.filter.agent = "all";
|
|
4057
|
+
} else {
|
|
4058
|
+
const match = agents.find((a) => a.toLowerCase().includes(trimmed.toLowerCase()));
|
|
4059
|
+
this.state.filter.agent = match || trimmed;
|
|
4060
|
+
}
|
|
4061
|
+
this.state.selectedIssue = 0;
|
|
4062
|
+
if (input.isTTY) {
|
|
4063
|
+
input.setRawMode(true);
|
|
4064
|
+
}
|
|
4065
|
+
this.startUpdateLoop();
|
|
3703
4066
|
this.render();
|
|
3704
4067
|
});
|
|
3705
4068
|
}
|
|
3706
4069
|
showHelp() {
|
|
3707
4070
|
this.isActive = false;
|
|
3708
4071
|
process.stdout.write("\x1B[2J\x1B[H");
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
console.log(
|
|
3712
|
-
console.log("
|
|
3713
|
-
console.log(
|
|
3714
|
-
console.log("
|
|
3715
|
-
console.log("
|
|
3716
|
-
console.log("
|
|
3717
|
-
console.log("
|
|
3718
|
-
console.log("
|
|
3719
|
-
console.log("
|
|
3720
|
-
console.log(
|
|
3721
|
-
console.log("
|
|
3722
|
-
console.log("
|
|
3723
|
-
console.log("
|
|
3724
|
-
console.log(
|
|
3725
|
-
console.log("
|
|
4072
|
+
const v = colors.border(box.vertical);
|
|
4073
|
+
const w = 68;
|
|
4074
|
+
console.log(colors.border(box.topLeft + this.line(w - 2) + box.topRight));
|
|
4075
|
+
console.log(v + " " + colors.brand("TRIE GUARDIAN") + " " + colors.dim("-") + " " + colors.header("HELP") + " ".repeat(w - 26) + v);
|
|
4076
|
+
console.log(colors.border(box.leftT + this.line(w - 2) + box.rightT));
|
|
4077
|
+
console.log(v + " " + colors.header("Navigation") + " ".repeat(w - 15) + v);
|
|
4078
|
+
console.log(v + " " + colors.highlight("Tab") + " " + colors.dim("Switch view (overview/issues/scouts/files)") + " ".repeat(w - 56) + v);
|
|
4079
|
+
console.log(v + " " + colors.highlight("j/k") + " " + colors.dim("Navigate up/down in lists") + " ".repeat(w - 40) + v);
|
|
4080
|
+
console.log(v + " " + colors.highlight("n/p") + " " + colors.dim("Next/previous page") + " ".repeat(w - 33) + v);
|
|
4081
|
+
console.log(v + " " + colors.highlight("Enter") + " " + colors.dim("View details / drill into scout") + " ".repeat(w - 46) + v);
|
|
4082
|
+
console.log(v + " " + colors.highlight("b") + " " + colors.dim("Go back (after drilling into scout)") + " ".repeat(w - 50) + v);
|
|
4083
|
+
console.log(v + " ".repeat(w - 2) + v);
|
|
4084
|
+
console.log(v + " " + colors.header("Filters") + " ".repeat(w - 12) + v);
|
|
4085
|
+
console.log(v + " " + colors.highlight("1-4") + " " + colors.dim("Filter by severity (1=critical, 4=low)") + " ".repeat(w - 53) + v);
|
|
4086
|
+
console.log(v + " " + colors.highlight("0") + " " + colors.dim("Show all severities") + " ".repeat(w - 34) + v);
|
|
4087
|
+
console.log(v + " " + colors.highlight("f") + " " + colors.dim("Search issues by text") + " ".repeat(w - 36) + v);
|
|
4088
|
+
console.log(v + " " + colors.highlight("s") + " " + colors.dim("Filter by scout name") + " ".repeat(w - 35) + v);
|
|
4089
|
+
console.log(v + " " + colors.highlight("c") + " " + colors.dim("Clear all filters") + " ".repeat(w - 32) + v);
|
|
4090
|
+
console.log(v + " ".repeat(w - 2) + v);
|
|
4091
|
+
console.log(v + " " + colors.header("Other") + " ".repeat(w - 10) + v);
|
|
4092
|
+
console.log(v + " " + colors.highlight("h") + " or " + colors.highlight("?") + " " + colors.dim("Show this help") + " ".repeat(w - 31) + v);
|
|
4093
|
+
console.log(v + " " + colors.highlight("q") + " or " + colors.highlight("Esc") + " " + colors.dim("Quit") + " ".repeat(w - 23) + v);
|
|
4094
|
+
console.log(colors.border(box.bottomLeft + this.line(w - 2) + box.bottomRight));
|
|
4095
|
+
console.log(" " + colors.dim("Press any key to return..."));
|
|
3726
4096
|
const resume = () => {
|
|
3727
4097
|
this.isActive = true;
|
|
3728
4098
|
this.render();
|
|
@@ -3732,25 +4102,28 @@ var InteractiveDashboard = class {
|
|
|
3732
4102
|
showIssueDetails(issue) {
|
|
3733
4103
|
this.isActive = false;
|
|
3734
4104
|
process.stdout.write("\x1B[2J\x1B[H");
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
console.log(
|
|
3739
|
-
console.log(
|
|
3740
|
-
console.log(
|
|
3741
|
-
console.log("
|
|
3742
|
-
|
|
4105
|
+
const v = colors.border(box.vertical);
|
|
4106
|
+
const w = 68;
|
|
4107
|
+
const severityColor = issue.severity === "critical" ? colors.critical : issue.severity === "serious" ? colors.serious : issue.severity === "moderate" ? colors.moderate : colors.low;
|
|
4108
|
+
console.log(colors.border(box.topLeft + this.line(w - 2) + box.topRight));
|
|
4109
|
+
console.log(v + " " + colors.header("ISSUE DETAILS") + " " + severityColor(`[${issue.severity.toUpperCase()}]`) + " ".repeat(Math.max(0, w - 30)) + v);
|
|
4110
|
+
console.log(colors.border(box.leftT + this.line(w - 2) + box.rightT));
|
|
4111
|
+
console.log(v + " " + colors.dim("File:") + " " + issue.file.slice(0, w - 12) + " ".repeat(Math.max(0, w - issue.file.length - 10)) + v);
|
|
4112
|
+
console.log(v + " " + colors.dim("Line:") + " " + (issue.line || "Unknown") + " " + colors.dim("Scout:") + " " + issue.agent + " ".repeat(Math.max(0, w - 40)) + v);
|
|
4113
|
+
console.log(colors.border(box.leftT + this.line(w - 2) + box.rightT));
|
|
4114
|
+
console.log(v + " " + colors.header("Issue") + " ".repeat(w - 10) + v);
|
|
4115
|
+
const issueLines = this.wrapText(issue.issue, w - 8);
|
|
3743
4116
|
for (const line of issueLines.slice(0, 4)) {
|
|
3744
|
-
console.log(
|
|
4117
|
+
console.log(v + " " + severityColor(line) + " ".repeat(Math.max(0, w - line.length - 6)) + v);
|
|
3745
4118
|
}
|
|
3746
|
-
console.log(
|
|
3747
|
-
console.log("
|
|
3748
|
-
const fixLines = this.wrapText(issue.fix,
|
|
4119
|
+
console.log(colors.border(box.leftT + this.line(w - 2) + box.rightT));
|
|
4120
|
+
console.log(v + " " + colors.success("Fix") + " ".repeat(w - 8) + v);
|
|
4121
|
+
const fixLines = this.wrapText(issue.fix, w - 8);
|
|
3749
4122
|
for (const line of fixLines.slice(0, 4)) {
|
|
3750
|
-
console.log(
|
|
4123
|
+
console.log(v + " " + colors.success(line) + " ".repeat(Math.max(0, w - line.length - 6)) + v);
|
|
3751
4124
|
}
|
|
3752
|
-
console.log(
|
|
3753
|
-
console.log(" Press any key to return...");
|
|
4125
|
+
console.log(colors.border(box.bottomLeft + this.line(w - 2) + box.bottomRight));
|
|
4126
|
+
console.log(" " + colors.dim("Press any key to return..."));
|
|
3754
4127
|
const resume = () => {
|
|
3755
4128
|
this.isActive = true;
|
|
3756
4129
|
this.render();
|
|
@@ -4504,13 +4877,13 @@ ${overdueAssignments.length} issues are overdue and require attention.`
|
|
|
4504
4877
|
* Get color for assignment priority
|
|
4505
4878
|
*/
|
|
4506
4879
|
getAssignmentColor(priority) {
|
|
4507
|
-
const
|
|
4880
|
+
const colors2 = {
|
|
4508
4881
|
urgent: "danger",
|
|
4509
4882
|
high: "warning",
|
|
4510
4883
|
medium: "good",
|
|
4511
4884
|
low: "#36a64f"
|
|
4512
4885
|
};
|
|
4513
|
-
return
|
|
4886
|
+
return colors2[priority] ?? "good";
|
|
4514
4887
|
}
|
|
4515
4888
|
/**
|
|
4516
4889
|
* Test Slack connection
|
|
@@ -5029,14 +5402,16 @@ var TrieScanTool = class {
|
|
|
5029
5402
|
const maxConcurrency = args?.maxConcurrency ?? agentConfig?.maxConcurrency;
|
|
5030
5403
|
const timeoutMs = args?.timeoutMs ?? agentConfig?.timeout ?? 12e4;
|
|
5031
5404
|
const useWorkerThreads = args?.workers ?? true;
|
|
5032
|
-
const streamingManager = streamingEnabled ? new StreamingManager() : void 0;
|
|
5033
|
-
const dashboard = interactiveEnabled ? new InteractiveDashboard() : void 0;
|
|
5405
|
+
const streamingManager = streamingEnabled ? args?.streamingManager instanceof StreamingManager ? args.streamingManager : new StreamingManager() : void 0;
|
|
5406
|
+
const dashboard = interactiveEnabled ? args?.dashboard instanceof InteractiveDashboard ? args.dashboard : new InteractiveDashboard() : void 0;
|
|
5034
5407
|
if (interactiveEnabled) {
|
|
5035
5408
|
setInteractiveMode(true);
|
|
5036
5409
|
}
|
|
5037
5410
|
if (dashboard && streamingManager) {
|
|
5038
|
-
|
|
5039
|
-
|
|
5411
|
+
if (!(args?.dashboard instanceof InteractiveDashboard)) {
|
|
5412
|
+
streamingManager.subscribe((update) => dashboard.handleStreamUpdate(update));
|
|
5413
|
+
await dashboard.start();
|
|
5414
|
+
}
|
|
5040
5415
|
} else if (streamingManager) {
|
|
5041
5416
|
streamingManager.subscribe((update) => {
|
|
5042
5417
|
const line = formatConsoleUpdate(update);
|
|
@@ -5771,6 +6146,8 @@ ${issue.fix}
|
|
|
5771
6146
|
|
|
5772
6147
|
export {
|
|
5773
6148
|
loadConfig,
|
|
6149
|
+
StreamingManager,
|
|
6150
|
+
InteractiveDashboard,
|
|
5774
6151
|
TrieScanTool
|
|
5775
6152
|
};
|
|
5776
|
-
//# sourceMappingURL=chunk-
|
|
6153
|
+
//# sourceMappingURL=chunk-3XZO27U7.js.map
|