fogact 1.2.7 → 1.2.8

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/lib/index.js CHANGED
@@ -17,6 +17,12 @@ const MENU_CHOICES = [
17
17
  { title: "4. 退出", value: "exit" },
18
18
  ];
19
19
 
20
+ const MENU_COLORS = {
21
+ test: "\x1b[34m",
22
+ exit: "\x1b[90m",
23
+ };
24
+ const ANSI_RESET = "\x1b[0m";
25
+
20
26
  const UPDATE_TIMEOUT_MS = 2500;
21
27
 
22
28
  function parseVersion(version) {
@@ -158,7 +164,9 @@ function renderMenu(cursor = 0) {
158
164
  ];
159
165
 
160
166
  MENU_CHOICES.forEach((choice, index) => {
161
- lines.push(`${index === cursor ? "❯" : " "} ${choice.title}`);
167
+ const color = MENU_COLORS[choice.value] || "";
168
+ const title = color ? `${color}${choice.title}${ANSI_RESET}` : choice.title;
169
+ lines.push(`${index === cursor ? "❯" : " "} ${title}`);
162
170
  });
163
171
 
164
172
  lines.push("");
@@ -5,6 +5,29 @@ const net = require("net");
5
5
  const { testNode } = require("./fogact-api");
6
6
 
7
7
  const PROBE_TIMEOUT_MS = 5000;
8
+ const ANSI = {
9
+ reset: "\x1b[0m",
10
+ green: "\x1b[32m",
11
+ yellow: "\x1b[33m",
12
+ red: "\x1b[31m",
13
+ };
14
+
15
+ function shouldColorize(options = {}) {
16
+ if (options.color === true || process.env.FORCE_COLOR) return true;
17
+ if (options.color === false || process.env.NO_COLOR) return false;
18
+ return Boolean(process.stdout.isTTY);
19
+ }
20
+
21
+ function colorize(value, color, enabled) {
22
+ if (!enabled || !color) return String(value);
23
+ return `${ANSI[color]}${value}${ANSI.reset}`;
24
+ }
25
+
26
+ function latencyColor(latency) {
27
+ if (latency < 60) return "green";
28
+ if (latency < 150) return "yellow";
29
+ return "red";
30
+ }
8
31
 
9
32
  function parseNodeUrl(nodeUrl) {
10
33
  const url = new URL(nodeUrl);
@@ -178,21 +201,26 @@ function padCell(value, width) {
178
201
  return `${text}${" ".repeat(Math.max(0, width - displayWidth))}`;
179
202
  }
180
203
 
181
- function formatProbe(entry) {
182
- if (!entry?.ok) return "--";
183
- return `${entry.latency}ms`;
204
+ function formatProbe(entry, colorEnabled) {
205
+ if (!entry?.ok) return colorize("--", "red", colorEnabled);
206
+ const value = `${entry.latency}ms`;
207
+ return colorize(value, latencyColor(entry.latency), colorEnabled);
184
208
  }
185
209
 
186
- function formatNodeLine(result, best) {
187
- const mark = result.available ? "✓" : "✗";
210
+ function formatNodeLine(result, best, colorEnabled) {
211
+ const mark = colorize(result.available ? "✓" : "✗", result.available ? "green" : "red", colorEnabled);
188
212
  const name = padCell(result.name || result.url || "FogAct", 12);
213
+ const ping = `ping:${formatProbe(result.ping, colorEnabled)}`;
214
+ const tcp = `tcp:${formatProbe(result.tcp, colorEnabled)}`;
215
+ const http = `http:${formatProbe(result.http, colorEnabled)}`;
189
216
 
190
217
  if (!result.available) {
191
- return ` ${mark} ${name} ping:${formatProbe(result.ping)} tcp:${formatProbe(result.tcp)} http:${formatProbe(result.http)} 不可达`;
218
+ return ` ${mark} ${name} ${ping} ${tcp} ${http} ${colorize("不可达", "red", colorEnabled)}`;
192
219
  }
193
220
 
194
- const bestMark = best && best === result ? " ★ 最优" : "";
195
- return ` ${mark} ${name} ping:${formatProbe(result.ping)} tcp:${formatProbe(result.tcp)} http:${formatProbe(result.http)} ${result.avgLatency}ms (±${result.latencyStdDev}ms) ${stabilityLabel(result.latencyStdDev)} ${getResultScore(result)}分${bestMark}`;
221
+ const latency = colorize(`${result.avgLatency}ms`, latencyColor(result.avgLatency), colorEnabled);
222
+ const bestMark = best && best === result ? ` ${colorize("★ 最优", "yellow", colorEnabled)}` : "";
223
+ return ` ${mark} ${name} ${ping} ${tcp} ${http} ${latency} (±${result.latencyStdDev}ms) ${stabilityLabel(result.latencyStdDev)} ${getResultScore(result)}分${bestMark}`;
196
224
  }
197
225
 
198
226
  function formatNodeResults(results, options = {}) {
@@ -201,13 +229,14 @@ function formatNodeResults(results, options = {}) {
201
229
  const availableCount = results.filter((result) => result.available).length;
202
230
  const lines = [];
203
231
  const title = options.title || "节点测试结果";
232
+ const colorEnabled = shouldColorize(options);
204
233
 
205
234
  lines.push(` ${title}`);
206
235
  lines.push(" ───────────────────────────────────────────────────");
207
236
  lines.push("");
208
237
 
209
238
  for (const result of sorted) {
210
- lines.push(formatNodeLine(result, best));
239
+ lines.push(formatNodeLine(result, best, colorEnabled));
211
240
  }
212
241
 
213
242
  lines.push("");
@@ -223,4 +252,5 @@ module.exports = {
223
252
  sortNodeResults,
224
253
  probeNode,
225
254
  testTcp,
255
+ shouldColorize,
226
256
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fogact",
3
- "version": "1.2.7",
3
+ "version": "1.2.8",
4
4
  "description": "FogAct activation helper for Claude Code and Codex",
5
5
  "keywords": [
6
6
  "fogact",