cc-code-status 1.1.5 → 2.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.
- package/README.md +309 -27
- package/dist/cli-legacy.d.ts +13 -0
- package/dist/cli-legacy.d.ts.map +1 -0
- package/dist/cli-legacy.js +535 -0
- package/dist/cli-legacy.js.map +1 -0
- package/dist/cli.backup.d.ts +3 -0
- package/dist/cli.backup.d.ts.map +1 -0
- package/dist/cli.backup.js +661 -0
- package/dist/cli.backup.js.map +1 -0
- package/dist/cli.d.ts +6 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +428 -393
- package/dist/cli.js.map +1 -1
- package/dist/config/constants.d.ts +17 -0
- package/dist/config/constants.d.ts.map +1 -0
- package/dist/config/constants.js +42 -0
- package/dist/config/constants.js.map +1 -0
- package/dist/config/manager.d.ts +121 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +273 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/config/validator.d.ts +17 -0
- package/dist/config/validator.d.ts.map +1 -0
- package/dist/config/validator.js +39 -0
- package/dist/config/validator.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +142 -5
- package/dist/index.js.map +1 -1
- package/dist/launcher.d.ts +27 -0
- package/dist/launcher.d.ts.map +1 -0
- package/dist/launcher.js +145 -0
- package/dist/launcher.js.map +1 -0
- package/dist/ui/prompts.d.ts +34 -0
- package/dist/ui/prompts.d.ts.map +1 -0
- package/dist/ui/prompts.js +192 -0
- package/dist/ui/prompts.js.map +1 -0
- package/dist/ui/welcome.d.ts +30 -0
- package/dist/ui/welcome.d.ts.map +1 -0
- package/dist/ui/welcome.js +95 -0
- package/dist/ui/welcome.js.map +1 -0
- package/dist/utils/installer.d.ts +15 -0
- package/dist/utils/installer.d.ts.map +1 -0
- package/dist/utils/installer.js +56 -0
- package/dist/utils/installer.js.map +1 -0
- package/dist/utils/logger.d.ts +12 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +32 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +16 -4
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* CLI 主入口
|
|
5
|
+
* v2.0.0 - 增强版 Claude Code 启动器 + 状态栏插件
|
|
6
|
+
*/
|
|
3
7
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
8
|
if (k2 === undefined) k2 = k;
|
|
5
9
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -33,447 +37,478 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
37
|
return result;
|
|
34
38
|
};
|
|
35
39
|
})();
|
|
40
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
41
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
42
|
+
};
|
|
36
43
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
|
|
44
|
+
exports.main = main;
|
|
45
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
46
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
47
|
+
const manager_1 = require("./config/manager");
|
|
48
|
+
const launcher_1 = require("./launcher");
|
|
49
|
+
const prompts_1 = require("./ui/prompts");
|
|
50
|
+
const welcome_1 = require("./ui/welcome");
|
|
51
|
+
const installer_1 = require("./utils/installer");
|
|
52
|
+
const logger_1 = require("./utils/logger");
|
|
53
|
+
const packageJson = require('../package.json');
|
|
54
|
+
// 解析命令行参数
|
|
41
55
|
const args = process.argv.slice(2);
|
|
42
56
|
const command = args[0];
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
else if (command === 'sync-enable') {
|
|
52
|
-
// 启用数据上报
|
|
53
|
-
setSyncEnabled(true);
|
|
54
|
-
}
|
|
55
|
-
else if (command === 'sync-disable') {
|
|
56
|
-
// 禁用数据上报
|
|
57
|
-
setSyncEnabled(false);
|
|
58
|
-
}
|
|
59
|
-
else if (command === 'sync-status') {
|
|
60
|
-
// 查看数据上报状态
|
|
61
|
-
showSyncStatus();
|
|
62
|
-
}
|
|
63
|
-
else if (command === 'sync-now' || command === 'sync') {
|
|
64
|
-
// 主动触发一次数据上报
|
|
65
|
-
const { StatusLinePlugin } = require('./index');
|
|
66
|
-
StatusLinePlugin.manualSync();
|
|
67
|
-
}
|
|
68
|
-
else if (command === 'week') {
|
|
69
|
-
// 显示本周统计
|
|
70
|
-
showWeekStats();
|
|
71
|
-
}
|
|
72
|
-
else if (command === 'help' || command === '--help' || command === '-h') {
|
|
73
|
-
// 显示帮助
|
|
74
|
-
showHelp();
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
// 默认:作为状态栏插件运行(用于 Claude Code)
|
|
78
|
-
const { StatusLinePlugin } = require('./index');
|
|
79
|
-
const plugin = new StatusLinePlugin();
|
|
80
|
-
plugin.run().catch(() => {
|
|
81
|
-
console.log('Error');
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
function setup() {
|
|
85
|
-
console.log('🚀 设置 CC Code Status 插件...');
|
|
86
|
-
const claudeSettingsDir = path.join(os.homedir(), '.claude');
|
|
87
|
-
const claudeSettingsFile = path.join(claudeSettingsDir, 'settings.json');
|
|
88
|
-
// 如果 .claude 目录不存在则创建
|
|
89
|
-
if (!fs.existsSync(claudeSettingsDir)) {
|
|
90
|
-
console.log('📁 创建 Claude 设置目录...');
|
|
91
|
-
fs.mkdirSync(claudeSettingsDir, { recursive: true });
|
|
92
|
-
}
|
|
93
|
-
// 获取全局命令路径
|
|
94
|
-
const commandPath = 'cc-code-status';
|
|
95
|
-
// 创建或更新 settings.json
|
|
96
|
-
let settings = {};
|
|
97
|
-
if (fs.existsSync(claudeSettingsFile)) {
|
|
98
|
-
console.log('📝 更新现有 settings.json...');
|
|
99
|
-
// 备份现有设置
|
|
100
|
-
const backupFile = `${claudeSettingsFile}.backup`;
|
|
101
|
-
fs.copyFileSync(claudeSettingsFile, backupFile);
|
|
102
|
-
console.log(` 备份保存至: ${backupFile}`);
|
|
103
|
-
try {
|
|
104
|
-
const existingContent = fs.readFileSync(claudeSettingsFile, 'utf8');
|
|
105
|
-
settings = JSON.parse(existingContent);
|
|
57
|
+
// 主函数
|
|
58
|
+
async function main() {
|
|
59
|
+
try {
|
|
60
|
+
// ========== 版本和帮助 ==========
|
|
61
|
+
if (args.includes('-v') || args.includes('--version')) {
|
|
62
|
+
console.log('CC Code Status v' + packageJson.version);
|
|
63
|
+
return;
|
|
106
64
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
65
|
+
if (command === 'help' || command === '--help' || command === '-h') {
|
|
66
|
+
(0, welcome_1.showHelp)();
|
|
67
|
+
return;
|
|
110
68
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
// 更新 statusLine 配置
|
|
116
|
-
settings.statusLine = {
|
|
117
|
-
type: 'command',
|
|
118
|
-
command: commandPath
|
|
119
|
-
};
|
|
120
|
-
// 写入更新后的设置
|
|
121
|
-
fs.writeFileSync(claudeSettingsFile, JSON.stringify(settings, null, 2));
|
|
122
|
-
console.log('✅ 设置更新成功!');
|
|
123
|
-
console.log('');
|
|
124
|
-
console.log('🎉 CC Code Status 插件已配置完成!');
|
|
125
|
-
console.log('');
|
|
126
|
-
console.log('插件将显示:');
|
|
127
|
-
console.log(' 📁 当前目录名称');
|
|
128
|
-
console.log(' 👤 Git 用户名');
|
|
129
|
-
console.log('');
|
|
130
|
-
console.log('卸载: npm uninstall -g cc-code-status');
|
|
131
|
-
}
|
|
132
|
-
function uninstall() {
|
|
133
|
-
console.log('🗑️ 移除 CC Code Status 插件配置...');
|
|
134
|
-
const claudeSettingsFile = path.join(os.homedir(), '.claude', 'settings.json');
|
|
135
|
-
if (!fs.existsSync(claudeSettingsFile)) {
|
|
136
|
-
console.log('⚠️ 未找到 Claude 设置文件。');
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
try {
|
|
140
|
-
const content = fs.readFileSync(claudeSettingsFile, 'utf8');
|
|
141
|
-
const settings = JSON.parse(content);
|
|
142
|
-
if (settings.statusLine) {
|
|
143
|
-
delete settings.statusLine;
|
|
144
|
-
fs.writeFileSync(claudeSettingsFile, JSON.stringify(settings, null, 2));
|
|
145
|
-
console.log('✅ StatusLine 配置已从 Claude 设置中移除。');
|
|
69
|
+
// ========== 配置命令 ==========
|
|
70
|
+
if (command === 'config') {
|
|
71
|
+
await handleConfigCommand(args.slice(1));
|
|
72
|
+
return;
|
|
146
73
|
}
|
|
147
|
-
|
|
148
|
-
|
|
74
|
+
// ========== 统计命令 ==========
|
|
75
|
+
if (command === 'stats' || command === 'week') {
|
|
76
|
+
await handleStatsCommand(args);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
// ========== 同步命令 ==========
|
|
80
|
+
if (command === 'sync-enable' || command === 'sync-disable' ||
|
|
81
|
+
command === 'sync-status' || command === 'sync-now' ||
|
|
82
|
+
command === 'sync' || command === 'custom-sync') {
|
|
83
|
+
await handleSyncCommand(args);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// ========== 排除命令 ==========
|
|
87
|
+
if (command === 'exclude') {
|
|
88
|
+
await handleExcludeCommand(args.slice(1));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// ========== 旧版命令(向后兼容)==========
|
|
92
|
+
if (command === 'setup' || command === 'install') {
|
|
93
|
+
await handleSetup();
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (command === 'uninstall') {
|
|
97
|
+
await handleUninstall();
|
|
98
|
+
return;
|
|
149
99
|
}
|
|
100
|
+
// ========== 状态栏模式 ==========
|
|
101
|
+
// 检测是否为状态栏模式(通过 stdin 调用)
|
|
102
|
+
if (command === '--statusline' || !process.stdin.isTTY) {
|
|
103
|
+
await runAsStatusLine();
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
// ========== 默认:启动器模式 ==========
|
|
107
|
+
await runAsLauncher(args);
|
|
150
108
|
}
|
|
151
109
|
catch (error) {
|
|
152
|
-
|
|
110
|
+
logger_1.Logger.error('程序执行失败: ' + error.message);
|
|
111
|
+
if (process.env.DEBUG) {
|
|
112
|
+
console.error(error);
|
|
113
|
+
}
|
|
114
|
+
process.exit(1);
|
|
153
115
|
}
|
|
154
|
-
console.log('');
|
|
155
|
-
console.log('完成卸载请运行:');
|
|
156
|
-
console.log(' npm uninstall -g cc-code-status');
|
|
157
116
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
if (fs.existsSync(configFile)) {
|
|
172
|
-
try {
|
|
173
|
-
const content = fs.readFileSync(configFile, 'utf8');
|
|
174
|
-
config = JSON.parse(content);
|
|
175
|
-
}
|
|
176
|
-
catch (error) {
|
|
177
|
-
console.error('⚠️ 读取配置文件失败,使用默认配置');
|
|
117
|
+
/**
|
|
118
|
+
* 处理 config 命令
|
|
119
|
+
*/
|
|
120
|
+
async function handleConfigCommand(subArgs) {
|
|
121
|
+
const config = new manager_1.ConfigManager();
|
|
122
|
+
const subCommand = subArgs[0];
|
|
123
|
+
// config list - 列出所有配置
|
|
124
|
+
if (subCommand === 'list') {
|
|
125
|
+
const profiles = config.getAllProfiles();
|
|
126
|
+
if (profiles.length === 0) {
|
|
127
|
+
logger_1.Logger.warning('当前没有配置');
|
|
128
|
+
logger_1.Logger.info('运行 ccs config add 添加配置');
|
|
129
|
+
return;
|
|
178
130
|
}
|
|
131
|
+
console.log(chalk_1.default.cyan('\n📋 配置列表\n'));
|
|
132
|
+
console.log(chalk_1.default.gray('─'.repeat(70)));
|
|
133
|
+
profiles.forEach(p => {
|
|
134
|
+
const safeKey = p.apiKey.length > 12
|
|
135
|
+
? `${p.apiKey.substring(0, 8)}...${p.apiKey.substring(p.apiKey.length - 4)}`
|
|
136
|
+
: '***';
|
|
137
|
+
// 从 baseUrl 提取域名
|
|
138
|
+
let domain = p.baseUrl;
|
|
139
|
+
try {
|
|
140
|
+
const url = new URL(p.baseUrl);
|
|
141
|
+
domain = url.hostname;
|
|
142
|
+
}
|
|
143
|
+
catch (e) {
|
|
144
|
+
// 如果不是有效 URL,使用原始值
|
|
145
|
+
}
|
|
146
|
+
console.log(chalk_1.default.white.bold('● ' + p.name));
|
|
147
|
+
console.log(chalk_1.default.gray(` Base URL: ${p.baseUrl}`));
|
|
148
|
+
console.log(chalk_1.default.gray(` API Key: ${safeKey}`));
|
|
149
|
+
if (p.model) {
|
|
150
|
+
console.log(chalk_1.default.gray(` Model: ${p.model}`));
|
|
151
|
+
}
|
|
152
|
+
if (p.smallFastModel) {
|
|
153
|
+
console.log(chalk_1.default.gray(` Small Fast Model: ${p.smallFastModel}`));
|
|
154
|
+
}
|
|
155
|
+
console.log('');
|
|
156
|
+
});
|
|
157
|
+
console.log(chalk_1.default.gray('─'.repeat(70)));
|
|
158
|
+
console.log(chalk_1.default.gray(`\n配置文件: ${config.getConfigPath()}\n`));
|
|
159
|
+
return;
|
|
179
160
|
}
|
|
180
|
-
//
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
161
|
+
// config add - 添加新配置
|
|
162
|
+
if (subCommand === 'add') {
|
|
163
|
+
(0, welcome_1.showWelcome)();
|
|
164
|
+
const answers = await (0, prompts_1.showConfigPrompts)();
|
|
165
|
+
// 检查配置是否已存在
|
|
166
|
+
if (config.hasProfile(answers.name)) {
|
|
167
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
168
|
+
{
|
|
169
|
+
type: 'confirm',
|
|
170
|
+
name: 'confirm',
|
|
171
|
+
message: chalk_1.default.yellow(`配置 "${answers.name}" 已存在,是否覆盖?`),
|
|
172
|
+
default: false
|
|
173
|
+
}
|
|
174
|
+
]);
|
|
175
|
+
if (!confirm) {
|
|
176
|
+
logger_1.Logger.info('已取消');
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
config.saveProfile(answers.name, {
|
|
181
|
+
apiKey: answers.apiKey,
|
|
182
|
+
baseUrl: answers.baseUrl,
|
|
183
|
+
model: answers.model,
|
|
184
|
+
smallFastModel: answers.smallFastModel
|
|
185
|
+
});
|
|
186
|
+
logger_1.Logger.success(`配置 "${answers.name}" 已保存`);
|
|
185
187
|
console.log('');
|
|
186
|
-
|
|
187
|
-
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
// config remove <name> - 删除配置
|
|
191
|
+
if (subCommand === 'remove' || subCommand === 'rm') {
|
|
192
|
+
const name = subArgs[1];
|
|
193
|
+
if (!name) {
|
|
194
|
+
logger_1.Logger.error('请指定要删除的配置名称');
|
|
188
195
|
console.log('');
|
|
189
|
-
console.log(
|
|
190
|
-
console.log(
|
|
196
|
+
console.log('用法: ccs config remove <配置名称>');
|
|
197
|
+
console.log('');
|
|
198
|
+
return;
|
|
191
199
|
}
|
|
192
|
-
|
|
193
|
-
|
|
200
|
+
if (!config.hasProfile(name)) {
|
|
201
|
+
logger_1.Logger.error(`配置 "${name}" 不存在`);
|
|
202
|
+
console.log('');
|
|
203
|
+
console.log('使用 ccs config list 查看所有配置');
|
|
204
|
+
console.log('');
|
|
205
|
+
return;
|
|
194
206
|
}
|
|
207
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
208
|
+
{
|
|
209
|
+
type: 'confirm',
|
|
210
|
+
name: 'confirm',
|
|
211
|
+
message: chalk_1.default.yellow(`确定要删除配置 "${name}" 吗?`),
|
|
212
|
+
default: false
|
|
213
|
+
}
|
|
214
|
+
]);
|
|
215
|
+
if (!confirm) {
|
|
216
|
+
logger_1.Logger.info('已取消');
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
config.removeProfile(name);
|
|
220
|
+
logger_1.Logger.success(`配置 "${name}" 已删除`);
|
|
195
221
|
console.log('');
|
|
196
|
-
|
|
197
|
-
console.log('');
|
|
222
|
+
return;
|
|
198
223
|
}
|
|
199
|
-
|
|
200
|
-
|
|
224
|
+
// config show / config --show - 显示配置(单个配置时显示详情,多个配置时显示列表)
|
|
225
|
+
if (subCommand === 'show' || subArgs.includes('--show')) {
|
|
226
|
+
const profiles = config.getAllProfiles();
|
|
227
|
+
if (profiles.length === 0) {
|
|
228
|
+
logger_1.Logger.warning('当前没有配置');
|
|
229
|
+
logger_1.Logger.info('运行 ccs config add 添加配置');
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
// 如果只有一个配置,显示详情
|
|
233
|
+
if (profiles.length === 1) {
|
|
234
|
+
const current = profiles[0];
|
|
235
|
+
const safeKey = current.apiKey.length > 12
|
|
236
|
+
? `${current.apiKey.substring(0, 8)}...${current.apiKey.substring(current.apiKey.length - 4)}`
|
|
237
|
+
: '***';
|
|
238
|
+
console.log(chalk_1.default.cyan('\n📝 当前配置'));
|
|
239
|
+
console.log(chalk_1.default.gray('─'.repeat(70)));
|
|
240
|
+
console.log(chalk_1.default.white('配置名称: ') + chalk_1.default.green(current.name));
|
|
241
|
+
console.log(chalk_1.default.white('Base URL: ') + chalk_1.default.cyan(current.baseUrl));
|
|
242
|
+
console.log(chalk_1.default.white('API Key: ') + chalk_1.default.yellow(safeKey));
|
|
243
|
+
if (current.model) {
|
|
244
|
+
console.log(chalk_1.default.white('Model: ') + chalk_1.default.gray(current.model));
|
|
245
|
+
}
|
|
246
|
+
if (current.smallFastModel) {
|
|
247
|
+
console.log(chalk_1.default.white('Small Fast Model: ') + chalk_1.default.gray(current.smallFastModel));
|
|
248
|
+
}
|
|
249
|
+
console.log(chalk_1.default.white('配置时间: ') + chalk_1.default.gray(new Date(current.configuredAt).toLocaleString('zh-CN')));
|
|
250
|
+
console.log(chalk_1.default.gray('─'.repeat(70)));
|
|
251
|
+
console.log(chalk_1.default.gray(`配置文件: ${config.getConfigPath()}\n`));
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
// 多个配置时,显示提示
|
|
255
|
+
logger_1.Logger.info(`当前有 ${profiles.length} 个配置,启动时将提示选择`);
|
|
256
|
+
console.log('');
|
|
257
|
+
console.log('使用 ccs config list 查看所有配置');
|
|
258
|
+
console.log('');
|
|
259
|
+
}
|
|
260
|
+
return;
|
|
201
261
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
262
|
+
// config --reset - 重置所有配置
|
|
263
|
+
if (subArgs.includes('--reset')) {
|
|
264
|
+
if (!config.hasAnyProfile()) {
|
|
265
|
+
logger_1.Logger.warning('当前没有配置');
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
269
|
+
{
|
|
270
|
+
type: 'confirm',
|
|
271
|
+
name: 'confirm',
|
|
272
|
+
message: chalk_1.default.red('⚠️ 确定要删除所有配置吗?此操作不可恢复!'),
|
|
273
|
+
default: false
|
|
274
|
+
}
|
|
275
|
+
]);
|
|
276
|
+
if (!confirm) {
|
|
277
|
+
logger_1.Logger.info('已取消');
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
config.reset();
|
|
281
|
+
logger_1.Logger.success('所有配置已重置');
|
|
282
|
+
logger_1.Logger.info('下次运行 ccs 时将重新配置');
|
|
211
283
|
console.log('');
|
|
212
284
|
return;
|
|
213
285
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
if (config.enabled) {
|
|
229
|
-
console.log('要禁用数据上报,运行:');
|
|
230
|
-
console.log(' cc-code-status sync-disable');
|
|
286
|
+
// config (无子命令) - 显示帮助或添加第一个配置
|
|
287
|
+
if (!subCommand) {
|
|
288
|
+
if (!config.hasAnyProfile()) {
|
|
289
|
+
// 如果没有配置,引导添加第一个配置
|
|
290
|
+
(0, welcome_1.showWelcome)();
|
|
291
|
+
const answers = await (0, prompts_1.showConfigPrompts)('default');
|
|
292
|
+
config.saveProfile(answers.name, {
|
|
293
|
+
apiKey: answers.apiKey,
|
|
294
|
+
baseUrl: answers.baseUrl,
|
|
295
|
+
model: answers.model,
|
|
296
|
+
smallFastModel: answers.smallFastModel
|
|
297
|
+
});
|
|
298
|
+
(0, welcome_1.showConfigSuccess)();
|
|
299
|
+
console.log('');
|
|
231
300
|
}
|
|
232
301
|
else {
|
|
233
|
-
|
|
234
|
-
console.log('
|
|
302
|
+
// 如果已有配置,显示配置管理帮助
|
|
303
|
+
console.log(chalk_1.default.cyan('\n⚙️ 配置管理\n'));
|
|
304
|
+
console.log('可用命令:');
|
|
305
|
+
console.log('');
|
|
306
|
+
console.log(chalk_1.default.white(' ccs config list ') + chalk_1.default.gray('列出所有配置'));
|
|
307
|
+
console.log(chalk_1.default.white(' ccs config add ') + chalk_1.default.gray('添加新配置'));
|
|
308
|
+
console.log(chalk_1.default.white(' ccs config remove <名称> ') + chalk_1.default.gray('删除指定配置'));
|
|
309
|
+
console.log(chalk_1.default.white(' ccs config show ') + chalk_1.default.gray('显示当前配置'));
|
|
310
|
+
console.log(chalk_1.default.white(' ccs config --reset ') + chalk_1.default.gray('重置所有配置'));
|
|
311
|
+
console.log('');
|
|
235
312
|
}
|
|
236
|
-
|
|
237
|
-
}
|
|
238
|
-
catch (error) {
|
|
239
|
-
console.error('❌ 读取配置失败:', error);
|
|
313
|
+
return;
|
|
240
314
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
console.log('CC Code Status Plugin - Claude Code git 用户信息显示');
|
|
244
|
-
console.log('');
|
|
245
|
-
console.log('用法:');
|
|
246
|
-
console.log(' cc-code-status 作为状态栏插件运行(由 Claude Code 使用)');
|
|
247
|
-
console.log(' cc-code-status setup 配置 Claude Code 使用此插件');
|
|
248
|
-
console.log(' cc-code-status uninstall 从 Claude Code 中移除插件配置');
|
|
249
|
-
console.log(' cc-code-status sync-enable 启用数据上报功能');
|
|
250
|
-
console.log(' cc-code-status sync-disable 禁用数据上报功能');
|
|
251
|
-
console.log(' cc-code-status sync-status 查看数据上报状态');
|
|
252
|
-
console.log(' cc-code-status sync-now 主动触发一次数据上报');
|
|
253
|
-
console.log(' cc-code-status week 显示本周统计(对话次数/轮数、代码行数)');
|
|
254
|
-
console.log(' cc-code-status help 显示此帮助信息');
|
|
315
|
+
// 未知子命令
|
|
316
|
+
logger_1.Logger.error(`未知的子命令: ${subCommand}`);
|
|
255
317
|
console.log('');
|
|
256
|
-
console.log('
|
|
318
|
+
console.log('运行 ccs config 查看帮助');
|
|
257
319
|
console.log('');
|
|
258
|
-
console.log('安装:');
|
|
259
|
-
console.log(' npm install -g cc-code-status');
|
|
260
|
-
console.log('');
|
|
261
|
-
console.log('安装后插件会自动配置。');
|
|
262
320
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
const today = new Date();
|
|
279
|
-
const dayOfWeek = today.getDay(); // 0=周日, 1=周一, ..., 6=周六
|
|
280
|
-
const daysToMonday = dayOfWeek === 0 ? 6 : dayOfWeek - 1; // 到本周一的天数
|
|
281
|
-
const weekStart = new Date(today);
|
|
282
|
-
weekStart.setDate(today.getDate() - daysToMonday);
|
|
283
|
-
weekStart.setHours(0, 0, 0, 0);
|
|
284
|
-
const weekEnd = new Date(weekStart);
|
|
285
|
-
weekEnd.setDate(weekStart.getDate() + 6);
|
|
286
|
-
weekEnd.setHours(23, 59, 59, 999);
|
|
287
|
-
// 收集本周每一天的数据
|
|
288
|
-
const dailyStats = [];
|
|
289
|
-
let totalConversations = 0;
|
|
290
|
-
let totalRounds = 0;
|
|
291
|
-
let totalAdded = 0;
|
|
292
|
-
let totalDeleted = 0;
|
|
293
|
-
const dayNames = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
|
|
294
|
-
for (let i = 0; i < 7; i++) {
|
|
295
|
-
const currentDay = new Date(weekStart);
|
|
296
|
-
currentDay.setDate(weekStart.getDate() + i);
|
|
297
|
-
const dayStart = new Date(currentDay);
|
|
298
|
-
dayStart.setHours(0, 0, 0, 0);
|
|
299
|
-
const dayEnd = new Date(currentDay);
|
|
300
|
-
dayEnd.setHours(23, 59, 59, 999);
|
|
301
|
-
const conversations = countConversations(dayStart, dayEnd);
|
|
302
|
-
const rounds = countRounds(dayStart, dayEnd);
|
|
303
|
-
const codeStats = countCodeChanges(dayStart, dayEnd);
|
|
304
|
-
totalConversations += conversations;
|
|
305
|
-
totalRounds += rounds;
|
|
306
|
-
totalAdded += codeStats.added;
|
|
307
|
-
totalDeleted += codeStats.deleted;
|
|
308
|
-
dailyStats.push({
|
|
309
|
-
date: formatDate(currentDay),
|
|
310
|
-
dayName: dayNames[currentDay.getDay()],
|
|
311
|
-
conversations,
|
|
312
|
-
rounds,
|
|
313
|
-
codeAdded: codeStats.added,
|
|
314
|
-
codeDeleted: codeStats.deleted
|
|
315
|
-
});
|
|
316
|
-
}
|
|
317
|
-
// 输出结果
|
|
321
|
+
/**
|
|
322
|
+
* 处理统计命令
|
|
323
|
+
*/
|
|
324
|
+
async function handleStatsCommand(args) {
|
|
325
|
+
const subCommand = args[0] === 'stats' ? args[1] : args[0];
|
|
326
|
+
if (subCommand === 'week' || args[0] === 'week') {
|
|
327
|
+
// 引入旧版的 showWeekStats 函数
|
|
328
|
+
const { showWeekStats } = await Promise.resolve().then(() => __importStar(require('./cli-legacy')));
|
|
329
|
+
showWeekStats();
|
|
330
|
+
}
|
|
331
|
+
else if (subCommand === 'today') {
|
|
332
|
+
// 显示今日统计
|
|
333
|
+
const { StatusLinePlugin } = await Promise.resolve().then(() => __importStar(require('./index')));
|
|
334
|
+
const plugin = new StatusLinePlugin();
|
|
335
|
+
const stats = await plugin.getTodayStats();
|
|
318
336
|
console.log('');
|
|
319
|
-
console.log('
|
|
320
|
-
console.log(` 本周统计 (${formatDate(weekStart)} 至 ${formatDate(weekEnd)})`);
|
|
321
|
-
console.log('========================================');
|
|
337
|
+
console.log(chalk_1.default.cyan('📊 今日统计'));
|
|
322
338
|
console.log('');
|
|
323
|
-
console.log(
|
|
339
|
+
console.log(`对话: ${stats.conversations}次/${stats.rounds}轮`);
|
|
340
|
+
console.log(`代码: +${stats.codeAdded}/-${stats.codeDeleted} 行`);
|
|
324
341
|
console.log('');
|
|
325
|
-
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
logger_1.Logger.error('未知的统计命令');
|
|
326
345
|
console.log('');
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
console.log(` ${dateStr.padEnd(20)} ${statsStr}`);
|
|
331
|
-
}
|
|
346
|
+
console.log('可用命令:');
|
|
347
|
+
console.log(' ccs stats today 显示今日统计');
|
|
348
|
+
console.log(' ccs stats week 显示本周统计');
|
|
332
349
|
console.log('');
|
|
333
350
|
}
|
|
334
|
-
|
|
335
|
-
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* 处理同步命令
|
|
354
|
+
*/
|
|
355
|
+
async function handleSyncCommand(args) {
|
|
356
|
+
const command = args[0];
|
|
357
|
+
// 引入旧版的同步函数
|
|
358
|
+
const { setSyncEnabled, showSyncStatus, manualSync, customSync } = await Promise.resolve().then(() => __importStar(require('./cli-legacy')));
|
|
359
|
+
if (command === 'sync-enable') {
|
|
360
|
+
setSyncEnabled(true);
|
|
361
|
+
}
|
|
362
|
+
else if (command === 'sync-disable') {
|
|
363
|
+
setSyncEnabled(false);
|
|
364
|
+
}
|
|
365
|
+
else if (command === 'sync-status') {
|
|
366
|
+
showSyncStatus();
|
|
367
|
+
}
|
|
368
|
+
else if (command === 'sync-now' || command === 'sync') {
|
|
369
|
+
await manualSync();
|
|
370
|
+
}
|
|
371
|
+
else if (command === 'custom-sync') {
|
|
372
|
+
await customSync();
|
|
336
373
|
}
|
|
337
374
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
const
|
|
343
|
-
|
|
375
|
+
/**
|
|
376
|
+
* 处理排除命令
|
|
377
|
+
*/
|
|
378
|
+
async function handleExcludeCommand(subArgs) {
|
|
379
|
+
const { handleExclude } = await Promise.resolve().then(() => __importStar(require('./cli-legacy')));
|
|
380
|
+
handleExclude(subArgs);
|
|
344
381
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
382
|
+
/**
|
|
383
|
+
* 处理 setup 命令(旧版兼容)
|
|
384
|
+
*/
|
|
385
|
+
async function handleSetup() {
|
|
386
|
+
const { setup } = await Promise.resolve().then(() => __importStar(require('./cli-legacy')));
|
|
387
|
+
setup();
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* 处理 uninstall 命令(旧版兼容)
|
|
391
|
+
*/
|
|
392
|
+
async function handleUninstall() {
|
|
393
|
+
const { uninstall } = await Promise.resolve().then(() => __importStar(require('./cli-legacy')));
|
|
394
|
+
uninstall();
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* 作为状态栏插件运行
|
|
398
|
+
*/
|
|
399
|
+
async function runAsStatusLine() {
|
|
400
|
+
const { StatusLinePlugin } = await Promise.resolve().then(() => __importStar(require('./index')));
|
|
401
|
+
const plugin = new StatusLinePlugin();
|
|
402
|
+
await plugin.run().catch(() => {
|
|
403
|
+
console.log('Error');
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* 作为启动器运行
|
|
408
|
+
*/
|
|
409
|
+
async function runAsLauncher(args) {
|
|
410
|
+
const config = new manager_1.ConfigManager();
|
|
411
|
+
// 检查是否有配置
|
|
412
|
+
if (!config.hasAnyProfile()) {
|
|
413
|
+
console.log('');
|
|
414
|
+
logger_1.Logger.info('首次使用需要配置 API');
|
|
415
|
+
console.log('');
|
|
416
|
+
// 显示欢迎信息
|
|
417
|
+
(0, welcome_1.showWelcome)();
|
|
418
|
+
// 交互式配置
|
|
419
|
+
const answers = await (0, prompts_1.showConfigPrompts)('default');
|
|
420
|
+
// 保存配置
|
|
421
|
+
config.saveProfile(answers.name, {
|
|
422
|
+
apiKey: answers.apiKey,
|
|
423
|
+
baseUrl: answers.baseUrl,
|
|
424
|
+
model: answers.model,
|
|
425
|
+
smallFastModel: answers.smallFastModel
|
|
426
|
+
});
|
|
427
|
+
// 显示成功信息
|
|
428
|
+
(0, welcome_1.showConfigSuccess)();
|
|
429
|
+
// 短暂延迟
|
|
430
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
431
|
+
}
|
|
432
|
+
// 如果有配置,检查是否需要选择配置
|
|
433
|
+
let selectedProfileName;
|
|
434
|
+
if (config.hasAnyProfile()) {
|
|
435
|
+
// 如果有多个配置,需要用户选择
|
|
436
|
+
const profileCount = config.getProfileCount();
|
|
437
|
+
// 检查命令行参数中是否指定了配置
|
|
438
|
+
const profileArgIndex = args.findIndex(arg => arg === '--profile' || arg === '-p');
|
|
439
|
+
if (profileArgIndex !== -1 && args[profileArgIndex + 1]) {
|
|
440
|
+
// 通过命令行参数指定配置
|
|
441
|
+
selectedProfileName = args[profileArgIndex + 1];
|
|
442
|
+
if (!config.hasProfile(selectedProfileName)) {
|
|
443
|
+
logger_1.Logger.error(`配置 "${selectedProfileName}" 不存在`);
|
|
444
|
+
console.log('');
|
|
445
|
+
console.log('使用 ccs config list 查看所有配置');
|
|
446
|
+
console.log('');
|
|
447
|
+
process.exit(1);
|
|
379
448
|
}
|
|
449
|
+
// 移除 --profile 参数(避免传递给 Claude)
|
|
450
|
+
args.splice(profileArgIndex, 2);
|
|
451
|
+
}
|
|
452
|
+
else if (profileCount > 1) {
|
|
453
|
+
// 如果有多个配置,让用户选择
|
|
454
|
+
const profiles = config.getAllProfiles().map(p => ({
|
|
455
|
+
name: p.name,
|
|
456
|
+
config: p
|
|
457
|
+
}));
|
|
458
|
+
console.log('');
|
|
459
|
+
logger_1.Logger.info('检测到多个配置,请选择要使用的配置');
|
|
460
|
+
console.log('');
|
|
461
|
+
selectedProfileName = await (0, prompts_1.selectProfile)(profiles);
|
|
462
|
+
console.log('');
|
|
463
|
+
logger_1.Logger.success(`已选择配置: ${selectedProfileName}`);
|
|
464
|
+
console.log('');
|
|
465
|
+
// 短暂延迟
|
|
466
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
380
467
|
}
|
|
381
|
-
return sessionIds.size;
|
|
382
468
|
}
|
|
383
|
-
|
|
384
|
-
|
|
469
|
+
// 检查 Claude Code 是否已安装
|
|
470
|
+
if (!(0, installer_1.checkClaudeInstallation)()) {
|
|
471
|
+
process.exit(1);
|
|
385
472
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
473
|
+
// 显示当前使用的配置
|
|
474
|
+
let displayProfile;
|
|
475
|
+
if (selectedProfileName) {
|
|
476
|
+
// 使用选中的配置
|
|
477
|
+
const profile = config.getProfile(selectedProfileName);
|
|
478
|
+
if (profile) {
|
|
479
|
+
displayProfile = { name: selectedProfileName, baseUrl: profile.baseUrl };
|
|
392
480
|
}
|
|
393
|
-
let count = 0;
|
|
394
|
-
const content = fs.readFileSync(historyPath, 'utf8');
|
|
395
|
-
const lines = content.trim().split('\n').filter(line => line.trim());
|
|
396
|
-
for (const line of lines) {
|
|
397
|
-
try {
|
|
398
|
-
const entry = JSON.parse(line);
|
|
399
|
-
const display = entry.display?.trim() || '';
|
|
400
|
-
if (!display || display.startsWith('/')) {
|
|
401
|
-
continue;
|
|
402
|
-
}
|
|
403
|
-
const timestamp = new Date(entry.timestamp || entry.createdAt || 0);
|
|
404
|
-
if (timestamp >= dayStart && timestamp <= dayEnd) {
|
|
405
|
-
count++;
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
catch {
|
|
409
|
-
// 忽略解析错误
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
return count;
|
|
413
481
|
}
|
|
414
|
-
|
|
415
|
-
|
|
482
|
+
else {
|
|
483
|
+
// 使用唯一配置
|
|
484
|
+
const current = config.getCurrentProfile();
|
|
485
|
+
if (current) {
|
|
486
|
+
displayProfile = { name: current.name, baseUrl: current.config.baseUrl };
|
|
487
|
+
}
|
|
416
488
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
489
|
+
if (displayProfile) {
|
|
490
|
+
// 从 baseUrl 提取域名
|
|
491
|
+
let domain = displayProfile.baseUrl;
|
|
492
|
+
try {
|
|
493
|
+
const url = new URL(displayProfile.baseUrl);
|
|
494
|
+
domain = url.hostname;
|
|
423
495
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
const projectDirs = fs.readdirSync(projectsDir);
|
|
427
|
-
for (const dir of projectDirs) {
|
|
428
|
-
const dirPath = path.join(projectsDir, dir);
|
|
429
|
-
if (!fs.statSync(dirPath).isDirectory())
|
|
430
|
-
continue;
|
|
431
|
-
const files = fs.readdirSync(dirPath).filter(f => f.endsWith('.jsonl'));
|
|
432
|
-
for (const file of files) {
|
|
433
|
-
const filePath = path.join(dirPath, file);
|
|
434
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
435
|
-
const lines = content.trim().split('\n');
|
|
436
|
-
for (const line of lines) {
|
|
437
|
-
try {
|
|
438
|
-
const record = JSON.parse(line);
|
|
439
|
-
if (!record.timestamp)
|
|
440
|
-
continue;
|
|
441
|
-
const timestamp = new Date(record.timestamp);
|
|
442
|
-
if (timestamp < dayStart || timestamp > dayEnd) {
|
|
443
|
-
continue;
|
|
444
|
-
}
|
|
445
|
-
if (record.type === 'assistant' && record.message?.content) {
|
|
446
|
-
for (const item of record.message.content) {
|
|
447
|
-
if (item.type === 'tool_use' && item.input) {
|
|
448
|
-
const { name, input } = item;
|
|
449
|
-
if (name === 'Edit') {
|
|
450
|
-
const oldLines = (input.old_string || '').split('\n').length;
|
|
451
|
-
const newLines = (input.new_string || '').split('\n').length;
|
|
452
|
-
if (newLines > oldLines) {
|
|
453
|
-
added += newLines - oldLines;
|
|
454
|
-
}
|
|
455
|
-
else {
|
|
456
|
-
deleted += oldLines - newLines;
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
else if (name === 'Write') {
|
|
460
|
-
const lineCount = (input.content || '').split('\n').length;
|
|
461
|
-
added += lineCount;
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
catch {
|
|
468
|
-
// 忽略解析错误
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
}
|
|
496
|
+
catch (e) {
|
|
497
|
+
// 如果不是有效 URL,使用原始值
|
|
472
498
|
}
|
|
473
|
-
|
|
474
|
-
}
|
|
475
|
-
catch {
|
|
476
|
-
return { added: 0, deleted: 0 };
|
|
499
|
+
console.log(chalk_1.default.gray(`使用配置: ${displayProfile.name} (${domain})\n`));
|
|
477
500
|
}
|
|
501
|
+
// 启动 Claude Code
|
|
502
|
+
const launcher = new launcher_1.ClaudeLauncher(config, selectedProfileName);
|
|
503
|
+
const { exitCode } = await launcher.launch({
|
|
504
|
+
args,
|
|
505
|
+
skipPermissions: true,
|
|
506
|
+
showStats: true
|
|
507
|
+
});
|
|
508
|
+
process.exit(exitCode);
|
|
509
|
+
}
|
|
510
|
+
// 运行主函数
|
|
511
|
+
if (require.main === module) {
|
|
512
|
+
main();
|
|
478
513
|
}
|
|
479
514
|
//# sourceMappingURL=cli.js.map
|