dme-agent 7.4.1 → 7.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/ui.mjs CHANGED
@@ -1,93 +1,180 @@
1
1
  /**
2
- * Terminal UI — neominimal, readable, no emoji spam.
2
+ * Terminal UI — colorful, ASCII-heavy, zero deps.
3
3
  */
4
4
 
5
- const isWin = process.platform === "win32";
5
+ export const isWin = process.platform === "win32";
6
+
6
7
  const forceColor =
7
8
  process.env.FORCE_COLOR === "1" ||
8
9
  process.env.DME_COLOR === "1" ||
9
- (process.stdout.isTTY && process.env.NO_COLOR !== "1");
10
-
11
- const c = {
12
- reset: forceColor ? "\x1b[0m" : "",
13
- bold: forceColor ? "\x1b[1m" : "",
14
- dim: forceColor ? "\x1b[2m" : "",
15
- yellow: forceColor ? "\x1b[33m" : "",
16
- cyan: forceColor ? "\x1b[36m" : "",
17
- green: forceColor ? "\x1b[32m" : "",
18
- red: forceColor ? "\x1b[31m" : "",
19
- white: forceColor ? "\x1b[37m" : "",
20
- gray: forceColor ? "\x1b[90m" : "",
21
- bg: forceColor ? "\x1b[40m" : "",
22
- bgYellow: forceColor ? "\x1b[43m" : "",
23
- black: forceColor ? "\x1b[30m" : "",
24
- };
25
-
26
- export const colors = c;
27
-
28
- export function banner(version = "7.4.1") {
29
- const y = c.yellow;
30
- const d = c.dim;
31
- const r = c.reset;
32
- const b = c.bold;
33
- const lines = [
10
+ (Boolean(process.stdout.isTTY) && process.env.NO_COLOR !== "1");
11
+
12
+ const esc = forceColor
13
+ ? {
14
+ reset: "\x1b[0m",
15
+ bold: "\x1b[1m",
16
+ dim: "\x1b[2m",
17
+ italic: "\x1b[3m",
18
+ underline: "\x1b[4m",
19
+ black: "\x1b[30m",
20
+ red: "\x1b[31m",
21
+ green: "\x1b[32m",
22
+ yellow: "\x1b[33m",
23
+ blue: "\x1b[34m",
24
+ magenta: "\x1b[35m",
25
+ cyan: "\x1b[36m",
26
+ white: "\x1b[37m",
27
+ gray: "\x1b[90m",
28
+ brightYellow: "\x1b[93m",
29
+ brightCyan: "\x1b[96m",
30
+ brightGreen: "\x1b[92m",
31
+ brightMagenta: "\x1b[95m",
32
+ brightWhite: "\x1b[97m",
33
+ bgBlack: "\x1b[40m",
34
+ bgYellow: "\x1b[43m",
35
+ bgCyan: "\x1b[46m",
36
+ bgMagenta: "\x1b[45m",
37
+ bgBlue: "\x1b[44m",
38
+ bgGray: "\x1b[100m",
39
+ }
40
+ : Object.fromEntries(
41
+ [
42
+ "reset","bold","dim","italic","underline","black","red","green","yellow",
43
+ "blue","magenta","cyan","white","gray","brightYellow","brightCyan",
44
+ "brightGreen","brightMagenta","brightWhite","bgBlack","bgYellow",
45
+ "bgCyan","bgMagenta","bgBlue","bgGray",
46
+ ].map((k) => [k, ""])
47
+ );
48
+
49
+ export const colors = esc;
50
+ export const c = esc;
51
+
52
+ export function clearScreen() {
53
+ if (process.stdout.isTTY) {
54
+ process.stdout.write("\x1b[2J\x1b[H");
55
+ }
56
+ }
57
+
58
+ export function hideCursor() {
59
+ if (process.stdout.isTTY) process.stdout.write("\x1b[?25l");
60
+ }
61
+
62
+ export function showCursor() {
63
+ if (process.stdout.isTTY) process.stdout.write("\x1b[?25h");
64
+ }
65
+
66
+ /** Big DME ASCII mark */
67
+ export function asciiLogo(version = "7.4.2") {
68
+ const y = esc.brightYellow;
69
+ const m = esc.magenta;
70
+ const cy = esc.brightCyan;
71
+ const d = esc.dim;
72
+ const r = esc.reset;
73
+ const b = esc.bold;
74
+ return [
34
75
  "",
35
- `${y}${b} ╔══════════════════════════════════════════════════╗${r}`,
36
- `${y}${b} ║${r} ${y}${b}║${r}`,
37
- `${y}${b} ║${r} ${b}D M E A G E N T${r} ${d}v${version}${r} ${y}${b}║${r}`,
38
- `${y}${b} ║${r} ${d}Neominimal Identity Engine${r} ${y}${b}║${r}`,
39
- `${y}${b} ║${r} ${y}${b}║${r}`,
40
- `${y}${b} ╚══════════════════════════════════════════════════╝${r}`,
41
- `${d} less, but better — with a face · shadcn first · UX for humans${r}`,
76
+ `${y}${b} ██████╗ ███╗ ███╗███████╗${r}`,
77
+ `${y}${b} ██╔══██╗████╗ ████║██╔════╝${r}`,
78
+ `${y}${b} ██║ ██║██╔████╔██║█████╗ ${r}`,
79
+ `${y}${b} ██║ ██║██║╚██╔╝██║██╔══╝ ${r}`,
80
+ `${y}${b} ██████╔╝██║ ╚═╝ ██║███████╗${r}`,
81
+ `${y}${b} ╚═════╝ ╚═╝ ╚═╝╚══════╝${r}`,
82
+ `${cy} ─────────────────────────────────────${r}`,
83
+ `${m}${b} A G E N T${r} ${d}v${version}${r} ${cy}· Neominimal Identity${r}`,
84
+ `${d} less, but better — with a face${r}`,
85
+ `${d} shadcn first · UX for humans · detect-only install${r}`,
42
86
  "",
43
- ];
44
- return lines.join("\n");
87
+ ].join("\n");
88
+ }
89
+
90
+ export function banner(version = "7.4.2") {
91
+ return asciiLogo(version);
45
92
  }
46
93
 
47
94
  export function step(n, total, msg) {
48
- return `${c.yellow}${c.bold}[${n}/${total}]${c.reset} ${msg}`;
95
+ return `${esc.bgYellow}${esc.black}${esc.bold} ${n}/${total} ${esc.reset} ${esc.brightCyan}${msg}${esc.reset}`;
49
96
  }
50
97
 
51
98
  export function ok(msg) {
52
- return `${c.green} ✓${c.reset} ${msg}`;
99
+ return `${esc.brightGreen}${esc.bold} ✔${esc.reset} ${msg}`;
53
100
  }
54
101
 
55
102
  export function fail(msg) {
56
- return `${c.red} ✗${c.reset} ${msg}`;
103
+ return `${esc.red}${esc.bold} ✖${esc.reset} ${msg}`;
57
104
  }
58
105
 
59
106
  export function skip(msg) {
60
- return `${c.gray} –${c.reset} ${c.dim}${msg}${c.reset}`;
107
+ return `${esc.gray} ·${esc.reset} ${esc.dim}${msg}${esc.reset}`;
61
108
  }
62
109
 
63
110
  export function info(msg) {
64
- return `${c.cyan} →${c.reset} ${msg}`;
111
+ return `${esc.brightCyan} ▸${esc.reset} ${msg}`;
65
112
  }
66
113
 
67
114
  export function warn(msg) {
68
- return `${c.yellow} !${c.reset} ${msg}`;
115
+ return `${esc.brightYellow}${esc.bold} !${esc.reset} ${msg}`;
116
+ }
117
+
118
+ export function detectTag(found) {
119
+ return found
120
+ ? `${esc.bgCyan}${esc.black} ON ${esc.reset}`
121
+ : `${esc.bgGray}${esc.white} OFF ${esc.reset}`;
69
122
  }
70
123
 
71
124
  export function hr() {
72
- return `${c.dim} ────────────────────────────────────────────────${c.reset}`;
125
+ return `${esc.magenta} ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─${esc.reset}`;
73
126
  }
74
127
 
75
- export function box(title, lines = []) {
76
- const width = 52;
77
- const top = `${c.yellow} ┌${"".repeat(width - 2)}┐${c.reset}`;
78
- const mid = `${c.yellow} │${c.reset} ${c.bold}${title.padEnd(width - 4)}${c.reset}${c.yellow}│${c.reset}`;
128
+ export function box(title, lines = [], color = "yellow") {
129
+ const col =
130
+ color === "cyan"
131
+ ? esc.brightCyan
132
+ : color === "magenta"
133
+ ? esc.magenta
134
+ : color === "green"
135
+ ? esc.brightGreen
136
+ : esc.brightYellow;
137
+ const width = 56;
138
+ const top = `${col} ╭${"─".repeat(width - 2)}╮${esc.reset}`;
139
+ const mid = `${col} │${esc.reset} ${esc.bold}${pad(title, width - 4)}${esc.reset}${col}│${esc.reset}`;
79
140
  const body = lines.map(
80
- (l) =>
81
- `${c.yellow} │${c.reset} ${String(l).slice(0, width - 4).padEnd(width - 4)}${c.yellow}│${c.reset}`
141
+ (l) => `${col} │${esc.reset} ${pad(String(l), width - 4)}${col}│${esc.reset}`
82
142
  );
83
- const bot = `${c.yellow} └${"─".repeat(width - 2)}┘${c.reset}`;
143
+ const bot = `${col} ╰${"─".repeat(width - 2)}╯${esc.reset}`;
84
144
  return [top, mid, ...body, bot].join("\n");
85
145
  }
86
146
 
147
+ function pad(s, n) {
148
+ const t = s.length > n ? s.slice(0, n - 1) + "…" : s;
149
+ return t + " ".repeat(Math.max(0, n - t.length));
150
+ }
151
+
87
152
  export function table(rows) {
88
153
  return rows
89
- .map(([k, v]) => ` ${c.dim}${String(k).padEnd(16)}${c.reset}${v}`)
154
+ .map(
155
+ ([k, v]) =>
156
+ ` ${esc.dim}${String(k).padEnd(16)}${esc.reset}${esc.brightWhite}${v}${esc.reset}`
157
+ )
90
158
  .join("\n");
91
159
  }
92
160
 
93
- export { isWin };
161
+ export function progressBar(done, total, width = 24) {
162
+ const ratio = total === 0 ? 1 : done / total;
163
+ const filled = Math.round(ratio * width);
164
+ const bar =
165
+ esc.brightYellow +
166
+ "█".repeat(filled) +
167
+ esc.dim +
168
+ "░".repeat(width - filled) +
169
+ esc.reset;
170
+ return `${bar} ${esc.cyan}${done}/${total}${esc.reset}`;
171
+ }
172
+
173
+ export function keyHint(keys) {
174
+ return keys
175
+ .map(
176
+ ([k, label]) =>
177
+ `${esc.bgGray}${esc.brightWhite} ${k} ${esc.reset}${esc.dim}${label}${esc.reset}`
178
+ )
179
+ .join(" ");
180
+ }