pumpkinai-config 1.0.19 → 1.0.21
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/claude-api.js +30 -10
- package/claude-fix.js +138 -0
- package/claude-setup.js +30 -10
- package/main-config.js +344 -0
- package/package.json +7 -5
package/claude-api.js
CHANGED
|
@@ -86,14 +86,14 @@ function installClaude() {
|
|
|
86
86
|
log('[安装] 开始安装 @anthropic-ai/claude-code...', 'cyan');
|
|
87
87
|
|
|
88
88
|
if (osType === 'windows') {
|
|
89
|
-
command = 'npm install -g @anthropic-ai/claude-code --registry https://registry.npmmirror.com';
|
|
89
|
+
command = 'npm install -g @anthropic-ai/claude-code@2.0.59 --registry https://registry.npmmirror.com';
|
|
90
90
|
} else {
|
|
91
91
|
// 检查是否已经是 root 用户(通过 sudo 运行或直接 root)
|
|
92
92
|
const isRoot = process.getuid && process.getuid() === 0;
|
|
93
93
|
if (isRoot) {
|
|
94
|
-
command = 'npm install -g @anthropic-ai/claude-code --registry https://registry.npmmirror.com';
|
|
94
|
+
command = 'npm install -g @anthropic-ai/claude-code@2.0.59 --registry https://registry.npmmirror.com';
|
|
95
95
|
} else {
|
|
96
|
-
command = 'sudo npm install -g @anthropic-ai/claude-code --registry https://registry.npmmirror.com';
|
|
96
|
+
command = 'sudo npm install -g @anthropic-ai/claude-code@2.0.59 --registry https://registry.npmmirror.com';
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -147,15 +147,35 @@ function setupEnvironmentVariables(apiKey) {
|
|
|
147
147
|
homeDir = os.homedir();
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
//
|
|
151
|
-
const
|
|
152
|
-
const
|
|
150
|
+
// 创建 .claude 目录和配置文件
|
|
151
|
+
const claudeDir = path.join(homeDir, '.claude');
|
|
152
|
+
const configPath = path.join(claudeDir, 'config.json');
|
|
153
|
+
const settingsPath = path.join(claudeDir, 'settings.json');
|
|
153
154
|
try {
|
|
154
|
-
if (fs.existsSync(
|
|
155
|
-
fs.
|
|
155
|
+
if (!fs.existsSync(claudeDir)) {
|
|
156
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
156
157
|
}
|
|
157
|
-
|
|
158
|
-
|
|
158
|
+
// 创建 config.json
|
|
159
|
+
const config = { primaryApiKey: "1" };
|
|
160
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
|
|
161
|
+
|
|
162
|
+
// 创建 settings.json
|
|
163
|
+
const settings = {
|
|
164
|
+
env: {
|
|
165
|
+
ANTHROPIC_AUTH_TOKEN: apiKey,
|
|
166
|
+
ANTHROPIC_BASE_URL: "https://new.aicode.us.com",
|
|
167
|
+
ANTHROPIC_SMALL_FAST_MODEL: "claude-3-5-haiku-20241022"
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf8');
|
|
171
|
+
|
|
172
|
+
// 如果是通过 sudo 运行的,修改文件所有者
|
|
173
|
+
if (process.platform !== 'win32' && process.env.SUDO_USER) {
|
|
174
|
+
const actualUser = process.env.SUDO_USER;
|
|
175
|
+
const group = process.platform === 'darwin' ? 'staff' : actualUser;
|
|
176
|
+
try {
|
|
177
|
+
execSync(`chown -R ${actualUser}:${group} ${claudeDir}`);
|
|
178
|
+
} catch (error) {}
|
|
159
179
|
}
|
|
160
180
|
} catch (error) {}
|
|
161
181
|
|
package/claude-fix.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Claude Code 报错修复工具
|
|
5
|
+
* 彻底清理并重新安装 Claude Code
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const os = require('os');
|
|
11
|
+
const { execSync } = require('child_process');
|
|
12
|
+
|
|
13
|
+
// 颜色输出
|
|
14
|
+
const colors = {
|
|
15
|
+
red: '\x1b[31m',
|
|
16
|
+
green: '\x1b[32m',
|
|
17
|
+
yellow: '\x1b[33m',
|
|
18
|
+
blue: '\x1b[34m',
|
|
19
|
+
magenta: '\x1b[35m',
|
|
20
|
+
cyan: '\x1b[36m',
|
|
21
|
+
reset: '\x1b[0m',
|
|
22
|
+
dim: '\x1b[2m'
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function log(message, color = 'reset') {
|
|
26
|
+
console.log(`${colors[color]}${message}${colors.reset}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// 获取用户目录
|
|
30
|
+
function getHomeDir() {
|
|
31
|
+
if (process.platform !== 'win32' && process.env.SUDO_USER) {
|
|
32
|
+
const actualUser = process.env.SUDO_USER;
|
|
33
|
+
return process.platform === 'darwin' ? `/Users/${actualUser}` : `/home/${actualUser}`;
|
|
34
|
+
}
|
|
35
|
+
return os.homedir();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 彻底重新安装 Claude Code
|
|
39
|
+
async function reinstallClaudeCode() {
|
|
40
|
+
console.clear();
|
|
41
|
+
log('\n[报错修复] 开始彻底重新安装 Claude Code...\n', 'cyan');
|
|
42
|
+
|
|
43
|
+
const homeDir = getHomeDir();
|
|
44
|
+
|
|
45
|
+
// 1. 删除 .claude 文件夹
|
|
46
|
+
const claudeDir = path.join(homeDir, '.claude');
|
|
47
|
+
if (fs.existsSync(claudeDir)) {
|
|
48
|
+
log('[清理] 删除 .claude 文件夹...', 'yellow');
|
|
49
|
+
try {
|
|
50
|
+
fs.rmSync(claudeDir, { recursive: true, force: true });
|
|
51
|
+
log('[成功] .claude 文件夹已删除', 'green');
|
|
52
|
+
} catch (error) {
|
|
53
|
+
log(`[警告] 删除 .claude 文件夹失败: ${error.message}`, 'yellow');
|
|
54
|
+
}
|
|
55
|
+
} else {
|
|
56
|
+
log('[跳过] .claude 文件夹不存在', 'dim');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 2. 删除 .claude.json
|
|
60
|
+
const claudeJson = path.join(homeDir, '.claude.json');
|
|
61
|
+
if (fs.existsSync(claudeJson)) {
|
|
62
|
+
log('[清理] 删除 .claude.json...', 'yellow');
|
|
63
|
+
try {
|
|
64
|
+
fs.unlinkSync(claudeJson);
|
|
65
|
+
log('[成功] .claude.json 已删除', 'green');
|
|
66
|
+
} catch (error) {
|
|
67
|
+
log(`[警告] 删除 .claude.json 失败: ${error.message}`, 'yellow');
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
log('[跳过] .claude.json 不存在', 'dim');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// 3. 删除 .claude.json.backup
|
|
74
|
+
const claudeJsonBackup = path.join(homeDir, '.claude.json.backup');
|
|
75
|
+
if (fs.existsSync(claudeJsonBackup)) {
|
|
76
|
+
log('[清理] 删除 .claude.json.backup...', 'yellow');
|
|
77
|
+
try {
|
|
78
|
+
fs.unlinkSync(claudeJsonBackup);
|
|
79
|
+
log('[成功] .claude.json.backup 已删除', 'green');
|
|
80
|
+
} catch (error) {
|
|
81
|
+
log(`[警告] 删除 .claude.json.backup 失败: ${error.message}`, 'yellow');
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
log('[跳过] .claude.json.backup 不存在', 'dim');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 4. 卸载 claude-code
|
|
88
|
+
log('\n[卸载] 卸载 @anthropic-ai/claude-code...', 'yellow');
|
|
89
|
+
try {
|
|
90
|
+
const osType = process.platform;
|
|
91
|
+
let uninstallCmd;
|
|
92
|
+
if (osType === 'win32') {
|
|
93
|
+
uninstallCmd = 'npm uninstall -g @anthropic-ai/claude-code';
|
|
94
|
+
} else {
|
|
95
|
+
const isRoot = process.getuid && process.getuid() === 0;
|
|
96
|
+
uninstallCmd = isRoot ? 'npm uninstall -g @anthropic-ai/claude-code' : 'sudo npm uninstall -g @anthropic-ai/claude-code';
|
|
97
|
+
}
|
|
98
|
+
execSync(uninstallCmd, { stdio: 'inherit' });
|
|
99
|
+
log('[成功] @anthropic-ai/claude-code 已卸载', 'green');
|
|
100
|
+
} catch (error) {
|
|
101
|
+
log('[提示] 卸载过程中出现问题,可能未安装', 'yellow');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
log('\n[完成] 清理完成,现在请选择套餐重新安装配置\n', 'green');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 主函数
|
|
108
|
+
async function main() {
|
|
109
|
+
await reinstallClaudeCode();
|
|
110
|
+
|
|
111
|
+
// 等待用户按键
|
|
112
|
+
log('按任意键返回菜单...', 'dim');
|
|
113
|
+
|
|
114
|
+
return new Promise((resolve) => {
|
|
115
|
+
if (process.stdin.isTTY) {
|
|
116
|
+
process.stdin.setRawMode(true);
|
|
117
|
+
}
|
|
118
|
+
process.stdin.resume();
|
|
119
|
+
process.stdin.once('data', () => {
|
|
120
|
+
if (process.stdin.isTTY) {
|
|
121
|
+
process.stdin.setRawMode(false);
|
|
122
|
+
}
|
|
123
|
+
resolve();
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// 如果直接运行此脚本
|
|
129
|
+
if (require.main === module) {
|
|
130
|
+
main().then(() => {
|
|
131
|
+
process.exit(0);
|
|
132
|
+
}).catch(error => {
|
|
133
|
+
log(`\n[错误] ${error.message}`, 'red');
|
|
134
|
+
process.exit(1);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
module.exports = { main, reinstallClaudeCode };
|
package/claude-setup.js
CHANGED
|
@@ -86,14 +86,14 @@ function installClaude() {
|
|
|
86
86
|
log('[安装] 开始安装 @anthropic-ai/claude-code...', 'cyan');
|
|
87
87
|
|
|
88
88
|
if (osType === 'windows') {
|
|
89
|
-
command = 'npm install -g @anthropic-ai/claude-code --registry https://registry.npmmirror.com';
|
|
89
|
+
command = 'npm install -g @anthropic-ai/claude-code@2.0.59 --registry https://registry.npmmirror.com';
|
|
90
90
|
} else {
|
|
91
91
|
// 检查是否已经是 root 用户(通过 sudo 运行或直接 root)
|
|
92
92
|
const isRoot = process.getuid && process.getuid() === 0;
|
|
93
93
|
if (isRoot) {
|
|
94
|
-
command = 'npm install -g @anthropic-ai/claude-code --registry https://registry.npmmirror.com';
|
|
94
|
+
command = 'npm install -g @anthropic-ai/claude-code@2.0.59 --registry https://registry.npmmirror.com';
|
|
95
95
|
} else {
|
|
96
|
-
command = 'sudo npm install -g @anthropic-ai/claude-code --registry https://registry.npmmirror.com';
|
|
96
|
+
command = 'sudo npm install -g @anthropic-ai/claude-code@2.0.59 --registry https://registry.npmmirror.com';
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -147,15 +147,35 @@ function setupEnvironmentVariables(apiKey) {
|
|
|
147
147
|
homeDir = os.homedir();
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
//
|
|
151
|
-
const
|
|
152
|
-
const
|
|
150
|
+
// 创建 .claude 目录和配置文件
|
|
151
|
+
const claudeDir = path.join(homeDir, '.claude');
|
|
152
|
+
const configPath = path.join(claudeDir, 'config.json');
|
|
153
|
+
const settingsPath = path.join(claudeDir, 'settings.json');
|
|
153
154
|
try {
|
|
154
|
-
if (fs.existsSync(
|
|
155
|
-
fs.
|
|
155
|
+
if (!fs.existsSync(claudeDir)) {
|
|
156
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
156
157
|
}
|
|
157
|
-
|
|
158
|
-
|
|
158
|
+
// 创建 config.json
|
|
159
|
+
const config = { primaryApiKey: "1" };
|
|
160
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
|
|
161
|
+
|
|
162
|
+
// 创建 settings.json
|
|
163
|
+
const settings = {
|
|
164
|
+
env: {
|
|
165
|
+
ANTHROPIC_AUTH_TOKEN: apiKey,
|
|
166
|
+
ANTHROPIC_BASE_URL: "https://code.ppchat.vip",
|
|
167
|
+
ANTHROPIC_SMALL_FAST_MODEL: "claude-3-5-haiku-20241022"
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf8');
|
|
171
|
+
|
|
172
|
+
// 如果是通过 sudo 运行的,修改文件所有者
|
|
173
|
+
if (process.platform !== 'win32' && process.env.SUDO_USER) {
|
|
174
|
+
const actualUser = process.env.SUDO_USER;
|
|
175
|
+
const group = process.platform === 'darwin' ? 'staff' : actualUser;
|
|
176
|
+
try {
|
|
177
|
+
execSync(`chown -R ${actualUser}:${group} ${claudeDir}`);
|
|
178
|
+
} catch (error) {}
|
|
159
179
|
}
|
|
160
180
|
} catch (error) {}
|
|
161
181
|
|
package/main-config.js
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* PumpkinAI 一键安装配置工具
|
|
5
|
+
* 整合 Claude Code 和 Codex 的安装配置
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// 颜色输出
|
|
9
|
+
const colors = {
|
|
10
|
+
red: '\x1b[31m',
|
|
11
|
+
green: '\x1b[32m',
|
|
12
|
+
yellow: '\x1b[33m',
|
|
13
|
+
blue: '\x1b[34m',
|
|
14
|
+
magenta: '\x1b[35m',
|
|
15
|
+
cyan: '\x1b[36m',
|
|
16
|
+
reset: '\x1b[0m',
|
|
17
|
+
dim: '\x1b[2m',
|
|
18
|
+
bright: '\x1b[1m'
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function log(message, color = 'reset') {
|
|
22
|
+
console.log(`${colors[color]}${message}${colors.reset}`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// 主菜单选项
|
|
26
|
+
const mainMenuOptions = [
|
|
27
|
+
{ name: 'Claude Code', desc: 'Anthropic Claude AI 编程助手' },
|
|
28
|
+
{ name: 'Codex', desc: 'OpenAI Codex 编程助手' },
|
|
29
|
+
{ name: '退出', desc: '' }
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
// Claude Code 子菜单选项
|
|
33
|
+
const claudeSubMenuOptions = [
|
|
34
|
+
{ name: '按请求计费套餐', desc: 'API地址: https://code.ppchat.vip' },
|
|
35
|
+
{ name: '按量计费套餐', desc: 'API地址: https://new.aicode.us.com' },
|
|
36
|
+
{ name: '报错修复', desc: '' },
|
|
37
|
+
{ name: '返回上级', desc: '' }
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
// Codex 子菜单选项
|
|
41
|
+
const codexSubMenuOptions = [
|
|
42
|
+
{ name: '按请求计费套餐', desc: 'API地址: https://code.ppchat.vip' },
|
|
43
|
+
{ name: '按量计费套餐', desc: 'API地址: https://new.aicode.us.com' },
|
|
44
|
+
{ name: '返回上级', desc: '' }
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
// 报错修复子菜单选项
|
|
48
|
+
const fixSubMenuOptions = [
|
|
49
|
+
{ name: '彻底重新安装', desc: '删除所有配置并重装 Claude Code' },
|
|
50
|
+
{ name: '返回上级', desc: '' }
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
// 脚本映射
|
|
54
|
+
const scriptMap = {
|
|
55
|
+
'Claude Code': {
|
|
56
|
+
'按请求计费套餐': './claude-setup.js',
|
|
57
|
+
'按量计费套餐': './claude-api.js'
|
|
58
|
+
},
|
|
59
|
+
'Codex': {
|
|
60
|
+
'按请求计费套餐': './codex-setup.js',
|
|
61
|
+
'按量计费套餐': './codex-api.js'
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
let selectedIndex = 0;
|
|
66
|
+
let currentMenu = 'main'; // 'main', 'claude_sub', 'codex_sub', 'fix_sub'
|
|
67
|
+
|
|
68
|
+
// 显示 Logo
|
|
69
|
+
function showLogo() {
|
|
70
|
+
console.log(' \x1b[38;5;208m██████╗ \x1b[38;5;214m██╗ ██╗\x1b[38;5;220m███╗ ███╗\x1b[38;5;226m██████╗ \x1b[38;5;190m██╗ ██╗\x1b[38;5;154m██╗\x1b[38;5;118m███╗ ██╗\x1b[0m');
|
|
71
|
+
console.log(' \x1b[38;5;208m██╔══██╗\x1b[38;5;214m██║ ██║\x1b[38;5;220m████╗ ████║\x1b[38;5;226m██╔══██╗\x1b[38;5;190m██║ ██╔╝\x1b[38;5;154m██║\x1b[38;5;118m████╗ ██║\x1b[0m');
|
|
72
|
+
console.log(' \x1b[38;5;208m██████╔╝\x1b[38;5;214m██║ ██║\x1b[38;5;220m██╔████╔██║\x1b[38;5;226m██████╔╝\x1b[38;5;190m█████╔╝ \x1b[38;5;154m██║\x1b[38;5;118m██╔██╗ ██║\x1b[0m');
|
|
73
|
+
console.log(' \x1b[38;5;208m██╔═══╝ \x1b[38;5;214m██║ ██║\x1b[38;5;220m██║╚██╔╝██║\x1b[38;5;226m██╔═══╝ \x1b[38;5;190m██╔═██╗ \x1b[38;5;154m██║\x1b[38;5;118m██║╚██╗██║\x1b[0m');
|
|
74
|
+
console.log(' \x1b[38;5;208m██║ \x1b[38;5;214m╚██████╔╝\x1b[38;5;220m██║ ╚═╝ ██║\x1b[38;5;226m██║ \x1b[38;5;190m██║ ██╗\x1b[38;5;154m██║\x1b[38;5;118m██║ ╚████║\x1b[0m');
|
|
75
|
+
console.log(' \x1b[38;5;208m╚═╝ \x1b[38;5;214m ╚═════╝ \x1b[38;5;220m╚═╝ ╚═╝\x1b[38;5;226m╚═╝ \x1b[38;5;190m╚═╝ ╚═╝\x1b[38;5;154m╚═╝\x1b[38;5;118m╚═╝ ╚═══╝\x1b[0m');
|
|
76
|
+
log('\n PumpkinAI 一键配置工具', 'magenta');
|
|
77
|
+
log(' ' + '='.repeat(54), 'cyan');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// 渲染通用菜单
|
|
81
|
+
function renderGenericMenu(title, options) {
|
|
82
|
+
console.clear();
|
|
83
|
+
log('\n', 'reset');
|
|
84
|
+
showLogo();
|
|
85
|
+
log('', 'reset');
|
|
86
|
+
|
|
87
|
+
log(` ${title}\n`, 'cyan');
|
|
88
|
+
|
|
89
|
+
options.forEach((option, index) => {
|
|
90
|
+
const isSelected = index === selectedIndex;
|
|
91
|
+
const prefix = isSelected ? ' ▶ ' : ' ';
|
|
92
|
+
const nameColor = isSelected ? '\x1b[1m\x1b[33m' : '\x1b[0m';
|
|
93
|
+
const descColor = isSelected ? '\x1b[36m' : '\x1b[2m';
|
|
94
|
+
|
|
95
|
+
console.log(`${prefix}${nameColor}${option.name}\x1b[0m`);
|
|
96
|
+
if (option.desc) {
|
|
97
|
+
console.log(` ${descColor}${option.desc}\x1b[0m`);
|
|
98
|
+
}
|
|
99
|
+
console.log('');
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
log(' ' + '='.repeat(54), 'cyan');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 渲染当前菜单
|
|
106
|
+
function renderMenu() {
|
|
107
|
+
switch (currentMenu) {
|
|
108
|
+
case 'main':
|
|
109
|
+
renderGenericMenu('请选择要配置的工具 (↑↓选择, Enter确认):', mainMenuOptions);
|
|
110
|
+
break;
|
|
111
|
+
case 'claude_sub':
|
|
112
|
+
renderGenericMenu('Claude Code - 请选择购买的套餐 (↑↓选择, Enter确认):', claudeSubMenuOptions);
|
|
113
|
+
break;
|
|
114
|
+
case 'codex_sub':
|
|
115
|
+
renderGenericMenu('Codex - 请选择购买的套餐 (↑↓选择, Enter确认):', codexSubMenuOptions);
|
|
116
|
+
break;
|
|
117
|
+
case 'fix_sub':
|
|
118
|
+
renderGenericMenu('报错修复 - 请选择操作 (↑↓选择, Enter确认):', fixSubMenuOptions);
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 获取当前菜单选项
|
|
124
|
+
function getCurrentOptions() {
|
|
125
|
+
switch (currentMenu) {
|
|
126
|
+
case 'main': return mainMenuOptions;
|
|
127
|
+
case 'claude_sub': return claudeSubMenuOptions;
|
|
128
|
+
case 'codex_sub': return codexSubMenuOptions;
|
|
129
|
+
case 'fix_sub': return fixSubMenuOptions;
|
|
130
|
+
default: return mainMenuOptions;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
// 处理主菜单选择
|
|
136
|
+
function handleMainMenuSelection() {
|
|
137
|
+
const selected = mainMenuOptions[selectedIndex];
|
|
138
|
+
|
|
139
|
+
if (selected.name === '退出') {
|
|
140
|
+
console.clear();
|
|
141
|
+
process.exit(0);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (selected.name === 'Claude Code') {
|
|
145
|
+
currentMenu = 'claude_sub';
|
|
146
|
+
} else {
|
|
147
|
+
currentMenu = 'codex_sub';
|
|
148
|
+
}
|
|
149
|
+
selectedIndex = 0;
|
|
150
|
+
renderMenu();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// 处理 Claude Code 子菜单选择
|
|
154
|
+
async function handleClaudeSubMenuSelection() {
|
|
155
|
+
const selected = claudeSubMenuOptions[selectedIndex];
|
|
156
|
+
|
|
157
|
+
if (selected.name === '返回上级') {
|
|
158
|
+
currentMenu = 'main';
|
|
159
|
+
selectedIndex = 0;
|
|
160
|
+
renderMenu();
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (selected.name === '报错修复') {
|
|
165
|
+
currentMenu = 'fix_sub';
|
|
166
|
+
selectedIndex = 0;
|
|
167
|
+
renderMenu();
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// 执行对应脚本
|
|
172
|
+
const scriptPath = scriptMap['Claude Code'][selected.name];
|
|
173
|
+
console.clear();
|
|
174
|
+
log(`\n[启动] 正在运行 Claude Code (${selected.name}) 配置...\n`, 'green');
|
|
175
|
+
|
|
176
|
+
try {
|
|
177
|
+
const script = require(scriptPath);
|
|
178
|
+
await script.main();
|
|
179
|
+
return true;
|
|
180
|
+
} catch (error) {
|
|
181
|
+
log(`\n[错误] ${error.message}`, 'red');
|
|
182
|
+
process.exit(1);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// 处理 Codex 子菜单选择
|
|
187
|
+
async function handleCodexSubMenuSelection() {
|
|
188
|
+
const selected = codexSubMenuOptions[selectedIndex];
|
|
189
|
+
|
|
190
|
+
if (selected.name === '返回上级') {
|
|
191
|
+
currentMenu = 'main';
|
|
192
|
+
selectedIndex = 0;
|
|
193
|
+
renderMenu();
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// 执行对应脚本
|
|
198
|
+
const scriptPath = scriptMap['Codex'][selected.name];
|
|
199
|
+
console.clear();
|
|
200
|
+
log(`\n[启动] 正在运行 Codex (${selected.name}) 配置...\n`, 'green');
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
const script = require(scriptPath);
|
|
204
|
+
await script.main();
|
|
205
|
+
return true;
|
|
206
|
+
} catch (error) {
|
|
207
|
+
log(`\n[错误] ${error.message}`, 'red');
|
|
208
|
+
process.exit(1);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// 处理报错修复子菜单选择
|
|
213
|
+
async function handleFixSubMenuSelection() {
|
|
214
|
+
const selected = fixSubMenuOptions[selectedIndex];
|
|
215
|
+
|
|
216
|
+
if (selected.name === '返回上级') {
|
|
217
|
+
currentMenu = 'claude_sub';
|
|
218
|
+
selectedIndex = 0;
|
|
219
|
+
renderMenu();
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (selected.name === '彻底重新安装') {
|
|
224
|
+
// 调用 claude-fix.js 中的修复功能
|
|
225
|
+
const claudeFix = require('./claude-fix.js');
|
|
226
|
+
await claudeFix.main();
|
|
227
|
+
currentMenu = 'claude_sub';
|
|
228
|
+
selectedIndex = 0;
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// 处理子菜单选择
|
|
236
|
+
async function handleSubMenuSelection() {
|
|
237
|
+
switch (currentMenu) {
|
|
238
|
+
case 'claude_sub':
|
|
239
|
+
return await handleClaudeSubMenuSelection();
|
|
240
|
+
case 'codex_sub':
|
|
241
|
+
return await handleCodexSubMenuSelection();
|
|
242
|
+
case 'fix_sub':
|
|
243
|
+
return await handleFixSubMenuSelection();
|
|
244
|
+
default:
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// 主函数
|
|
250
|
+
async function main() {
|
|
251
|
+
// 启用原始模式以捕获按键
|
|
252
|
+
if (process.stdin.isTTY) {
|
|
253
|
+
process.stdin.setRawMode(true);
|
|
254
|
+
}
|
|
255
|
+
process.stdin.resume();
|
|
256
|
+
process.stdin.setEncoding('utf8');
|
|
257
|
+
|
|
258
|
+
renderMenu();
|
|
259
|
+
|
|
260
|
+
return new Promise((resolve) => {
|
|
261
|
+
const handleKeyPress = async (key) => {
|
|
262
|
+
const options = getCurrentOptions();
|
|
263
|
+
|
|
264
|
+
// Ctrl+C 退出
|
|
265
|
+
if (key === '\u0003') {
|
|
266
|
+
console.clear();
|
|
267
|
+
process.exit(0);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// ESC 返回上级菜单
|
|
271
|
+
if (key === '\u001b') {
|
|
272
|
+
if (currentMenu === 'fix_sub') {
|
|
273
|
+
currentMenu = 'claude_sub';
|
|
274
|
+
selectedIndex = 0;
|
|
275
|
+
renderMenu();
|
|
276
|
+
return;
|
|
277
|
+
} else if (currentMenu === 'claude_sub' || currentMenu === 'codex_sub') {
|
|
278
|
+
currentMenu = 'main';
|
|
279
|
+
selectedIndex = 0;
|
|
280
|
+
renderMenu();
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// 上箭头
|
|
286
|
+
if (key === '\u001b[A' || key === 'k') {
|
|
287
|
+
selectedIndex = selectedIndex > 0 ? selectedIndex - 1 : options.length - 1;
|
|
288
|
+
renderMenu();
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// 下箭头
|
|
292
|
+
if (key === '\u001b[B' || key === 'j') {
|
|
293
|
+
selectedIndex = selectedIndex < options.length - 1 ? selectedIndex + 1 : 0;
|
|
294
|
+
renderMenu();
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Enter 确认
|
|
298
|
+
if (key === '\r' || key === '\n') {
|
|
299
|
+
if (currentMenu === 'main') {
|
|
300
|
+
handleMainMenuSelection();
|
|
301
|
+
} else {
|
|
302
|
+
if (process.stdin.isTTY) {
|
|
303
|
+
process.stdin.setRawMode(false);
|
|
304
|
+
}
|
|
305
|
+
process.stdin.removeAllListeners('data');
|
|
306
|
+
const done = await handleSubMenuSelection();
|
|
307
|
+
if (done) {
|
|
308
|
+
resolve();
|
|
309
|
+
} else {
|
|
310
|
+
// 重新启用监听
|
|
311
|
+
if (process.stdin.isTTY) {
|
|
312
|
+
process.stdin.setRawMode(true);
|
|
313
|
+
}
|
|
314
|
+
process.stdin.on('data', handleKeyPress);
|
|
315
|
+
renderMenu();
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// 数字键快捷选择
|
|
321
|
+
const num = parseInt(key);
|
|
322
|
+
if (num >= 1 && num <= options.length - 1) {
|
|
323
|
+
selectedIndex = num - 1;
|
|
324
|
+
renderMenu();
|
|
325
|
+
}
|
|
326
|
+
if (key === '0') {
|
|
327
|
+
selectedIndex = options.length - 1;
|
|
328
|
+
renderMenu();
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
process.stdin.on('data', handleKeyPress);
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// 如果直接运行此脚本
|
|
337
|
+
if (require.main === module) {
|
|
338
|
+
main().catch(error => {
|
|
339
|
+
log(`\n[错误] ${error.message}`, 'red');
|
|
340
|
+
process.exit(1);
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
module.exports = { main };
|
package/package.json
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pumpkinai-config",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.21",
|
|
4
4
|
"description": "PumpkinAI 一键安装配置工具 - 支持 Codex 和 Claude Code",
|
|
5
|
-
"main": "
|
|
5
|
+
"main": "main-config.js",
|
|
6
6
|
"bin": {
|
|
7
|
+
"pumpkinai": "./main-config.js",
|
|
7
8
|
"codex-config": "./codex-setup.js",
|
|
8
9
|
"codex-api": "./codex-api.js",
|
|
9
10
|
"claude-config": "./claude-setup.js",
|
|
10
|
-
"claude-api": "./claude-api.js"
|
|
11
|
+
"claude-api": "./claude-api.js",
|
|
12
|
+
"claude-fix": "./claude-fix.js"
|
|
11
13
|
},
|
|
12
14
|
"scripts": {
|
|
13
|
-
"test": "node
|
|
14
|
-
"start": "node
|
|
15
|
+
"test": "node main-config.js",
|
|
16
|
+
"start": "node main-config.js"
|
|
15
17
|
},
|
|
16
18
|
"keywords": [
|
|
17
19
|
"codex",
|