@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(`[*] Agent started: ${update.data.agent}`);
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(`[+] Agent complete: ${update.data.agent} (${update.data.issueCount} issues)`);
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 "-".repeat(width);
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 "[" + "#".repeat(width) + "]";
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
- return "[" + "#".repeat(filled) + ".".repeat(empty) + "]";
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
- const icons = {
3341
- critical: "[!]",
3342
- serious: "[x]",
3343
- moderate: "[~]",
3344
- low: "[-]"
3345
- };
3346
- return icons[severity] || "[-]";
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
- const icons = {
3353
- running: "*",
3354
- done: "+",
3355
- waiting: "o"
3356
- };
3357
- return icons[status];
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
- let status = "SCANNING (...)";
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
- status = "SCAN COMPLETE [OK]";
3394
- }
3395
- console.log("+" + this.line(width - 2) + "+");
3396
- console.log("| TRIE GUARDIAN" + " ".repeat(width - 35 - status.length) + status + " " + time + " |");
3397
- console.log("+" + this.line(width - 2) + "+");
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("|" + " ".repeat(width - 2) + "|");
3409
- console.log(`| Scanning: ${current.slice(0, 40).padEnd(40)}` + " ".repeat(width - 56) + "|");
3410
- console.log(`| ${progressBar} ${percent}% (${processedFiles}/${totalFiles} files)`.padEnd(width - 1) + "|");
3411
- console.log("|" + " ".repeat(width - 2) + "|");
3412
- console.log("+" + this.line(width - 2) + "+");
3413
- console.log("| AGENTS" + " ".repeat(width - 11) + "|");
3414
- console.log("| " + this.line(width - 6) + " |");
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 status = isActive ? "analyzing" : isDone ? `done (${this.getAgentIssueCount(agent)})` : "waiting";
3424
- const entry = `${icon} ${agent.slice(0, 12).padEnd(12)} ... ${status.padEnd(15)}`;
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`.padEnd(35);
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, 4);
3440
- for (let i = 0; i < maxRows && i < 4; 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(`| ${left} ${right}`.slice(0, width - 1).padEnd(width - 1) + "|");
3444
- }
3445
- console.log("|" + " ".repeat(width - 2) + "|");
3446
- console.log("+" + this.line(width - 2) + "+");
3447
- console.log("| ISSUES FOUND" + " ".repeat(width - 17) + "|");
3448
- console.log("| " + this.line(width - 6) + " |");
3449
- console.log(`| [!] Critical ${issuesBySeverity.critical.toString().padStart(4)} [~] Moderate ${issuesBySeverity.moderate.toString().padStart(5)}`.padEnd(width - 1) + "|");
3450
- console.log(`| [x] Serious ${issuesBySeverity.serious.toString().padStart(4)} [-] Low ${issuesBySeverity.low.toString().padStart(5)}`.padEnd(width - 1) + "|");
3451
- console.log("|" + " ".repeat(width - 2) + "|");
3452
- console.log("+" + this.line(width - 2) + "+");
3453
- console.log("| ACTIVITY LOG" + " ".repeat(width - 17) + "|");
3454
- console.log("| " + this.line(width - 6) + " |");
3455
- const recentActivity = this.state.activityLog.slice(0, 6);
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 line = `${entry.time} ${entry.message}`.slice(0, width - 6);
3458
- console.log(`| ${line.padEnd(width - 4)}|`);
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 < 6; i++) {
3461
- console.log("|" + " ".repeat(width - 2) + "|");
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
- console.log("|" + " ".repeat(width - 2) + "|");
3478
- console.log(`| ${processedFiles} files scanned in ${elapsed}s`.padEnd(width - 1) + "|");
3479
- console.log(`| ${completedAgents.length} agents activated`.padEnd(width - 1) + "|");
3480
- console.log("|" + " ".repeat(width - 2) + "|");
3481
- console.log("+" + this.line(width - 2) + "+");
3482
- console.log("| SUMMARY" + " ".repeat(width - 12) + "|");
3483
- console.log("| " + this.line(width - 6) + " |");
3484
- const criticalLabel = issuesBySeverity.critical > 0 ? "<- FIX NOW" : "";
3485
- console.log(`| [!] ${issuesBySeverity.critical.toString().padStart(4)} Critical issues ${criticalLabel}`.padEnd(width - 1) + "|");
3486
- console.log(`| [x] ${issuesBySeverity.serious.toString().padStart(4)} Serious issues`.padEnd(width - 1) + "|");
3487
- console.log(`| [~] ${issuesBySeverity.moderate.toString().padStart(4)} Moderate issues`.padEnd(width - 1) + "|");
3488
- console.log(`| [-] ${issuesBySeverity.low.toString().padStart(4)} Low issues`.padEnd(width - 1) + "|");
3489
- console.log("|" + " ".repeat(width - 2) + "|");
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("+" + this.line(width - 2) + "+");
3493
- console.log("| TOP CRITICAL ISSUES" + " ".repeat(width - 24) + "|");
3494
- console.log("| " + this.line(width - 6) + " |");
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 line = issue.line ? `:${issue.line}` : "";
3498
- const location = `${filename}${line}`;
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(`| > ${description}`.slice(0, width - 1).padEnd(width - 1) + "|");
3501
- console.log(`| ${location}`.slice(0, width - 1).padEnd(width - 1) + "|");
3502
- console.log("|" + " ".repeat(width - 2) + "|");
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("+" + this.line(width - 2) + "+");
3506
- console.log("| [OK] No issues found - code looks good!".padEnd(width - 1) + "|");
3507
- console.log("|" + " ".repeat(width - 2) + "|");
3508
- }
3509
- console.log("+" + this.line(width - 2) + "+");
3510
- console.log("| ACTIVITY LOG" + " ".repeat(width - 17) + "|");
3511
- console.log("| " + this.line(width - 6) + " |");
3512
- const recentActivity = this.state.activityLog.slice(0, 8);
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 line = `${entry.time} ${entry.message}`.slice(0, width - 6);
3515
- console.log(`| ${line.padEnd(width - 4)}|`);
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 < 4; i++) {
3518
- console.log("|" + " ".repeat(width - 2) + "|");
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
- console.log("| Filter: " + this.getFilterDescription().padEnd(width - 13) + "|");
3528
- console.log("+" + this.line(width - 2) + "+");
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 line = `${severityIcon} ${cursor} ${description.padEnd(38)} ${location.padEnd(20)}`;
3542
- console.log(`| ${line}`.slice(0, width - 1).padEnd(width - 1) + "|");
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("|" + " ".repeat(width - 2) + "|");
3737
+ console.log(v + " ".repeat(width - 2) + v);
3546
3738
  }
3547
3739
  if (filteredIssues[selectedIssue]) {
3548
3740
  const selected = filteredIssues[selectedIssue];
3549
- console.log("+" + this.line(width - 2) + "+");
3550
- console.log("| SELECTED: " + selected.issue.slice(0, width - 15).padEnd(width - 15) + "|");
3551
- console.log("| " + this.line(width - 6) + " |");
3552
- console.log(`| File: ${selected.file}`.slice(0, width - 1).padEnd(width - 1) + "|");
3553
- console.log(`| Line: ${selected.line || "Unknown"} Agent: ${selected.agent}`.padEnd(width - 1) + "|");
3554
- console.log("|" + " ".repeat(width - 2) + "|");
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("| Fix:".padEnd(width - 1) + "|");
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(`| ${line}`.padEnd(width - 1) + "|");
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 { completedAgents, activeAgents } = this.state.progress;
3567
- console.log("| AGENTS STATUS" + " ".repeat(width - 18) + "|");
3568
- console.log("+" + this.line(width - 2) + "+");
3569
- if (activeAgents.length > 0) {
3570
- console.log("| * ACTIVE AGENTS" + " ".repeat(width - 20) + "|");
3571
- for (const agent of activeAgents) {
3572
- console.log(`| - ${agent}`.padEnd(width - 1) + "|");
3573
- }
3574
- console.log("|" + " ".repeat(width - 2) + "|");
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("| + COMPLETED AGENTS" + " ".repeat(width - 23) + "|");
3577
- for (const agent of completedAgents) {
3578
- const agentIssues = this.state.issues.filter((i) => i.agent === agent);
3579
- const criticalCount = agentIssues.filter((i) => i.severity === "critical").length;
3580
- const statusText = criticalCount > 0 ? `${criticalCount} critical` : `${agentIssues.length} issues`;
3581
- console.log(`| - ${agent.padEnd(25)} ${statusText}`.padEnd(width - 1) + "|");
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("| FILES WITH ISSUES" + " ".repeat(width - 22) + "|");
3597
- console.log("+" + this.line(width - 2) + "+");
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
- console.log(`| ${filename.padEnd(35)} ${totalCount} issues${criticalText}`.slice(0, width - 1).padEnd(width - 1) + "|");
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
- console.log("+" + this.line(width - 2) + "+");
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(" [q] Quit [v] Verbose mode [Esc] Cancel scan");
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(" [Tab] Switch view [up/down] Navigate [1-4] Filter [q] Quit");
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(`Agent: ${this.state.filter.agent}`);
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
- this.rl.question("Search filter (leave empty to clear): ", (answer) => {
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
- console.log("+" + this.line(66) + "+");
3710
- console.log("| TRIE GUARDIAN - HELP" + " ".repeat(44) + "|");
3711
- console.log("+" + this.line(66) + "+");
3712
- console.log("| Navigation" + " ".repeat(54) + "|");
3713
- console.log("| Tab Switch view (overview/issues/agents/files)" + " ".repeat(8) + "|");
3714
- console.log("| up/down Navigate issues list" + " ".repeat(29) + "|");
3715
- console.log("| Enter View issue details" + " ".repeat(31) + "|");
3716
- console.log("| Filters" + " ".repeat(57) + "|");
3717
- console.log("| 1-4 Filter by severity (critical->low)" + " ".repeat(16) + "|");
3718
- console.log("| 0 Clear severity filter" + " ".repeat(28) + "|");
3719
- console.log("| f Search filter" + " ".repeat(36) + "|");
3720
- console.log("| c Clear all filters" + " ".repeat(32) + "|");
3721
- console.log("| Other" + " ".repeat(59) + "|");
3722
- console.log("| h or ? Show this help" + " ".repeat(35) + "|");
3723
- console.log("| q Quit" + " ".repeat(45) + "|");
3724
- console.log("+" + this.line(66) + "+");
3725
- console.log(" Press any key to return...");
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
- console.log("+" + this.line(66) + "+");
3736
- console.log("| ISSUE DETAILS" + " ".repeat(51) + "|");
3737
- console.log("+" + this.line(66) + "+");
3738
- console.log(`| File: ${issue.file}`.slice(0, 66).padEnd(66) + "|");
3739
- console.log(`| Line: ${issue.line || "Unknown"} Agent: ${issue.agent}`.slice(0, 66).padEnd(66) + "|");
3740
- console.log("+" + this.line(66) + "+");
3741
- console.log("| Issue" + " ".repeat(59) + "|");
3742
- const issueLines = this.wrapText(issue.issue, 62);
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(`| ${line}`.padEnd(66) + "|");
4117
+ console.log(v + " " + severityColor(line) + " ".repeat(Math.max(0, w - line.length - 6)) + v);
3745
4118
  }
3746
- console.log("+" + this.line(66) + "+");
3747
- console.log("| Fix" + " ".repeat(61) + "|");
3748
- const fixLines = this.wrapText(issue.fix, 62);
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(`| ${line}`.padEnd(66) + "|");
4123
+ console.log(v + " " + colors.success(line) + " ".repeat(Math.max(0, w - line.length - 6)) + v);
3751
4124
  }
3752
- console.log("+" + this.line(66) + "+");
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 colors = {
4880
+ const colors2 = {
4508
4881
  urgent: "danger",
4509
4882
  high: "warning",
4510
4883
  medium: "good",
4511
4884
  low: "#36a64f"
4512
4885
  };
4513
- return colors[priority] ?? "good";
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
- streamingManager.subscribe((update) => dashboard.handleStreamUpdate(update));
5039
- await dashboard.start();
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-3NTILEEL.js.map
6153
+ //# sourceMappingURL=chunk-3XZO27U7.js.map