claude-key-manager
Version:
🚀 Claude Key Manager 4.1.3 - 修复密钥验证问题,支持更多密钥格式
337 lines (299 loc) • 10.1 kB
JavaScript
const inquirer = require('inquirer');
const chalk = require('chalk');
const KeyManager = require('./key-manager');
class InlineMenu {
constructor(keyManager) {
this.keyManager = keyManager;
this.options = [
{
key: '1',
name: '📝 添加新的API密钥',
description: '添加Claude API密钥到安全存储',
action: 'add'
},
{
key: '2',
name: '📋 列出所有密钥',
description: '显示已保存的所有密钥信息',
action: 'list'
},
{
key: '3',
name: '🔄 切换当前密钥',
description: '切换到不同的API密钥',
action: 'switch'
},
{
key: '4',
name: '🗑️ 删除密钥',
description: '安全删除指定的密钥',
action: 'delete'
},
{
key: '5',
name: '👁️ 查看当前密钥',
description: '显示当前活跃密钥信息',
action: 'current'
},
{
key: '6',
name: '📋 版本信息',
description: '检查版本和更新',
action: 'version'
},
{
key: '7',
name: '🔄 检查更新',
description: '检查并更新到最新版本',
action: 'update'
},
{
key: '8',
name: '❓ 帮助信息',
description: '显示详细使用帮助',
action: 'help'
}
];
}
/**
* 显示内联选项菜单 (你要的功能!)
*/
async showInlineOptions() {
console.log(chalk.blue('\n💡 Claude Key Manager - 快速命令'));
console.log(chalk.gray('─'.repeat(50)));
// 显示选项
this.options.forEach(option => {
console.log(`${chalk.yellow(option.key)}. ${option.name}`);
console.log(` ${chalk.gray(option.description)}`);
});
console.log(chalk.gray('─'.repeat(50)));
console.log(chalk.blue('输入数字选择操作,按 Esc 或 Ctrl+C 退出'));
// 监听单个按键输入
return new Promise((resolve) => {
process.stdin.setRawMode(true);
process.stdin.resume();
process.stdin.setEncoding('utf8');
const handleKeypress = (key) => {
// ESC键 (ASCII 27)
if (key === '\u001b') {
process.stdin.setRawMode(false);
process.stdin.removeListener('data', handleKeypress);
console.log(chalk.gray('\n已退出命令选择'));
resolve(null);
return;
}
// Ctrl+C
if (key === '\u0003') {
process.stdin.setRawMode(false);
process.stdin.removeListener('data', handleKeypress);
console.log(chalk.gray('\n已退出'));
process.exit(0);
}
// 数字键选择
const choice = parseInt(key);
if (choice >= 1 && choice <= this.options.length) {
process.stdin.setRawMode(false);
process.stdin.removeListener('data', handleKeypress);
const selectedOption = this.options[choice - 1];
console.log(chalk.green(`\n✅ 已选择: ${selectedOption.name}`));
console.log(''); // 空行分隔
resolve(selectedOption.action);
} else {
// 无效输入,显示提示但不退出
process.stdout.write(`\r${chalk.red('请输入 1-' + this.options.length + ' 或按 Esc 退出')}`);
setTimeout(() => {
process.stdout.write('\r' + ' '.repeat(30) + '\r');
}, 1500);
}
};
process.stdin.on('data', handleKeypress);
});
}
/**
* 执行选中的操作
*/
async executeAction(action) {
if (!action) return;
try {
switch (action) {
case 'add':
await this.handleAdd();
break;
case 'list':
await this.handleList();
break;
case 'switch':
await this.handleSwitch();
break;
case 'delete':
await this.handleDelete();
break;
case 'current':
await this.handleCurrent();
break;
case 'version':
await this.handleVersion();
break;
case 'update':
await this.handleUpdate();
break;
case 'help':
await this.handleHelp();
break;
default:
console.log(chalk.yellow('未知操作'));
}
} catch (error) {
console.log(chalk.red('❌ 错误:'), error.message);
}
}
async handleAdd() {
console.log(chalk.blue('📝 添加新的API密钥\n'));
const answers = await inquirer.prompt([
{
type: 'input',
name: 'key',
message: '请输入Claude API密钥:',
validate: (input) => {
try {
this.keyManager.validateKey(input);
return true;
} catch (error) {
return error.message;
}
}
},
{
type: 'input',
name: 'name',
message: '为此密钥设置名称:',
default: 'default',
validate: (input) => input.trim() ? true : '名称不能为空'
},
{
type: 'input',
name: 'description',
message: '密钥描述 (可选):',
default: ''
},
{
type: 'input',
name: 'apiUrl',
message: 'API Base URL (按回车使用默认):',
default: 'https://api.anthropic.com',
validate: (input) => {
if (!input.trim()) return true;
try {
new URL(input.trim());
return true;
} catch {
return '请输入有效的URL格式';
}
}
}
]);
await this.keyManager.addKey(
answers.key.trim(),
answers.name.trim(),
answers.description.trim(),
answers.apiUrl.trim()
);
console.log(chalk.green('✅ 密钥添加成功!'));
}
async handleList() {
console.log(chalk.blue('📋 已保存的密钥\n'));
const keys = await this.keyManager.listKeys(true);
if (keys.length === 0) {
console.log(chalk.yellow('⚠️ 没有找到任何密钥'));
return;
}
keys.forEach(k => {
const status = k.active ? chalk.green('👉 [当前]') : ' ';
const name = chalk.bold(k.name);
const desc = k.description ? chalk.gray(` - ${k.description}`) : '';
const apiUrl = chalk.blue(`\n API: ${k.apiUrl}`);
const created = chalk.gray(`\n 创建: ${new Date(k.createdAt).toLocaleString()}`);
const preview = k.preview ? chalk.gray(`\n 预览: ${k.preview}`) : '';
console.log(`${status} ${name}${desc}${apiUrl}${created}${preview}\n`);
});
}
async handleSwitch() {
console.log(chalk.blue('🔄 切换当前使用的密钥\n'));
const keys = await this.keyManager.listKeys();
if (keys.length === 0) {
console.log(chalk.yellow('⚠️ 没有可用的密钥'));
return;
}
const choices = keys.map(k => ({
name: `${k.name}${k.description ? ` - ${k.description}` : ''}${k.active ? chalk.green(' (当前)') : ''}`,
value: k.name,
disabled: k.active ? '已经是当前密钥' : false
}));
const { selectedKey } = await inquirer.prompt([{
type: 'list',
name: 'selectedKey',
message: '选择要切换到的密钥:',
choices: choices
}]);
await this.keyManager.switchKey(selectedKey);
console.log(chalk.green(`✅ 已切换到密钥: ${selectedKey}`));
}
async handleDelete() {
console.log(chalk.blue('🗑️ 删除密钥\n'));
const keys = await this.keyManager.listKeys();
if (keys.length === 0) {
console.log(chalk.yellow('⚠️ 没有可删除的密钥'));
return;
}
const choices = keys.map(k => ({
name: `${k.name}${k.description ? ` - ${k.description}` : ''}${k.active ? chalk.red(' (当前使用中!)') : ''}`,
value: k.name
}));
const { keyToDelete } = await inquirer.prompt([{
type: 'list',
name: 'keyToDelete',
message: '选择要删除的密钥:',
choices: choices
}]);
await this.keyManager.deleteKey(keyToDelete);
}
async handleCurrent() {
console.log(chalk.blue('👁️ 当前密钥详情\n'));
const current = await this.keyManager.getCurrentKey();
if (!current) {
console.log(chalk.yellow('⚠️ 没有设置当前密钥'));
return;
}
console.log(`🔑 名称: ${chalk.bold(current.name)}`);
console.log(`📝 描述: ${current.description || chalk.gray('无')}`);
console.log(`🌐 API URL: ${chalk.blue(current.apiUrl || 'https://api.anthropic.com')}`);
console.log(`🔍 预览: ${current.preview}`);
console.log(`⏰ 完整密钥长度: ${current.key.length} 字符`);
}
async handleVersion() {
const VersionManager = require('./version-manager');
const versionManager = new VersionManager();
await versionManager.showVersionInfo();
}
async handleUpdate() {
const VersionManager = require('./version-manager');
const versionManager = new VersionManager();
await versionManager.updateHelper();
}
async handleHelp() {
console.log(chalk.blue('❓ Claude Key Manager 帮助\n'));
console.log(`${chalk.bold('基本命令:')}`);
console.log(` claude-key add <key> 添加新密钥`);
console.log(` claude-key list 列出所有密钥`);
console.log(` claude-key switch <name> 切换密钥`);
console.log(` claude-key delete <name> 删除密钥`);
console.log(` claude-key current 显示当前密钥`);
console.log(` claude-key version 显示版本信息`);
console.log(` claude-key update 更新到最新版本`);
console.log('');
console.log(`${chalk.bold('快速操作:')}`);
console.log(` 输入 claude-key 然后按 "/" 打开此命令面板`);
console.log(` 或直接运行 claude-key interactive`);
}
}
module.exports = InlineMenu;