Skip to content

Commit 4daac0a

Browse files
unknownclaude
andcommitted
Replace raw ANSI codes with picocolors for cross-platform color support
- Use picocolors (2.6KB, zero deps) instead of raw escape sequences - Automatically detects color support (TTY, NO_COLOR env, Windows cmd) - Removed unused displayProgress export - Fixed "Next steps" to show correct thinktank apply commands Closes #27 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 9d48ba9 commit 4daac0a

File tree

3 files changed

+35
-46
lines changed

3 files changed

+35
-46
lines changed

package-lock.json

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
"LICENSE"
3232
],
3333
"dependencies": {
34-
"commander": "^14.0.3"
34+
"commander": "^14.0.3",
35+
"picocolors": "^1.1.1"
3536
},
3637
"devDependencies": {
3738
"@biomejs/biome": "^2.4.9",

src/utils/display.ts

Lines changed: 25 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,20 @@
1-
import type { AgentResult, ConvergenceGroup, EnsembleResult, TestResult } from "../types.js";
2-
3-
const COLORS = {
4-
reset: "\x1b[0m",
5-
bold: "\x1b[1m",
6-
dim: "\x1b[2m",
7-
green: "\x1b[32m",
8-
red: "\x1b[31m",
9-
yellow: "\x1b[33m",
10-
blue: "\x1b[34m",
11-
cyan: "\x1b[36m",
12-
};
13-
14-
function c(color: keyof typeof COLORS, text: string): string {
15-
return `${COLORS[color]}${text}${COLORS.reset}`;
16-
}
1+
import pc from "picocolors";
2+
import type { EnsembleResult } from "../types.js";
173

184
export function displayHeader(prompt: string, attempts: number, model: string): void {
195
console.log();
20-
console.log(c("bold", "thinktank") + c("dim", " — ensemble AI coding"));
6+
console.log(pc.bold("thinktank") + pc.dim(" — ensemble AI coding"));
217
console.log();
228
console.log(` Task: ${prompt}`);
239
console.log(` Agents: ${attempts} parallel attempts`);
2410
console.log(` Model: ${model}`);
2511
console.log();
2612
}
2713

28-
export function displayProgress(id: number, status: string): void {
29-
const icon = status === "running" ? "..." : status === "done" ? "done" : "err";
30-
process.stdout.write(`\r Agent ${id}: ${icon} `);
31-
}
32-
3314
export function displayResults(result: EnsembleResult): void {
3415
console.log();
35-
console.log(c("bold", "Results"));
36-
console.log(c("dim", "─".repeat(60)));
16+
console.log(pc.bold("Results"));
17+
console.log(pc.dim("─".repeat(60)));
3718
console.log();
3819

3920
// Agent summary table
@@ -46,21 +27,21 @@ export function displayResults(result: EnsembleResult): void {
4627
padRight("+/-", 12) +
4728
padRight("Time", 8),
4829
);
49-
console.log(" " + c("dim", "─".repeat(54)));
30+
console.log(" " + pc.dim("─".repeat(54)));
5031

5132
for (const agent of result.agents) {
5233
const test = result.tests.find((t) => t.agentId === agent.id);
5334
const statusIcon =
5435
agent.status === "success"
55-
? c("green", "ok")
36+
? pc.green("ok")
5637
: agent.status === "timeout"
57-
? c("yellow", "timeout")
58-
: c("red", "error");
38+
? pc.yellow("timeout")
39+
: pc.red("error");
5940

60-
const testIcon = test ? (test.passed ? c("green", "pass") : c("red", "fail")) : c("dim", "n/a");
41+
const testIcon = test ? (test.passed ? pc.green("pass") : pc.red("fail")) : pc.dim("n/a");
6142

6243
const isRecommended = result.recommended === agent.id;
63-
const prefix = isRecommended ? c("cyan", ">>") : " ";
44+
const prefix = isRecommended ? pc.cyan(">>") : " ";
6445

6546
console.log(
6647
prefix +
@@ -76,23 +57,23 @@ export function displayResults(result: EnsembleResult): void {
7657
// Convergence analysis
7758
if (result.convergence.length > 0) {
7859
console.log();
79-
console.log(c("bold", "Convergence"));
80-
console.log(c("dim", "─".repeat(60)));
60+
console.log(pc.bold("Convergence"));
61+
console.log(pc.dim("─".repeat(60)));
8162
for (const group of result.convergence) {
8263
const pct = Math.round(group.similarity * 100);
8364
const bar = "█".repeat(Math.round(pct / 5)) + "░".repeat(20 - Math.round(pct / 5));
8465
console.log(` Agents [${group.agents.join(", ")}]: ${bar} ${pct}%`);
85-
console.log(` ${c("dim", group.description)}`);
86-
console.log(` ${c("dim", "Files: " + group.filesChanged.join(", "))}`);
66+
console.log(` ${pc.dim(group.description)}`);
67+
console.log(` ${pc.dim("Files: " + group.filesChanged.join(", "))}`);
8768
console.log();
8869
}
8970
}
9071

9172
// Recommendation
9273
if (result.recommended !== null) {
9374
console.log(
94-
c("cyan", ` Recommended: Agent #${result.recommended}`) +
95-
c("dim", " (highest score based on tests + convergence + diff size)"),
75+
pc.cyan(` Recommended: Agent #${result.recommended}`) +
76+
pc.dim(" (highest score based on tests + convergence + diff size)"),
9677
);
9778
console.log();
9879
}
@@ -101,20 +82,20 @@ export function displayResults(result: EnsembleResult): void {
10182
export function displayApplyInstructions(result: EnsembleResult): void {
10283
const completed = result.agents.filter((a) => a.status === "success" && a.diff.length > 0);
10384
if (completed.length === 0) {
104-
console.log(c("red", " No agents produced changes."));
85+
console.log(pc.red(" No agents produced changes."));
10586
return;
10687
}
10788

108-
console.log(c("bold", "Next steps"));
109-
console.log(c("dim", "─".repeat(60)));
89+
console.log(pc.bold("Next steps"));
90+
console.log(pc.dim("─".repeat(60)));
11091
console.log();
111-
console.log(" To inspect a specific agent's changes:");
112-
console.log(c("dim", ` cd <worktree-path> && git diff HEAD`));
92+
console.log(" To apply the recommended result:");
93+
console.log(pc.dim(" thinktank apply"));
11394
console.log();
114-
console.log(" To apply the recommended agent's changes:");
115-
console.log(c("dim", ` cd <repo-root> && git diff --no-index /dev/null <worktree>/...`));
95+
console.log(" To apply a specific agent:");
96+
console.log(pc.dim(" thinktank apply --agent N"));
11697
console.log();
117-
console.log(c("dim", " Worktrees will be cleaned up automatically on next run."));
98+
console.log(pc.dim(" Worktrees will be cleaned up on next run or after apply."));
11899
console.log();
119100
}
120101

0 commit comments

Comments
 (0)