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-setup.js CHANGED
@@ -88,7 +88,13 @@ function installClaude() {
88
88
  if (osType === 'windows') {
89
89
  command = 'npm install -g @anthropic-ai/claude-code --registry https://registry.npmmirror.com';
90
90
  } else {
91
- command = 'sudo npm install -g @anthropic-ai/claude-code --registry https://registry.npmmirror.com';
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
+ }
92
98
  }
93
99
 
94
100
  log(`[执行] ${command}`, 'yellow');
@@ -99,7 +105,28 @@ function installClaude() {
99
105
  return true;
100
106
  } catch (error) {
101
107
  log('[错误] @anthropic-ai/claude-code 安装失败', 'red');
102
- log(`[错误] ${error.message}`, '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
+
103
130
  log('\n[提示] 你可以手动安装:', 'yellow');
104
131
  log(` ${command}`, 'yellow');
105
132
  log(' 然后重新运行此工具', 'yellow');
@@ -107,61 +134,40 @@ function installClaude() {
107
134
  }
108
135
  }
109
136
 
110
- // 创建 .claude 目录和配置文件
111
- function createClaudeConfig(apiKey) {
112
- log('\n[配置] 创建 Claude 配置文件...', 'cyan');
137
+ // 设置系统用户环境变量
138
+ function setupEnvironmentVariables(apiKey) {
139
+ log('\n[配置] 设置系统用户环境变量...', 'cyan');
113
140
 
114
- // 获取实际用户的 home 目录
141
+ const osType = getOS();
115
142
  let homeDir;
116
143
  if (process.platform !== 'win32' && process.env.SUDO_USER) {
117
- // Linux/Mac 使用 sudo 时,获取实际用户的 home 目录
118
144
  const actualUser = process.env.SUDO_USER;
119
145
  homeDir = process.platform === 'darwin' ? `/Users/${actualUser}` : `/home/${actualUser}`;
120
146
  } else {
121
147
  homeDir = os.homedir();
122
148
  }
123
149
 
150
+ // 创建 .claude 目录和配置文件
124
151
  const claudeDir = path.join(homeDir, '.claude');
125
- const settingsPath = path.join(claudeDir, 'settings.json');
126
152
  const configPath = path.join(claudeDir, 'config.json');
127
- const oldConfigPath = path.join(homeDir, '.claude.json');
128
- const oldConfigBackupPath = path.join(homeDir, '.claude.json.backup');
129
-
153
+ const settingsPath = path.join(claudeDir, 'settings.json');
130
154
  try {
131
- // 删除旧的配置文件(不提示用户)
132
- if (fs.existsSync(oldConfigPath)) {
133
- fs.unlinkSync(oldConfigPath);
134
- }
135
- if (fs.existsSync(oldConfigBackupPath)) {
136
- fs.unlinkSync(oldConfigBackupPath);
137
- }
138
-
139
- // 创建 .claude 目录
140
155
  if (!fs.existsSync(claudeDir)) {
141
156
  fs.mkdirSync(claudeDir, { recursive: true });
142
- log(`[成功] 创建目录: ${claudeDir}`, 'green');
143
- } else {
144
- log(`[提示] 目录已存在: ${claudeDir}`, 'yellow');
145
157
  }
158
+ // 创建 config.json
159
+ const config = { primaryApiKey: "1" };
160
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
146
161
 
147
- // 创建 settings.json 配置
162
+ // 创建 settings.json
148
163
  const settings = {
149
164
  env: {
150
165
  ANTHROPIC_AUTH_TOKEN: apiKey,
151
- ANTHROPIC_BASE_URL: "https://code.ppchat.vip"
166
+ ANTHROPIC_BASE_URL: "https://code.ppchat.vip",
167
+ ANTHROPIC_SMALL_FAST_MODEL: "claude-3-5-haiku-20241022"
152
168
  }
153
169
  };
154
-
155
170
  fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf8');
156
- log(`[成功] 创建配置文件: ${settingsPath}`, 'green');
157
-
158
- // 创建 config.json 配置
159
- const config = {
160
- primaryApiKey: "1"
161
- };
162
-
163
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
164
- log(`[成功] 创建配置文件: ${configPath}`, 'green');
165
171
 
166
172
  // 如果是通过 sudo 运行的,修改文件所有者
167
173
  if (process.platform !== 'win32' && process.env.SUDO_USER) {
@@ -169,15 +175,122 @@ function createClaudeConfig(apiKey) {
169
175
  const group = process.platform === 'darwin' ? 'staff' : actualUser;
170
176
  try {
171
177
  execSync(`chown -R ${actualUser}:${group} ${claudeDir}`);
172
- log(`[成功] 设置文件所有者为: ${actualUser}`, 'green');
173
- } catch (error) {
174
- log(`[警告] 无法设置文件所有者: ${error.message}`, 'yellow');
178
+ } catch (error) {}
179
+ }
180
+ } catch (error) {}
181
+
182
+ // 需要设置的环境变量
183
+ const envVars = {
184
+ ANTHROPIC_AUTH_TOKEN: apiKey,
185
+ ANTHROPIC_BASE_URL: "https://code.ppchat.vip",
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) {}
175
285
  }
286
+
287
+ log(`[成功] 环境变量已写入: ${bashrcPath}`, 'green');
288
+ log('[提示] 请重新打开终端或运行: source ~/.bashrc', 'yellow');
289
+ return true;
176
290
  }
177
291
 
178
- return true;
179
292
  } catch (error) {
180
- log(`[错误] 创建配置文件失败: ${error.message}`, 'red');
293
+ log(`[错误] 设置环境变量失败: ${error.message}`, 'red');
181
294
  return false;
182
295
  }
183
296
  }
