@kikkimo/claude-launcher 2.4.0 → 3.0.0

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.
@@ -11,6 +11,7 @@ const EventEmitter = require('events');
11
11
  const crypto = require('crypto');
12
12
  const colors = require('../ui/colors');
13
13
  const i18n = require('../i18n');
14
+ const screen = require('../ui/screen');
14
15
 
15
16
  /**
16
17
  * Generate a cryptographically unique ID
@@ -111,7 +112,7 @@ class StdinManager extends EventEmitter {
111
112
  */
112
113
  _debug(...args) {
113
114
  if (this.debugMode) {
114
- console.error('[StdinManager]', ...args);
115
+ screen.debug('[StdinManager] ' + args.join(' '));
115
116
  }
116
117
  }
117
118
 
@@ -389,8 +390,8 @@ class StdinManager extends EventEmitter {
389
390
  // Clear the warning text only in TTY mode to avoid spamming ANSI codes
390
391
  if (process.stdout && process.stdout.isTTY) {
391
392
  // Clear the warning text (2 lines: empty line + warning line)
392
- process.stdout.write('\x1b[1A\r\x1b[K'); // Up 1 line, clear warning
393
- process.stdout.write('\x1b[1A\r\x1b[K'); // Up 1 line, clear empty line
393
+ screen.write('\x1b[1A\r\x1b[K'); // Up 1 line, clear warning
394
+ screen.write('\x1b[1A\r\x1b[K'); // Up 1 line, clear empty line
394
395
  }
395
396
  this._debug('Ctrl+C cancelled by user input');
396
397
  }
@@ -432,8 +433,8 @@ class StdinManager extends EventEmitter {
432
433
  // Clear the warning text only in TTY mode to avoid spamming ANSI codes
433
434
  if (process.stdout && process.stdout.isTTY) {
434
435
  // Clear the warning text (2 lines: empty line + warning line)
435
- process.stdout.write('\x1b[1A\r\x1b[K'); // Up 1 line, clear warning
436
- process.stdout.write('\x1b[1A\r\x1b[K'); // Up 1 line, clear empty line
436
+ screen.write('\x1b[1A\r\x1b[K'); // Up 1 line, clear warning
437
+ screen.write('\x1b[1A\r\x1b[K'); // Up 1 line, clear empty line
437
438
  }
438
439
  this._debug('Ctrl+C timer expired - warning cleared, returning to normal operation');
439
440
  }
