ccjk 10.1.0 → 10.2.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 (109) hide show
  1. package/dist/chunks/agent-teams.mjs +1 -1
  2. package/dist/chunks/agent.mjs +1 -1
  3. package/dist/chunks/api-providers.mjs +1 -1
  4. package/dist/chunks/api.mjs +3 -3
  5. package/dist/chunks/auto-bootstrap.mjs +1 -1
  6. package/dist/chunks/auto-updater.mjs +1 -1
  7. package/dist/{shared/ccjk.Br91zBIG.mjs → chunks/banner.mjs} +52 -3
  8. package/dist/chunks/boost.mjs +2 -2
  9. package/dist/chunks/ccjk-agents.mjs +1 -1
  10. package/dist/chunks/ccjk-all.mjs +1 -1
  11. package/dist/chunks/ccjk-config.mjs +1 -1
  12. package/dist/chunks/ccjk-hooks.mjs +1 -1
  13. package/dist/chunks/ccjk-mcp.mjs +2 -2
  14. package/dist/chunks/ccjk-setup.mjs +1 -1
  15. package/dist/chunks/ccjk-skills.mjs +1 -1
  16. package/dist/chunks/ccr.mjs +10 -10
  17. package/dist/chunks/ccu.mjs +1 -1
  18. package/dist/chunks/check-updates.mjs +3 -3
  19. package/dist/chunks/claude-code-config-manager.mjs +7 -7
  20. package/dist/chunks/claude-code-incremental-manager.mjs +2 -2
  21. package/dist/chunks/claude-config.mjs +3 -3
  22. package/dist/chunks/claude-wrapper.mjs +2 -2
  23. package/dist/chunks/codex-config-switch.mjs +2 -2
  24. package/dist/chunks/codex-provider-manager.mjs +2 -2
  25. package/dist/chunks/codex-uninstaller.mjs +2 -2
  26. package/dist/chunks/codex.mjs +5 -5
  27. package/dist/chunks/commands.mjs +88 -391
  28. package/dist/chunks/commands2.mjs +391 -88
  29. package/dist/chunks/completion.mjs +1 -1
  30. package/dist/chunks/config-consolidator.mjs +2 -2
  31. package/dist/chunks/config-switch.mjs +3 -3
  32. package/dist/chunks/config.mjs +5 -5
  33. package/dist/chunks/config2.mjs +410 -400
  34. package/dist/chunks/config3.mjs +400 -410
  35. package/dist/chunks/constants.mjs +1 -1
  36. package/dist/chunks/context.mjs +283 -1
  37. package/dist/chunks/dashboard.mjs +365 -0
  38. package/dist/chunks/doctor.mjs +4 -4
  39. package/dist/chunks/features.mjs +11 -11
  40. package/dist/chunks/fs-operations.mjs +1 -1
  41. package/dist/chunks/health-alerts.mjs +304 -0
  42. package/dist/chunks/health-check.mjs +532 -0
  43. package/dist/chunks/index.mjs +10 -177
  44. package/dist/chunks/index2.mjs +168 -1162
  45. package/dist/chunks/index3.mjs +1076 -910
  46. package/dist/chunks/index4.mjs +947 -137
  47. package/dist/chunks/index5.mjs +167 -635
  48. package/dist/chunks/index6.mjs +663 -0
  49. package/dist/chunks/init.mjs +19 -19
  50. package/dist/chunks/installer.mjs +649 -147
  51. package/dist/chunks/installer2.mjs +147 -649
  52. package/dist/chunks/interview.mjs +2 -2
  53. package/dist/chunks/marketplace.mjs +1 -1
  54. package/dist/chunks/mcp.mjs +4 -4
  55. package/dist/chunks/menu.mjs +16 -9
  56. package/dist/chunks/metrics-display.mjs +152 -0
  57. package/dist/chunks/migrator.mjs +1 -1
  58. package/dist/chunks/monitor.mjs +2 -2
  59. package/dist/chunks/notification.mjs +1 -1
  60. package/dist/chunks/onboarding.mjs +2 -2
  61. package/dist/chunks/package.mjs +1 -1
  62. package/dist/chunks/permission-manager.mjs +2 -2
  63. package/dist/chunks/permissions.mjs +1 -1
  64. package/dist/chunks/persistence-manager.mjs +781 -0
  65. package/dist/chunks/persistence.mjs +667 -0
  66. package/dist/chunks/platform.mjs +1 -1
  67. package/dist/chunks/plugin.mjs +1 -1
  68. package/dist/chunks/prompts.mjs +1 -1
  69. package/dist/chunks/providers.mjs +1 -1
  70. package/dist/chunks/quick-actions.mjs +321 -0
  71. package/dist/chunks/quick-setup.mjs +8 -8
  72. package/dist/chunks/silent-updater.mjs +1 -1
  73. package/dist/chunks/simple-config.mjs +2 -2
  74. package/dist/chunks/skill.mjs +1 -1
  75. package/dist/chunks/skills-sync.mjs +1 -1
  76. package/dist/chunks/skills.mjs +1 -1
  77. package/dist/chunks/slash-commands.mjs +208 -0
  78. package/dist/chunks/smart-defaults.mjs +1 -1
  79. package/dist/chunks/startup.mjs +1 -1
  80. package/dist/chunks/stats.mjs +1 -1
  81. package/dist/chunks/status.mjs +31 -2
  82. package/dist/chunks/team.mjs +1 -1
  83. package/dist/chunks/thinking.mjs +2 -2
  84. package/dist/chunks/uninstall.mjs +5 -5
  85. package/dist/chunks/update.mjs +7 -7
  86. package/dist/chunks/upgrade-manager.mjs +2 -2
  87. package/dist/chunks/version-checker.mjs +3 -3
  88. package/dist/chunks/vim.mjs +1 -1
  89. package/dist/cli.mjs +191 -21
  90. package/dist/i18n/locales/en/cli.json +14 -1
  91. package/dist/i18n/locales/en/common.json +27 -0
  92. package/dist/i18n/locales/en/context.json +54 -1
  93. package/dist/i18n/locales/en/dashboard.json +78 -0
  94. package/dist/i18n/locales/en/persistence.json +127 -0
  95. package/dist/i18n/locales/en/quick-actions.json +78 -0
  96. package/dist/i18n/locales/zh-CN/cli.json +14 -1
  97. package/dist/i18n/locales/zh-CN/common.json +27 -0
  98. package/dist/i18n/locales/zh-CN/context.json +54 -1
  99. package/dist/i18n/locales/zh-CN/dashboard.json +78 -0
  100. package/dist/i18n/locales/zh-CN/persistence.json +127 -0
  101. package/dist/i18n/locales/zh-CN/quick-actions.json +78 -0
  102. package/dist/index.mjs +2 -2
  103. package/dist/shared/{ccjk.DE91nClQ.mjs → ccjk.BKoi8-Hy.mjs} +1 -1
  104. package/dist/shared/{ccjk.Dpw86UX0.mjs → ccjk.CxtuJxaS.mjs} +1 -1
  105. package/dist/shared/{ccjk.ClzTOz9n.mjs → ccjk.DB2UYcq0.mjs} +5 -5
  106. package/dist/shared/{ccjk.Bndhan7G.mjs → ccjk.DfwJOEok.mjs} +1 -1
  107. package/dist/shared/{ccjk.DvIrK0wz.mjs → ccjk.DrMygfCF.mjs} +1 -1
  108. package/dist/shared/{ccjk.CmsW23FN.mjs → ccjk.IbImMVWM.mjs} +3 -3
  109. package/package.json +19 -19
