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.
Files changed (50) hide show
  1. package/README.md +309 -27
  2. package/dist/cli-legacy.d.ts +13 -0
  3. package/dist/cli-legacy.d.ts.map +1 -0
  4. package/dist/cli-legacy.js +535 -0
  5. package/dist/cli-legacy.js.map +1 -0
  6. package/dist/cli.backup.d.ts +3 -0
  7. package/dist/cli.backup.d.ts.map +1 -0
  8. package/dist/cli.backup.js +661 -0
  9. package/dist/cli.backup.js.map +1 -0
  10. package/dist/cli.d.ts +6 -1
  11. package/dist/cli.d.ts.map +1 -1
  12. package/dist/cli.js +428 -393
  13. package/dist/cli.js.map +1 -1
  14. package/dist/config/constants.d.ts +17 -0
  15. package/dist/config/constants.d.ts.map +1 -0
  16. package/dist/config/constants.js +42 -0
  17. package/dist/config/constants.js.map +1 -0
  18. package/dist/config/manager.d.ts +121 -0
  19. package/dist/config/manager.d.ts.map +1 -0
  20. package/dist/config/manager.js +273 -0
  21. package/dist/config/manager.js.map +1 -0
  22. package/dist/config/validator.d.ts +17 -0
  23. package/dist/config/validator.d.ts.map +1 -0
  24. package/dist/config/validator.js +39 -0
  25. package/dist/config/validator.js.map +1 -0
  26. package/dist/index.d.ts +14 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +142 -5
  29. package/dist/index.js.map +1 -1
  30. package/dist/launcher.d.ts +27 -0
  31. package/dist/launcher.d.ts.map +1 -0
  32. package/dist/launcher.js +145 -0
  33. package/dist/launcher.js.map +1 -0
  34. package/dist/ui/prompts.d.ts +34 -0
  35. package/dist/ui/prompts.d.ts.map +1 -0
  36. package/dist/ui/prompts.js +192 -0
  37. package/dist/ui/prompts.js.map +1 -0
  38. package/dist/ui/welcome.d.ts +30 -0
  39. package/dist/ui/welcome.d.ts.map +1 -0
  40. package/dist/ui/welcome.js +95 -0
  41. package/dist/ui/welcome.js.map +1 -0
  42. package/dist/utils/installer.d.ts +15 -0
  43. package/dist/utils/installer.d.ts.map +1 -0
  44. package/dist/utils/installer.js +56 -0
  45. package/dist/utils/installer.js.map +1 -0
  46. package/dist/utils/logger.d.ts +12 -0
  47. package/dist/utils/logger.d.ts.map +1 -0
  48. package/dist/utils/logger.js +32 -0
  49. package/dist/utils/logger.js.map +1 -0
  50. 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
