@quangnv13/nonstop 1.0.4 → 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/dist/ui.js +74 -97
- package/package.json +1 -1
package/dist/ui.js
CHANGED
|
@@ -67,12 +67,22 @@ function infoRow(label, value, valueColor = (s) => s) {
|
|
|
67
67
|
function separator() {
|
|
68
68
|
return chalk_1.default.gray(' ' + '─'.repeat(44));
|
|
69
69
|
}
|
|
70
|
-
async function
|
|
71
|
-
|
|
70
|
+
async function askQuestion(query) {
|
|
71
|
+
const rl = (0, promises_1.createInterface)({ input: node_process_1.stdin, output: node_process_1.stdout });
|
|
72
|
+
try {
|
|
73
|
+
return await rl.question(query);
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
rl.close();
|
|
77
|
+
process.stdin.resume();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function pause() {
|
|
81
|
+
await askQuestion(`\n${chalk_1.default.gray('Nhấn Enter để tiếp tục...')}`);
|
|
72
82
|
}
|
|
73
|
-
async function askWithDefault(
|
|
83
|
+
async function askWithDefault(label, currentValue) {
|
|
74
84
|
const prompt = `${chalk_1.default.bold(label)}${currentValue ? chalk_1.default.gray(` [${currentValue}]`) : ''}: `;
|
|
75
|
-
const answer = await
|
|
85
|
+
const answer = await askQuestion(prompt);
|
|
76
86
|
return answer.trim() || currentValue;
|
|
77
87
|
}
|
|
78
88
|
async function runSelectionMenu(headerRenderer, options, initialIndex = 0) {
|
|
@@ -172,15 +182,9 @@ async function launchControlCenter() {
|
|
|
172
182
|
let config = (0, config_js_1.loadConfigFromDisk)();
|
|
173
183
|
const isTTY = process.stdin.isTTY;
|
|
174
184
|
const wasRaw = process.stdin.isRaw;
|
|
175
|
-
let rl;
|
|
176
185
|
try {
|
|
177
186
|
if ((0, config_js_1.getMissingConfigFields)(config).length > 0) {
|
|
178
|
-
|
|
179
|
-
config = result.config;
|
|
180
|
-
rl = result.rl;
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
rl = (0, promises_1.createInterface)({ input: node_process_1.stdin, output: node_process_1.stdout });
|
|
187
|
+
config = await runSetupWizard(config);
|
|
184
188
|
}
|
|
185
189
|
let lastSelection = 0;
|
|
186
190
|
while (true) {
|
|
@@ -200,47 +204,39 @@ async function launchControlCenter() {
|
|
|
200
204
|
{ label: t('menu.logs'), value: 'logs' },
|
|
201
205
|
{ label: t('menu.exit'), value: 'exit' }
|
|
202
206
|
];
|
|
203
|
-
rl.pause();
|
|
204
207
|
const choice = await runSelectionMenu(() => renderDashboardHeader(config, (0, runtime_manager_js_1.getRuntimeStatus)().snapshot), options, lastSelection);
|
|
205
|
-
rl.resume();
|
|
206
208
|
lastSelection = options.findIndex(opt => opt.value === choice);
|
|
207
209
|
if (lastSelection < 0)
|
|
208
210
|
lastSelection = 0;
|
|
209
211
|
if (choice === 'exit')
|
|
210
212
|
break;
|
|
211
213
|
if (choice === 'toggle') {
|
|
212
|
-
await handleToggleRuntime(config
|
|
214
|
+
await handleToggleRuntime(config);
|
|
213
215
|
continue;
|
|
214
216
|
}
|
|
215
217
|
if (choice === 'settings') {
|
|
216
|
-
config = await editConfig(config
|
|
218
|
+
config = await editConfig(config);
|
|
217
219
|
continue;
|
|
218
220
|
}
|
|
219
221
|
if (choice === 'workspaces') {
|
|
220
|
-
await manageWorkspaces(
|
|
222
|
+
await manageWorkspaces(config.language);
|
|
221
223
|
continue;
|
|
222
224
|
}
|
|
223
225
|
if (choice === 'startup') {
|
|
224
|
-
config = await configureStartup(config
|
|
226
|
+
config = await configureStartup(config);
|
|
225
227
|
continue;
|
|
226
228
|
}
|
|
227
229
|
if (choice === 'language') {
|
|
228
|
-
config = await switchLanguage(config
|
|
230
|
+
config = await switchLanguage(config);
|
|
229
231
|
continue;
|
|
230
232
|
}
|
|
231
233
|
if (choice === 'logs') {
|
|
232
|
-
await showRecentLogs(
|
|
234
|
+
await showRecentLogs();
|
|
233
235
|
continue;
|
|
234
236
|
}
|
|
235
237
|
}
|
|
236
238
|
}
|
|
237
239
|
finally {
|
|
238
|
-
if (rl) {
|
|
239
|
-
try {
|
|
240
|
-
rl.close();
|
|
241
|
-
}
|
|
242
|
-
catch { /* ignore */ }
|
|
243
|
-
}
|
|
244
240
|
process.stdout.write('\u001b[?25h');
|
|
245
241
|
if (isTTY) {
|
|
246
242
|
try {
|
|
@@ -261,49 +257,37 @@ async function runSetupWizard(currentConfig) {
|
|
|
261
257
|
{ label: 'English (en)', value: 'en' }
|
|
262
258
|
], currentConfig.language === 'en' ? 1 : 0);
|
|
263
259
|
const t = (0, i18n_js_1.createTranslator)(language);
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
const clientName = await askWithDefault(rl, t('wizard.clientName'), currentConfig.clientName);
|
|
272
|
-
rl.pause();
|
|
273
|
-
const startupMode = await runSelectionMenu(() => {
|
|
274
|
-
console.log(titleBox(t('wizard.title')));
|
|
275
|
-
console.log(chalk_1.default.gray(` ${t('wizard.startupMode')}:`));
|
|
276
|
-
}, [
|
|
277
|
-
{ label: `Tắt (disabled)`, value: 'disabled' },
|
|
278
|
-
{ label: `Chạy nền (background)`, value: 'background' },
|
|
279
|
-
{ label: `Mở giao diện (open-ui)`, value: 'open-ui' }
|
|
280
|
-
], 0);
|
|
281
|
-
rl.resume();
|
|
282
|
-
const nextConfig = {
|
|
283
|
-
...currentConfig,
|
|
284
|
-
language,
|
|
285
|
-
telegramBotToken,
|
|
286
|
-
adminUsername,
|
|
287
|
-
telegramUsername: adminUsername,
|
|
288
|
-
clientName,
|
|
289
|
-
startupMode
|
|
290
|
-
};
|
|
291
|
-
(0, config_js_1.saveConfigToDisk)(nextConfig);
|
|
292
|
-
clearScreen();
|
|
260
|
+
clearScreen();
|
|
261
|
+
console.log(titleBox(t('wizard.title')));
|
|
262
|
+
console.log('');
|
|
263
|
+
const telegramBotToken = await askWithDefault(t('wizard.token'), currentConfig.telegramBotToken);
|
|
264
|
+
const adminUsername = await askWithDefault(t('wizard.admin'), currentConfig.adminUsername);
|
|
265
|
+
const clientName = await askWithDefault(t('wizard.clientName'), currentConfig.clientName);
|
|
266
|
+
const startupMode = await runSelectionMenu(() => {
|
|
293
267
|
console.log(titleBox(t('wizard.title')));
|
|
294
|
-
console.log(
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
268
|
+
console.log(chalk_1.default.gray(` ${t('wizard.startupMode')}:`));
|
|
269
|
+
}, [
|
|
270
|
+
{ label: `Tắt (disabled)`, value: 'disabled' },
|
|
271
|
+
{ label: `Chạy nền (background)`, value: 'background' },
|
|
272
|
+
{ label: `Mở giao diện (open-ui)`, value: 'open-ui' }
|
|
273
|
+
], 0);
|
|
274
|
+
const nextConfig = {
|
|
275
|
+
...currentConfig,
|
|
276
|
+
language,
|
|
277
|
+
telegramBotToken,
|
|
278
|
+
adminUsername,
|
|
279
|
+
telegramUsername: adminUsername,
|
|
280
|
+
clientName,
|
|
281
|
+
startupMode
|
|
282
|
+
};
|
|
283
|
+
(0, config_js_1.saveConfigToDisk)(nextConfig);
|
|
284
|
+
clearScreen();
|
|
285
|
+
console.log(titleBox(t('wizard.title')));
|
|
286
|
+
console.log(`\n${chalk_1.default.green(t('wizard.complete'))}`);
|
|
287
|
+
await pause();
|
|
288
|
+
return nextConfig;
|
|
305
289
|
}
|
|
306
|
-
async function handleToggleRuntime(config
|
|
290
|
+
async function handleToggleRuntime(config) {
|
|
307
291
|
const status = (0, runtime_manager_js_1.getRuntimeStatus)();
|
|
308
292
|
const targetState = !status.running;
|
|
309
293
|
clearScreen();
|
|
@@ -326,31 +310,30 @@ async function handleToggleRuntime(config, rl) {
|
|
|
326
310
|
}
|
|
327
311
|
catch (error) {
|
|
328
312
|
console.log(`\n${chalk_1.default.red(error instanceof Error ? error.message : String(error))}`);
|
|
329
|
-
await pause(
|
|
313
|
+
await pause();
|
|
330
314
|
return;
|
|
331
315
|
}
|
|
332
|
-
// Không pause — quay lại menu ngay để trạng thái cập nhật tức thì
|
|
333
316
|
}
|
|
334
|
-
async function editConfig(config
|
|
317
|
+
async function editConfig(config) {
|
|
335
318
|
clearScreen();
|
|
336
319
|
console.log(titleBox('Sửa cấu hình'));
|
|
337
320
|
console.log('');
|
|
338
321
|
const nextConfig = {
|
|
339
322
|
...config,
|
|
340
|
-
telegramBotToken: await askWithDefault(
|
|
341
|
-
adminUsername: await askWithDefault(
|
|
342
|
-
clientName: await askWithDefault(
|
|
343
|
-
telegramUsername: await askWithDefault(
|
|
344
|
-
codexCmd: await askWithDefault(
|
|
345
|
-
antigravityCmd: await askWithDefault(
|
|
323
|
+
telegramBotToken: await askWithDefault('TELEGRAM_BOT_TOKEN', config.telegramBotToken),
|
|
324
|
+
adminUsername: await askWithDefault('ADMIN_USERNAME', config.adminUsername),
|
|
325
|
+
clientName: await askWithDefault('CLIENT_NAME', config.clientName),
|
|
326
|
+
telegramUsername: await askWithDefault('TELEGRAM_USERNAME', config.telegramUsername),
|
|
327
|
+
codexCmd: await askWithDefault('CODEX_CMD', config.codexCmd),
|
|
328
|
+
antigravityCmd: await askWithDefault('ANTIGRAVITY_CMD', config.antigravityCmd)
|
|
346
329
|
};
|
|
347
330
|
(0, config_js_1.saveConfigToDisk)(nextConfig);
|
|
348
331
|
console.log(`\n${chalk_1.default.green('✓ Đã lưu cấu hình.')}`);
|
|
349
332
|
console.log(chalk_1.default.gray('Khởi động lại runtime nền nếu đang chạy để áp dụng thay đổi.'));
|
|
350
|
-
await pause(
|
|
333
|
+
await pause();
|
|
351
334
|
return nextConfig;
|
|
352
335
|
}
|
|
353
|
-
async function manageWorkspaces(
|
|
336
|
+
async function manageWorkspaces(language) {
|
|
354
337
|
const isVi = language === 'vi';
|
|
355
338
|
while (true) {
|
|
356
339
|
const workspaces = (0, store_js_1.loadWorkspaces)();
|
|
@@ -362,23 +345,21 @@ async function manageWorkspaces(rl, language) {
|
|
|
362
345
|
})),
|
|
363
346
|
{ label: isVi ? '← Quay lại menu chính' : '← Back', value: { type: 'back' } }
|
|
364
347
|
];
|
|
365
|
-
rl.pause();
|
|
366
348
|
const selection = await runSelectionMenu(() => {
|
|
367
349
|
console.log(titleBox(isVi ? 'Quản lý Workspace' : 'Manage Workspaces'));
|
|
368
350
|
console.log(chalk_1.default.gray(` ${isVi ? 'Chọn workspace hoặc thêm mới:' : 'Select workspace or add new:'}`));
|
|
369
351
|
}, options);
|
|
370
|
-
rl.resume();
|
|
371
352
|
if (selection.type === 'back')
|
|
372
353
|
return;
|
|
373
354
|
if (selection.type === 'add') {
|
|
374
355
|
clearScreen();
|
|
375
356
|
console.log(titleBox(isVi ? 'Thêm workspace mới' : 'Add workspace'));
|
|
376
357
|
console.log('');
|
|
377
|
-
const name = (await
|
|
378
|
-
const rawPath = (await
|
|
358
|
+
const name = (await askQuestion(chalk_1.default.bold(isVi ? 'Tên workspace: ' : 'Workspace name: '))).trim();
|
|
359
|
+
const rawPath = (await askQuestion(chalk_1.default.bold(isVi ? 'Đường dẫn: ' : 'Path: '))).trim();
|
|
379
360
|
if (!rawPath) {
|
|
380
361
|
console.log(chalk_1.default.red(isVi ? ' Đường dẫn không được để trống.' : ' Path cannot be empty.'));
|
|
381
|
-
await pause(
|
|
362
|
+
await pause();
|
|
382
363
|
continue;
|
|
383
364
|
}
|
|
384
365
|
const resolvedPath = path.resolve(rawPath);
|
|
@@ -388,7 +369,7 @@ async function manageWorkspaces(rl, language) {
|
|
|
388
369
|
workspaces.push({ id: (0, store_js_1.createWorkspaceId)(), name: name || 'Workspace', path: resolvedPath });
|
|
389
370
|
(0, store_js_1.saveWorkspaces)(workspaces);
|
|
390
371
|
console.log(chalk_1.default.green(`\n ✓ ${isVi ? 'Đã thêm workspace.' : 'Workspace added.'}`));
|
|
391
|
-
await pause(
|
|
372
|
+
await pause();
|
|
392
373
|
continue;
|
|
393
374
|
}
|
|
394
375
|
if (selection.type === 'workspace' && typeof selection.index === 'number') {
|
|
@@ -410,15 +391,15 @@ async function manageWorkspaces(rl, language) {
|
|
|
410
391
|
(0, store_js_1.saveWorkspaces)(workspaces);
|
|
411
392
|
clearScreen();
|
|
412
393
|
console.log(chalk_1.default.green(`\n ✓ ${isVi ? 'Đã xóa workspace.' : 'Workspace deleted.'}`));
|
|
413
|
-
await pause(
|
|
394
|
+
await pause();
|
|
414
395
|
continue;
|
|
415
396
|
}
|
|
416
397
|
if (action === 'edit') {
|
|
417
398
|
clearScreen();
|
|
418
399
|
console.log(titleBox(isVi ? 'Sửa workspace' : 'Edit workspace'));
|
|
419
400
|
console.log('');
|
|
420
|
-
const newName = await askWithDefault(
|
|
421
|
-
const newPath = await askWithDefault(
|
|
401
|
+
const newName = await askWithDefault(isVi ? 'Tên mới' : 'New name', ws.name);
|
|
402
|
+
const newPath = await askWithDefault(isVi ? 'Đường dẫn mới' : 'New path', ws.path);
|
|
422
403
|
const resolvedPath = path.resolve(newPath.trim());
|
|
423
404
|
if (!fs.existsSync(resolvedPath)) {
|
|
424
405
|
console.log(chalk_1.default.yellow(` ⚠ ${isVi ? 'Đường dẫn không tồn tại.' : 'Path does not exist.'}`));
|
|
@@ -426,15 +407,14 @@ async function manageWorkspaces(rl, language) {
|
|
|
426
407
|
workspaces[idx] = { ...ws, name: newName.trim() || ws.name, path: resolvedPath };
|
|
427
408
|
(0, store_js_1.saveWorkspaces)(workspaces);
|
|
428
409
|
console.log(chalk_1.default.green(`\n ✓ ${isVi ? 'Đã cập nhật workspace.' : 'Workspace updated.'}`));
|
|
429
|
-
await pause(
|
|
410
|
+
await pause();
|
|
430
411
|
continue;
|
|
431
412
|
}
|
|
432
413
|
}
|
|
433
414
|
}
|
|
434
415
|
}
|
|
435
|
-
async function configureStartup(config
|
|
416
|
+
async function configureStartup(config) {
|
|
436
417
|
const isVi = config.language === 'vi';
|
|
437
|
-
rl.pause();
|
|
438
418
|
const nextMode = await runSelectionMenu(() => {
|
|
439
419
|
console.log(titleBox(isVi ? 'Cấu hình khởi động' : 'Configure startup'));
|
|
440
420
|
console.log(chalk_1.default.gray(` ${isVi ? 'Chế độ hiện tại:' : 'Current mode:'} ${config.startupMode}`));
|
|
@@ -443,7 +423,6 @@ async function configureStartup(config, rl) {
|
|
|
443
423
|
{ label: isVi ? 'Chạy nền (background)' : 'Background', value: 'background' },
|
|
444
424
|
{ label: isVi ? 'Mở giao diện (open-ui)' : 'Open UI', value: 'open-ui' }
|
|
445
425
|
], ['disabled', 'background', 'open-ui'].indexOf(config.startupMode));
|
|
446
|
-
rl.resume();
|
|
447
426
|
const entryScriptPath = path.join(process.cwd(), 'dist', 'index.js');
|
|
448
427
|
const result = (0, startup_js_1.applyStartupMode)(nextMode, entryScriptPath, process.cwd());
|
|
449
428
|
const nextConfig = { ...config, startupMode: nextMode };
|
|
@@ -451,11 +430,10 @@ async function configureStartup(config, rl) {
|
|
|
451
430
|
clearScreen();
|
|
452
431
|
console.log(titleBox(isVi ? 'Cấu hình khởi động' : 'Configure startup'));
|
|
453
432
|
console.log(`\n${chalk_1.default.green(result)}`);
|
|
454
|
-
await pause(
|
|
433
|
+
await pause();
|
|
455
434
|
return nextConfig;
|
|
456
435
|
}
|
|
457
|
-
async function switchLanguage(config
|
|
458
|
-
rl.pause();
|
|
436
|
+
async function switchLanguage(config) {
|
|
459
437
|
const language = await runSelectionMenu(() => {
|
|
460
438
|
console.log(titleBox('Đổi ngôn ngữ / Switch language'));
|
|
461
439
|
console.log(chalk_1.default.gray(` Hiện tại: ${config.language}`));
|
|
@@ -463,21 +441,20 @@ async function switchLanguage(config, rl) {
|
|
|
463
441
|
{ label: 'Tiếng Việt (vi)', value: 'vi' },
|
|
464
442
|
{ label: 'English (en)', value: 'en' }
|
|
465
443
|
], config.language === 'en' ? 1 : 0);
|
|
466
|
-
rl.resume();
|
|
467
444
|
const nextConfig = { ...config, language };
|
|
468
445
|
(0, config_js_1.saveConfigToDisk)(nextConfig);
|
|
469
446
|
return nextConfig;
|
|
470
447
|
}
|
|
471
|
-
async function showRecentLogs(
|
|
448
|
+
async function showRecentLogs() {
|
|
472
449
|
clearScreen();
|
|
473
450
|
console.log(titleBox('Nhật ký gần đây'));
|
|
474
451
|
const logPath = path.join(process.cwd(), 'data', 'nonstop.log');
|
|
475
452
|
if (!fs.existsSync(logPath)) {
|
|
476
453
|
console.log(chalk_1.default.gray('\n Chưa có nhật ký.'));
|
|
477
|
-
await pause(
|
|
454
|
+
await pause();
|
|
478
455
|
return;
|
|
479
456
|
}
|
|
480
457
|
const lines = fs.readFileSync(logPath, 'utf8').split(/\r?\n/).filter(Boolean).slice(-25);
|
|
481
458
|
console.log('\n' + lines.map(l => chalk_1.default.gray(' ') + l).join('\n'));
|
|
482
|
-
await pause(
|
|
459
|
+
await pause();
|
|
483
460
|
}
|