@@ -200,14 +313,14 @@ async function configureEnvironment() {
200
313
  return false;
201
314
  }
202
315
 
203
- return createClaudeConfig(apiKey);
316
+ return setupEnvironmentVariables(apiKey);
204
317
  }
205
318
 
206
319
  // 显示完成信息
207
320
  function showCompletionInfo() {
208
321
  const osType = getOS();
209
322
 
210
- // 获取配置文件路径
323
+ // 获取 home 目录
211
324
  let homeDir;
212
325
  if (process.platform !== 'win32' && process.env.SUDO_USER) {
213
326
  const actualUser = process.env.SUDO_USER;
@@ -215,40 +328,43 @@ function showCompletionInfo() {
215
328
  } else {
216
329
  homeDir = os.homedir();
217
330
  }
218
- const claudeDir = path.join(homeDir, '.claude');
219
- const settingsPath = path.join(claudeDir, 'settings.json');
220
- const configPath = path.join(claudeDir, 'config.json');
221
331
 
222
332
  log('\n', 'reset');
223
- log('' + ''.repeat(68) + '', 'yellow');
224
- log('║' + ' '.repeat(9) + '欢迎使用 Claude 开始您的 AI 编程之旅' + ' '.repeat(9) + '║', 'yellow');
225
- log('' + ''.repeat(68) + '', 'yellow');
226
-
227
- log('\n ┌─ 已完成操作', 'cyan');
228
- log(' ', 'cyan');
229
- log(' │ ✓ 安装 @anthropic-ai/claude-code', 'green');
230
- log(' │ ✓ 创建配置文件 settings.json', 'green');
231
- log(' │ ✓ 创建配置文件 config.json', 'green');
232
- log(' │', 'cyan');
233
- log(' └─────────────────────────────────────────────', 'cyan');
234
-
235
- log('\n ┌─ 配置文件路径', 'cyan');
236
- log(' ', 'cyan');
237
- log(` │ settings.json(可在此处修改key和域名url)`, 'reset');
238
- log(` │ ${settingsPath}`, 'yellow');
239
- log(' │', 'cyan');
240
- log(` │ config.json`, 'reset');
241
- log(` │ ${configPath}`, 'yellow');
242
- log(' │', 'cyan');
243
- log(' └─────────────────────────────────────────────', 'cyan');
244
-
245
- log('\n ┌─ 终端的使用方式', 'cyan');
246
- log(' │', 'cyan');
247
- log(' │ 在终端输入以下命令启动 Claude Code:', 'reset');
248
- log(' ', 'cyan');
249
- log(' claude', 'yellow');
250
- log(' │', 'cyan');
251
- log(' └─────────────────────────────────────────────', 'cyan');
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
+ }
252
368
 
253
369
  const claudeVersion = getClaudeVersion();
254
370
  log('\n Claude Code 版本: v' + claudeVersion, 'reset');
@@ -260,15 +376,15 @@ function showCompletionInfo() {
260
376
  async function main() {
261
377
  console.clear();
262
378
 
263
- // ASCII 艺术 Logo
379
+ // ASCII Logo - 水平渐变 (蓝→紫→粉)
264
380
  log('\n', 'reset');
265
- log(' ██████╗██╗ █████╗ ██╗ ██╗██████╗ ███████╗', 'cyan');
266
- log(' ██╔════╝██║ ██╔══██╗██║ ██║██╔══██╗██╔════╝', 'cyan');
267
- log(' ██║ ██║ ███████║██║ ██║██║ ██║█████╗ ', 'cyan');
268
- log(' ██║ ██║ ██╔══██║██║ ██║██║ ██║██╔══╝ ', 'cyan');
269
- log(' ╚██████╗███████╗██║ ██║╚██████╔╝██████╔╝███████╗', 'cyan');
270
- log(' ╚═════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝', 'cyan');
271
- log('\n PPChat Claude Code 一键安装配置工具', 'magenta');
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', 'magenta');
272
388
  log(' ' + '='.repeat(50), 'cyan');
273
389
  log('', 'reset');
274
390
 
@@ -279,7 +395,7 @@ async function main() {
279
395
  log('\n[提示] 安装失败,但你可以继续配置环境变量', 'yellow');
280
396
  }
281
397
 
282
- // 2. 配置环境变量
398
+ // 2. 配置 API Key (会自动设置环境变量)
283
399
  const configSuccess = await configureEnvironment();
284
400
  if (!configSuccess) {
285
401
  process.exit(1);
@@ -303,5 +419,6 @@ if (require.main === module) {
303
419
  module.exports = {
304
420
  main,
305
421
  installClaude,
306
- configureEnvironment
422
+ configureEnvironment,
423
+ setupEnvironmentVariables
307
424
  };