mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-22 16:40:25 +00:00
refactor: 简化CLI工具管理命令
- 移除复杂的API Key管理和账户管理命令 - 简化admin命令直接创建初始管理员 - 保留核心的status命令用于系统状态查看 - 减少CLI工具的复杂度,专注于核心功能 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
562
cli/index.js
562
cli/index.js
@@ -45,218 +45,12 @@ program
|
||||
.action(async () => {
|
||||
await initialize();
|
||||
|
||||
const { action } = await inquirer.prompt({
|
||||
type: 'list',
|
||||
name: 'action',
|
||||
message: '选择操作:',
|
||||
choices: [
|
||||
{ name: '🔑 设置管理员密码', value: 'set-password' },
|
||||
{ name: '👤 创建初始管理员', value: 'create-admin' },
|
||||
{ name: '🔄 重置管理员密码', value: 'reset-password' },
|
||||
{ name: '📊 查看管理员信息', value: 'view-admin' }
|
||||
]
|
||||
});
|
||||
|
||||
switch (action) {
|
||||
case 'set-password':
|
||||
await setAdminPassword();
|
||||
break;
|
||||
case 'create-admin':
|
||||
await createInitialAdmin();
|
||||
break;
|
||||
case 'reset-password':
|
||||
await resetAdminPassword();
|
||||
break;
|
||||
case 'view-admin':
|
||||
await viewAdminInfo();
|
||||
break;
|
||||
}
|
||||
// 直接执行创建初始管理员
|
||||
await createInitialAdmin();
|
||||
|
||||
await redis.disconnect();
|
||||
});
|
||||
|
||||
// 🔑 API Key 管理
|
||||
program
|
||||
.command('keys')
|
||||
.description('API Key 管理')
|
||||
.action(async () => {
|
||||
await initialize();
|
||||
|
||||
// 尝试兼容不同版本的inquirer
|
||||
let prompt = inquirer.prompt || inquirer.default?.prompt || inquirer;
|
||||
if (typeof prompt !== 'function') {
|
||||
prompt = (await import('inquirer')).default;
|
||||
}
|
||||
|
||||
const { action } = await prompt({
|
||||
type: 'list',
|
||||
name: 'action',
|
||||
message: '选择操作:',
|
||||
choices: [
|
||||
{ name: '📋 列出所有 API Keys', value: 'list' },
|
||||
{ name: '🔑 创建新的 API Key', value: 'create' },
|
||||
{ name: '📝 更新 API Key', value: 'update' },
|
||||
{ name: '🗑️ 删除 API Key', value: 'delete' },
|
||||
{ name: '📊 查看使用统计', value: 'stats' },
|
||||
{ name: '🧹 重置所有统计数据', value: 'reset-stats' }
|
||||
]
|
||||
});
|
||||
|
||||
switch (action) {
|
||||
case 'list':
|
||||
await listApiKeys();
|
||||
break;
|
||||
case 'create':
|
||||
await createApiKey();
|
||||
break;
|
||||
case 'update':
|
||||
await updateApiKey();
|
||||
break;
|
||||
case 'delete':
|
||||
await deleteApiKey();
|
||||
break;
|
||||
case 'stats':
|
||||
await viewApiKeyStats();
|
||||
break;
|
||||
case 'reset-stats':
|
||||
await resetAllApiKeyStats();
|
||||
break;
|
||||
}
|
||||
|
||||
await redis.disconnect();
|
||||
});
|
||||
|
||||
// 🏢 Claude 账户管理
|
||||
program
|
||||
.command('accounts')
|
||||
.description('Claude 账户管理')
|
||||
.action(async () => {
|
||||
await initialize();
|
||||
|
||||
const { action } = await inquirer.prompt({
|
||||
type: 'list',
|
||||
name: 'action',
|
||||
message: '选择操作:',
|
||||
choices: [
|
||||
{ name: '📋 列出所有账户', value: 'list' },
|
||||
{ name: '🏢 创建新账户', value: 'create' },
|
||||
{ name: '📝 更新账户', value: 'update' },
|
||||
{ name: '🗑️ 删除账户', value: 'delete' },
|
||||
{ name: '🔄 刷新 Token', value: 'refresh' },
|
||||
{ name: '🧪 测试账户', value: 'test' }
|
||||
]
|
||||
});
|
||||
|
||||
switch (action) {
|
||||
case 'list':
|
||||
await listClaudeAccounts();
|
||||
break;
|
||||
case 'create':
|
||||
await createClaudeAccount();
|
||||
break;
|
||||
case 'update':
|
||||
await updateClaudeAccount();
|
||||
break;
|
||||
case 'delete':
|
||||
await deleteClaudeAccount();
|
||||
break;
|
||||
case 'refresh':
|
||||
await refreshAccountToken();
|
||||
break;
|
||||
case 'test':
|
||||
await testClaudeAccount();
|
||||
break;
|
||||
}
|
||||
|
||||
await redis.disconnect();
|
||||
});
|
||||
|
||||
// 🧹 重置统计数据命令
|
||||
program
|
||||
.command('reset-stats')
|
||||
.description('重置所有API Key的统计数据')
|
||||
.option('--force', '跳过确认直接重置')
|
||||
.option('--debug', '显示详细的Redis键调试信息')
|
||||
.action(async (options) => {
|
||||
await initialize();
|
||||
|
||||
console.log(styles.title('\n🧹 重置所有API Key统计数据\n'));
|
||||
|
||||
// 如果启用调试,显示当前Redis键
|
||||
if (options.debug) {
|
||||
console.log(styles.info('🔍 调试模式: 检查Redis中的实际键...\n'));
|
||||
try {
|
||||
const usageKeys = await redis.getClient().keys('usage:*');
|
||||
const apiKeyKeys = await redis.getClient().keys('apikey:*');
|
||||
|
||||
console.log(styles.dim('API Key 键:'));
|
||||
apiKeyKeys.forEach(key => console.log(` ${key}`));
|
||||
|
||||
console.log(styles.dim('\nUsage 键:'));
|
||||
usageKeys.forEach(key => console.log(` ${key}`));
|
||||
|
||||
// 检查今日统计键
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
const dailyKeys = await redis.getClient().keys(`usage:daily:*:${today}`);
|
||||
console.log(styles.dim(`\n今日统计键 (${today}):`));
|
||||
dailyKeys.forEach(key => console.log(` ${key}`));
|
||||
|
||||
console.log('');
|
||||
} catch (error) {
|
||||
console.error(styles.error('调试信息获取失败:', error.message));
|
||||
}
|
||||
}
|
||||
|
||||
// 显示警告信息
|
||||
console.log(styles.warning('⚠️ 警告: 此操作将删除所有API Key的使用统计数据!'));
|
||||
console.log(styles.dim(' 包括: Token使用量、请求数量、每日/每月统计、最后使用时间等'));
|
||||
console.log(styles.dim(' 此操作不可逆,请谨慎操作!\n'));
|
||||
|
||||
if (!options.force) {
|
||||
console.log(styles.info('如需强制执行,请使用: npm run cli reset-stats -- --force\n'));
|
||||
console.log(styles.error('操作已取消 - 请添加 --force 参数确认重置'));
|
||||
await redis.disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取当前统计概览
|
||||
const spinner = ora('正在获取当前统计数据...').start();
|
||||
try {
|
||||
const apiKeys = await apiKeyService.getAllApiKeys();
|
||||
const totalTokens = apiKeys.reduce((sum, key) => sum + (key.usage?.total?.tokens || 0), 0);
|
||||
const totalRequests = apiKeys.reduce((sum, key) => sum + (key.usage?.total?.requests || 0), 0);
|
||||
|
||||
spinner.succeed('统计数据获取完成');
|
||||
|
||||
console.log(styles.info('\n📊 当前统计概览:'));
|
||||
console.log(` API Keys 数量: ${apiKeys.length}`);
|
||||
console.log(` 总 Token 使用量: ${totalTokens.toLocaleString()}`);
|
||||
console.log(` 总请求数量: ${totalRequests.toLocaleString()}\n`);
|
||||
|
||||
// 执行重置操作
|
||||
const resetSpinner = ora('正在重置所有API Key统计数据...').start();
|
||||
|
||||
const stats = await redis.resetAllUsageStats();
|
||||
|
||||
resetSpinner.succeed('所有统计数据重置完成');
|
||||
|
||||
// 显示重置结果
|
||||
console.log(styles.success('\n✅ 重置操作完成!\n'));
|
||||
console.log(styles.info('📊 重置详情:'));
|
||||
console.log(` 重置的API Key数量: ${stats.resetApiKeys}`);
|
||||
console.log(` 删除的总体统计: ${stats.deletedKeys} 个`);
|
||||
console.log(` 删除的每日统计: ${stats.deletedDailyKeys} 个`);
|
||||
console.log(` 删除的每月统计: ${stats.deletedMonthlyKeys} 个`);
|
||||
|
||||
console.log(styles.warning('\n💡 提示: API Key本身未被删除,只是清空了使用统计数据'));
|
||||
|
||||
} catch (error) {
|
||||
spinner.fail('重置操作失败');
|
||||
console.error(styles.error(error.message));
|
||||
}
|
||||
|
||||
await redis.disconnect();
|
||||
});
|
||||
|
||||
// 📊 系统状态
|
||||
program
|
||||
@@ -304,47 +98,6 @@ program
|
||||
await redis.disconnect();
|
||||
});
|
||||
|
||||
// 🧹 清理命令
|
||||
program
|
||||
.command('cleanup')
|
||||
.description('清理过期数据')
|
||||
.action(async () => {
|
||||
await initialize();
|
||||
|
||||
const { confirm } = await inquirer.prompt({
|
||||
type: 'confirm',
|
||||
name: 'confirm',
|
||||
message: '确定要清理过期数据吗?',
|
||||
default: false
|
||||
});
|
||||
|
||||
if (!confirm) {
|
||||
console.log(styles.warning('操作已取消'));
|
||||
await redis.disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
const spinner = ora('正在清理过期数据...').start();
|
||||
|
||||
try {
|
||||
const [expiredKeys, errorAccounts] = await Promise.all([
|
||||
apiKeyService.cleanupExpiredKeys(),
|
||||
claudeAccountService.cleanupErrorAccounts()
|
||||
]);
|
||||
|
||||
await redis.cleanup();
|
||||
|
||||
spinner.succeed('清理完成');
|
||||
console.log(`${styles.success('✅')} 清理了 ${expiredKeys} 个过期 API Key`);
|
||||
console.log(`${styles.success('✅')} 重置了 ${errorAccounts} 个错误账户`);
|
||||
|
||||
} catch (error) {
|
||||
spinner.fail('清理失败');
|
||||
console.error(styles.error(error.message));
|
||||
}
|
||||
|
||||
await redis.disconnect();
|
||||
});
|
||||
|
||||
// 实现具体功能函数
|
||||
|
||||
@@ -397,315 +150,10 @@ async function createInitialAdmin() {
|
||||
}
|
||||
}
|
||||
|
||||
async function setAdminPassword() {
|
||||
console.log(styles.title('\n🔑 设置管理员密码\n'));
|
||||
|
||||
const passwordData = await inquirer.prompt([
|
||||
{
|
||||
type: 'password',
|
||||
name: 'newPassword',
|
||||
message: '新密码:',
|
||||
validate: input => input.length >= 8 || '密码至少8个字符'
|
||||
},
|
||||
{
|
||||
type: 'password',
|
||||
name: 'confirmPassword',
|
||||
message: '确认密码:',
|
||||
validate: (input, answers) => input === answers.newPassword || '密码不匹配'
|
||||
}
|
||||
]);
|
||||
|
||||
const spinner = ora('正在更新密码...').start();
|
||||
|
||||
try {
|
||||
const adminData = await redis.getSession('admin_credentials');
|
||||
|
||||
if (!adminData || Object.keys(adminData).length === 0) {
|
||||
spinner.fail('未找到管理员账户');
|
||||
console.log(styles.warning('请先创建初始管理员账户'));
|
||||
return;
|
||||
}
|
||||
|
||||
const passwordHash = await bcrypt.hash(passwordData.newPassword, 12);
|
||||
adminData.passwordHash = passwordHash;
|
||||
adminData.updatedAt = new Date().toISOString();
|
||||
|
||||
await redis.setSession('admin_credentials', adminData, 0);
|
||||
|
||||
spinner.succeed('密码更新成功');
|
||||
console.log(`${styles.success('✅')} 管理员密码已更新`);
|
||||
|
||||
} catch (error) {
|
||||
spinner.fail('密码更新失败');
|
||||
console.error(styles.error(error.message));
|
||||
}
|
||||
}
|
||||
|
||||
async function listApiKeys() {
|
||||
const spinner = ora('正在获取 API Keys...').start();
|
||||
|
||||
try {
|
||||
const apiKeys = await apiKeyService.getAllApiKeys();
|
||||
spinner.succeed(`找到 ${apiKeys.length} 个 API Key`);
|
||||
|
||||
if (apiKeys.length === 0) {
|
||||
console.log(styles.warning('没有找到任何 API Key'));
|
||||
return;
|
||||
}
|
||||
|
||||
const tableData = [
|
||||
['ID', '名称', '状态', 'Token使用', '请求数', '创建时间']
|
||||
];
|
||||
|
||||
apiKeys.forEach(key => {
|
||||
tableData.push([
|
||||
key.id.substring(0, 8) + '...',
|
||||
key.name,
|
||||
key.isActive ? '🟢 活跃' : '🔴 停用',
|
||||
key.usage?.total?.tokens?.toLocaleString() || '0',
|
||||
key.usage?.total?.requests?.toLocaleString() || '0',
|
||||
new Date(key.createdAt).toLocaleDateString()
|
||||
]);
|
||||
});
|
||||
|
||||
console.log('\n📋 API Keys 列表:\n');
|
||||
console.log(table(tableData));
|
||||
|
||||
} catch (error) {
|
||||
spinner.fail('获取 API Keys 失败');
|
||||
console.error(styles.error(error.message));
|
||||
}
|
||||
}
|
||||
|
||||
async function createApiKey() {
|
||||
console.log(styles.title('\n🔑 创建新的 API Key\n'));
|
||||
|
||||
const keyData = await inquirer.prompt([
|
||||
{
|
||||
type: 'input',
|
||||
name: 'name',
|
||||
message: 'API Key 名称:',
|
||||
validate: input => input.length > 0 || '名称不能为空'
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
name: 'description',
|
||||
message: '描述 (可选):'
|
||||
},
|
||||
{
|
||||
type: 'number',
|
||||
name: 'tokenLimit',
|
||||
message: 'Token 限制 (0=无限制):',
|
||||
default: 1000000
|
||||
},
|
||||
]);
|
||||
|
||||
const spinner = ora('正在创建 API Key...').start();
|
||||
|
||||
try {
|
||||
const newKey = await apiKeyService.generateApiKey(keyData);
|
||||
|
||||
spinner.succeed('API Key 创建成功');
|
||||
console.log(`${styles.success('✅')} API Key: ${styles.warning(newKey.apiKey)}`);
|
||||
console.log(`${styles.info('ℹ️')} 请妥善保管此 API Key,它只会显示一次`);
|
||||
|
||||
} catch (error) {
|
||||
spinner.fail('创建 API Key 失败');
|
||||
console.error(styles.error(error.message));
|
||||
}
|
||||
}
|
||||
|
||||
async function resetAllApiKeyStats() {
|
||||
console.log(styles.title('\n🧹 重置所有API Key统计数据\n'));
|
||||
|
||||
// 显示警告信息
|
||||
console.log(styles.warning('⚠️ 警告: 此操作将删除所有API Key的使用统计数据!'));
|
||||
console.log(styles.dim(' 包括: Token使用量、请求数量、每日/每月统计、最后使用时间等'));
|
||||
console.log(styles.dim(' 此操作不可逆,请谨慎操作!\n'));
|
||||
|
||||
// 第一次确认
|
||||
const { firstConfirm } = await inquirer.prompt({
|
||||
type: 'confirm',
|
||||
name: 'firstConfirm',
|
||||
message: '您确定要重置所有API Key的统计数据吗?',
|
||||
default: false
|
||||
});
|
||||
|
||||
if (!firstConfirm) {
|
||||
console.log(styles.info('操作已取消'));
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取当前统计概览
|
||||
const spinner = ora('正在获取当前统计数据...').start();
|
||||
try {
|
||||
const apiKeys = await apiKeyService.getAllApiKeys();
|
||||
const totalTokens = apiKeys.reduce((sum, key) => sum + (key.usage?.total?.tokens || 0), 0);
|
||||
const totalRequests = apiKeys.reduce((sum, key) => sum + (key.usage?.total?.requests || 0), 0);
|
||||
|
||||
spinner.succeed('统计数据获取完成');
|
||||
|
||||
console.log(styles.info('\n📊 当前统计概览:'));
|
||||
console.log(` API Keys 数量: ${apiKeys.length}`);
|
||||
console.log(` 总 Token 使用量: ${totalTokens.toLocaleString()}`);
|
||||
console.log(` 总请求数量: ${totalRequests.toLocaleString()}\n`);
|
||||
|
||||
// 第二次确认(需要输入"RESET")
|
||||
const { confirmation } = await inquirer.prompt({
|
||||
type: 'input',
|
||||
name: 'confirmation',
|
||||
message: '请输入 "RESET" 来确认重置操作:',
|
||||
validate: input => input === 'RESET' || '请输入正确的确认文本 "RESET"'
|
||||
});
|
||||
|
||||
if (confirmation !== 'RESET') {
|
||||
console.log(styles.info('操作已取消'));
|
||||
return;
|
||||
}
|
||||
|
||||
// 执行重置操作
|
||||
const resetSpinner = ora('正在重置所有API Key统计数据...').start();
|
||||
|
||||
const stats = await redis.resetAllUsageStats();
|
||||
|
||||
resetSpinner.succeed('所有统计数据重置完成');
|
||||
|
||||
// 显示重置结果
|
||||
console.log(styles.success('\n✅ 重置操作完成!\n'));
|
||||
console.log(styles.info('📊 重置详情:'));
|
||||
console.log(` 重置的API Key数量: ${stats.resetApiKeys}`);
|
||||
console.log(` 删除的总体统计: ${stats.deletedKeys} 个`);
|
||||
console.log(` 删除的每日统计: ${stats.deletedDailyKeys} 个`);
|
||||
console.log(` 删除的每月统计: ${stats.deletedMonthlyKeys} 个`);
|
||||
|
||||
console.log(styles.warning('\n💡 提示: API Key本身未被删除,只是清空了使用统计数据'));
|
||||
|
||||
} catch (error) {
|
||||
spinner.fail('重置操作失败');
|
||||
console.error(styles.error(error.message));
|
||||
}
|
||||
}
|
||||
|
||||
async function viewApiKeyStats() {
|
||||
console.log(styles.title('\n📊 API Key 使用统计\n'));
|
||||
|
||||
const spinner = ora('正在获取统计数据...').start();
|
||||
|
||||
try {
|
||||
const apiKeys = await apiKeyService.getAllApiKeys();
|
||||
|
||||
if (apiKeys.length === 0) {
|
||||
spinner.succeed('获取完成');
|
||||
console.log(styles.warning('没有找到任何 API Key'));
|
||||
return;
|
||||
}
|
||||
|
||||
spinner.succeed(`找到 ${apiKeys.length} 个 API Key 的统计数据`);
|
||||
|
||||
const tableData = [
|
||||
['名称', 'Token总量', '输入Token', '输出Token', '请求数', '最后使用']
|
||||
];
|
||||
|
||||
let totalTokens = 0;
|
||||
let totalRequests = 0;
|
||||
|
||||
apiKeys.forEach(key => {
|
||||
const usage = key.usage?.total || {};
|
||||
const tokens = usage.tokens || 0;
|
||||
const inputTokens = usage.inputTokens || 0;
|
||||
const outputTokens = usage.outputTokens || 0;
|
||||
const requests = usage.requests || 0;
|
||||
|
||||
totalTokens += tokens;
|
||||
totalRequests += requests;
|
||||
|
||||
tableData.push([
|
||||
key.name,
|
||||
tokens.toLocaleString(),
|
||||
inputTokens.toLocaleString(),
|
||||
outputTokens.toLocaleString(),
|
||||
requests.toLocaleString(),
|
||||
key.lastUsedAt ? new Date(key.lastUsedAt).toLocaleDateString() : '从未使用'
|
||||
]);
|
||||
});
|
||||
|
||||
console.log(table(tableData));
|
||||
|
||||
console.log(styles.info('\n📈 总计统计:'));
|
||||
console.log(`总 Token 使用量: ${styles.success(totalTokens.toLocaleString())}`);
|
||||
console.log(`总请求数量: ${styles.success(totalRequests.toLocaleString())}`);
|
||||
|
||||
} catch (error) {
|
||||
spinner.fail('获取统计数据失败');
|
||||
console.error(styles.error(error.message));
|
||||
}
|
||||
}
|
||||
|
||||
async function updateApiKey() {
|
||||
console.log(styles.title('\n📝 更新 API Key\n'));
|
||||
console.log(styles.warning('功能开发中...'));
|
||||
}
|
||||
|
||||
async function deleteApiKey() {
|
||||
console.log(styles.title('\n🗑️ 删除 API Key\n'));
|
||||
console.log(styles.warning('功能开发中...'));
|
||||
}
|
||||
|
||||
async function resetAdminPassword() {
|
||||
console.log(styles.title('\n🔄 重置管理员密码\n'));
|
||||
console.log(styles.warning('功能开发中...'));
|
||||
}
|
||||
|
||||
async function viewAdminInfo() {
|
||||
console.log(styles.title('\n👤 管理员信息\n'));
|
||||
|
||||
const spinner = ora('正在获取管理员信息...').start();
|
||||
|
||||
try {
|
||||
const adminData = await redis.getSession('admin_credentials');
|
||||
|
||||
if (!adminData || Object.keys(adminData).length === 0) {
|
||||
spinner.fail('未找到管理员账户');
|
||||
console.log(styles.warning('请先创建初始管理员账户'));
|
||||
return;
|
||||
}
|
||||
|
||||
spinner.succeed('管理员信息获取成功');
|
||||
|
||||
console.log(`用户名: ${styles.info(adminData.username)}`);
|
||||
console.log(`创建时间: ${styles.dim(new Date(adminData.createdAt).toLocaleString())}`);
|
||||
console.log(`最后登录: ${adminData.lastLogin ? styles.dim(new Date(adminData.lastLogin).toLocaleString()) : '从未登录'}`);
|
||||
|
||||
} catch (error) {
|
||||
spinner.fail('获取管理员信息失败');
|
||||
console.error(styles.error(error.message));
|
||||
}
|
||||
}
|
||||
|
||||
async function createClaudeAccount() {
|
||||
console.log(styles.title('\n🏢 创建 Claude 账户\n'));
|
||||
console.log(styles.warning('功能开发中... 请使用Web界面创建OAuth账户'));
|
||||
}
|
||||
|
||||
async function updateClaudeAccount() {
|
||||
console.log(styles.title('\n📝 更新 Claude 账户\n'));
|
||||
console.log(styles.warning('功能开发中...'));
|
||||
}
|
||||
|
||||
async function deleteClaudeAccount() {
|
||||
console.log(styles.title('\n🗑️ 删除 Claude 账户\n'));
|
||||
console.log(styles.warning('功能开发中...'));
|
||||
}
|
||||
|
||||
async function refreshAccountToken() {
|
||||
console.log(styles.title('\n🔄 刷新账户 Token\n'));
|
||||
console.log(styles.warning('功能开发中...'));
|
||||
}
|
||||
|
||||
async function testClaudeAccount() {
|
||||
console.log(styles.title('\n🧪 测试 Claude 账户\n'));
|
||||
console.log(styles.warning('功能开发中...'));
|
||||
}
|
||||
|
||||
async function listClaudeAccounts() {
|
||||
const spinner = ora('正在获取 Claude 账户...').start();
|
||||
@@ -756,11 +204,7 @@ program.parse();
|
||||
if (!process.argv.slice(2).length) {
|
||||
console.log(styles.title('🚀 Claude Relay Service CLI\n'));
|
||||
console.log('使用以下命令管理服务:\n');
|
||||
console.log(' claude-relay-cli admin - 管理员账户操作');
|
||||
console.log(' claude-relay-cli keys - API Key 管理 (包含重置统计数据)');
|
||||
console.log(' claude-relay-cli accounts - Claude 账户管理');
|
||||
console.log(' claude-relay-cli admin - 创建初始管理员账户');
|
||||
console.log(' claude-relay-cli status - 查看系统状态');
|
||||
console.log(' claude-relay-cli cleanup - 清理过期数据');
|
||||
console.log(' claude-relay-cli reset-stats - 重置所有API Key统计数据');
|
||||
console.log('\n使用 --help 查看详细帮助信息');
|
||||
}
|
||||
Reference in New Issue
Block a user