@noobdemon/noob-cli 1.0.3 → 1.0.5
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 +1 -1
- package/src/i18n.js +2 -1
- package/src/repl.js +47 -8
- package/src/update.js +5 -0
package/package.json
CHANGED
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
|
|
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
|
@@ -20,6 +20,14 @@ export async function startRepl(opts = {}) {
|
|
|
20
20
|
yolo: !!opts.yolo,
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
+
// Prompt = dòng trạng thái sống. Luôn phản ánh yolo + version theo thời gian
|
|
24
|
+
// thực (vẽ lại mỗi lượt và ngay khi Shift+Tab), nên không cần gõ /status.
|
|
25
|
+
const promptStr = (lead = true) => {
|
|
26
|
+
const nl = lead ? "\n" : "";
|
|
27
|
+
const yolo = state.yolo ? c.err("⚡ yolo ") : "";
|
|
28
|
+
return c.user(nl + t.promptYou) + yolo + c.dim("v" + CURRENT + " › ");
|
|
29
|
+
};
|
|
30
|
+
|
|
23
31
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout, prompt: "" });
|
|
24
32
|
let closed = false;
|
|
25
33
|
const queue = []; // lines typed/piped, consumed in order
|
|
@@ -64,7 +72,8 @@ export async function startRepl(opts = {}) {
|
|
|
64
72
|
process.stdin.on("keypress", (_str, key) => {
|
|
65
73
|
if (!key || key.name !== "tab" || !key.shift) return;
|
|
66
74
|
state.yolo = !state.yolo;
|
|
67
|
-
console.log(state.yolo ? c.err("
|
|
75
|
+
console.log(state.yolo ? c.err(" " + t.yoloOn) : c.ok(" " + t.yoloOff));
|
|
76
|
+
rl.setPrompt(promptStr(false)); // cập nhật dòng trạng thái ngay lập tức
|
|
68
77
|
rl.prompt(true);
|
|
69
78
|
});
|
|
70
79
|
}
|
|
@@ -88,6 +97,20 @@ export async function startRepl(opts = {}) {
|
|
|
88
97
|
rl.prompt(true);
|
|
89
98
|
});
|
|
90
99
|
|
|
100
|
+
// Đừng để một lỗi bất ngờ làm "tự động tắt" CLI. Nguyên nhân hay gặp:
|
|
101
|
+
// tiến trình cập nhật nền (spawn npm) phát sự kiện 'error' không ai bắt,
|
|
102
|
+
// hoặc lỗi async trong một lượt → Node thoát ngay. Ở đây bắt lại, in ra,
|
|
103
|
+
// rồi vẽ lại prompt để phiên làm việc vẫn sống.
|
|
104
|
+
process.on("uncaughtException", (err) => {
|
|
105
|
+
if (abort) { abort.abort(); abort = null; }
|
|
106
|
+
console.log(c.err("\n ✗ lỗi: " + (err?.message || err)));
|
|
107
|
+
if (!closed) rl.prompt(true);
|
|
108
|
+
});
|
|
109
|
+
process.on("unhandledRejection", (err) => {
|
|
110
|
+
console.log(c.err("\n ✗ lỗi nền: " + (err?.message || err)));
|
|
111
|
+
if (!closed) rl.prompt(true);
|
|
112
|
+
});
|
|
113
|
+
|
|
91
114
|
banner();
|
|
92
115
|
printStatus(state);
|
|
93
116
|
if (!config.apiKey) console.log("\n" + c.tool(" " + t.notLoggedIn) + "\n");
|
|
@@ -112,18 +135,26 @@ export async function startRepl(opts = {}) {
|
|
|
112
135
|
|
|
113
136
|
// Main loop — runs until /exit, double Ctrl+C, or EOF. Never exits after a task.
|
|
114
137
|
while (true) {
|
|
115
|
-
const raw = await ask(
|
|
138
|
+
const raw = await ask(promptStr());
|
|
116
139
|
if (raw == null) break; // stdin fully closed and drained
|
|
117
140
|
const input = raw.trim();
|
|
118
141
|
if (!input) continue;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
142
|
+
// Bọc cả lượt: một lỗi trong xử lý lệnh/agent không được phép thoát ra
|
|
143
|
+
// ngoài vòng lặp (sẽ rơi vào .catch ở bin/noob.js → process.exit(1) =
|
|
144
|
+
// "tự động tắt"). Bắt ở đây, in lỗi, rồi tiếp tục vòng lặp.
|
|
145
|
+
try {
|
|
146
|
+
if (input.startsWith("/")) {
|
|
147
|
+
const done = await command(input);
|
|
148
|
+
if (done) break;
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
await handle(input);
|
|
152
|
+
} catch (err) {
|
|
153
|
+
printError(err);
|
|
123
154
|
}
|
|
124
|
-
await handle(input);
|
|
125
155
|
}
|
|
126
156
|
rl.close();
|
|
157
|
+
process.exit(0);
|
|
127
158
|
|
|
128
159
|
// ── turn handler ─────────────────────────────────────────────────────────
|
|
129
160
|
async function handle(text) {
|
|
@@ -277,6 +308,10 @@ export async function startRepl(opts = {}) {
|
|
|
277
308
|
case "status":
|
|
278
309
|
printStatus(state);
|
|
279
310
|
break;
|
|
311
|
+
case "version":
|
|
312
|
+
case "v":
|
|
313
|
+
console.log(c.dim(" noob ") + c.accent("v" + CURRENT) + (state.yolo ? c.err(" ⚡ yolo: BẬT") : c.dim(" yolo: tắt")));
|
|
314
|
+
break;
|
|
280
315
|
case "exit":
|
|
281
316
|
case "quit":
|
|
282
317
|
case "q":
|
|
@@ -337,7 +372,10 @@ export async function startRepl(opts = {}) {
|
|
|
337
372
|
const mode =
|
|
338
373
|
s.mode === "merge" ? c.tool("Merge AI") : s.mode === "search" ? c.accent("Tìm web") : modelBadge(s.model);
|
|
339
374
|
const key = config.apiKey ? c.ok(" 🔑") : c.err(" 🔒");
|
|
340
|
-
|
|
375
|
+
const yolo = s.yolo ? c.err(" ⚡ yolo: BẬT") : c.dim(" yolo: tắt");
|
|
376
|
+
console.log(
|
|
377
|
+
" " + mode + key + yolo + c.dim(" v" + CURRENT) + c.dim(" thư mục: " + shortCwd()),
|
|
378
|
+
);
|
|
341
379
|
}
|
|
342
380
|
}
|
|
343
381
|
|
|
@@ -399,6 +437,7 @@ function printHelp() {
|
|
|
399
437
|
" " + t.cmdUpdate,
|
|
400
438
|
" " + t.cmdClear,
|
|
401
439
|
" " + t.cmdStatus,
|
|
440
|
+
" " + t.cmdVersion,
|
|
402
441
|
" " + t.cmdExit,
|
|
403
442
|
"",
|
|
404
443
|
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
|
}
|