|
|
@@ -18,7 +18,8 @@ import {
|
|
|
installVscode,
|
|
|
installGit,
|
|
|
installAll,
|
|
|
- uninstallSoftware
|
|
|
+ uninstallSoftware,
|
|
|
+ getNpmPath
|
|
|
} from './installer'
|
|
|
import { addInstallHistory, getInstallHistory } from './config'
|
|
|
import logger from './logger'
|
|
|
@@ -314,21 +315,57 @@ export function registerHandlers(): void {
|
|
|
logger.info('开始安装 Claude Code...')
|
|
|
sendToRenderer('install-status', { software: 'claudeCode', message: '正在安装 Claude Code...', progress: 30 })
|
|
|
|
|
|
- // 使用 npm 全局安装 @anthropic-ai/claude-code
|
|
|
- await execa('npm', ['install', '-g', '@anthropic-ai/claude-code'])
|
|
|
+ // 使用完整的 npm 路径,避免 PATH 未生效的问题
|
|
|
+ const npmPath = getNpmPath()
|
|
|
+ logger.info(`使用 npm 路径: ${npmPath}`)
|
|
|
|
|
|
- sendToRenderer('install-status', { software: 'claudeCode', message: '安装完成,正在验证...', progress: 90 })
|
|
|
+ // 使用 npm 全局安装 @anthropic-ai/claude-code
|
|
|
+ const result = await execa(npmPath, ['install', '-g', '@anthropic-ai/claude-code'], {
|
|
|
+ encoding: 'utf8',
|
|
|
+ // 捕获输出以便记录日志
|
|
|
+ stdout: 'pipe',
|
|
|
+ stderr: 'pipe'
|
|
|
+ })
|
|
|
|
|
|
- // 验证安装
|
|
|
- const result = await execa('claude', ['--version'])
|
|
|
- const version = result.stdout.trim()
|
|
|
+ // 记录安装输出
|
|
|
+ if (result.stdout) {
|
|
|
+ logger.info(`npm install stdout: ${result.stdout}`)
|
|
|
+ }
|
|
|
+ if (result.stderr) {
|
|
|
+ logger.warn(`npm install stderr: ${result.stderr}`)
|
|
|
+ }
|
|
|
|
|
|
- logger.info(`Claude Code 安装成功: ${version}`)
|
|
|
- sendToRenderer('install-complete', { software: 'claudeCode', message: '✅ Claude Code 安装完成!' })
|
|
|
+ sendToRenderer('install-status', { software: 'claudeCode', message: '安装完成,正在验证...', progress: 90 })
|
|
|
|
|
|
- return { success: true }
|
|
|
+ // 验证安装 - 使用 commandExistsWithRefresh 来刷新 PATH
|
|
|
+ const { commandExistsWithRefresh, getCommandVersionWithRefresh } = await import('./utils')
|
|
|
+ const claudeExists = await commandExistsWithRefresh('claude')
|
|
|
+
|
|
|
+ if (claudeExists) {
|
|
|
+ const version = await getCommandVersionWithRefresh('claude', ['--version'])
|
|
|
+ logger.info(`Claude Code 安装成功: ${version}`)
|
|
|
+ sendToRenderer('install-complete', { software: 'claudeCode', message: '✅ Claude Code 安装完成!' })
|
|
|
+ return { success: true }
|
|
|
+ } else {
|
|
|
+ // 即使验证失败,安装可能已成功,只是 PATH 还没生效
|
|
|
+ logger.info('Claude Code 安装完成,但验证失败(可能需要重启终端)')
|
|
|
+ sendToRenderer('install-complete', { software: 'claudeCode', message: '✅ Claude Code 安装完成!(可能需要重启终端才能使用)' })
|
|
|
+ return { success: true }
|
|
|
+ }
|
|
|
} catch (error) {
|
|
|
- const errorMessage = (error as Error).message
|
|
|
+ // 提取更有意义的错误信息
|
|
|
+ const execaError = error as { message?: string; stderr?: string; stdout?: string; shortMessage?: string }
|
|
|
+ let errorMessage = execaError.shortMessage || execaError.message || '未知错误'
|
|
|
+
|
|
|
+ // 如果有 stderr,尝试从中提取有用信息
|
|
|
+ if (execaError.stderr) {
|
|
|
+ // 过滤掉乱码字符,只保留可读字符
|
|
|
+ const stderrClean = execaError.stderr.replace(/[^\x20-\x7E\u4e00-\u9fa5\n\r]/g, '').trim()
|
|
|
+ if (stderrClean) {
|
|
|
+ errorMessage = `${errorMessage}\n${stderrClean}`
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
logger.error('Claude Code 安装失败', error)
|
|
|
sendToRenderer('install-error', { software: 'claudeCode', message: `❌ 安装失败:${errorMessage}` })
|
|
|
return { success: false, error: errorMessage }
|