@kaitranntt/ccs 2.5.1 → 3.0.1

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.
@@ -0,0 +1,135 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const os = require('os');
6
+
7
+ /**
8
+ * Auto-recovery for missing or corrupted configuration
9
+ */
10
+ class RecoveryManager {
11
+ constructor() {
12
+ this.homedir = os.homedir();
13
+ this.ccsDir = path.join(this.homedir, '.ccs');
14
+ this.claudeDir = path.join(this.homedir, '.claude');
15
+ this.recovered = [];
16
+ }
17
+
18
+ /**
19
+ * Ensure ~/.ccs/ directory exists
20
+ */
21
+ ensureCcsDirectory() {
22
+ if (!fs.existsSync(this.ccsDir)) {
23
+ fs.mkdirSync(this.ccsDir, { recursive: true, mode: 0o755 });
24
+ this.recovered.push('Created ~/.ccs/ directory');
25
+ return true;
26
+ }
27
+ return false;
28
+ }
29
+
30
+ /**
31
+ * Ensure ~/.ccs/config.json exists with defaults
32
+ */
33
+ ensureConfigJson() {
34
+ const configPath = path.join(this.ccsDir, 'config.json');
35
+
36
+ // Check if exists and valid
37
+ if (fs.existsSync(configPath)) {
38
+ try {
39
+ const content = fs.readFileSync(configPath, 'utf8');
40
+ JSON.parse(content); // Validate JSON
41
+ return false; // No recovery needed
42
+ } catch (e) {
43
+ // Corrupted - backup and recreate
44
+ const backupPath = `${configPath}.backup.${Date.now()}`;
45
+ fs.renameSync(configPath, backupPath);
46
+ this.recovered.push(`Backed up corrupted config.json to ${path.basename(backupPath)}`);
47
+ }
48
+ }
49
+
50
+ // Create default config
51
+ const defaultConfig = {
52
+ profiles: {
53
+ glm: '~/.ccs/glm.settings.json',
54
+ kimi: '~/.ccs/kimi.settings.json',
55
+ default: '~/.claude/settings.json'
56
+ }
57
+ };
58
+
59
+ const tmpPath = `${configPath}.tmp`;
60
+ fs.writeFileSync(tmpPath, JSON.stringify(defaultConfig, null, 2) + '\n', 'utf8');
61
+ fs.renameSync(tmpPath, configPath);
62
+
63
+ this.recovered.push('Created ~/.ccs/config.json');
64
+ return true;
65
+ }
66
+
67
+ /**
68
+ * Ensure ~/.claude/settings.json exists
69
+ */
70
+ ensureClaudeSettings() {
71
+ const claudeSettingsPath = path.join(this.claudeDir, 'settings.json');
72
+
73
+ // Create ~/.claude/ if missing
74
+ if (!fs.existsSync(this.claudeDir)) {
75
+ fs.mkdirSync(this.claudeDir, { recursive: true, mode: 0o755 });
76
+ this.recovered.push('Created ~/.claude/ directory');
77
+ }
78
+
79
+ // Create settings.json if missing
80
+ if (!fs.existsSync(claudeSettingsPath)) {
81
+ const tmpPath = `${claudeSettingsPath}.tmp`;
82
+ fs.writeFileSync(tmpPath, '{}\n', 'utf8');
83
+ fs.renameSync(tmpPath, claudeSettingsPath);
84
+
85
+ this.recovered.push('Created ~/.claude/settings.json');
86
+ return true;
87
+ }
88
+
89
+ return false;
90
+ }
91
+
92
+ /**
93
+ * Run all recovery operations
94
+ * @returns {boolean} True if any recovery performed
95
+ */
96
+ recoverAll() {
97
+ this.recovered = [];
98
+
99
+ this.ensureCcsDirectory();
100
+ this.ensureConfigJson();
101
+ this.ensureClaudeSettings();
102
+
103
+ return this.recovered.length > 0;
104
+ }
105
+
106
+ /**
107
+ * Get recovery summary
108
+ * @returns {string[]} List of recovery actions performed
109
+ */
110
+ getRecoverySummary() {
111
+ return this.recovered;
112
+ }
113
+
114
+ /**
115
+ * Show recovery hints
116
+ */
117
+ showRecoveryHints() {
118
+ if (this.recovered.length === 0) return;
119
+
120
+ console.log('');
121
+ console.log('[i] Auto-recovery completed:');
122
+ this.recovered.forEach(msg => console.log(` - ${msg}`));
123
+
124
+ // Show login hint if created Claude settings
125
+ if (this.recovered.some(msg => msg.includes('settings.json'))) {
126
+ console.log('');
127
+ console.log('[i] Next step: Login to Claude CLI');
128
+ console.log(' Run: claude /login');
129
+ }
130
+
131
+ console.log('');
132
+ }
133
+ }
134
+
135
+ module.exports = RecoveryManager;