aicodeswitch 1.2.6 → 1.3.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.
package/bin/cli.js CHANGED
@@ -34,6 +34,7 @@ const commands = {
34
34
  stop: () => require(path.join(binDir, 'stop')),
35
35
  restart: () => require(path.join(binDir, 'restart')),
36
36
  update: () => require(path.join(binDir, 'update')),
37
+ restore: () => require(path.join(binDir, 'restore')),
37
38
  version: () => require(path.join(binDir, 'version')),
38
39
  };
39
40
 
@@ -46,6 +47,7 @@ Commands:
46
47
  stop Stop the AI Code Switch server
47
48
  restart Restart the AI Code Switch server
48
49
  update Update to the latest version and restart
50
+ restore Restore original configuration files
49
51
  version Show current version information
50
52
 
51
53
  Example:
@@ -53,6 +55,9 @@ Example:
53
55
  aicos stop
54
56
  aicos restart
55
57
  aicos update
58
+ aicos restore
59
+ aicos restore claude-code
60
+ aicos restore codex
56
61
  aicos version
57
62
  `);
58
63
  process.exit(1);
package/bin/restore.js ADDED
@@ -0,0 +1,220 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const os = require('os');
4
+ const chalk = require('chalk');
5
+ const boxen = require('boxen');
6
+ const ora = require('ora');
7
+
8
+ // 恢复 Claude Code 配置
9
+ const restoreClaudeConfig = () => {
10
+ const results = {
11
+ restored: [],
12
+ notFound: [],
13
+ errors: []
14
+ };
15
+
16
+ try {
17
+ const homeDir = os.homedir();
18
+ const claudeDir = path.join(homeDir, '.claude');
19
+ const claudeSettingsPath = path.join(claudeDir, 'settings.json');
20
+ const claudeSettingsBakPath = path.join(claudeDir, 'settings.json.bak');
21
+
22
+ // Restore settings.json
23
+ if (fs.existsSync(claudeSettingsBakPath)) {
24
+ if (fs.existsSync(claudeSettingsPath)) {
25
+ fs.unlinkSync(claudeSettingsPath);
26
+ }
27
+ fs.renameSync(claudeSettingsBakPath, claudeSettingsPath);
28
+ results.restored.push('settings.json');
29
+ } else {
30
+ results.notFound.push('settings.json.bak');
31
+ }
32
+ } catch (err) {
33
+ results.errors.push({ file: 'settings.json', error: err.message });
34
+ }
35
+
36
+ try {
37
+ const homeDir = os.homedir();
38
+ const claudeJsonPath = path.join(homeDir, '.claude.json');
39
+ const claudeJsonBakPath = path.join(homeDir, '.claude.json.bak');
40
+
41
+ // Restore .claude.json
42
+ if (fs.existsSync(claudeJsonBakPath)) {
43
+ if (fs.existsSync(claudeJsonPath)) {
44
+ fs.unlinkSync(claudeJsonPath);
45
+ }
46
+ fs.renameSync(claudeJsonBakPath, claudeJsonPath);
47
+ results.restored.push('.claude.json');
48
+ } else {
49
+ results.notFound.push('.claude.json.bak');
50
+ }
51
+ } catch (err) {
52
+ results.errors.push({ file: '.claude.json', error: err.message });
53
+ }
54
+
55
+ return results;
56
+ };
57
+
58
+ // 恢复 Codex 配置
59
+ const restoreCodexConfig = () => {
60
+ const results = {
61
+ restored: [],
62
+ notFound: [],
63
+ errors: []
64
+ };
65
+
66
+ try {
67
+ const homeDir = os.homedir();
68
+ const codexDir = path.join(homeDir, '.codex');
69
+ const codexConfigPath = path.join(codexDir, 'config.toml');
70
+ const codexConfigBakPath = path.join(codexDir, 'config.toml.bak');
71
+
72
+ // Restore config.toml
73
+ if (fs.existsSync(codexConfigBakPath)) {
74
+ if (fs.existsSync(codexConfigPath)) {
75
+ fs.unlinkSync(codexConfigPath);
76
+ }
77
+ fs.renameSync(codexConfigBakPath, codexConfigPath);
78
+ results.restored.push('config.toml');
79
+ } else {
80
+ results.notFound.push('config.toml.bak');
81
+ }
82
+ } catch (err) {
83
+ results.errors.push({ file: 'config.toml', error: err.message });
84
+ }
85
+
86
+ try {
87
+ const homeDir = os.homedir();
88
+ const codexAuthPath = path.join(homeDir, '.codex', 'auth.json');
89
+ const codexAuthBakPath = path.join(homeDir, '.codex', 'auth.json.bak');
90
+
91
+ // Restore auth.json
92
+ if (fs.existsSync(codexAuthBakPath)) {
93
+ if (fs.existsSync(codexAuthPath)) {
94
+ fs.unlinkSync(codexAuthPath);
95
+ }
96
+ fs.renameSync(codexAuthBakPath, codexAuthPath);
97
+ results.restored.push('auth.json');
98
+ } else {
99
+ results.notFound.push('auth.json.bak');
100
+ }
101
+ } catch (err) {
102
+ results.errors.push({ file: 'auth.json', error: err.message });
103
+ }
104
+
105
+ return results;
106
+ };
107
+
108
+ // 显示恢复结果
109
+ const showRestoreResult = (target, results) => {
110
+ const targetName = target === 'claude-code' ? 'Claude Code' : 'Codex';
111
+ const targetColor = target === 'claude-code' ? chalk.cyan : chalk.magenta;
112
+
113
+ let message = targetColor.bold(`${targetName} Configuration Restore\n\n`);
114
+
115
+ if (results.restored.length > 0) {
116
+ message += chalk.green('Restored files:\n');
117
+ results.restored.forEach(file => {
118
+ message += chalk.white(` ✓ ${file}\n`);
119
+ });
120
+ message += '\n';
121
+ }
122
+
123
+ if (results.notFound.length > 0) {
124
+ message += chalk.gray('No backup found:\n');
125
+ results.notFound.forEach(file => {
126
+ message += chalk.gray(` - ${file}\n`);
127
+ });
128
+ message += '\n';
129
+ }
130
+
131
+ if (results.errors.length > 0) {
132
+ message += chalk.red('Errors:\n');
133
+ results.errors.forEach(({ file, error }) => {
134
+ message += chalk.red(` ✗ ${file}: ${error}\n`);
135
+ });
136
+ message += '\n';
137
+ }
138
+
139
+ // 添加重启提示
140
+ if (results.restored.length > 0) {
141
+ message += chalk.yellow.bold('⚠️ Important:\n\n');
142
+ if (target === 'claude-code') {
143
+ message += chalk.white('Please restart ') + chalk.cyan.bold('Claude Code') + chalk.white(' to apply the restored configuration.\n');
144
+ } else {
145
+ message += chalk.white('Please restart ') + chalk.magenta.bold('Codex') + chalk.white(' to apply the restored configuration.\n');
146
+ }
147
+ }
148
+
149
+ const borderColor = results.errors.length > 0 ? 'red' :
150
+ results.restored.length > 0 ? 'green' : 'gray';
151
+
152
+ console.log(boxen(message, {
153
+ padding: 1,
154
+ margin: 1,
155
+ borderStyle: 'round',
156
+ borderColor
157
+ }));
158
+ };
159
+
160
+ // 主恢复逻辑
161
+ const restore = async () => {
162
+ const args = process.argv.slice(2);
163
+ const target = args[0]; // claude-code, codex, or undefined (all)
164
+
165
+ console.log('\n');
166
+
167
+ const validTargets = ['claude-code', 'codex', undefined];
168
+
169
+ if (target && !validTargets.includes(target)) {
170
+ console.log(boxen(
171
+ chalk.red.bold('✗ Invalid target\n\n') +
172
+ chalk.white('Usage: ') + chalk.cyan('aicos restore [target]\n\n') +
173
+ chalk.white('Targets:\n') +
174
+ chalk.white(' claude-code Restore Claude Code configuration\n') +
175
+ chalk.white(' codex Restore Codex configuration\n') +
176
+ chalk.white(' (no arg) Restore all configurations\n'),
177
+ {
178
+ padding: 1,
179
+ margin: 1,
180
+ borderStyle: 'round',
181
+ borderColor: 'red'
182
+ }
183
+ ));
184
+ console.log('');
185
+ process.exit(1);
186
+ }
187
+
188
+ // 恢复配置
189
+ if (target === 'claude-code' || !target) {
190
+ const spinner = ora({
191
+ text: chalk.cyan('Restoring Claude Code configuration...'),
192
+ color: 'cyan'
193
+ }).start();
194
+
195
+ const claudeResults = restoreClaudeConfig();
196
+ spinner.succeed(chalk.green('Claude Code restore complete'));
197
+ showRestoreResult('claude-code', claudeResults);
198
+ }
199
+
200
+ if (target === 'codex' || !target) {
201
+ if (!target) console.log(''); // Add spacing when restoring both
202
+
203
+ const spinner = ora({
204
+ text: chalk.magenta('Restoring Codex configuration...'),
205
+ color: 'magenta'
206
+ }).start();
207
+
208
+ const codexResults = restoreCodexConfig();
209
+ spinner.succeed(chalk.green('Codex restore complete'));
210
+ showRestoreResult('codex', codexResults);
211
+ }
212
+
213
+ console.log('');
214
+ console.log(chalk.cyan('💡 Tips:\n'));
215
+ console.log(chalk.white(' • Write config: ') + chalk.cyan('aicos write-config [target]'));
216
+ console.log(chalk.white(' • Start server: ') + chalk.cyan('aicos start'));
217
+ console.log('\n');
218
+ };
219
+
220
+ module.exports = restore();
package/bin/update.js CHANGED
@@ -268,19 +268,19 @@ const update = async () => {
268
268
  color: 'cyan'
269
269
  }).start();
270
270
 
271
- try {
272
- const npmArgs = ['install', '-g', `${PACKAGE_NAME}@latest`];
273
- if (needSudo) {
274
- npmArgs.unshift('sudo');
275
- }
271
+ const npmArgs = ['npm', 'install', '-g', `${PACKAGE_NAME}@latest`];
272
+ if (needSudo) {
273
+ npmArgs.unshift('sudo');
274
+ }
276
275
 
277
- await execCommand(needSudo ? 'sudo' : 'npm', npmArgs);
276
+ try {
277
+ await execCommand(npmArgs);
278
278
  updateSpinner.succeed(chalk.green('Update successful!'));
279
279
  } catch (err) {
280
280
  updateSpinner.fail(chalk.red('Update failed'));
281
281
  console.log(chalk.yellow(`\nUpdate failed with error code ${err.code || 'unknown'}\n`));
282
282
  console.log(chalk.white('You can try manually updating:\n'));
283
- console.log(chalk.cyan(` ${needSudo ? 'sudo ' : ''}npm install -g ${PACKAGE_NAME}@latest\n`));
283
+ console.log(chalk.cyan(` ${npmArgs.join(' ')}\n`));
284
284
 
285
285
  // 尝试重新启动服务器
286
286
  console.log(chalk.yellow('Attempting to restart server...\n'));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aicodeswitch",
3
- "version": "1.2.6",
3
+ "version": "1.3.1",
4
4
  "description": "A tool to help you manage AI programming tools to access large language models locally. It allows your Claude Code, Codex and other tools to no longer be limited to official models.",
5
5
  "author": "tangshuang",
6
6
  "license": "MIT",