@@ -464,8 +465,8 @@ class StdinManager extends EventEmitter {
464
465
 
465
466
  if (this.ctrlCCount === 1) {
466
467
  // First Ctrl+C - show warning
467
- console.log('');
468
- console.log(colors.yellow + '⚠️ ' + i18n.tSync('messages.prompts.ctrl_c_again') + colors.reset);
468
+ screen.write('\n');
469
+ screen.write(colors.yellow + '⚠️ ' + i18n.tSync('messages.prompts.ctrl_c_again') + colors.reset + '\n');
469
470
 
470
471
  // Clear any existing timer
471
472
  if (this.ctrlCTimer) {
@@ -486,8 +487,8 @@ class StdinManager extends EventEmitter {
486
487
  this.ctrlCTimer = null;
487
488
  }
488
489
 
489
- console.log('');
490
- console.log(colors.green + i18n.tSync('ui.general.goodbye') + colors.reset);
490
+ screen.write('\n');
491
+ screen.write(colors.green + i18n.tSync('ui.general.goodbye') + colors.reset + '\n');
491
492
 
492
493
  // Clean up stdin before exit
493
494
  // Use clearAll=true since we're exiting anyway
@@ -497,6 +498,7 @@ class StdinManager extends EventEmitter {
497
498
  // Ignore cleanup errors during exit
498
499
  }
499
500
 
501
+ screen.exit();
500
502
  process.exit(0);
501
503
  }
502
504
  }
@@ -27,17 +27,34 @@ async function loadConfig() {
27
27
  // Add new fields for backward compatibility
28
28
  if (config.autoModelUpgrade === undefined) config.autoModelUpgrade = false;
29
29
  if (config.lastModelUpgradeCheck === undefined) config.lastModelUpgradeCheck = 0;
30
+ if (config.disableTelemetry === undefined) config.disableTelemetry = true;
31
+ if (config.showModelUpgradeNotification === undefined) config.showModelUpgradeNotification = true;
32
+ if (config.apiLaunchMode === undefined) config.apiLaunchMode = 'direct';
30
33
 
31
34
  return config;
32
35
  } catch (error) {
33
36
  // Return default config if file doesn't exist
34
- return {
35
- language: 'zh',
37
+ // Default language must be 'en' to match LanguageManager default
38
+ const defaultConfig = {
39
+ language: 'en',
36
40
  lastVersionCheck: 0,
37
41
  cachedLatestVersion: null,
38
42
  autoModelUpgrade: false,
39
- lastModelUpgradeCheck: 0
43
+ lastModelUpgradeCheck: 0,
44
+ disableTelemetry: true,
45
+ showModelUpgradeNotification: true,
46
+ apiLaunchMode: 'direct'
40
47
  };
48
+
49
+ // Write default config on first run so subsequent reads are consistent
50
+ try {
51
+ const configPath = getConfigPath();
52
+ await fs.writeFile(configPath, JSON.stringify(defaultConfig, null, 2), 'utf8');
53
+ } catch (_) {
54
+ // Silently fail
55
+ }
56
+
57
+ return defaultConfig;
41
58
  }
42
59
  }
43
60
 
@@ -249,11 +266,54 @@ async function setAutoModelUpgrade(enabled) {
249
266
  await saveConfig(config);
250
267
  }
251
268
 
269
+ /**
270
+ * Load configuration from file synchronously
271
+ * Used by launcher.js where async is not available
272
+ */
273
+ function loadConfigSync() {
274
+ try {
275
+ const fsSync = require('fs');
276
+ const data = fsSync.readFileSync(getConfigPath(), 'utf8');
277
+ const config = JSON.parse(data);
278
+
279
+ if (config.autoModelUpgrade === undefined) config.autoModelUpgrade = false;
280
+ if (config.lastModelUpgradeCheck === undefined) config.lastModelUpgradeCheck = 0;
281
+ if (config.disableTelemetry === undefined) config.disableTelemetry = true;
282
+ if (config.showModelUpgradeNotification === undefined) config.showModelUpgradeNotification = true;
283
+ if (config.apiLaunchMode === undefined) config.apiLaunchMode = 'direct';
284
+
285
+ return config;
286
+ } catch (_) {
287
+ // Default language must be 'en' to match LanguageManager default
288
+ const defaultConfig = {
289
+ language: 'en',
290
+ lastVersionCheck: 0,
291
+ cachedLatestVersion: null,
292
+ autoModelUpgrade: false,
293
+ lastModelUpgradeCheck: 0,
294
+ disableTelemetry: true,
295
+ showModelUpgradeNotification: true,
296
+ apiLaunchMode: 'direct'
297
+ };
298
+
299
+ // Write default config on first run so subsequent reads are consistent
300
+ try {
301
+ const fsSync = require('fs');
302
+ fsSync.writeFileSync(getConfigPath(), JSON.stringify(defaultConfig, null, 2), 'utf8');
303
+ } catch (__) {
304
+ // Silently fail
305
+ }
306
+
307
+ return defaultConfig;
308
+ }
309
+ }
310
+
252
311
  module.exports = {
253
312
  checkForUpdates,
254
313
  forceCheckForUpdates,
255
314
  clearCache,
256
315
  loadConfig,
316
+ loadConfigSync,
257
317
  saveConfig,
258
318
  setAutoModelUpgrade
259
319
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kikkimo/claude-launcher",
3
- "version": "2.4.0",
3
+ "version": "3.0.0",
4
4
  "description": "Interactive launcher for Claude Code with beautiful Claude-style interface",
5
5
  "main": "claude-launcher",
6
6
  "bin": {
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "scripts": {
10
10
  "start": "node claude-launcher",
11
- "test": "echo \"No tests specified\" && exit 0",
11
+ "test": "node test/providers.test.js && node test/menu-hints.test.js && node test/version-checker.test.js && node test/api-manager.test.js && node test/launcher.test.js && node test/config-management.test.js && node test/api-select.test.js",
12
12
  "prepublishOnly": "echo \"Publishing claude-launcher...\"",
13
13
  "postinstall": "echo \"Claude Launcher installed successfully! Run 'claude-launcher' to start.\"",
14
14
  "publish:public": "npm publish --access public"