@@ -0,0 +1,321 @@
1
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import ansis from 'ansis';
4
+ import { join } from 'pathe';
5
+ import { getContextPersistence } from './persistence.mjs';
6
+ import { MetricsDisplay } from './metrics-display.mjs';
7
+ import { r as runHealthCheck } from '../shared/ccjk.DfwJOEok.mjs';
8
+ import 'better-sqlite3';
9
+ import './constants.mjs';
10
+ import './index2.mjs';
11
+ import 'node:process';
12
+ import 'node:url';
13
+ import 'i18next';
14
+ import 'i18next-fs-backend';
15
+
16
+ const HABIT_FILE = join(homedir(), ".ccjk", "habits.json");
17
+ function loadHabitStats() {
18
+ try {
19
+ if (!existsSync(HABIT_FILE)) {
20
+ return {
21
+ totalCommands: 0,
22
+ lastUsed: 0,
23
+ streak: 0,
24
+ longestStreak: 0,
25
+ commandCounts: {},
26
+ firstUsed: Date.now()
27
+ };
28
+ }
29
+ return JSON.parse(readFileSync(HABIT_FILE, "utf-8"));
30
+ } catch {
31
+ return {
32
+ totalCommands: 0,
33
+ lastUsed: 0,
34
+ streak: 0,
35
+ longestStreak: 0,
36
+ commandCounts: {},
37
+ firstUsed: Date.now()
38
+ };
39
+ }
40
+ }
41
+ function saveHabitStats(stats) {
42
+ try {
43
+ const dir = join(homedir(), ".ccjk");
44
+ if (!existsSync(dir)) {
45
+ require("node:fs").mkdirSync(dir, { recursive: true });
46
+ }
47
+ writeFileSync(HABIT_FILE, JSON.stringify(stats, null, 2), "utf-8");
48
+ } catch {
49
+ }
50
+ }
51
+ function updateHabitStats(command) {
52
+ const stats = loadHabitStats();
53
+ const now = Date.now();
54
+ const lastUsedDate = new Date(stats.lastUsed).toDateString();
55
+ const todayDate = new Date(now).toDateString();
56
+ const yesterdayDate = new Date(now - 24 * 60 * 60 * 1e3).toDateString();
57
+ if (lastUsedDate === todayDate) ; else if (lastUsedDate === yesterdayDate) {
58
+ stats.streak++;
59
+ } else {
60
+ stats.streak = 1;
61
+ }
62
+ if (stats.streak > stats.longestStreak) {
63
+ stats.longestStreak = stats.streak;
64
+ }
65
+ stats.commandCounts[command] = (stats.commandCounts[command] || 0) + 1;
66
+ stats.totalCommands++;
67
+ stats.lastUsed = now;
68
+ saveHabitStats(stats);
69
+ return stats;
70
+ }
71
+ function getDaysUsed() {
72
+ const stats = loadHabitStats();
73
+ if (stats.totalCommands === 0) return 0;
74
+ const firstDate = new Date(stats.firstUsed);
75
+ const now = /* @__PURE__ */ new Date();
76
+ const diffTime = Math.abs(now.getTime() - firstDate.getTime());
77
+ const diffDays = Math.ceil(diffTime / (1e3 * 60 * 60 * 24));
78
+ return diffDays;
79
+ }
80
+ function getMotivationalMessage(stats, tokensSaved, costSavings) {
81
+ const messages = [];
82
+ if (stats.streak >= 7) {
83
+ messages.push(ansis.green.bold(`\u{1F389} ${stats.streak}-day streak! You're on fire!`));
84
+ } else if (stats.streak >= 3) {
85
+ messages.push(ansis.cyan(`\u{1F525} ${stats.streak}-day streak! Keep it going!`));
86
+ } else if (stats.streak === 1) {
87
+ messages.push(ansis.yellow(`\u2728 New streak started! Come back tomorrow!`));
88
+ }
89
+ if (costSavings >= 50) {
90
+ messages.push(ansis.green.bold(`\u{1F4B0} You've saved $${costSavings.toFixed(2)} this week!`));
91
+ } else if (costSavings >= 10) {
92
+ messages.push(ansis.cyan(`\u{1F4B5} $${costSavings.toFixed(2)} saved this week!`));
93
+ }
94
+ if (tokensSaved >= 1e5) {
95
+ messages.push(ansis.magenta.bold(`\u{1F680} ${MetricsDisplay.formatTokenCount(tokensSaved)} tokens saved!`));
96
+ } else if (tokensSaved >= 1e4) {
97
+ messages.push(ansis.blue(`\u{1F4CA} ${MetricsDisplay.formatTokenCount(tokensSaved)} tokens saved!`));
98
+ }
99
+ if (stats.totalCommands === 10) {
100
+ messages.push(ansis.yellow(`\u{1F3AF} 10 commands milestone! You're getting the hang of it!`));
101
+ } else if (stats.totalCommands === 50) {
102
+ messages.push(ansis.green(`\u{1F3C6} 50 commands milestone! You're a power user!`));
103
+ } else if (stats.totalCommands === 100) {
104
+ messages.push(ansis.magenta.bold(`\u{1F451} 100 commands milestone! You're a CCJK master!`));
105
+ }
106
+ if (stats.longestStreak >= 30) {
107
+ messages.push(ansis.magenta.bold(`\u{1F3C5} Longest streak: ${stats.longestStreak} days! Legendary!`));
108
+ } else if (stats.longestStreak >= 14) {
109
+ messages.push(ansis.green(`\u{1F3C5} Longest streak: ${stats.longestStreak} days!`));
110
+ }
111
+ return messages.length > 0 ? messages.join("\n ") : "";
112
+ }
113
+ function getSuggestion(stats) {
114
+ const now = Date.now();
115
+ const lastUsed = stats.lastUsed;
116
+ const hoursSinceLastUse = (now - lastUsed) / (1e3 * 60 * 60);
117
+ if (hoursSinceLastUse >= 168) {
118
+ return ansis.yellow(`\u{1F4A1} Tip: Run ${ansis.cyan("ccjk cleanup")} weekly to keep DB healthy`);
119
+ }
120
+ if (hoursSinceLastUse >= 24) {
121
+ return ansis.yellow(`\u{1F4A1} Tip: Run ${ansis.cyan("ccjk review")} to see your daily stats`);
122
+ }
123
+ if ((stats.commandCounts.commit || 0) < 5) {
124
+ return ansis.yellow(`\u{1F4A1} Tip: Try ${ansis.cyan("ccjk commit")} for smart commits with compression stats`);
125
+ }
126
+ const tips = [
127
+ `\u{1F4A1} Tip: ${ansis.cyan("ccjk morning")} gives you a quick health check`,
128
+ `\u{1F4A1} Tip: ${ansis.cyan("ccjk review")} shows your token savings`,
129
+ `\u{1F4A1} Tip: ${ansis.cyan("ccjk cleanup")} keeps your database optimized`
130
+ ];
131
+ return tips[Math.floor(Math.random() * tips.length)];
132
+ }
133
+ async function morningCommand(options = {}) {
134
+ const stats = updateHabitStats("morning");
135
+ if (!options.silent) {
136
+ console.log();
137
+ console.log(ansis.cyan.bold("\u2600\uFE0F Good morning! Here's your CCJK status:"));
138
+ console.log();
139
+ }
140
+ try {
141
+ const health = await runHealthCheck();
142
+ const persistence = getContextPersistence();
143
+ const metrics = persistence.getCompressionMetricsStats();
144
+ if (options.json) {
145
+ console.log(JSON.stringify({
146
+ health,
147
+ metrics,
148
+ habits: stats
149
+ }, null, 2));
150
+ return;
151
+ }
152
+ const gradeColor = health.grade === "S" ? ansis.magenta.bold : health.grade === "A" ? ansis.green.bold : health.grade === "B" ? ansis.cyan.bold : health.grade === "C" ? ansis.yellow.bold : ansis.red.bold;
153
+ console.log(` ${ansis.gray("Health Score:")} ${gradeColor(health.grade)} ${ansis.gray(`(${health.totalScore}/100)`)}`);
154
+ if (metrics.totalCompressions > 0) {
155
+ console.log(` ${ansis.gray("Total Saved:")} ${ansis.green(MetricsDisplay.formatTokenCount(metrics.totalTokensSaved))} tokens`);
156
+ console.log(` ${ansis.gray("Cost Savings:")} ${ansis.green.bold(MetricsDisplay.formatCost(metrics.estimatedCostSavings))}`);
157
+ if (metrics.sessionStats && metrics.sessionStats.compressions > 0) {
158
+ console.log(` ${ansis.gray("Last 24h:")} ${ansis.white(metrics.sessionStats.compressions)} compressions, ${ansis.green(MetricsDisplay.formatCost(metrics.sessionStats.costSavings))} saved`);
159
+ }
160
+ }
161
+ if (stats.streak > 0) {
162
+ console.log(` ${ansis.gray("Streak:")} ${ansis.yellow(`${stats.streak} day${stats.streak > 1 ? "s" : ""}`)}`);
163
+ }
164
+ console.log();
165
+ const message = getMotivationalMessage(stats, metrics.totalTokensSaved, metrics.weeklyStats?.costSavings || 0);
166
+ if (message) {
167
+ console.log(` ${message}`);
168
+ console.log();
169
+ }
170
+ if (health.recommendations.length > 0) {
171
+ console.log(ansis.yellow.bold(" \u{1F4CB} Top Recommendations:"));
172
+ for (const rec of health.recommendations.slice(0, 2)) {
173
+ const priority = rec.priority === "high" ? ansis.red("!") : rec.priority === "medium" ? ansis.yellow("\u2022") : ansis.gray("\xB7");
174
+ console.log(` ${priority} ${rec.title}`);
175
+ if (rec.command) {
176
+ console.log(` ${ansis.gray("\u2192")} ${ansis.cyan(rec.command)}`);
177
+ }
178
+ }
179
+ console.log();
180
+ }
181
+ const suggestion = getSuggestion(stats);
182
+ if (suggestion) {
183
+ console.log(` ${suggestion}`);
184
+ console.log();
185
+ }
186
+ } catch (error) {
187
+ console.error(ansis.red("Error running morning command:"), error);
188
+ process.exit(1);
189
+ }
190
+ }
191
+ async function reviewCommand(options = {}) {
192
+ const stats = updateHabitStats("review");
193
+ if (!options.silent) {
194
+ console.log();
195
+ console.log(ansis.cyan.bold("\u{1F4CA} Daily Review"));
196
+ console.log();
197
+ }
198
+ try {
199
+ const persistence = getContextPersistence();
200
+ const metrics = persistence.getCompressionMetricsStats();
201
+ if (options.json) {
202
+ console.log(JSON.stringify({
203
+ metrics,
204
+ habits: stats
205
+ }, null, 2));
206
+ return;
207
+ }
208
+ console.log(ansis.cyan.bold(" Overall Statistics"));
209
+ console.log(` ${ansis.gray("Total Compressions:")} ${ansis.white(metrics.totalCompressions)}`);
210
+ console.log(` ${ansis.gray("Total Saved:")} ${ansis.green(MetricsDisplay.formatTokenCount(metrics.totalTokensSaved))} tokens`);
211
+ console.log(` ${ansis.gray("Avg Reduction:")} ${ansis.yellow(MetricsDisplay.formatRatio(metrics.averageCompressionRatio))}`);
212
+ console.log(` ${ansis.gray("Cost Savings:")} ${ansis.green.bold(MetricsDisplay.formatCost(metrics.estimatedCostSavings))}`);
213
+ console.log();
214
+ if (metrics.sessionStats && metrics.sessionStats.compressions > 0) {
215
+ console.log(ansis.cyan.bold(" Last 24 Hours"));
216
+ console.log(` ${ansis.gray("Compressions:")} ${ansis.white(metrics.sessionStats.compressions)}`);
217
+ console.log(` ${ansis.gray("Tokens Saved:")} ${ansis.green(MetricsDisplay.formatTokenCount(metrics.sessionStats.tokensSaved))}`);
218
+ console.log(` ${ansis.gray("Cost Savings:")} ${ansis.green(MetricsDisplay.formatCost(metrics.sessionStats.costSavings))}`);
219
+ console.log();
220
+ }
221
+ if (metrics.weeklyStats && metrics.weeklyStats.compressions > 0) {
222
+ console.log(ansis.cyan.bold(" Last 7 Days"));
223
+ console.log(` ${ansis.gray("Compressions:")} ${ansis.white(metrics.weeklyStats.compressions)}`);
224
+ console.log(` ${ansis.gray("Tokens Saved:")} ${ansis.green(MetricsDisplay.formatTokenCount(metrics.weeklyStats.tokensSaved))}`);
225
+ console.log(` ${ansis.gray("Cost Savings:")} ${ansis.green(MetricsDisplay.formatCost(metrics.weeklyStats.costSavings))}`);
226
+ console.log();
227
+ }
228
+ if (metrics.monthlyStats && metrics.monthlyStats.compressions > 0) {
229
+ console.log(ansis.cyan.bold(" Last 30 Days"));
230
+ console.log(` ${ansis.gray("Compressions:")} ${ansis.white(metrics.monthlyStats.compressions)}`);
231
+ console.log(` ${ansis.gray("Tokens Saved:")} ${ansis.green(MetricsDisplay.formatTokenCount(metrics.monthlyStats.tokensSaved))}`);
232
+ console.log(` ${ansis.gray("Cost Savings:")} ${ansis.green(MetricsDisplay.formatCost(metrics.monthlyStats.costSavings))}`);
233
+ console.log();
234
+ }
235
+ console.log(ansis.cyan.bold(" Your Habits"));
236
+ console.log(` ${ansis.gray("Total Commands:")} ${ansis.white(stats.totalCommands)}`);
237
+ console.log(` ${ansis.gray("Current Streak:")} ${ansis.yellow(`${stats.streak} day${stats.streak !== 1 ? "s" : ""}`)}`);
238
+ console.log(` ${ansis.gray("Longest Streak:")} ${ansis.yellow(`${stats.longestStreak} day${stats.longestStreak !== 1 ? "s" : ""}`)}`);
239
+ console.log(` ${ansis.gray("Days Active:")} ${ansis.white(getDaysUsed())}`);
240
+ console.log();
241
+ const message = getMotivationalMessage(stats, metrics.totalTokensSaved, metrics.weeklyStats?.costSavings || 0);
242
+ if (message) {
243
+ console.log(` ${message}`);
244
+ console.log();
245
+ }
246
+ const suggestion = getSuggestion(stats);
247
+ if (suggestion) {
248
+ console.log(` ${suggestion}`);
249
+ console.log();
250
+ }
251
+ } catch (error) {
252
+ console.error(ansis.red("Error running review command:"), error);
253
+ process.exit(1);
254
+ }
255
+ }
256
+ async function cleanupCommand(options = {}) {
257
+ const stats = updateHabitStats("cleanup");
258
+ if (!options.silent) {
259
+ console.log();
260
+ console.log(ansis.cyan.bold("\u{1F9F9} Database Cleanup"));
261
+ console.log();
262
+ }
263
+ try {
264
+ const persistence = getContextPersistence();
265
+ const statsBefore = persistence.getStats();
266
+ if (!options.silent) {
267
+ console.log(` ${ansis.gray("Database size before:")} ${ansis.white(MetricsDisplay.formatBytes(statsBefore.totalSize))}`);
268
+ console.log(` ${ansis.gray("Total contexts:")} ${ansis.white(statsBefore.totalContexts)}`);
269
+ console.log();
270
+ }
271
+ const maxAge = 30 * 24 * 60 * 60 * 1e3;
272
+ const deletedContexts = persistence.cleanup(maxAge);
273
+ if (!options.silent && deletedContexts > 0) {
274
+ console.log(` ${ansis.green("\u2713")} Deleted ${ansis.white(deletedContexts)} old context${deletedContexts !== 1 ? "s" : ""}`);
275
+ }
276
+ const metricsMaxAge = 90 * 24 * 60 * 60 * 1e3;
277
+ const deletedMetrics = persistence.cleanupCompressionMetrics(metricsMaxAge);
278
+ if (!options.silent && deletedMetrics > 0) {
279
+ console.log(` ${ansis.green("\u2713")} Deleted ${ansis.white(deletedMetrics)} old metric${deletedMetrics !== 1 ? "s" : ""}`);
280
+ }
281
+ if (!options.silent) {
282
+ console.log(` ${ansis.gray("Running VACUUM...")}`);
283
+ }
284
+ persistence.vacuum();
285
+ const statsAfter = persistence.getStats();
286
+ const sizeSaved = statsBefore.totalSize - statsAfter.totalSize;
287
+ if (!options.silent) {
288
+ console.log(` ${ansis.green("\u2713")} VACUUM complete`);
289
+ console.log();
290
+ console.log(` ${ansis.gray("Database size after:")} ${ansis.white(MetricsDisplay.formatBytes(statsAfter.totalSize))}`);
291
+ console.log(` ${ansis.gray("Space reclaimed:")} ${ansis.green(MetricsDisplay.formatBytes(sizeSaved))}`);
292
+ console.log(` ${ansis.gray("Total contexts:")} ${ansis.white(statsAfter.totalContexts)}`);
293
+ console.log();
294
+ console.log(` ${ansis.green.bold("\u2713 Cleanup complete!")}`);
295
+ console.log();
296
+ }
297
+ if (options.json) {
298
+ console.log(JSON.stringify({
299
+ deletedContexts,
300
+ deletedMetrics,
301
+ sizeSaved,
302
+ statsBefore,
303
+ statsAfter
304
+ }, null, 2));
305
+ }
306
+ if (!options.silent) {
307
+ const message = getMotivationalMessage(stats, 0, 0);
308
+ if (message) {
309
+ console.log(` ${message}`);
310
+ console.log();
311
+ }
312
+ console.log(` ${ansis.yellow(`\u{1F4A1} Tip: Run cleanup weekly to keep your database healthy`)}`);
313
+ console.log();
314
+ }
315
+ } catch (error) {
316
+ console.error(ansis.red("Error running cleanup command:"), error);
317
+ process.exit(1);
318
+ }
319
+ }
320
+
321
+ export { cleanupCommand, morningCommand, reviewCommand };
@@ -2,7 +2,7 @@ import ansis from 'ansis';
2
2
  import inquirer from 'inquirer';