- const fs = __importStar(require("fs"));
38
- const path = __importStar(require("path"));
39
- const os = __importStar(require("os"));
40
- // CLI 用于全局安装 - 处理状态栏执行和设置
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
- if (command === 'setup' || command === 'install') {
44
- // 运行设置
45
- setup();
46
- }
47
- else if (command === 'uninstall') {
48
- // 运行卸载
49
- uninstall();
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
- catch (error) {
108
- console.error('⚠️ 读取现有设置出错,创建新设置...');
109
- settings = {};
65
+ if (command === 'help' || command === '--help' || command === '-h') {
66
+ (0, welcome_1.showHelp)();
67
+ return;
110
68
  }
111
- }
112
- else {
113
- console.log('📝 创建新的 settings.json...');
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
- else {
148
- console.log('⚠️ 设置中未找到 statusLine 配置。');
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
- console.error(' 更新设置时出错:', error);
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
- function setSyncEnabled(enabled) {
159
- const configDir = path.join(os.homedir(), '.cc-code-status');
160
- const configFile = path.join(configDir, 'config.json');
161
- // 确保目录存在
162
- if (!fs.existsSync(configDir)) {
163
- fs.mkdirSync(configDir, { recursive: true });
164
- }
165
- // 读取现有配置
166
- let config = {
167
- apiUrl: 'http://10.40.0.70:8087/api/cloudcode-ai/batch-receive',
168
- syncInterval: 1800000,
169
- enabled: false
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
- // 更新 enabled 状态
181
- config.enabled = enabled;
182
- // 写入配置
183
- try {
184
- fs.writeFileSync(configFile, JSON.stringify(config, null, 2));
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
- if (enabled) {
187
- console.log('✅ 数据上报功能已启用');
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(`📡 API 地址: ${config.apiUrl}`);
190
- console.log(`⏱️ 同步间隔: ${config.syncInterval / 1000 / 60} 分钟`);
196
+ console.log('用法: ccs config remove <配置名称>');
197
+ console.log('');
198
+ return;
191
199
  }
192
- else {
193
- console.log('✅ 数据上报功能已禁用');
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
- console.log(`配置文件: ${configFile}`);
197
- console.log('');
222
+ return;
198
223
  }
199
- catch (error) {
200
- console.error(' 写入配置文件失败:', error);
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
- function showSyncStatus() {
204
- const configFile = path.join(os.homedir(), '.cc-code-status', 'config.json');
205
- if (!fs.existsSync(configFile)) {
206
- console.log('');
207
- console.log('⚠️ 配置文件不存在');
208
- console.log('');
209
- console.log('运行以下命令启用数据上报:');
210
- console.log(' cc-code-status sync-enable');
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
- try {
215
- const content = fs.readFileSync(configFile, 'utf8');
216
- const config = JSON.parse(content);
217
- console.log('');
218
- console.log('========================================');
219
- console.log(' 数据上报状态');
220
- console.log('========================================');
221
- console.log('');
222
- console.log(`状态: ${config.enabled ? '✅ 已启用' : '❌ 已禁用'}`);
223
- console.log(`API 地址: ${config.apiUrl || '(未配置)'}`);
224
- console.log(`同步间隔: ${(config.syncInterval || 1800000) / 1000 / 60} 分钟`);
225
- console.log('');
226
- console.log(`配置文件: ${configFile}`);
227
- console.log('');
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
- console.log('要启用数据上报,运行:');
234
- console.log(' cc-code-status sync-enable');
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
- console.log('');
237
- }
238
- catch (error) {
239
- console.error('❌ 读取配置失败:', error);
313
+ return;
240
314
  }
241
- }
242
- function showHelp() {
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('别名: 所有命令都支持短别名 ccs(如 ccs sync-now)');
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
- function showWeekStats() {
264
- const { execSync } = require('child_process');
265
- try {
266
- // 获取 git 用户名
267
- let username = 'Unknown';
268
- try {
269
- username = execSync('git config user.name', {
270
- encoding: 'utf8',
271
- stdio: ['pipe', 'pipe', 'ignore']
272
- }).trim();
273
- }
274
- catch {
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(`总计: ${totalConversations}次/${totalRounds}轮 | +${totalAdded}/-${totalDeleted} 行`);
339
+ console.log(`对话: ${stats.conversations}次/${stats.rounds}轮`);
340
+ console.log(`代码: +${stats.codeAdded}/-${stats.codeDeleted} 行`);
324
341
  console.log('');
325
- console.log('每日明细:');
342
+ }
343
+ else {
344
+ logger_1.Logger.error('未知的统计命令');
326
345
  console.log('');
327
- for (const day of dailyStats) {
328
- const dateStr = `${day.dayName} (${day.date})`;
329
- const statsStr = `${day.conversations}次/${day.rounds}轮 | +${day.codeAdded}/-${day.codeDeleted} 行`;
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
- catch (error) {
335
- console.error('❌ 统计失败:', error);
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
- function formatDate(date) {
340
- const year = date.getFullYear();
341
- const month = String(date.getMonth() + 1).padStart(2, '0');
342
- const day = String(date.getDate()).padStart(2, '0');
343
- return `${year}-${month}-${day}`;
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
- function countConversations(dayStart, dayEnd) {
346
- try {
347
- const projectsDir = path.join(os.homedir(), '.claude', 'projects');
348
- if (!fs.existsSync(projectsDir)) {
349
- return 0;
350
- }
351
- const sessionIds = new Set();
352
- const projectDirs = fs.readdirSync(projectsDir);
353
- for (const dir of projectDirs) {
354
- const dirPath = path.join(projectsDir, dir);
355
- if (!fs.statSync(dirPath).isDirectory())
356
- continue;
357
- const files = fs.readdirSync(dirPath).filter(f => f.endsWith('.jsonl') && !f.startsWith('agent-'));
358
- for (const file of files) {
359
- const filePath = path.join(dirPath, file);
360
- const content = fs.readFileSync(filePath, 'utf8');
361
- const lines = content.trim().split('\n');
362
- if (lines.length === 0)
363
- continue;
364
- for (const line of lines) {
365
- try {
366
- const record = JSON.parse(line);
367
- if (record.sessionId && record.timestamp) {
368
- const timestamp = new Date(record.timestamp);
369
- if (timestamp >= dayStart && timestamp <= dayEnd) {
370
- sessionIds.add(record.sessionId);
371
- }
372
- break;
373
- }
374
- }
375
- catch {
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
- catch {
384
- return 0;
469
+ // 检查 Claude Code 是否已安装
470
+ if (!(0, installer_1.checkClaudeInstallation)()) {
471
+ process.exit(1);
385
472
  }
386
- }
387
- function countRounds(dayStart, dayEnd) {
388
- try {
389
- const historyPath = path.join(os.homedir(), '.claude', 'history.jsonl');
390
- if (!fs.existsSync(historyPath)) {
391
- return 0;
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
- catch {
415
- return 0;
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
- function countCodeChanges(dayStart, dayEnd) {
419
- try {
420
- const projectsDir = path.join(os.homedir(), '.claude', 'projects');
421
- if (!fs.existsSync(projectsDir)) {
422
- return { added: 0, deleted: 0 };
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
- let added = 0;
425
- let deleted = 0;
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
- return { added, deleted };
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