@noobdemon/noob-cli 1.0.3 → 1.0.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noobdemon/noob-cli",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
package/src/i18n.js CHANGED
@@ -55,7 +55,8 @@ export const t = {
55
55
  cmdLogin: "/login <key> đăng nhập bằng API key",
56
56
  cmdLogout: "/logout đăng xuất",
57
57
  cmdUsage: "/usage xem hạn mức key còn lại",
58
- cmdStatus: "/status xem mô hình + thư mục hiện tại",
58
+ cmdStatus: "/status xem mô hình, version, trạng thái yolo, thư mục",
59
+ cmdVersion: "/version /v xem version hiện tại + trạng thái yolo",
59
60
  cmdExit: "/exit /quit thoát",
60
61
  tip1: "• Mô tả việc cần làm; noob sẽ đọc/sửa file & chạy lệnh giúp bạn.",
61
62
  tip2: "• Thao tác nguy hiểm sẽ hỏi phép, trừ khi bật yolo (Shift+Tab).",
package/src/repl.js CHANGED
@@ -88,6 +88,20 @@ export async function startRepl(opts = {}) {
88
88
  rl.prompt(true);
89
89
  });
90
90
 
91
+ // Đừng để một lỗi bất ngờ làm "tự động tắt" CLI. Nguyên nhân hay gặp:
92
+ // tiến trình cập nhật nền (spawn npm) phát sự kiện 'error' không ai bắt,
93
+ // hoặc lỗi async trong một lượt → Node thoát ngay. Ở đây bắt lại, in ra,
94
+ // rồi vẽ lại prompt để phiên làm việc vẫn sống.
95
+ process.on("uncaughtException", (err) => {
96
+ if (abort) { abort.abort(); abort = null; }
97
+ console.log(c.err("\n ✗ lỗi: " + (err?.message || err)));
98
+ if (!closed) rl.prompt(true);
99
+ });
100
+ process.on("unhandledRejection", (err) => {
101
+ console.log(c.err("\n ✗ lỗi nền: " + (err?.message || err)));
102
+ if (!closed) rl.prompt(true);
103
+ });
104
+
91
105
  banner();
92
106
  printStatus(state);
93
107
  if (!config.apiKey) console.log("\n" + c.tool(" " + t.notLoggedIn) + "\n");
@@ -112,18 +126,26 @@ export async function startRepl(opts = {}) {
112
126
 
113
127
  // Main loop — runs until /exit, double Ctrl+C, or EOF. Never exits after a task.
114
128
  while (true) {
115
- const raw = await ask(c.user("\n" + t.promptYou) + c.dim("› "));
129
+ const raw = await ask(c.user("\n" + t.promptYou) + (state.yolo ? c.err("⚡ ") : "") + c.dim("› "));
116
130
  if (raw == null) break; // stdin fully closed and drained
117
131
  const input = raw.trim();
118
132
  if (!input) continue;
119
- if (input.startsWith("/")) {
120
- const done = await command(input);
121
- if (done) break;
122
- continue;
133
+ // Bọc cả lượt: một lỗi trong xử lý lệnh/agent không được phép thoát ra
134
+ // ngoài vòng lặp (sẽ rơi vào .catch ở bin/noob.js → process.exit(1) =
135
+ // "tự động tắt"). Bắt ở đây, in lỗi, rồi tiếp tục vòng lặp.
136
+ try {
137
+ if (input.startsWith("/")) {
138
+ const done = await command(input);
139
+ if (done) break;
140
+ continue;
141
+ }
142
+ await handle(input);
143
+ } catch (err) {
144
+ printError(err);
123
145
  }
124
- await handle(input);
125
146
  }
126
147
  rl.close();
148
+ process.exit(0);
127
149
 
128
150
  // ── turn handler ─────────────────────────────────────────────────────────
129
151
  async function handle(text) {
@@ -277,6 +299,10 @@ export async function startRepl(opts = {}) {
277
299
  case "status":
278
300
  printStatus(state);
279
301
  break;
302
+ case "version":
303
+ case "v":
304
+ console.log(c.dim(" noob ") + c.accent("v" + CURRENT) + (state.yolo ? c.err(" ⚡ yolo: BẬT") : c.dim(" yolo: tắt")));
305
+ break;
280
306
  case "exit":
281
307
  case "quit":
282
308
  case "q":
@@ -337,7 +363,10 @@ export async function startRepl(opts = {}) {
337
363
  const mode =
338
364
  s.mode === "merge" ? c.tool("Merge AI") : s.mode === "search" ? c.accent("Tìm web") : modelBadge(s.model);
339
365
  const key = config.apiKey ? c.ok(" 🔑") : c.err(" 🔒");
340
- console.log(" " + mode + key + (s.yolo ? c.err(" yolo") : "") + c.dim(" thư mục: " + shortCwd()));
366
+ const yolo = s.yolo ? c.err(" yolo: BẬT") : c.dim(" yolo: tắt");
367
+ console.log(
368
+ " " + mode + key + yolo + c.dim(" v" + CURRENT) + c.dim(" thư mục: " + shortCwd()),
369
+ );
341
370
  }
342
371
  }
343
372
 
@@ -399,6 +428,7 @@ function printHelp() {
399
428
  " " + t.cmdUpdate,
400
429
  " " + t.cmdClear,
401
430
  " " + t.cmdStatus,
431
+ " " + t.cmdVersion,
402
432
  " " + t.cmdExit,
403
433
  "",
404
434
  chalk.bold(t.helpTips),
package/src/update.js CHANGED
@@ -61,6 +61,11 @@ export function runUpdate({ background = false } = {}) {
61
61
  }
62
62
  if (background) {
63
63
  const child = spawn(cmd, args, { detached: true, stdio: "ignore", env, shell: isWin });
64
+ // QUAN TRỌNG: nếu spawn lỗi (vd npm không có trong PATH, hoặc shell trục
65
+ // trặc trên Windows) mà không có listener 'error', Node sẽ ném
66
+ // uncaughtException → tiến trình tự tắt ngay sau khi khởi động. Nuốt lỗi ở
67
+ // đây vì cập nhật nền chỉ là "best effort".
68
+ child.on("error", () => {});
64
69
  child.unref();
65
70
  return Promise.resolve(true);
66
71
  }