3
3
  import { version } from './package.mjs';
4
4
  import { detectSmartDefaults } from './smart-defaults.mjs';
5
- import { i18n } from './index.mjs';
5
+ import { i18n } from './index2.mjs';
6
6
  import { updateZcfConfig } from './ccjk-config.mjs';
7
7
  import { i as init } from './init.mjs';
8
8
  import 'node:child_process';
@@ -32,17 +32,17 @@ import '../shared/ccjk.BFQ7yr5S.mjs';
32
32
  import './prompts.mjs';
33
33
  import '../shared/ccjk.DHbrGcgg.mjs';
34
34
  import 'inquirer-toggle';
35
- import '../shared/ccjk.CmsW23FN.mjs';
36
- import '../shared/ccjk.Br91zBIG.mjs';
37
- import './config3.mjs';
35
+ import '../shared/ccjk.IbImMVWM.mjs';
36
+ import './banner.mjs';
37
+ import './config2.mjs';
38
38
  import 'node:util';
39
39
  import './auto-updater.mjs';
40
40
  import './version-checker.mjs';
41
41
  import 'node:path';
42
- import '../shared/ccjk.Dpw86UX0.mjs';
43
- import '../shared/ccjk.DvIrK0wz.mjs';
44
- import './installer2.mjs';
45
- import '../shared/ccjk.DE91nClQ.mjs';
42
+ import '../shared/ccjk.CxtuJxaS.mjs';
43
+ import '../shared/ccjk.DrMygfCF.mjs';
44
+ import './installer.mjs';
45
+ import '../shared/ccjk.BKoi8-Hy.mjs';
46
46
 
