@quangnv13/nonstop 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.
Files changed (2) hide show
  1. package/dist/ui.js +51 -56
  2. 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 pause(rl) {
71
- await rl.question(`\n${chalk_1.default.gray('Nhấn Enter để tiếp tục...')}`);
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(rl, label, currentValue) {
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 rl.question(prompt);
85
+ const answer = await askQuestion(prompt);
76
86
  return answer.trim() || currentValue;
77
87
  }
78
88
  async function runSelectionMenu(headerRenderer, options, initialIndex = 0) {
@@ -172,10 +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
- const rl = (0, promises_1.createInterface)({ input: node_process_1.stdin, output: node_process_1.stdout });
176
185
  try {
177
186
  if ((0, config_js_1.getMissingConfigFields)(config).length > 0) {
178
- config = await runSetupWizard(config, rl);
187
+ config = await runSetupWizard(config);
179
188
  }
180
189
  let lastSelection = 0;
181
190
  while (true) {
@@ -195,42 +204,39 @@ async function launchControlCenter() {
195
204
  { label: t('menu.logs'), value: 'logs' },
196
205
  { label: t('menu.exit'), value: 'exit' }
197
206
  ];
198
- rl.pause();
199
207
  const choice = await runSelectionMenu(() => renderDashboardHeader(config, (0, runtime_manager_js_1.getRuntimeStatus)().snapshot), options, lastSelection);
200
- rl.resume();
201
208
  lastSelection = options.findIndex(opt => opt.value === choice);
202
209
  if (lastSelection < 0)
203
210
  lastSelection = 0;
204
211
  if (choice === 'exit')
205
212
  break;
206
213
  if (choice === 'toggle') {
207
- await handleToggleRuntime(config, rl);
214
+ await handleToggleRuntime(config);
208
215
  continue;
209
216
  }
210
217
  if (choice === 'settings') {
211
- config = await editConfig(config, rl);
218
+ config = await editConfig(config);
212
219
  continue;
213
220
  }
214
221
  if (choice === 'workspaces') {
215
- await manageWorkspaces(rl, config.language);
222
+ await manageWorkspaces(config.language);
216
223
  continue;
217
224
  }
218
225
  if (choice === 'startup') {
219
- config = await configureStartup(config, rl);
226
+ config = await configureStartup(config);
220
227
  continue;
221
228
  }
222
229
  if (choice === 'language') {
223
- config = await switchLanguage(config, rl);
230
+ config = await switchLanguage(config);
224
231
  continue;
225
232
  }
226
233
  if (choice === 'logs') {
227
- await showRecentLogs(rl);
234
+ await showRecentLogs();
228
235
  continue;
229
236
  }
230
237
  }
231
238
  }
232
239
  finally {
233
- rl.close();
234
240
  process.stdout.write('\u001b[?25h');
235
241
  if (isTTY) {
236
242
  try {
@@ -242,8 +248,7 @@ async function launchControlCenter() {
242
248
  console.log(chalk_1.default.gray('Đã thoát nonstop client.'));
243
249
  }
244
250
  }
245
- async function runSetupWizard(currentConfig, rl) {
246
- rl.pause();
251
+ async function runSetupWizard(currentConfig) {
247
252
  const language = await runSelectionMenu(() => {
248
253
  console.log(titleBox('Thiết lập nonstop'));
249
254
  console.log(chalk_1.default.gray(' Chọn ngôn ngữ / Choose language:'));
@@ -251,15 +256,13 @@ async function runSetupWizard(currentConfig, rl) {
251
256
  { label: 'Tiếng Việt (vi)', value: 'vi' },
252
257
  { label: 'English (en)', value: 'en' }
253
258
  ], currentConfig.language === 'en' ? 1 : 0);
254
- rl.resume();
255
259
  const t = (0, i18n_js_1.createTranslator)(language);
256
260
  clearScreen();
257
261
  console.log(titleBox(t('wizard.title')));
258
262
  console.log('');
259
- const telegramBotToken = await askWithDefault(rl, t('wizard.token'), currentConfig.telegramBotToken);
260
- const adminUsername = await askWithDefault(rl, t('wizard.admin'), currentConfig.adminUsername);
261
- const clientName = await askWithDefault(rl, t('wizard.clientName'), currentConfig.clientName);
262
- rl.pause();
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);
263
266
  const startupMode = await runSelectionMenu(() => {
264
267
  console.log(titleBox(t('wizard.title')));
265
268
  console.log(chalk_1.default.gray(` ${t('wizard.startupMode')}:`));
@@ -268,7 +271,6 @@ async function runSetupWizard(currentConfig, rl) {
268
271
  { label: `Chạy nền (background)`, value: 'background' },
269
272
  { label: `Mở giao diện (open-ui)`, value: 'open-ui' }
270
273
  ], 0);
271
- rl.resume();
272
274
  const nextConfig = {
273
275
  ...currentConfig,
274
276
  language,
@@ -282,10 +284,10 @@ async function runSetupWizard(currentConfig, rl) {
282
284
  clearScreen();
283
285
  console.log(titleBox(t('wizard.title')));
284
286
  console.log(`\n${chalk_1.default.green(t('wizard.complete'))}`);
285
- await pause(rl);
287
+ await pause();
286
288
  return nextConfig;
287
289
  }
288
- async function handleToggleRuntime(config, rl) {
290
+ async function handleToggleRuntime(config) {
289
291
  const status = (0, runtime_manager_js_1.getRuntimeStatus)();
290
292
  const targetState = !status.running;
291
293
  clearScreen();
@@ -308,31 +310,30 @@ async function handleToggleRuntime(config, rl) {
308
310
  }
309
311
  catch (error) {
310
312
  console.log(`\n${chalk_1.default.red(error instanceof Error ? error.message : String(error))}`);
311
- await pause(rl);
313
+ await pause();
312
314
  return;
313
315
  }
314
- // Không pause — quay lại menu ngay để trạng thái cập nhật tức thì
315
316
  }
316
- async function editConfig(config, rl) {
317
+ async function editConfig(config) {
317
318
  clearScreen();
318
319
  console.log(titleBox('Sửa cấu hình'));
319
320
  console.log('');
320
321
  const nextConfig = {
321
322
  ...config,
322
- telegramBotToken: await askWithDefault(rl, 'TELEGRAM_BOT_TOKEN', config.telegramBotToken),
323
- adminUsername: await askWithDefault(rl, 'ADMIN_USERNAME', config.adminUsername),
324
- clientName: await askWithDefault(rl, 'CLIENT_NAME', config.clientName),
325
- telegramUsername: await askWithDefault(rl, 'TELEGRAM_USERNAME', config.telegramUsername),
326
- codexCmd: await askWithDefault(rl, 'CODEX_CMD', config.codexCmd),
327
- antigravityCmd: await askWithDefault(rl, 'ANTIGRAVITY_CMD', config.antigravityCmd)
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)
328
329
  };
329
330
  (0, config_js_1.saveConfigToDisk)(nextConfig);
330
331
  console.log(`\n${chalk_1.default.green('✓ Đã lưu cấu hình.')}`);
331
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.'));
332
- await pause(rl);
333
+ await pause();
333
334
  return nextConfig;
334
335
  }
335
- async function manageWorkspaces(rl, language) {
336
+ async function manageWorkspaces(language) {
336
337
  const isVi = language === 'vi';
337
338
  while (true) {
338
339
  const workspaces = (0, store_js_1.loadWorkspaces)();
@@ -344,23 +345,21 @@ async function manageWorkspaces(rl, language) {
344
345
  })),
345
346
  { label: isVi ? '← Quay lại menu chính' : '← Back', value: { type: 'back' } }
346
347
  ];
347
- rl.pause();
348
348
  const selection = await runSelectionMenu(() => {
349
349
  console.log(titleBox(isVi ? 'Quản lý Workspace' : 'Manage Workspaces'));
350
350
  console.log(chalk_1.default.gray(` ${isVi ? 'Chọn workspace hoặc thêm mới:' : 'Select workspace or add new:'}`));
351
351
  }, options);
352
- rl.resume();
353
352
  if (selection.type === 'back')
354
353
  return;
355
354
  if (selection.type === 'add') {
356
355
  clearScreen();
357
356
  console.log(titleBox(isVi ? 'Thêm workspace mới' : 'Add workspace'));
358
357
  console.log('');
359
- const name = (await rl.question(chalk_1.default.bold(isVi ? 'Tên workspace: ' : 'Workspace name: '))).trim();
360
- const rawPath = (await rl.question(chalk_1.default.bold(isVi ? 'Đường dẫn: ' : 'Path: '))).trim();
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();
361
360
  if (!rawPath) {
362
361
  console.log(chalk_1.default.red(isVi ? ' Đường dẫn không được để trống.' : ' Path cannot be empty.'));
363
- await pause(rl);
362
+ await pause();
364
363
  continue;
365
364
  }
366
365
  const resolvedPath = path.resolve(rawPath);
@@ -370,7 +369,7 @@ async function manageWorkspaces(rl, language) {
370
369
  workspaces.push({ id: (0, store_js_1.createWorkspaceId)(), name: name || 'Workspace', path: resolvedPath });
371
370
  (0, store_js_1.saveWorkspaces)(workspaces);
372
371
  console.log(chalk_1.default.green(`\n ✓ ${isVi ? 'Đã thêm workspace.' : 'Workspace added.'}`));
373
- await pause(rl);
372
+ await pause();
374
373
  continue;
375
374
  }
376
375
  if (selection.type === 'workspace' && typeof selection.index === 'number') {
@@ -392,15 +391,15 @@ async function manageWorkspaces(rl, language) {
392
391
  (0, store_js_1.saveWorkspaces)(workspaces);
393
392
  clearScreen();
394
393
  console.log(chalk_1.default.green(`\n ✓ ${isVi ? 'Đã xóa workspace.' : 'Workspace deleted.'}`));
395
- await pause(rl);
394
+ await pause();
396
395
  continue;
397
396
  }
398
397
  if (action === 'edit') {
399
398
  clearScreen();
400
399
  console.log(titleBox(isVi ? 'Sửa workspace' : 'Edit workspace'));
401
400
  console.log('');
402
- const newName = await askWithDefault(rl, isVi ? 'Tên mới' : 'New name', ws.name);
403
- const newPath = await askWithDefault(rl, isVi ? 'Đường dẫn mới' : 'New path', ws.path);
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);
404
403
  const resolvedPath = path.resolve(newPath.trim());
405
404
  if (!fs.existsSync(resolvedPath)) {
406
405
  console.log(chalk_1.default.yellow(` ⚠ ${isVi ? 'Đường dẫn không tồn tại.' : 'Path does not exist.'}`));
@@ -408,15 +407,14 @@ async function manageWorkspaces(rl, language) {
408
407
  workspaces[idx] = { ...ws, name: newName.trim() || ws.name, path: resolvedPath };
409
408
  (0, store_js_1.saveWorkspaces)(workspaces);
410
409
  console.log(chalk_1.default.green(`\n ✓ ${isVi ? 'Đã cập nhật workspace.' : 'Workspace updated.'}`));
411
- await pause(rl);
410
+ await pause();
412
411
  continue;
413
412
  }
414
413
  }
415
414
  }
416
415
  }
417
- async function configureStartup(config, rl) {
416
+ async function configureStartup(config) {
418
417
  const isVi = config.language === 'vi';
419
- rl.pause();
420
418
  const nextMode = await runSelectionMenu(() => {
421
419
  console.log(titleBox(isVi ? 'Cấu hình khởi động' : 'Configure startup'));
422
420
  console.log(chalk_1.default.gray(` ${isVi ? 'Chế độ hiện tại:' : 'Current mode:'} ${config.startupMode}`));
@@ -425,7 +423,6 @@ async function configureStartup(config, rl) {
425
423
  { label: isVi ? 'Chạy nền (background)' : 'Background', value: 'background' },
426
424
  { label: isVi ? 'Mở giao diện (open-ui)' : 'Open UI', value: 'open-ui' }
427
425
  ], ['disabled', 'background', 'open-ui'].indexOf(config.startupMode));
428
- rl.resume();
429
426
  const entryScriptPath = path.join(process.cwd(), 'dist', 'index.js');
430
427
  const result = (0, startup_js_1.applyStartupMode)(nextMode, entryScriptPath, process.cwd());
431
428
  const nextConfig = { ...config, startupMode: nextMode };
@@ -433,11 +430,10 @@ async function configureStartup(config, rl) {
433
430
  clearScreen();
434
431
  console.log(titleBox(isVi ? 'Cấu hình khởi động' : 'Configure startup'));
435
432
  console.log(`\n${chalk_1.default.green(result)}`);
436
- await pause(rl);
433
+ await pause();
437
434
  return nextConfig;
438
435
  }
439
- async function switchLanguage(config, rl) {
440
- rl.pause();
436
+ async function switchLanguage(config) {
441
437
  const language = await runSelectionMenu(() => {
442
438
  console.log(titleBox('Đổi ngôn ngữ / Switch language'));
443
439
  console.log(chalk_1.default.gray(` Hiện tại: ${config.language}`));
@@ -445,21 +441,20 @@ async function switchLanguage(config, rl) {
445
441
  { label: 'Tiếng Việt (vi)', value: 'vi' },
446
442
  { label: 'English (en)', value: 'en' }
447
443
  ], config.language === 'en' ? 1 : 0);
448
- rl.resume();
449
444
  const nextConfig = { ...config, language };
450
445
  (0, config_js_1.saveConfigToDisk)(nextConfig);
451
446
  return nextConfig;
452
447
  }
453
- async function showRecentLogs(rl) {
448
+ async function showRecentLogs() {
454
449
  clearScreen();
455
450
  console.log(titleBox('Nhật ký gần đây'));
456
451
  const logPath = path.join(process.cwd(), 'data', 'nonstop.log');
457
452
  if (!fs.existsSync(logPath)) {
458
453
  console.log(chalk_1.default.gray('\n Chưa có nhật ký.'));
459
- await pause(rl);
454
+ await pause();
460
455
  return;
461
456
  }
462
457
  const lines = fs.readFileSync(logPath, 'utf8').split(/\r?\n/).filter(Boolean).slice(-25);
463
458
  console.log('\n' + lines.map(l => chalk_1.default.gray(' ') + l).join('\n'));
464
- await pause(rl);
459
+ await pause();
465
460
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quangnv13/nonstop",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "preferGlobal": true,
5
5
  "publishConfig": {
6
6
  "access": "public"