pumpkinai-config 1.3.1 → 1.5.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.
package/claude-api.js ADDED
@@ -0,0 +1,424 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * PPChat Claude Code 一键安装配置工具 (API 版本)
5
+ * 自动安装 @anthropic-ai/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
+ const readline = require('readline');
13
+
14
+ // 颜色输出
15
+ const colors = {
16
+ red: '\x1b[31m',
17
+ green: '\x1b[32m',
18
+ yellow: '\x1b[33m',
19
+ blue: '\x1b[34m',
20
+ magenta: '\x1b[35m',
21
+ cyan: '\x1b[36m',
22
+ reset: '\x1b[0m'
23
+ };
24
+
25
+ function log(message, color = 'reset') {
26
+ console.log(`${colors[color]}${message}${colors.reset}`);
27
+ }
28
+
29
+ // 检测操作系统
30
+ function getOS() {
31
+ const platform = os.platform();
32
+ if (platform === 'win32') return 'windows';
33
+ if (platform === 'darwin') return 'mac';
34
+ return 'linux';
35
+ }
36
+
37
+ // 获取用户输入
38
+ function getUserInput(question) {
39
+ const rl = readline.createInterface({
40
+ input: process.stdin,
41
+ output: process.stdout
42
+ });
43
+
44
+ return new Promise((resolve) => {
45
+ rl.question(question, (answer) => {
46
+ rl.close();
47
+ resolve(answer.trim());
48
+ });
49
+ });
50
+ }
51
+
52
+ // 检查 @anthropic-ai/claude-code 是否已安装
53
+ function checkClaudeInstalled() {
54
+ try {
55
+ const output = execSync('npm list -g @anthropic-ai/claude-code --depth=0', { encoding: 'utf8' });
56
+ return output.includes('@anthropic-ai/claude-code');
57
+ } catch (error) {
58
+ return false;
59
+ }
60
+ }
61
+
62
+ // 获取 @anthropic-ai/claude-code 版本号
63
+ function getClaudeVersion() {
64
+ try {
65
+ const output = execSync('npm list -g @anthropic-ai/claude-code --depth=0', { encoding: 'utf8' });
66
+ const match = output.match(/@anthropic-ai\/claude-code@([\d.]+)/);
67
+ return match ? match[1] : '未知';
68
+ } catch (error) {
69
+ return '未知';
70
+ }
71
+ }
72
+
73
+ // 安装 @anthropic-ai/claude-code
74
+ function installClaude() {
75
+ const osType = getOS();
76
+ let command;
77
+
78
+ log('\n[检查] 检查 @anthropic-ai/claude-code 安装状态...', 'cyan');
79
+
80
+ // 先检查是否已安装
81
+ if (checkClaudeInstalled()) {
82
+ log('[成功] @anthropic-ai/claude-code 已安装,跳过安装步骤', 'green');
83
+ return true;
84
+ }
85
+
86
+ log('[安装] 开始安装 @anthropic-ai/claude-code...', 'cyan');
87
+
88
+ if (osType === 'windows') {
89
+ command = 'npm install -g @anthropic-ai/claude-code --registry https://registry.npmmirror.com';
90
+ } else {
91
+ // 检查是否已经是 root 用户(通过 sudo 运行或直接 root)
92
+ const isRoot = process.getuid && process.getuid() === 0;
93
+ if (isRoot) {
94
+ command = 'npm install -g @anthropic-ai/claude-code --registry https://registry.npmmirror.com';
95
+ } else {
96
+ command = 'sudo npm install -g @anthropic-ai/claude-code --registry https://registry.npmmirror.com';
97
+ }
98
+ }
99
+
100
+ log(`[执行] ${command}`, 'yellow');
101
+
102
+ try {
103
+ execSync(command, { stdio: 'inherit' });
104
+ log('[成功] @anthropic-ai/claude-code 安装成功', 'green');
105
+ return true;
106
+ } catch (error) {
107
+ log('[错误] @anthropic-ai/claude-code 安装失败', 'red');
108
+ log('\n[错误详情]', 'red');
109
+
110
+ // 显示错误信息
111
+ if (error.message) {
112
+ log(`错误信息: ${error.message}`, 'red');
113
+ }
114
+
115
+ // 显示退出码
116
+ if (error.status !== undefined) {
117
+ log(`退出码: ${error.status}`, 'red');
118
+ }
119
+
120
+ // 显示错误输出
121
+ if (error.stderr) {
122
+ log(`错误输出:\n${error.stderr.toString()}`, 'red');
123
+ }
124
+
125
+ // 显示标准输出(可能包含有用信息)
126
+ if (error.stdout) {
127
+ log(`标准输出:\n${error.stdout.toString()}`, 'yellow');
128
+ }
129
+
130
+ log('\n[提示] 你可以手动安装:', 'yellow');
131
+ log(` ${command}`, 'yellow');
132
+ log(' 然后重新运行此工具', 'yellow');
133
+ return false;
134
+ }
135
+ }
136
+
137
+ // 设置系统用户环境变量
138
+ function setupEnvironmentVariables(apiKey) {
139
+ log('\n[配置] 设置系统用户环境变量...', 'cyan');
140
+
141
+ const osType = getOS();
142
+ let homeDir;
143
+ if (process.platform !== 'win32' && process.env.SUDO_USER) {
144
+ const actualUser = process.env.SUDO_USER;
145
+ homeDir = process.platform === 'darwin' ? `/Users/${actualUser}` : `/home/${actualUser}`;
146
+ } else {
147
+ homeDir = os.homedir();
148
+ }
149
+
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');
154
+ try {
155
+ if (!fs.existsSync(claudeDir)) {
156
+ fs.mkdirSync(claudeDir, { recursive: true });
157
+ }
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) {}
179
+ }
180
+ } catch (error) {}
181
+
182
+ // 需要设置的环境变量
183
+ const envVars = {
184
+ ANTHROPIC_AUTH_TOKEN: apiKey,
185
+ ANTHROPIC_BASE_URL: "https://new.aicode.us.com",
186
+ CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS:"1",
187
+ ANTHROPIC_SMALL_FAST_MODEL:"claude-3-5-haiku-20241022"
188
+ };
189
+
190
+ try {
191
+ if (osType === 'windows') {
192
+ // Windows: 使用 setx 设置用户环境变量(永久生效)
193
+ for (const [key, value] of Object.entries(envVars)) {
194
+ try {
195
+ execSync(`setx ${key} "${value}"`, { stdio: 'pipe' });
196
+ log(`[成功] 设置环境变量: ${key}`, 'green');
197
+ } catch (error) {
198
+ log(`[错误] 设置环境变量 ${key} 失败: ${error.message}`, 'red');
199
+ return false;
200
+ }
201
+ }
202
+ log('[提示] 请重新打开终端使环境变量生效', 'yellow');
203
+ return true;
204
+
205
+ } else if (osType === 'mac') {
206
+ // macOS: 写入 ~/.zshrc
207
+ const zshrcPath = path.join(homeDir, '.zshrc');
208
+ let zshrcContent = '';
209
+ if (fs.existsSync(zshrcPath)) {
210
+ zshrcContent = fs.readFileSync(zshrcPath, 'utf8');
211
+ }
212
+
213
+ // 构建环境变量行
214
+ let envLines = '\n# Claude Code 环境变量 (pumpkinai)\n';
215
+ for (const [key, value] of Object.entries(envVars)) {
216
+ const envLine = `export ${key}="${value}"`;
217
+ if (!zshrcContent.includes(`export ${key}=`)) {
218
+ envLines += envLine + '\n';
219
+ log(`[成功] 添加环境变量: ${key}`, 'green');
220
+ } else {
221
+ // 替换已存在的环境变量
222
+ const regex = new RegExp(`export ${key}=.*`, 'g');
223
+ zshrcContent = zshrcContent.replace(regex, envLine);
224
+ log(`[更新] 更新环境变量: ${key}`, 'yellow');
225
+ }
226
+ }
227
+
228
+ // 写入文件
229
+ if (envLines !== '\n# Claude Code 环境变量 (pumpkinai)\n') {
230
+ const newContent = zshrcContent + envLines;
231
+ fs.writeFileSync(zshrcPath, newContent, 'utf8');
232
+ } else {
233
+ fs.writeFileSync(zshrcPath, zshrcContent, 'utf8');
234
+ }
235
+
236
+ // 修改文件所有者
237
+ if (process.env.SUDO_USER) {
238
+ const actualUser = process.env.SUDO_USER;
239
+ try {
240
+ execSync(`chown ${actualUser}:staff ${zshrcPath}`);
241
+ } catch (error) {}
242
+ }
243
+
244
+ log(`[成功] 环境变量已写入: ${zshrcPath}`, 'green');
245
+ log('[提示] 请重新打开终端或运行: source ~/.zshrc', 'yellow');
246
+ return true;
247
+
248
+ } else {
249
+ // Linux: 写入 ~/.bashrc
250
+ const bashrcPath = path.join(homeDir, '.bashrc');
251
+ let bashrcContent = '';
252
+ if (fs.existsSync(bashrcPath)) {
253
+ bashrcContent = fs.readFileSync(bashrcPath, 'utf8');
254
+ }
255
+
256
+ // 构建环境变量行
257
+ let envLines = '\n# Claude Code 环境变量 (pumpkinai)\n';
258
+ for (const [key, value] of Object.entries(envVars)) {
259
+ const envLine = `export ${key}="${value}"`;
260
+ if (!bashrcContent.includes(`export ${key}=`)) {
261
+ envLines += envLine + '\n';
262
+ log(`[成功] 添加环境变量: ${key}`, 'green');
263
+ } else {
264
+ // 替换已存在的环境变量
265
+ const regex = new RegExp(`export ${key}=.*`, 'g');
266
+ bashrcContent = bashrcContent.replace(regex, envLine);
267
+ log(`[更新] 更新环境变量: ${key}`, 'yellow');
268
+ }
269
+ }
270
+
271
+ // 写入文件
272
+ if (envLines !== '\n# Claude Code 环境变量 (pumpkinai)\n') {
273
+ const newContent = bashrcContent + envLines;
274
+ fs.writeFileSync(bashrcPath, newContent, 'utf8');
275
+ } else {
276
+ fs.writeFileSync(bashrcPath, bashrcContent, 'utf8');
277
+ }
278
+
279
+ // 修改文件所有者
280
+ if (process.env.SUDO_USER) {
281
+ const actualUser = process.env.SUDO_USER;
282
+ try {
283
+ execSync(`chown ${actualUser}:${actualUser} ${bashrcPath}`);
284
+ } catch (error) {}
285
+ }
286
+
287
+ log(`[成功] 环境变量已写入: ${bashrcPath}`, 'green');
288
+ log('[提示] 请重新打开终端或运行: source ~/.bashrc', 'yellow');
289
+ return true;
290
+ }
291
+
292
+ } catch (error) {
293
+ log(`[错误] 设置环境变量失败: ${error.message}`, 'red');
294
+ return false;
295
+ }
296
+ }
297
+
298
+ // 配置 Claude
299
+ async function configureEnvironment() {
300
+ log('\n[配置] 配置 API Key...', 'cyan');
301
+
302
+ // 显示粘贴提示
303
+ if (process.platform === 'win32') {
304
+ log('[提示] Windows 粘贴方式:', 'yellow');
305
+ log(' • CMD/PowerShell: 鼠标右键 或 Shift+Insert', 'yellow');
306
+
307
+ }
308
+
309
+ const apiKey = await getUserInput('请输入你的 Claude API Key (sk-xxx): ');
310
+
311
+ if (!apiKey || !apiKey.startsWith('sk-')) {
312
+ log('[错误] API Key 格式不正确,应该以 sk- 开头', 'red');
313
+ return false;
314
+ }
315
+
316
+ return setupEnvironmentVariables(apiKey);
317
+ }
318
+
319
+ // 显示完成信息
320
+ function showCompletionInfo() {
321
+ const osType = getOS();
322
+
323
+ // 获取 home 目录
324
+ let homeDir;
325
+ if (process.platform !== 'win32' && process.env.SUDO_USER) {
326
+ const actualUser = process.env.SUDO_USER;
327
+ homeDir = process.platform === 'darwin' ? `/Users/${actualUser}` : `/home/${actualUser}`;
328
+ } else {
329
+ homeDir = os.homedir();
330
+ }
331
+
332
+ log('\n', 'reset');
333
+ log('=' + '='.repeat(68) + '=', 'yellow');
334
+ log(' 欢迎使用 Claude 开始您的 AI 编程之旅', 'yellow');
335
+ log('=' + '='.repeat(68) + '=', 'yellow');
336
+
337
+ log('\n[已完成操作]', 'cyan');
338
+ log(' * 安装 @anthropic-ai/claude-code', 'green');
339
+ log(' * 设置用户环境变量 ANTHROPIC_AUTH_TOKEN', 'green');
340
+ log(' * 设置用户环境变量 ANTHROPIC_BASE_URL', 'green');
341
+ log(' * 设置用户环境变量 ANTHROPIC_SMALL_FAST_MODEL', 'green');
342
+
343
+ log('\n[环境变量配置]', 'cyan');
344
+ if (osType === 'windows') {
345
+ log(' 环境变量已通过 setx 设置到用户环境变量', 'reset');
346
+ log(' 可在 系统属性 -> 高级 -> 环境变量 中查看', 'yellow');
347
+ } else if (osType === 'mac') {
348
+ log(' 环境变量已写入: ~/.zshrc', 'reset');
349
+ log(` ${path.join(homeDir, '.zshrc')}`, 'yellow');
350
+ } else {
351
+ log(' 环境变量已写入: ~/.bashrc', 'reset');
352
+ log(` ${path.join(homeDir, '.bashrc')}`, 'yellow');
353
+ }
354
+
355
+ log('\n[启动方式]', 'cyan');
356
+
357
+ if (osType === 'windows') {
358
+ log(' 请重新打开终端后运行:', 'reset');
359
+ log(' claude', 'yellow');
360
+ } else if (osType === 'mac') {
361
+ log(' 请重新打开终端后运行:', 'reset');
362
+ log(' claude', 'yellow');
363
+
364
+ } else {
365
+ log(' 请重新打开终端后运行:', 'reset');
366
+ log(' claude', 'yellow');
367
+ }
368
+
369
+ const claudeVersion = getClaudeVersion();
370
+ log('\n Claude Code 版本: v' + claudeVersion, 'reset');
371
+ log(' 支持系统: Windows 10/11 • macOS • Linux', 'reset');
372
+ log('\n', 'reset');
373
+ }
374
+
375
+ // 主函数
376
+ async function main() {
377
+ console.clear();
378
+
379
+ // ASCII Logo - 水平渐变 (蓝→紫→粉)
380
+ log('\n', 'reset');
381
+ console.log(' \x1b[38;5;39m██████╗\x1b[38;5;75m██╗ \x1b[38;5;111m█████╗ \x1b[38;5;147m██╗ ██╗\x1b[38;5;183m██████╗ \x1b[38;5;219m███████╗\x1b[0m');
382
+ console.log(' \x1b[38;5;39m██╔════╝\x1b[38;5;75m██║ \x1b[38;5;111m██╔══██╗\x1b[38;5;147m██║ ██║\x1b[38;5;183m██╔══██╗\x1b[38;5;219m██╔════╝\x1b[0m');
383
+ console.log(' \x1b[38;5;45m██║ \x1b[38;5;81m██║ \x1b[38;5;117m███████║\x1b[38;5;153m██║ ██║\x1b[38;5;189m██║ ██║\x1b[38;5;225m█████╗ \x1b[0m');
384
+ console.log(' \x1b[38;5;75m██║ \x1b[38;5;111m██║ \x1b[38;5;147m██╔══██║\x1b[38;5;183m██║ ██║\x1b[38;5;219m██║ ██║\x1b[38;5;225m██╔══╝ \x1b[0m');
385
+ console.log(' \x1b[38;5;111m╚██████╗\x1b[38;5;147m███████╗\x1b[38;5;183m██║ ██║\x1b[38;5;219m╚██████╔╝\x1b[38;5;225m██████╔╝\x1b[38;5;231m███████╗\x1b[0m');
386
+ console.log(' \x1b[38;5;147m╚═════╝\x1b[38;5;183m╚══════╝\x1b[38;5;219m╚═╝ ╚═╝\x1b[38;5;225m ╚═════╝ \x1b[38;5;231m╚═════╝ ╚══════╝\x1b[0m');
387
+ log('\n pumpkinai Claude Code config Tool (API)', 'magenta');
388
+ log(' ' + '='.repeat(50), 'cyan');
389
+ log('', 'reset');
390
+
391
+ try {
392
+ // 1. 安装 @anthropic-ai/claude-code
393
+ const installSuccess = installClaude();
394
+ if (!installSuccess) {
395
+ log('\n[提示] 安装失败,但你可以继续配置环境变量', 'yellow');
396
+ }
397
+
398
+ // 2. 配置 API Key
399
+ const configSuccess = await configureEnvironment();
400
+ if (!configSuccess) {
401
+ process.exit(1);
402
+ }
403
+
404
+ // 3. 显示完成信息 (不再设置系统环境变量)
405
+ showCompletionInfo();
406
+
407
+ } catch (error) {
408
+ log(`\n[错误] 安装过程中出现错误: ${error.message}`, 'red');
409
+ process.exit(1);
410
+ }
411
+ }
412
+
413
+ // 如果直接运行此脚本
414
+ if (require.main === module) {
415
+ main();
416
+ }
417
+
418
+ // 导出函数供其他模块使用
419
+ module.exports = {
420
+ main,
421
+ installClaude,
422
+ configureEnvironment,
423
+ setupEnvironmentVariables
424
+ };