@kikkimo/claude-launcher 2.2.0 → 2.4.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.
- package/CHANGELOG.md +67 -0
- package/README.md +22 -8
- package/claude-launcher +390 -42
- package/docs/README-zh.md +22 -8
- package/lib/api-manager.js +135 -1
- package/lib/i18n/locales/de.js +68 -3
- package/lib/i18n/locales/en.js +66 -2
- package/lib/i18n/locales/es.js +68 -3
- package/lib/i18n/locales/fr.js +68 -3
- package/lib/i18n/locales/it.js +66 -2
- package/lib/i18n/locales/ja.js +68 -3
- package/lib/i18n/locales/ko.js +68 -3
- package/lib/i18n/locales/pt.js +66 -2
- package/lib/i18n/locales/ru.js +66 -2
- package/lib/i18n/locales/zh-TW.js +68 -3
- package/lib/i18n/locales/zh.js +68 -3
- package/lib/presets/providers.js +97 -10
- package/lib/utils/model-upgrade-checker.js +103 -0
- package/lib/utils/version-checker.js +22 -3
- package/package.json +1 -1
package/claude-launcher
CHANGED
|
@@ -263,9 +263,52 @@ async function addNewThirdPartyApi() {
|
|
|
263
263
|
}
|
|
264
264
|
|
|
265
265
|
/**
|
|
266
|
-
* Remove third-party API
|
|
266
|
+
* Remove third-party API menu with submenu
|
|
267
267
|
*/
|
|
268
268
|
async function removeThirdPartyApi() {
|
|
269
|
+
console.clear();
|
|
270
|
+
console.log('');
|
|
271
|
+
console.log(colors.bright + colors.orange + '🗑️ ' + await i18n.t('menu.remove_api.title') + colors.reset);
|
|
272
|
+
console.log('');
|
|
273
|
+
|
|
274
|
+
const apis = apiManager.getApis();
|
|
275
|
+
|
|
276
|
+
// Show current API count
|
|
277
|
+
if (apis.length > 0) {
|
|
278
|
+
console.log(colors.cyan + ' ' + await i18n.t('messages.info.current_api_count', apis.length) + colors.reset);
|
|
279
|
+
console.log('');
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const menuOptions = [
|
|
283
|
+
await i18n.t('menu.remove_api.delete_single'),
|
|
284
|
+
await i18n.t('menu.remove_api.clear_all'),
|
|
285
|
+
await i18n.t('menu.remove_api.back')
|
|
286
|
+
];
|
|
287
|
+
|
|
288
|
+
initializeGlobalMenus();
|
|
289
|
+
globalApiManagementMenu.setOptions(menuOptions);
|
|
290
|
+
const choice = await globalApiManagementMenu.navigate();
|
|
291
|
+
|
|
292
|
+
switch (choice) {
|
|
293
|
+
case 0: // Delete Single API
|
|
294
|
+
await deleteSingleApi();
|
|
295
|
+
return;
|
|
296
|
+
|
|
297
|
+
case 1: // Clear All APIs
|
|
298
|
+
await clearAllApis();
|
|
299
|
+
return;
|
|
300
|
+
|
|
301
|
+
case 2: // Back
|
|
302
|
+
case -1:
|
|
303
|
+
default:
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Delete a single API
|
|
310
|
+
*/
|
|
311
|
+
async function deleteSingleApi() {
|
|
269
312
|
try {
|
|
270
313
|
// Get API list
|
|
271
314
|
const apis = apiManager.getApis();
|
|
@@ -281,7 +324,7 @@ async function removeThirdPartyApi() {
|
|
|
281
324
|
);
|
|
282
325
|
|
|
283
326
|
if (!selectedApi) {
|
|
284
|
-
return
|
|
327
|
+
return;
|
|
285
328
|
}
|
|
286
329
|
|
|
287
330
|
// Show confirmation dialog
|
|
@@ -299,23 +342,20 @@ async function removeThirdPartyApi() {
|
|
|
299
342
|
`${await i18n.t('api.details.provider')}: ${selectedApi.provider}`
|
|
300
343
|
]);
|
|
301
344
|
|
|
302
|
-
// Show success message
|
|
345
|
+
// Show success message
|
|
303
346
|
const remainingApis = apiManager.getApis();
|
|
304
347
|
if (remainingApis.length === 0) {
|
|
305
348
|
showInfo(await i18n.t('messages.info.all_apis_removed'));
|
|
306
349
|
}
|
|
307
350
|
await waitForKey(await i18n.t('messages.prompts.press_any_key'));
|
|
308
|
-
return showMenu();
|
|
309
351
|
|
|
310
352
|
} catch (removeError) {
|
|
311
353
|
showError(await i18n.t('errors.api.failed_remove', removeError.message));
|
|
312
354
|
await waitForKey(await i18n.t('messages.prompts.press_any_key'));
|
|
313
|
-
return showMenu();
|
|
314
355
|
}
|
|
315
356
|
} else {
|
|
316
357
|
showInfo(await i18n.t('messages.info.removal_cancelled'));
|
|
317
358
|
await waitForKey(await i18n.t('messages.prompts.press_any_key'));
|
|
318
|
-
return showMenu();
|
|
319
359
|
}
|
|
320
360
|
|
|
321
361
|
} catch (error) {
|
|
@@ -325,6 +365,42 @@ async function removeThirdPartyApi() {
|
|
|
325
365
|
}
|
|
326
366
|
}
|
|
327
367
|
|
|
368
|
+
/**
|
|
369
|
+
* Clear all APIs with confirmation
|
|
370
|
+
*/
|
|
371
|
+
async function clearAllApis() {
|
|
372
|
+
const { simpleInput } = require('./lib/ui/prompts');
|
|
373
|
+
|
|
374
|
+
const apis = apiManager.getApis();
|
|
375
|
+
const count = apis.length;
|
|
376
|
+
|
|
377
|
+
if (count === 0) {
|
|
378
|
+
console.clear();
|
|
379
|
+
showInfo(await i18n.t('messages.info.no_apis'));
|
|
380
|
+
await waitForKey(await i18n.t('messages.prompts.press_any_key'));
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
console.clear();
|
|
385
|
+
console.log('');
|
|
386
|
+
console.log(colors.bright + colors.red + '⚠️ ' + await i18n.t('menu.remove_api.clear_all') + colors.reset);
|
|
387
|
+
console.log('');
|
|
388
|
+
console.log(colors.yellow + ' ' + await i18n.t('messages.prompts.confirm_clear_all', count) + colors.reset);
|
|
389
|
+
console.log('');
|
|
390
|
+
|
|
391
|
+
const input = await simpleInput(colors.cyan + ' ' + await i18n.t('messages.prompts.confirm_clear_all_input') + colors.reset);
|
|
392
|
+
|
|
393
|
+
if (input === 'CLEAR') {
|
|
394
|
+
const clearedCount = apiManager.clearAllApis();
|
|
395
|
+
console.clear();
|
|
396
|
+
showSuccess(await i18n.t('messages.info.all_apis_cleared', clearedCount));
|
|
397
|
+
await waitForKey(await i18n.t('messages.prompts.press_any_key'));
|
|
398
|
+
} else {
|
|
399
|
+
showInfo(await i18n.t('messages.info.clear_cancelled'));
|
|
400
|
+
await waitForKey(await i18n.t('messages.prompts.press_any_key'));
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
328
404
|
/**
|
|
329
405
|
* Switch active third-party API
|
|
330
406
|
*/
|
|
@@ -357,40 +433,110 @@ async function switchThirdPartyApi() {
|
|
|
357
433
|
/**
|
|
358
434
|
* View API statistics
|
|
359
435
|
*/
|
|
436
|
+
/**
|
|
437
|
+
* Format timestamp to relative time
|
|
438
|
+
* @param {string|null} timestamp - ISO timestamp or null
|
|
439
|
+
* @returns {string} Relative time string
|
|
440
|
+
*/
|
|
441
|
+
function formatRelativeTime(timestamp) {
|
|
442
|
+
if (!timestamp) return i18n.tSync('statistics.time_never');
|
|
443
|
+
|
|
444
|
+
const now = Date.now();
|
|
445
|
+
const diff = now - new Date(timestamp).getTime();
|
|
446
|
+
const minutes = Math.floor(diff / 60000);
|
|
447
|
+
const hours = Math.floor(diff / 3600000);
|
|
448
|
+
const days = Math.floor(diff / 86400000);
|
|
449
|
+
|
|
450
|
+
if (minutes < 1) return i18n.tSync('statistics.time_just_now');
|
|
451
|
+
if (minutes < 60) return i18n.tSync('statistics.time_minutes_ago', minutes);
|
|
452
|
+
if (hours < 24) return i18n.tSync('statistics.time_hours_ago', hours);
|
|
453
|
+
return i18n.tSync('statistics.time_days_ago', days);
|
|
454
|
+
}
|
|
455
|
+
|
|
360
456
|
async function viewStatistics() {
|
|
361
457
|
console.clear();
|
|
362
458
|
console.log('');
|
|
363
459
|
console.log(colors.bright + colors.orange + '📊 ' + await i18n.t('statistics.title') + colors.reset);
|
|
364
460
|
console.log('');
|
|
365
461
|
|
|
366
|
-
const
|
|
367
|
-
|
|
462
|
+
const menuOptions = [
|
|
463
|
+
await i18n.t('statistics.menu_view'),
|
|
464
|
+
await i18n.t('statistics.menu_reset'),
|
|
465
|
+
await i18n.t('statistics.menu_back')
|
|
466
|
+
];
|
|
467
|
+
|
|
468
|
+
initializeGlobalMenus();
|
|
469
|
+
globalApiManagementMenu.setOptions(menuOptions);
|
|
470
|
+
const choice = await globalApiManagementMenu.navigate();
|
|
471
|
+
|
|
472
|
+
switch (choice) {
|
|
473
|
+
case 0: // View Statistics Details
|
|
474
|
+
await showStatisticsDetails();
|
|
475
|
+
return viewStatistics();
|
|
476
|
+
|
|
477
|
+
case 1: // Reset Statistics
|
|
478
|
+
const { simpleInput } = require('./lib/ui/prompts');
|
|
479
|
+
const confirm = await simpleInput(colors.yellow + ' ' + await i18n.t('statistics.reset_confirm') + ' ' + colors.reset);
|
|
480
|
+
if (confirm.toLowerCase() === 'y') {
|
|
481
|
+
apiManager.resetStatistics();
|
|
482
|
+
console.log(colors.green + ' ✓ ' + await i18n.t('statistics.reset_success') + colors.reset);
|
|
483
|
+
await waitForKey(await i18n.t('messages.prompts.press_any_key'));
|
|
484
|
+
}
|
|
485
|
+
return viewStatistics();
|
|
486
|
+
|
|
487
|
+
case 2: // Back
|
|
488
|
+
case -1:
|
|
489
|
+
default:
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Show detailed statistics
|
|
496
|
+
*/
|
|
497
|
+
async function showStatisticsDetails() {
|
|
498
|
+
const { padStringToWidth } = require('./lib/utils/string-width');
|
|
368
499
|
|
|
369
|
-
console.
|
|
500
|
+
console.clear();
|
|
501
|
+
console.log('');
|
|
502
|
+
console.log(colors.bright + colors.orange + '📊 ' + await i18n.t('statistics.title') + colors.reset);
|
|
503
|
+
console.log('');
|
|
504
|
+
|
|
505
|
+
const stats = apiManager.getEnhancedStatistics();
|
|
506
|
+
|
|
507
|
+
// Summary section
|
|
508
|
+
console.log(colors.cyan + ' ' + i18n.tSync('ui.general.summary') + ':' + colors.reset);
|
|
370
509
|
console.log(colors.gray + ` ${await i18n.t('statistics.total_apis', stats.totalApis)}` + colors.reset);
|
|
371
510
|
console.log(colors.gray + ` ${await i18n.t('statistics.active_api', stats.activeApiName)}` + colors.reset);
|
|
372
511
|
console.log(colors.gray + ` ${await i18n.t('statistics.most_used', stats.mostUsedApi)}` + colors.reset);
|
|
373
512
|
console.log(colors.gray + ` ${await i18n.t('statistics.total_usage', stats.totalUsage)}` + colors.reset);
|
|
513
|
+
console.log(colors.gray + ` ${await i18n.t('statistics.success_rate', stats.successRate)}` + colors.reset);
|
|
374
514
|
console.log('');
|
|
375
515
|
|
|
376
|
-
if (
|
|
377
|
-
console.log(colors.cyan + ' ' + i18n.tSync('ui.general.configured_apis') + colors.reset);
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
console.log(colors.
|
|
392
|
-
|
|
393
|
-
|
|
516
|
+
if (stats.apiStats.length > 0) {
|
|
517
|
+
console.log(colors.cyan + ' ' + i18n.tSync('ui.general.configured_apis') + ':' + colors.reset);
|
|
518
|
+
console.log('');
|
|
519
|
+
|
|
520
|
+
// Table header
|
|
521
|
+
console.log(colors.dim + ' ' +
|
|
522
|
+
padStringToWidth(await i18n.t('statistics.header_name'), 20) +
|
|
523
|
+
padStringToWidth(await i18n.t('statistics.header_usage'), 10) +
|
|
524
|
+
padStringToWidth(await i18n.t('statistics.header_success'), 10) +
|
|
525
|
+
await i18n.t('statistics.header_last_used') +
|
|
526
|
+
colors.reset);
|
|
527
|
+
console.log(colors.dim + ' ' + '─'.repeat(60) + colors.reset);
|
|
528
|
+
|
|
529
|
+
for (const api of stats.apiStats) {
|
|
530
|
+
const lastUsedText = formatRelativeTime(api.lastUsed);
|
|
531
|
+
console.log(colors.gray + ' ' +
|
|
532
|
+
padStringToWidth(api.name, 20) +
|
|
533
|
+
padStringToWidth(String(api.usageCount), 10) +
|
|
534
|
+
padStringToWidth(api.successRate, 10) +
|
|
535
|
+
lastUsedText +
|
|
536
|
+
colors.reset);
|
|
537
|
+
}
|
|
538
|
+
} else {
|
|
539
|
+
console.log(colors.gray + ' ' + await i18n.t('statistics.no_usage') + colors.reset);
|
|
394
540
|
}
|
|
395
541
|
|
|
396
542
|
console.log('');
|
|
@@ -568,20 +714,23 @@ async function showApiManagementMenu() {
|
|
|
568
714
|
|
|
569
715
|
// Build menu options based on password setup status
|
|
570
716
|
const menuOptions = [
|
|
571
|
-
await i18n.t('menu.api_management.add_new'),
|
|
572
|
-
await i18n.t('menu.api_management.remove'),
|
|
573
|
-
await i18n.t('menu.api_management.switch'),
|
|
574
|
-
await i18n.t('menu.api_management.statistics')
|
|
717
|
+
await i18n.t('menu.api_management.add_new'), // 0
|
|
718
|
+
await i18n.t('menu.api_management.remove'), // 1
|
|
719
|
+
await i18n.t('menu.api_management.switch'), // 2
|
|
720
|
+
await i18n.t('menu.api_management.statistics') // 3
|
|
575
721
|
];
|
|
576
722
|
|
|
577
723
|
// Add import/export options only if password is set
|
|
578
724
|
if (apiManager.canUseImportExport()) {
|
|
579
|
-
menuOptions.push(await i18n.t('menu.api_management.export'));
|
|
580
|
-
menuOptions.push(await i18n.t('menu.api_management.import'));
|
|
581
|
-
menuOptions.push(await i18n.t('menu.api_management.change_password'));
|
|
725
|
+
menuOptions.push(await i18n.t('menu.api_management.export')); // 4
|
|
726
|
+
menuOptions.push(await i18n.t('menu.api_management.import')); // 5
|
|
727
|
+
menuOptions.push(await i18n.t('menu.api_management.change_password')); // 6
|
|
582
728
|
}
|
|
583
729
|
|
|
584
|
-
|
|
730
|
+
// Add model upgrade settings (always available)
|
|
731
|
+
menuOptions.push(await i18n.t('model_upgrade.settings_title')); // 4 or 7 (depending on import/export)
|
|
732
|
+
|
|
733
|
+
menuOptions.push(await i18n.t('menu.api_management.back')); // 5 or 8
|
|
585
734
|
|
|
586
735
|
// Ensure global menus are initialized
|
|
587
736
|
initializeGlobalMenus();
|
|
@@ -604,7 +753,7 @@ async function showApiManagementMenu() {
|
|
|
604
753
|
await viewStatistics();
|
|
605
754
|
return showMenu();
|
|
606
755
|
} else if (apiManager.canUseImportExport()) {
|
|
607
|
-
//
|
|
756
|
+
// With import/export enabled: indices 4-8
|
|
608
757
|
if (choice === 4) { // Export Configuration
|
|
609
758
|
await exportConfiguration();
|
|
610
759
|
return showMenu();
|
|
@@ -614,12 +763,16 @@ async function showApiManagementMenu() {
|
|
|
614
763
|
} else if (choice === 6) { // Change Password
|
|
615
764
|
await changePassword();
|
|
616
765
|
return showMenu();
|
|
617
|
-
} else if (choice === 7) { //
|
|
766
|
+
} else if (choice === 7) { // Model Upgrade Settings (NEW)
|
|
767
|
+
return await showModelUpgradeSettings();
|
|
768
|
+
} else if (choice === 8) { // Back to Main Menu
|
|
618
769
|
return showMenu();
|
|
619
770
|
}
|
|
620
771
|
} else {
|
|
621
|
-
//
|
|
622
|
-
if (choice === 4) { //
|
|
772
|
+
// Without import/export: indices 4-5
|
|
773
|
+
if (choice === 4) { // Model Upgrade Settings (NEW)
|
|
774
|
+
return await showModelUpgradeSettings();
|
|
775
|
+
} else if (choice === 5) { // Back to Main Menu
|
|
623
776
|
return showMenu();
|
|
624
777
|
}
|
|
625
778
|
}
|
|
@@ -628,6 +781,144 @@ async function showApiManagementMenu() {
|
|
|
628
781
|
return showMenu();
|
|
629
782
|
}
|
|
630
783
|
|
|
784
|
+
/**
|
|
785
|
+
* Show model upgrade settings menu
|
|
786
|
+
*/
|
|
787
|
+
async function showModelUpgradeSettings() {
|
|
788
|
+
const versionChecker = require('./lib/utils/version-checker');
|
|
789
|
+
const upgradeChecker = require('./lib/utils/model-upgrade-checker');
|
|
790
|
+
|
|
791
|
+
console.clear();
|
|
792
|
+
console.log('');
|
|
793
|
+
console.log(colors.bright + colors.orange + '⚙️ ' + await i18n.t('model_upgrade.settings_title') + colors.reset);
|
|
794
|
+
console.log('');
|
|
795
|
+
|
|
796
|
+
const config = await versionChecker.loadConfig();
|
|
797
|
+
const isAutoOn = config.autoModelUpgrade === true;
|
|
798
|
+
|
|
799
|
+
console.log(colors.cyan + ' ' + await i18n.t('model_upgrade.current_config') + ':' + colors.reset);
|
|
800
|
+
console.log(colors.gray + ' ' + await i18n.t('model_upgrade.auto_upgrade_label') + ': ' +
|
|
801
|
+
(isAutoOn
|
|
802
|
+
? colors.green + await i18n.t('model_upgrade.auto_upgrade_on')
|
|
803
|
+
: colors.dim + await i18n.t('model_upgrade.auto_upgrade_off')
|
|
804
|
+
) + colors.reset);
|
|
805
|
+
console.log('');
|
|
806
|
+
|
|
807
|
+
const menuOptions = [
|
|
808
|
+
isAutoOn
|
|
809
|
+
? await i18n.t('model_upgrade.menu_toggle_auto_on')
|
|
810
|
+
: await i18n.t('model_upgrade.menu_toggle_auto_off'),
|
|
811
|
+
await i18n.t('model_upgrade.menu_manual_upgrade'),
|
|
812
|
+
await i18n.t('model_upgrade.menu_back')
|
|
813
|
+
];
|
|
814
|
+
|
|
815
|
+
initializeGlobalMenus();
|
|
816
|
+
globalApiManagementMenu.setOptions(menuOptions);
|
|
817
|
+
const choice = await globalApiManagementMenu.navigate();
|
|
818
|
+
|
|
819
|
+
switch (choice) {
|
|
820
|
+
case 0: // Toggle auto upgrade
|
|
821
|
+
await versionChecker.setAutoModelUpgrade(!isAutoOn);
|
|
822
|
+
console.log('');
|
|
823
|
+
console.log(colors.green + '✓ ' + await i18n.t('model_upgrade.auto_upgrade_label') + ': ' +
|
|
824
|
+
(!isAutoOn
|
|
825
|
+
? await i18n.t('model_upgrade.auto_upgrade_on')
|
|
826
|
+
: await i18n.t('model_upgrade.auto_upgrade_off')
|
|
827
|
+
) + colors.reset);
|
|
828
|
+
await waitForKey(await i18n.t('messages.prompts.press_any_key'));
|
|
829
|
+
return showModelUpgradeSettings();
|
|
830
|
+
|
|
831
|
+
case 1: // Manual upgrade
|
|
832
|
+
await performManualUpgrade();
|
|
833
|
+
return showModelUpgradeSettings();
|
|
834
|
+
|
|
835
|
+
case 2: // Back
|
|
836
|
+
case -1:
|
|
837
|
+
default:
|
|
838
|
+
return showApiManagementMenu();
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
/**
|
|
843
|
+
* Perform manual upgrade for all APIs with interactive confirmation
|
|
844
|
+
*/
|
|
845
|
+
async function performManualUpgrade() {
|
|
846
|
+
const { getLatestModel, getProvider } = require('./lib/presets/providers');
|
|
847
|
+
const { simpleInput } = require('./lib/ui/prompts');
|
|
848
|
+
|
|
849
|
+
console.clear();
|
|
850
|
+
console.log('');
|
|
851
|
+
console.log(colors.bright + colors.orange + '🔄 ' + await i18n.t('model_upgrade.manual_title') + colors.reset);
|
|
852
|
+
console.log('');
|
|
853
|
+
|
|
854
|
+
const apis = apiManager.getApis();
|
|
855
|
+
|
|
856
|
+
if (apis.length === 0) {
|
|
857
|
+
console.log(colors.yellow + ' ' + await i18n.t('messages.info.no_apis') + colors.reset);
|
|
858
|
+
await waitForKey(await i18n.t('messages.prompts.press_any_key'));
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
console.log(colors.gray + ' ' + await i18n.t('model_upgrade.manual_checking', apis.length) + colors.reset);
|
|
863
|
+
console.log('');
|
|
864
|
+
|
|
865
|
+
let upgradedCount = 0;
|
|
866
|
+
let skippedUpToDate = 0;
|
|
867
|
+
let skippedNoInfo = 0;
|
|
868
|
+
let skippedByUser = 0;
|
|
869
|
+
|
|
870
|
+
for (let i = 0; i < apis.length; i++) {
|
|
871
|
+
const api = apis[i];
|
|
872
|
+
const latestModel = getLatestModel(api.model, api.provider);
|
|
873
|
+
|
|
874
|
+
console.log(colors.cyan + ' ─────────────────────────────────────────────────' + colors.reset);
|
|
875
|
+
console.log(colors.bright + ` ${i + 1}/${apis.length} ${api.name}` + colors.reset);
|
|
876
|
+
console.log(colors.gray + ' ' + await i18n.t('model_upgrade.manual_api_current', api.model) + colors.reset);
|
|
877
|
+
|
|
878
|
+
if (latestModel) {
|
|
879
|
+
console.log(colors.green + ' ' + await i18n.t('model_upgrade.manual_api_latest', latestModel) + colors.reset);
|
|
880
|
+
console.log('');
|
|
881
|
+
|
|
882
|
+
// Ask for confirmation
|
|
883
|
+
const answer = await simpleInput(colors.yellow + ' ' + await i18n.t('model_upgrade.manual_confirm') + ' ' + colors.reset);
|
|
884
|
+
|
|
885
|
+
if (answer.toLowerCase() === 'y') {
|
|
886
|
+
apiManager.updateApiModel(api.id, latestModel);
|
|
887
|
+
console.log(colors.green + ' ✓ ' + await i18n.t('model_upgrade.manual_upgraded', api.model, latestModel) + colors.reset);
|
|
888
|
+
upgradedCount++;
|
|
889
|
+
} else {
|
|
890
|
+
console.log(colors.dim + ' ' + await i18n.t('model_upgrade.manual_skipped') + colors.reset);
|
|
891
|
+
skippedByUser++;
|
|
892
|
+
}
|
|
893
|
+
} else {
|
|
894
|
+
// No upgrade info available - check if model exists in provider
|
|
895
|
+
const provider = getProvider(api.provider);
|
|
896
|
+
if (provider && provider.models && provider.models.includes(api.model)) {
|
|
897
|
+
// Model exists in provider, likely already latest or no alias defined
|
|
898
|
+
console.log(colors.dim + ' ' + await i18n.t('model_upgrade.manual_api_uptodate') + colors.reset);
|
|
899
|
+
skippedUpToDate++;
|
|
900
|
+
} else {
|
|
901
|
+
console.log(colors.dim + ' ' + await i18n.t('model_upgrade.manual_api_no_info') + colors.reset);
|
|
902
|
+
skippedNoInfo++;
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
console.log('');
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
console.log(colors.cyan + ' ─────────────────────────────────────────────────' + colors.reset);
|
|
910
|
+
console.log('');
|
|
911
|
+
console.log(colors.green + ' ' + await i18n.t('model_upgrade.manual_complete') + colors.reset);
|
|
912
|
+
console.log(colors.gray + ' ' + await i18n.t('model_upgrade.manual_stats_upgraded', upgradedCount) + colors.reset);
|
|
913
|
+
console.log(colors.gray + ' ' + await i18n.t('model_upgrade.manual_stats_skipped',
|
|
914
|
+
skippedUpToDate + skippedNoInfo + skippedByUser,
|
|
915
|
+
skippedUpToDate,
|
|
916
|
+
skippedNoInfo) + colors.reset);
|
|
917
|
+
console.log('');
|
|
918
|
+
|
|
919
|
+
await waitForKey(await i18n.t('messages.prompts.press_any_key'));
|
|
920
|
+
}
|
|
921
|
+
|
|
631
922
|
/**
|
|
632
923
|
* Handle third-party API launch
|
|
633
924
|
*/
|
|
@@ -646,12 +937,15 @@ async function handleThirdPartyApiLaunch(skipPermissions = false) {
|
|
|
646
937
|
return showMenu();
|
|
647
938
|
}
|
|
648
939
|
|
|
649
|
-
//
|
|
650
|
-
apiManager.
|
|
940
|
+
// Record successful launch BEFORE launching (since process exits after)
|
|
941
|
+
apiManager.recordSuccessfulLaunch();
|
|
651
942
|
|
|
652
943
|
launchClaudeWithApi(activeApi, skipPermissions);
|
|
653
944
|
|
|
654
945
|
} catch (error) {
|
|
946
|
+
// Record failed launch
|
|
947
|
+
apiManager.recordFailedLaunch(error.message);
|
|
948
|
+
|
|
655
949
|
showError('Failed to launch with third-party API', [error.message]);
|
|
656
950
|
|
|
657
951
|
setTimeout(() => {
|
|
@@ -741,6 +1035,60 @@ async function showMenu() {
|
|
|
741
1035
|
// Silently ignore update check errors
|
|
742
1036
|
}
|
|
743
1037
|
|
|
1038
|
+
// ========================================
|
|
1039
|
+
// Model upgrade check (new feature)
|
|
1040
|
+
// ========================================
|
|
1041
|
+
let modelUpgradeInfo = null;
|
|
1042
|
+
try {
|
|
1043
|
+
const upgradeChecker = require('./lib/utils/model-upgrade-checker');
|
|
1044
|
+
const autoUpgrade = await upgradeChecker.isAutoUpgradeEnabled();
|
|
1045
|
+
|
|
1046
|
+
if (autoUpgrade) {
|
|
1047
|
+
// Auto upgrade enabled: always check and upgrade (bypass cache)
|
|
1048
|
+
const upgrades = upgradeChecker.checkAllApiUpgrades(apiManager);
|
|
1049
|
+
if (upgrades.length > 0) {
|
|
1050
|
+
const upgraded = upgradeChecker.performAutoUpgrade(apiManager, upgrades);
|
|
1051
|
+
if (upgraded.length > 0) {
|
|
1052
|
+
modelUpgradeInfo = colors.green + ' ✓ ' +
|
|
1053
|
+
i18n.tSync('model_upgrade.auto_upgraded', upgraded[0].from, upgraded[0].to) + colors.reset;
|
|
1054
|
+
if (upgraded.length > 1) {
|
|
1055
|
+
modelUpgradeInfo += '\n' + colors.green + ' ' +
|
|
1056
|
+
`(+${upgraded.length - 1} more)` + colors.reset;
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
} else {
|
|
1061
|
+
// Auto upgrade disabled: use cache for notification
|
|
1062
|
+
const result = await upgradeChecker.checkForModelUpgrades(apiManager);
|
|
1063
|
+
if (result.needsCheck && result.upgrades.length > 0) {
|
|
1064
|
+
const first = result.upgrades[0];
|
|
1065
|
+
modelUpgradeInfo = colors.yellow + ' ⚠️ ' +
|
|
1066
|
+
i18n.tSync('model_upgrade.notification', first.currentModel, first.latestModel) +
|
|
1067
|
+
colors.reset + '\n' +
|
|
1068
|
+
colors.yellow + ' ' +
|
|
1069
|
+
i18n.tSync('model_upgrade.notification_api', first.apiName) +
|
|
1070
|
+
colors.reset + '\n' +
|
|
1071
|
+
colors.gray + ' ' +
|
|
1072
|
+
i18n.tSync('model_upgrade.notification_hint') +
|
|
1073
|
+
colors.reset;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
} catch (error) {
|
|
1077
|
+
// Silently ignore model upgrade check errors
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
// Combine version info and model upgrade info
|
|
1081
|
+
let displayInfo = '';
|
|
1082
|
+
if (versionInfo) {
|
|
1083
|
+
displayInfo += versionInfo;
|
|
1084
|
+
}
|
|
1085
|
+
if (modelUpgradeInfo) {
|
|
1086
|
+
if (displayInfo) {
|
|
1087
|
+
displayInfo += '\n';
|
|
1088
|
+
}
|
|
1089
|
+
displayInfo += modelUpgradeInfo;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
744
1092
|
// Populate menu options dynamically with i18n translations
|
|
745
1093
|
menuOptions = [
|
|
746
1094
|
await i18n.t('menu.main.launch_default'),
|
|
@@ -754,7 +1102,7 @@ async function showMenu() {
|
|
|
754
1102
|
];
|
|
755
1103
|
|
|
756
1104
|
globalMainMenu.setOptions(menuOptions);
|
|
757
|
-
const selection = await globalMainMenu.navigate(false,
|
|
1105
|
+
const selection = await globalMainMenu.navigate(false, displayInfo || null); // Pass combined info to display between banner and nav
|
|
758
1106
|
|
|
759
1107
|
if (selection === -1) {
|
|
760
1108
|
console.log('');
|
package/docs/README-zh.md
CHANGED
|
@@ -25,11 +25,12 @@
|
|
|
25
25
|
- 强密码要求和验证
|
|
26
26
|
|
|
27
27
|
### 🚀 **第三方 API 管理**
|
|
28
|
-
- 全面支持多个第三方 API 提供商(OpenAI、
|
|
28
|
+
- 全面支持多个第三方 API 提供商(Anthropic、OpenAI、DeepSeek、Moonshot/Kimi、MiniMax、GLM/智谱AI 和自定义 API)
|
|
29
29
|
- 带验证的交互式 API 配置
|
|
30
|
-
- API
|
|
30
|
+
- API 使用统计,支持成功/失败率追踪
|
|
31
|
+
- 模型升级通知和自动升级支持
|
|
31
32
|
- 安全的配置备份和恢复
|
|
32
|
-
- 简单的 API
|
|
33
|
+
- 简单的 API 切换、删除和批量清空
|
|
33
34
|
|
|
34
35
|
### 🌍 **企业级功能**
|
|
35
36
|
- 全局安装 - 在任何地方都可以使用 `claude-launcher`
|
|
@@ -85,7 +86,11 @@ node claude-launcher
|
|
|
85
86
|
2. **启动 Claude Code(跳过权限)** - 使用 `--dangerously-skip-permissions` 启动
|
|
86
87
|
3. **使用第三方 API 启动 Claude Code** - 使用配置的第三方 API
|
|
87
88
|
4. **使用第三方 API 启动 Claude Code(跳过权限)** - 结合第三方 API 和跳过权限
|
|
88
|
-
5. **第三方 API 管理** -
|
|
89
|
+
5. **第三方 API 管理** - 完整的 API 生命周期管理:
|
|
90
|
+
- 添加、切换和删除 API
|
|
91
|
+
- 查看使用统计(含成功/失败率)
|
|
92
|
+
- 模型升级设置(自动/手动升级)
|
|
93
|
+
- 导入/导出配置
|
|
89
94
|
6. **语言设置** - 在11种支持的语言之间切换
|
|
90
95
|
7. **版本更新检查** - 检查启动器更新
|
|
91
96
|
8. **退出** - 关闭启动器
|
|
@@ -126,15 +131,23 @@ $ claude-launcher
|
|
|
126
131
|
📋 第三方 API 管理
|
|
127
132
|
|
|
128
133
|
→ 添加新 API
|
|
129
|
-
删除 API
|
|
134
|
+
删除 API → 删除单个 API / 清空所有 API
|
|
130
135
|
切换活动 API
|
|
131
|
-
查看统计信息
|
|
136
|
+
查看统计信息 → 查看详情 / 重置统计
|
|
137
|
+
模型升级设置 → 自动升级 [开/关] / 手动升级
|
|
132
138
|
导出配置
|
|
133
139
|
导入配置
|
|
134
140
|
更改密码
|
|
135
141
|
返回主菜单
|
|
136
142
|
```
|
|
137
143
|
|
|
144
|
+
### 模型升级功能
|
|
145
|
+
|
|
146
|
+
启动器会在启动时自动检查模型升级:
|
|
147
|
+
- **自动升级**:自动使用最新的模型版本
|
|
148
|
+
- **手动升级**:逐个审核并确认模型升级
|
|
149
|
+
- **启动通知**:当有新模型版本可用时收到通知
|
|
150
|
+
|
|
138
151
|
## ⚙️ 配置
|
|
139
152
|
|
|
140
153
|
### 现代配置系统
|
|
@@ -158,10 +171,11 @@ Claude Launcher 2.0 使用先进的配置系统:
|
|
|
158
171
|
|
|
159
172
|
通过交互界面配置任何第三方 API 提供商:
|
|
160
173
|
|
|
161
|
-
- **支持的提供商**:OpenAI、
|
|
174
|
+
- **支持的提供商**:Anthropic、OpenAI、DeepSeek、Moonshot/Kimi、MiniMax(国内版/国际版)、GLM/智谱AI(GLM-4、GLM-5)和自定义 Anthropic 兼容 API
|
|
162
175
|
- **安全存储**:所有 API 令牌在存储前加密
|
|
163
176
|
- **验证**:URL、令牌和模型的实时验证
|
|
164
|
-
- **使用跟踪**:监控 API
|
|
177
|
+
- **使用跟踪**:监控 API 使用统计,支持成功/失败率追踪
|
|
178
|
+
- **模型升级**:自动检测并升级到最新模型版本
|
|
165
179
|
- **提供商特定功能**:为每个提供商优化配置,提供有用的注释和建议
|
|
166
180
|
|
|
167
181
|
### 配置导入/导出
|