cc-code-status
Version:
Enhanced Claude Code launcher with statusline - supports multiple custom API configurations and code statistics
514 lines • 20 kB
JavaScript
;
/**
* CLI 主入口
* v2.0.0 - 增强版 Claude Code 启动器 + 状态栏插件
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.main = main;
const chalk_1 = __importDefault(require("chalk"));
const inquirer_1 = __importDefault(require("inquirer"));
const extended_manager_1 = require("./config/extended-manager");
const extended_launcher_1 = require("./launcher/extended-launcher");
const prompts_1 = require("./ui/prompts");
const welcome_1 = require("./ui/welcome");
const ccgo_1 = require("ccgo");
const logger_1 = require("./utils/logger");
const packageJson = require('../package.json');
// 解析命令行参数
const args = process.argv.slice(2);
const command = args[0];
// 主函数
async function main() {
try {
// ========== 版本和帮助 ==========
if (args.includes('-v') || args.includes('--version')) {
console.log('CC Code Status v' + packageJson.version);
return;
}
if (command === 'help' || command === '--help' || command === '-h') {
(0, welcome_1.showHelp)();
return;
}
// ========== 配置命令 ==========
if (command === 'config') {
await handleConfigCommand(args.slice(1));
return;
}
// ========== 统计命令 ==========
if (command === 'stats' || command === 'week') {
await handleStatsCommand(args);
return;
}
// ========== 同步命令 ==========
if (command === 'sync-enable' || command === 'sync-disable' ||
command === 'sync-status' || command === 'sync-now' ||
command === 'sync' || command === 'custom-sync') {
await handleSyncCommand(args);
return;
}
// ========== 排除命令 ==========
if (command === 'exclude') {
await handleExcludeCommand(args.slice(1));
return;
}
// ========== 旧版命令(向后兼容)==========
if (command === 'setup' || command === 'install') {
await handleSetup();
return;
}
if (command === 'uninstall') {
await handleUninstall();
return;
}
// ========== 状态栏模式 ==========
// 检测是否为状态栏模式(通过 stdin 调用)
if (command === '--statusline' || !process.stdin.isTTY) {
await runAsStatusLine();
return;
}
// ========== 默认:启动器模式 ==========
await runAsLauncher(args);
}
catch (error) {
logger_1.Logger.error('程序执行失败: ' + error.message);
if (process.env.DEBUG) {
console.error(error);
}
process.exit(1);
}
}
/**
* 处理 config 命令
*/
async function handleConfigCommand(subArgs) {
const config = new extended_manager_1.ExtendedConfigManager();
const subCommand = subArgs[0];
// config list - 列出所有配置
if (subCommand === 'list') {
const profiles = config.getAllProfiles();
if (profiles.length === 0) {
logger_1.Logger.warning('当前没有配置');
logger_1.Logger.info('运行 ccs config add 添加配置');
return;
}
console.log(chalk_1.default.cyan('\n📋 配置列表\n'));
console.log(chalk_1.default.gray('─'.repeat(70)));
profiles.forEach(p => {
const safeKey = p.apiKey.length > 12
? `${p.apiKey.substring(0, 8)}...${p.apiKey.substring(p.apiKey.length - 4)}`
: '***';
// 从 baseUrl 提取域名
let domain = p.baseUrl;
try {
const url = new URL(p.baseUrl);
domain = url.hostname;
}
catch (e) {
// 如果不是有效 URL,使用原始值
}
console.log(chalk_1.default.white.bold('● ' + p.name));
console.log(chalk_1.default.gray(` Base URL: ${p.baseUrl}`));
console.log(chalk_1.default.gray(` API Key: ${safeKey}`));
if (p.model) {
console.log(chalk_1.default.gray(` Model: ${p.model}`));
}
if (p.smallFastModel) {
console.log(chalk_1.default.gray(` Small Fast Model: ${p.smallFastModel}`));
}
console.log('');
});
console.log(chalk_1.default.gray('─'.repeat(70)));
console.log(chalk_1.default.gray(`\n配置文件: ${config.getConfigPath()}\n`));
return;
}
// config add - 添加新配置
if (subCommand === 'add') {
(0, welcome_1.showWelcome)();
const answers = await (0, prompts_1.showConfigPrompts)();
// 检查配置是否已存在
if (config.hasProfile(answers.name)) {
const { confirm } = await inquirer_1.default.prompt([
{
type: 'confirm',
name: 'confirm',
message: chalk_1.default.yellow(`配置 "${answers.name}" 已存在,是否覆盖?`),
default: false
}
]);
if (!confirm) {
logger_1.Logger.info('已取消');
return;
}
}
config.saveProfile(answers.name, {
apiKey: answers.apiKey,
baseUrl: answers.baseUrl,
model: answers.model,
smallFastModel: answers.smallFastModel
});
logger_1.Logger.success(`配置 "${answers.name}" 已保存`);
console.log('');
return;
}
// config remove <name> - 删除配置
if (subCommand === 'remove' || subCommand === 'rm') {
const name = subArgs[1];
if (!name) {
logger_1.Logger.error('请指定要删除的配置名称');
console.log('');
console.log('用法: ccs config remove <配置名称>');
console.log('');
return;
}
if (!config.hasProfile(name)) {
logger_1.Logger.error(`配置 "${name}" 不存在`);
console.log('');
console.log('使用 ccs config list 查看所有配置');
console.log('');
return;
}
const { confirm } = await inquirer_1.default.prompt([
{
type: 'confirm',
name: 'confirm',
message: chalk_1.default.yellow(`确定要删除配置 "${name}" 吗?`),
default: false
}
]);
if (!confirm) {
logger_1.Logger.info('已取消');
return;
}
config.removeProfile(name);
logger_1.Logger.success(`配置 "${name}" 已删除`);
console.log('');
return;
}
// config show / config --show - 显示配置(单个配置时显示详情,多个配置时显示列表)
if (subCommand === 'show' || subArgs.includes('--show')) {
const profiles = config.getAllProfiles();
if (profiles.length === 0) {
logger_1.Logger.warning('当前没有配置');
logger_1.Logger.info('运行 ccs config add 添加配置');
return;
}
// 如果只有一个配置,显示详情
if (profiles.length === 1) {
const current = profiles[0];
const safeKey = current.apiKey.length > 12
? `${current.apiKey.substring(0, 8)}...${current.apiKey.substring(current.apiKey.length - 4)}`
: '***';
console.log(chalk_1.default.cyan('\n📝 当前配置'));
console.log(chalk_1.default.gray('─'.repeat(70)));
console.log(chalk_1.default.white('配置名称: ') + chalk_1.default.green(current.name));
console.log(chalk_1.default.white('Base URL: ') + chalk_1.default.cyan(current.baseUrl));
console.log(chalk_1.default.white('API Key: ') + chalk_1.default.yellow(safeKey));
if (current.model) {
console.log(chalk_1.default.white('Model: ') + chalk_1.default.gray(current.model));
}
if (current.smallFastModel) {
console.log(chalk_1.default.white('Small Fast Model: ') + chalk_1.default.gray(current.smallFastModel));
}
console.log(chalk_1.default.white('配置时间: ') + chalk_1.default.gray(new Date(current.configuredAt).toLocaleString('zh-CN')));
console.log(chalk_1.default.gray('─'.repeat(70)));
console.log(chalk_1.default.gray(`配置文件: ${config.getConfigPath()}\n`));
}
else {
// 多个配置时,显示提示
logger_1.Logger.info(`当前有 ${profiles.length} 个配置,启动时将提示选择`);
console.log('');
console.log('使用 ccs config list 查看所有配置');
console.log('');
}
return;
}
// config --reset - 重置所有配置
if (subArgs.includes('--reset')) {
if (!config.hasAnyProfile()) {
logger_1.Logger.warning('当前没有配置');
return;
}
const { confirm } = await inquirer_1.default.prompt([
{
type: 'confirm',
name: 'confirm',
message: chalk_1.default.red('⚠️ 确定要删除所有配置吗?此操作不可恢复!'),
default: false
}
]);
if (!confirm) {
logger_1.Logger.info('已取消');
return;
}
config.reset();
logger_1.Logger.success('所有配置已重置');
logger_1.Logger.info('下次运行 ccs 时将重新配置');
console.log('');
return;
}
// config (无子命令) - 显示帮助或添加第一个配置
if (!subCommand) {
if (!config.hasAnyProfile()) {
// 如果没有配置,引导添加第一个配置
(0, welcome_1.showWelcome)();
const answers = await (0, prompts_1.showConfigPrompts)('default');
config.saveProfile(answers.name, {
apiKey: answers.apiKey,
baseUrl: answers.baseUrl,
model: answers.model,
smallFastModel: answers.smallFastModel
});
(0, welcome_1.showConfigSuccess)();
console.log('');
}
else {
// 如果已有配置,显示配置管理帮助
console.log(chalk_1.default.cyan('\n⚙️ 配置管理\n'));
console.log('可用命令:');
console.log('');
console.log(chalk_1.default.white(' ccs config list ') + chalk_1.default.gray('列出所有配置'));
console.log(chalk_1.default.white(' ccs config add ') + chalk_1.default.gray('添加新配置'));
console.log(chalk_1.default.white(' ccs config remove <名称> ') + chalk_1.default.gray('删除指定配置'));
console.log(chalk_1.default.white(' ccs config show ') + chalk_1.default.gray('显示当前配置'));
console.log(chalk_1.default.white(' ccs config --reset ') + chalk_1.default.gray('重置所有配置'));
console.log('');
}
return;
}
// 未知子命令
logger_1.Logger.error(`未知的子命令: ${subCommand}`);
console.log('');
console.log('运行 ccs config 查看帮助');
console.log('');
}
/**
* 处理统计命令
*/
async function handleStatsCommand(args) {
const subCommand = args[0] === 'stats' ? args[1] : args[0];
if (subCommand === 'week' || args[0] === 'week') {
// 引入旧版的 showWeekStats 函数
const { showWeekStats } = await Promise.resolve().then(() => __importStar(require('./cli-legacy')));
showWeekStats();
}
else if (subCommand === 'today') {
// 显示今日统计
const { StatusLinePlugin } = await Promise.resolve().then(() => __importStar(require('./index')));
const plugin = new StatusLinePlugin();
const stats = await plugin.getTodayStats();
console.log('');
console.log(chalk_1.default.cyan('📊 今日统计'));
console.log('');
console.log(`对话: ${stats.conversations}次/${stats.rounds}轮`);
console.log(`代码: +${stats.codeAdded}/-${stats.codeDeleted} 行`);
console.log('');
}
else {
logger_1.Logger.error('未知的统计命令');
console.log('');
console.log('可用命令:');
console.log(' ccs stats today 显示今日统计');
console.log(' ccs stats week 显示本周统计');
console.log('');
}
}
/**
* 处理同步命令
*/
async function handleSyncCommand(args) {
const command = args[0];
// 引入旧版的同步函数
const { setSyncEnabled, showSyncStatus, manualSync, customSync } = await Promise.resolve().then(() => __importStar(require('./cli-legacy')));
if (command === 'sync-enable') {
setSyncEnabled(true);
}
else if (command === 'sync-disable') {
setSyncEnabled(false);
}
else if (command === 'sync-status') {
showSyncStatus();
}
else if (command === 'sync-now' || command === 'sync') {
await manualSync();
}
else if (command === 'custom-sync') {
await customSync();
}
}
/**
* 处理排除命令
*/
async function handleExcludeCommand(subArgs) {
const { handleExclude } = await Promise.resolve().then(() => __importStar(require('./cli-legacy')));
handleExclude(subArgs);
}
/**
* 处理 setup 命令(旧版兼容)
*/
async function handleSetup() {
const { setup } = await Promise.resolve().then(() => __importStar(require('./cli-legacy')));
setup();
}
/**
* 处理 uninstall 命令(旧版兼容)
*/
async function handleUninstall() {
const { uninstall } = await Promise.resolve().then(() => __importStar(require('./cli-legacy')));
uninstall();
}
/**
* 作为状态栏插件运行
*/
async function runAsStatusLine() {
const { StatusLinePlugin } = await Promise.resolve().then(() => __importStar(require('./index')));
const plugin = new StatusLinePlugin();
await plugin.run().catch(() => {
console.log('Error');
});
}
/**
* 作为启动器运行
*/
async function runAsLauncher(args) {
const config = new extended_manager_1.ExtendedConfigManager();
// 检查是否有配置
if (!config.hasAnyProfile()) {
console.log('');
logger_1.Logger.info('首次使用需要配置 API');
console.log('');
// 显示欢迎信息
(0, welcome_1.showWelcome)();
// 交互式配置
const answers = await (0, prompts_1.showConfigPrompts)('default');
// 保存配置
config.saveProfile(answers.name, {
apiKey: answers.apiKey,
baseUrl: answers.baseUrl,
model: answers.model,
smallFastModel: answers.smallFastModel
});
// 显示成功信息
(0, welcome_1.showConfigSuccess)();
// 短暂延迟
await new Promise(resolve => setTimeout(resolve, 1000));
}
// 如果有配置,检查是否需要选择配置
let selectedProfileName;
if (config.hasAnyProfile()) {
// 如果有多个配置,需要用户选择
const profileCount = config.getProfileCount();
// 检查命令行参数中是否指定了配置
const profileArgIndex = args.findIndex(arg => arg === '--profile' || arg === '-p');
if (profileArgIndex !== -1 && args[profileArgIndex + 1]) {
// 通过命令行参数指定配置
selectedProfileName = args[profileArgIndex + 1];
if (!config.hasProfile(selectedProfileName)) {
logger_1.Logger.error(`配置 "${selectedProfileName}" 不存在`);
console.log('');
console.log('使用 ccs config list 查看所有配置');
console.log('');
process.exit(1);
}
// 移除 --profile 参数(避免传递给 Claude)
args.splice(profileArgIndex, 2);
}
else if (profileCount > 1) {
// 如果有多个配置,让用户选择
const profiles = config.getAllProfiles().map(p => ({
name: p.name,
config: p
}));
console.log('');
logger_1.Logger.info('检测到多个配置,请选择要使用的配置');
console.log('');
selectedProfileName = await (0, prompts_1.selectProfile)(profiles);
console.log('');
logger_1.Logger.success(`已选择配置: ${selectedProfileName}`);
console.log('');
// 短暂延迟
await new Promise(resolve => setTimeout(resolve, 500));
}
}
// 检查 Claude Code 是否已安装
if (!(0, ccgo_1.checkClaudeInstallation)()) {
process.exit(1);
}
// 显示当前使用的配置
let displayProfile;
if (selectedProfileName) {
// 使用选中的配置
const profile = config.getProfile(selectedProfileName);
if (profile) {
displayProfile = { name: selectedProfileName, baseUrl: profile.baseUrl };
}
}
else {
// 使用唯一配置
const current = config.getCurrentProfile();
if (current) {
displayProfile = { name: current.name, baseUrl: current.config.baseUrl };
}
}
if (displayProfile) {
// 从 baseUrl 提取域名
let domain = displayProfile.baseUrl;
try {
const url = new URL(displayProfile.baseUrl);
domain = url.hostname;
}
catch (e) {
// 如果不是有效 URL,使用原始值
}
console.log(chalk_1.default.gray(`使用配置: ${displayProfile.name} (${domain})\n`));
}
// 启动 Claude Code
const launcher = new extended_launcher_1.ExtendedClaudeLauncher(config, selectedProfileName);
const { exitCode } = await launcher.launch({
args,
skipPermissions: true,
showStats: true
});
process.exit(exitCode);
}
// 运行主函数
if (require.main === module) {
main();
}
//# sourceMappingURL=cli.js.map