47
47
  function displayHeader() {
48
48
  console.log("");
@@ -5,7 +5,7 @@ import { fileURLToPath } from 'node:url';
5
5
  import { join, dirname } from 'pathe';
6
6
  import { CCJK_CONFIG_DIR } from './constants.mjs';
7
7
  import { getCloudState, updateCloudState } from './auto-bootstrap.mjs';
8
- import './index.mjs';
8
+ import './index2.mjs';
9
9
  import 'i18next';
10
10
  import 'i18next-fs-backend';
11
11
  import 'node:crypto';
@@ -5,9 +5,9 @@ import { exec } from 'tinyexec';
5
5
  import { SETTINGS_FILE, CLAUDE_DIR } from './constants.mjs';
6
6
  import { ensureDir, writeFileAtomic } from './fs-operations.mjs';
7
7
  import { m as mergeAndCleanPermissions } from './config.mjs';
8
- import { d as getPlatform } from './platform.mjs';
8
+ import { g as getPlatform } from './platform.mjs';
9
9
  import 'node:os';
10
- import './index.mjs';
10
+ import './index2.mjs';
11
11
  import 'node:process';
12
12
  import 'i18next';
13
13
  import 'i18next-fs-backend';
@@ -8,7 +8,7 @@ import { join, dirname } from 'pathe';
8
8
  import { g as getPluginManager } from '../shared/ccjk.BsXQugfY.mjs';
9
9
  import 'tinyexec';
10
10
  import './constants.mjs';
11
- import './index.mjs';
11
+ import './index2.mjs';
12
12
  import 'node:process';
13
13
  import 'i18next';
14
14
  import 'i18next-fs-backend';
@@ -1,6 +1,6 @@
1
1
  import ansis from 'ansis';
2
2
  import inquirer from 'inquirer';
3
- import { getTranslation } from './index.mjs';
3
+ import { getTranslation } from './index2.mjs';
4
4
  import { createHash } from 'node:crypto';
5
5
  import { existsSync, readdirSync, readFileSync, mkdirSync } from 'node:fs';
6
6
  import process__default from 'node:process';
@@ -1,6 +1,6 @@
1
1
  import ansis from 'ansis';
2
2
  import inquirer from 'inquirer';
3
- import { i18n } from './index.mjs';
3
+ import { i18n } from './index2.mjs';
4
4
  import { existsSync, unlinkSync, mkdirSync, readdirSync, readFileSync } from 'node:fs';
5
5
  import 'node:os';
6
6
  import { join } from 'pathe';
@@ -0,0 +1,208 @@
1
+ import ansis from 'ansis';
2
+ import { i18n } from './index2.mjs';
3
+ import { getContextPersistence } from './persistence.mjs';
4
+ import 'node:fs';
5
+ import 'node:process';
6
+ import 'node:url';
7
+ import 'i18next';
8
+ import 'i18next-fs-backend';
9
+ import 'pathe';
10
+ import 'better-sqlite3';
11
+
12
+ function parseSlashCommand(input) {
13
+ const trimmed = input.trim();
14
+ if (!trimmed.startsWith("/")) {
15
+ return null;
16
+ }
17
+ const parts = trimmed.slice(1).split(/\s+/);
18
+ const command = parts[0].toLowerCase();
19
+ const args = parts.slice(1);
20
+ return { command, args };
21
+ }
22
+ function getSlashCommands() {
23
+ return [
24
+ {
25
+ name: "status",
26
+ aliases: ["s"],
27
+ description: "Show Brain Dashboard with health score",
28
+ descriptionZh: "\u663E\u793A Brain \u4EEA\u8868\u677F\u548C\u5065\u5EB7\u8BC4\u5206",
29
+ category: "brain",
30
+ handler: async () => {
31
+ const { statusCommand } = await import('./status.mjs');
32
+ await statusCommand({ compact: false });
33
+ }
34
+ },
35
+ {
36
+ name: "health",
37
+ aliases: ["h"],
38
+ description: "Run comprehensive health check",
39
+ descriptionZh: "\u8FD0\u884C\u5168\u9762\u5065\u5EB7\u68C0\u67E5",
40
+ category: "brain",
41
+ handler: async () => {
42
+ const { runHealthCheck } = await import('./index.mjs');
43
+ const report = await runHealthCheck();
44
+ console.log(ansis.cyan.bold("\n\u{1F3E5} Health Check Results\n"));
45
+ console.log(`${ansis.gray("Overall Score:")} ${ansis.green.bold(report.totalScore + "/100")}`);
46
+ console.log(`${ansis.gray("Grade:")} ${ansis.green.bold(report.grade)}`);
47
+ if (report.recommendations.length > 0) {
48
+ console.log(ansis.yellow.bold("\n\u{1F4A1} Recommendations:\n"));
49
+ report.recommendations.forEach((rec, i) => {
50
+ console.log(`${ansis.yellow(i + 1 + ".")} ${rec.description}`);
51
+ if (rec.command) {
52
+ console.log(` ${ansis.gray("\u2192")} ${ansis.cyan(rec.command)}`);
53
+ }
54
+ });
55
+ }
56
+ console.log();
57
+ }
58
+ },
59
+ {
60
+ name: "search",
61
+ aliases: ["find", "query"],
62
+ description: "Search contexts using FTS5 full-text search",
63
+ descriptionZh: "\u4F7F\u7528 FTS5 \u5168\u6587\u641C\u7D22\u4E0A\u4E0B\u6587",
64
+ category: "context",
65
+ handler: async (args) => {
66
+ if (args.length === 0) {
67
+ console.log(ansis.yellow("Usage: /search <query>"));
68
+ console.log(ansis.gray('Example: /search "authentication logic"'));
69
+ return;
70
+ }
71
+ const query = args.join(" ");
72
+ const persistence = getContextPersistence();
73
+ const results = await persistence.searchContexts(query, { limit: 10 });
74
+ if (results.length === 0) {
75
+ console.log(ansis.yellow(`No results found for: ${query}`));
76
+ return;
77
+ }
78
+ console.log(ansis.cyan.bold(`
79
+ \u{1F50D} Search Results (${results.length})
80
+ `));
81
+ results.forEach((result, i) => {
82
+ console.log(ansis.white.bold(`${i + 1}. ${result.id}`));
83
+ console.log(` ${ansis.gray("Rank:")} ${ansis.yellow(result.rank.toFixed(2))}`);
84
+ console.log(` ${ansis.gray("Tokens:")} ${result.originalTokens} \u2192 ${result.compressedTokens}`);
85
+ console.log(` ${ansis.gray("Algorithm:")} ${result.algorithm}`);
86
+ if (result.snippet) {
87
+ console.log(` ${ansis.gray("Snippet:")} ${ansis.dim(result.snippet)}`);
88
+ }
89
+ console.log();
90
+ });
91
+ }
92
+ },
93
+ {
94
+ name: "compress",
95
+ aliases: ["stats", "metrics"],
96
+ description: "Show compression statistics and metrics",
97
+ descriptionZh: "\u663E\u793A\u538B\u7F29\u7EDF\u8BA1\u548C\u6307\u6807",
98
+ category: "context",
99
+ handler: async () => {
100
+ const persistence = getContextPersistence();
101
+ const stats = persistence.getCompressionMetricsStats();
102
+ const { displayCompressionStats } = await import('./metrics-display.mjs');
103
+ displayCompressionStats(stats);
104
+ }
105
+ },
106
+ {
107
+ name: "tasks",
108
+ aliases: ["task", "t"],
109
+ description: "Open task manager (Brain system)",
110
+ descriptionZh: "\u6253\u5F00\u4EFB\u52A1\u7BA1\u7406\u5668\uFF08Brain \u7CFB\u7EDF\uFF09",
111
+ category: "brain",
112
+ handler: async () => {
113
+ console.log(ansis.cyan.bold("\n\u{1F4CB} Task Manager\n"));
114
+ console.log(ansis.yellow("Task management is integrated with Brain system."));
115
+ console.log(ansis.gray("Use: ccjk status --tasks to view active tasks"));
116
+ console.log();
117
+ }
118
+ },
119
+ {
120
+ name: "backup",
121
+ aliases: ["save"],
122
+ description: "Create configuration backup",
123
+ descriptionZh: "\u521B\u5EFA\u914D\u7F6E\u5907\u4EFD",
124
+ category: "system",
125
+ handler: async () => {
126
+ const { backupExistingConfig } = await import('./config.mjs').then(function (n) { return n.j; });
127
+ const backupPath = backupExistingConfig();
128
+ if (backupPath) {
129
+ console.log(ansis.green(`\u2705 Backup created: ${backupPath}`));
130
+ } else {
131
+ console.log(ansis.yellow("\u26A0\uFE0F No configuration to backup"));
132
+ }
133
+ }
134
+ },
135
+ {
136
+ name: "optimize",
137
+ aliases: ["vacuum", "cleanup"],
138
+ description: "Run VACUUM + checkpoint on context database",
139
+ descriptionZh: "\u5BF9\u4E0A\u4E0B\u6587\u6570\u636E\u5E93\u8FD0\u884C VACUUM + checkpoint",
140
+ category: "context",
141
+ handler: async () => {
142
+ console.log(ansis.cyan("\u{1F5DC}\uFE0F Optimizing context database..."));
143
+ const persistence = getContextPersistence();
144
+ persistence.vacuum();
145
+ console.log(ansis.green("\u2705 Database optimized (VACUUM completed)"));
146
+ }
147
+ },
148
+ {
149
+ name: "help",
150
+ aliases: ["?", "commands"],
151
+ description: "Show all CCJK slash commands",
152
+ descriptionZh: "\u663E\u793A\u6240\u6709 CCJK \u659C\u6760\u547D\u4EE4",
153
+ category: "system",
154
+ handler: async () => {
155
+ displaySlashCommandsHelp();
156
+ }
157
+ }
158
+ ];
159
+ }
160
+ async function executeSlashCommand(input) {
161
+ const parsed = parseSlashCommand(input);
162
+ if (!parsed) {
163
+ return false;
164
+ }
165
+ const commands = getSlashCommands();
166
+ const command = commands.find(
167
+ (cmd) => cmd.name === parsed.command || cmd.aliases?.includes(parsed.command)
168
+ );
169
+ if (!command) {
170
+ console.log(ansis.yellow(`Unknown command: /${parsed.command}`));
171
+ console.log(ansis.gray("Type /help to see all available commands"));
172
+ return true;
173
+ }
174
+ try {
175
+ await command.handler(parsed.args);
176
+ return true;
177
+ } catch (error) {
178
+ console.error(ansis.red(`Error executing /${parsed.command}:`), error);
179
+ return true;
180
+ }
181
+ }
182
+ function displaySlashCommandsHelp() {
183
+ const isZh = i18n.language === "zh-CN";
184
+ const commands = getSlashCommands();
185
+ console.log(ansis.cyan.bold("\n\u{1F4A1} CCJK Slash Commands\n"));
186
+ const categories = {
187
+ brain: { title: isZh ? "\u{1F9E0} Brain \u7CFB\u7EDF" : "\u{1F9E0} Brain System", commands: [] },
188
+ context: { title: isZh ? "\u{1F4E6} \u4E0A\u4E0B\u6587\u7BA1\u7406" : "\u{1F4E6} Context Management", commands: [] },
189
+ system: { title: isZh ? "\u2699\uFE0F \u7CFB\u7EDF\u5DE5\u5177" : "\u2699\uFE0F System Tools", commands: [] }
190
+ };
191
+ commands.forEach((cmd) => {
192
+ categories[cmd.category].commands.push(cmd);
193
+ });
194
+ Object.values(categories).forEach((category) => {
195
+ if (category.commands.length === 0) return;
196
+ console.log(ansis.white.bold(category.title));
197
+ category.commands.forEach((cmd) => {
198
+ const aliases = cmd.aliases ? ansis.gray(` (${cmd.aliases.map((a) => `/${a}`).join(", ")})`) : "";
199
+ const desc = isZh ? cmd.descriptionZh : cmd.description;
200
+ console.log(` ${ansis.green(`/${cmd.name}`)}${aliases}`);
201
+ console.log(` ${ansis.gray(desc)}`);
202
+ });
203
+ console.log();
204
+ });
205
+ console.log(ansis.gray("Tip: Type /help or /? to see this message again\n"));
206
+ }
207
+
208
+ export { displaySlashCommandsHelp, executeSlashCommand, getSlashCommands, parseSlashCommand };
@@ -2,7 +2,7 @@ import { execSync } from 'node:child_process';
2
2
  import { existsSync, readFileSync } from 'node:fs';
3
3
  import { homedir } from 'node:os';
4
4
  import { join } from 'pathe';
5
- import { d as getPlatform } from './platform.mjs';
5
+ import { g as getPlatform } from './platform.mjs';
6
6
  import { s as scanProject } from '../shared/ccjk.DKojSRzw.mjs';
7
7
  import 'node:process';
8
8
  import 'tinyexec';
@@ -2,7 +2,7 @@ import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync } from
2
2
  import { mkdir } from 'node:fs/promises';
3
3
  import { homedir } from 'node:os';
4
4
  import { join, basename } from 'pathe';
5
- import { i18n } from './index.mjs';
5
+ import { i18n } from './index2.mjs';
6
6
  import 'node:process';
7
7
  import 'node:url';
8
8
  import 'i18next';
@@ -1,5 +1,5 @@
1
1
  import ansis from 'ansis';
2
- import { i18n } from './index.mjs';
2
+ import { i18n } from './index2.mjs';
3
3
  import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync } from 'node:fs';
4
4
  import { homedir } from 'node:os';
5
5
  import { join } from 'pathe';