feat: pwsh7默认终端 + Phase1依赖增强 + Phase6 MCP预安装
- Phase 1: +PowerShell 7/Python 3.12/uv, pwsh升为核心依赖
- Phase 4: 修复缓存命中后仍弹密码框的逻辑缺陷
- Phase 5: 新增 {{PWSH_PATH}} 占位符渲染
- Phase 6: npm cache add + uv tool install 预缓存(超时保护)
- Phase 7: Start-Process pwsh 独立窗口启动Claude
- install.ps1: Render函数添加 {{PWSH_PATH}} + Start-Process启动
- OneClick.bat: 新增步骤4/8安装PowerShell 7
- 所有.bat: start pwsh新窗口模式 + CRLF修复
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
53b25253fd
commit
dee7742a12
@ -58,16 +58,18 @@ echo.
|
||||
:: 更新到最新版本
|
||||
git pull >nul 2>nul
|
||||
|
||||
:: 检测 PowerShell 7 (pwsh) 或退回 5.1 (powershell)
|
||||
:: 检测 PowerShell 7 (pwsh): 新窗口启动, 退出 cmd
|
||||
where pwsh >nul 2>nul
|
||||
if %errorlevel% equ 0 (
|
||||
echo [OK] 使用 PowerShell 7
|
||||
pwsh -ExecutionPolicy Bypass -File auto-setup.ps1
|
||||
) else (
|
||||
echo [..] 使用 PowerShell 5.1
|
||||
powershell -ExecutionPolicy Bypass -File auto-setup.ps1
|
||||
start "Bookworm 全自动安装" pwsh -NoLogo -ExecutionPolicy Bypass -File "%CD%\auto-setup.ps1"
|
||||
exit
|
||||
)
|
||||
|
||||
:: 回退 PowerShell 5.1 (auto-setup 会安装 pwsh7, Phase 7 再切换)
|
||||
echo [..] PowerShell 7 未安装, 先用 5.1 执行安装 (将自动安装 pwsh7)
|
||||
powershell -ExecutionPolicy Bypass -File auto-setup.ps1
|
||||
|
||||
if %errorlevel% neq 0 (
|
||||
echo.
|
||||
echo [!!] 安装过程中出现错误
|
||||
|
||||
@ -39,8 +39,8 @@ echo ^| ^|
|
||||
echo +============================================================+
|
||||
echo.
|
||||
|
||||
:: ─── 步骤 1/7: winget 检测 ──────────────────────────
|
||||
echo [1/7] 检测包管理器...
|
||||
:: ─── 步骤 1/8: winget 检测 ──────────────────────────
|
||||
echo [1/8] 检测包管理器...
|
||||
where winget >nul 2>nul
|
||||
if %errorlevel% neq 0 (
|
||||
echo.
|
||||
@ -58,8 +58,8 @@ if %errorlevel% neq 0 (
|
||||
echo [OK] winget 可用
|
||||
echo.
|
||||
|
||||
:: ─── 步骤 2/7: 安装 Git ────────────────────────────
|
||||
echo [2/7] 检查 Git...
|
||||
:: ─── 步骤 2/8: 安装 Git ────────────────────────────
|
||||
echo [2/8] 检查 Git...
|
||||
where git >nul 2>nul
|
||||
if %errorlevel% neq 0 (
|
||||
echo [..] Git 未安装, 正在通过 winget 安装...
|
||||
@ -76,8 +76,8 @@ if %errorlevel% neq 0 (
|
||||
)
|
||||
echo.
|
||||
|
||||
:: ─── 步骤 3/7: 安装 Node.js ────────────────────────
|
||||
echo [3/7] 检查 Node.js...
|
||||
:: ─── 步骤 3/8: 安装 Node.js ────────────────────────
|
||||
echo [3/8] 检查 Node.js...
|
||||
where node >nul 2>nul
|
||||
if %errorlevel% neq 0 (
|
||||
echo [..] Node.js 未安装, 正在通过 winget 安装...
|
||||
@ -94,6 +94,24 @@ if %errorlevel% neq 0 (
|
||||
)
|
||||
echo.
|
||||
|
||||
:: ─── 步骤 4/8: 安装 PowerShell 7 ────────────────────
|
||||
echo [4/8] 检查 PowerShell 7...
|
||||
where pwsh >nul 2>nul
|
||||
if %errorlevel% neq 0 (
|
||||
echo [..] PowerShell 7 未安装, 正在通过 winget 安装...
|
||||
winget install Microsoft.PowerShell --accept-source-agreements --accept-package-agreements --silent
|
||||
if !errorlevel! neq 0 (
|
||||
echo [!!] PowerShell 7 安装失败
|
||||
set /a ERRORS+=1
|
||||
) else (
|
||||
echo [OK] PowerShell 7 安装成功
|
||||
set "NEED_PATH_REFRESH=1"
|
||||
)
|
||||
) else (
|
||||
echo [OK] PowerShell 7 已安装
|
||||
)
|
||||
echo.
|
||||
|
||||
:: ─── 刷新 PATH (新装软件需要) ────────────────────────
|
||||
if "%NEED_PATH_REFRESH%"=="1" (
|
||||
echo [..] 刷新系统 PATH...
|
||||
@ -102,12 +120,12 @@ if "%NEED_PATH_REFRESH%"=="1" (
|
||||
for /f "tokens=2*" %%a in ('reg query "HKCU\Environment" /v Path 2^>nul') do set "USR_PATH=%%b"
|
||||
set "PATH=!SYS_PATH!;!USR_PATH!"
|
||||
:: 同时添加常见 Node.js / Git 路径
|
||||
set "PATH=!PATH!;C:\Program Files\nodejs;C:\Program Files\Git\cmd;C:\Program Files\Git\usr\bin"
|
||||
set "PATH=!PATH!;C:\Program Files\nodejs;C:\Program Files\Git\cmd;C:\Program Files\Git\usr\bin;C:\Program Files\PowerShell\7"
|
||||
echo [OK] PATH 已刷新
|
||||
echo.
|
||||
)
|
||||
|
||||
:: ─── 二次验证: Git + Node ────────────────────────────
|
||||
:: ─── 二次验证: Git + Node + pwsh ─────────────────────
|
||||
where git >nul 2>nul
|
||||
if %errorlevel% neq 0 (
|
||||
echo [FATAL] Git 仍然不可用
|
||||
@ -122,9 +140,13 @@ if %errorlevel% neq 0 (
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
where pwsh >nul 2>nul
|
||||
if %errorlevel% neq 0 (
|
||||
echo [WARN] PowerShell 7 未就绪, Claude Code 将使用 PowerShell 5.1
|
||||
)
|
||||
|
||||
:: ─── 步骤 4/7: 安装 Claude Code ─────────────────────
|
||||
echo [4/7] 检查 Claude Code...
|
||||
:: ─── 步骤 5/8: 安装 Claude Code ─────────────────────
|
||||
echo [5/8] 检查 Claude Code...
|
||||
:: 国内 npm 镜像 - 淘宝源, 避免 npmjs.org 超时
|
||||
call npm config set registry https://registry.npmmirror.com 2>nul
|
||||
where claude >nul 2>nul
|
||||
@ -143,8 +165,8 @@ if %errorlevel% neq 0 (
|
||||
)
|
||||
echo.
|
||||
|
||||
:: ─── 步骤 5/7: 克隆/更新 Bookworm ──────────────────
|
||||
echo [5/7] 同步 Bookworm 配置...
|
||||
:: ─── 步骤 6/8: 克隆/更新 Bookworm ──────────────────
|
||||
echo [6/8] 同步 Bookworm 配置...
|
||||
|
||||
:: 配置 git credential helper (免重复输密码)
|
||||
git config --global credential.helper manager 2>nul
|
||||
@ -175,8 +197,8 @@ if exist "%INSTALL_DIR%\.git" (
|
||||
echo [OK] Bookworm 文件已就绪
|
||||
echo.
|
||||
|
||||
:: ─── 步骤 6/7: 执行安装配置 ────────────────────────
|
||||
echo [6/7] 执行安装配置...
|
||||
:: ─── 步骤 7/8: 执行安装配置 ────────────────────────
|
||||
echo [7/8] 执行安装配置...
|
||||
echo.
|
||||
|
||||
if exist "%INSTALL_DIR%\install.ps1" (
|
||||
@ -192,8 +214,8 @@ if exist "%INSTALL_DIR%\install.ps1" (
|
||||
)
|
||||
echo.
|
||||
|
||||
:: ─── 步骤 7/7: 创建桌面快捷方式 + 完成 ──────────────
|
||||
echo [7/7] 创建桌面快捷方式...
|
||||
:: ─── 步骤 8/8: 创建桌面快捷方式 + 完成 ──────────────
|
||||
echo [8/8] 创建桌面快捷方式...
|
||||
|
||||
:: 用 PowerShell 创建快捷方式
|
||||
powershell -ExecutionPolicy Bypass -Command ^
|
||||
@ -223,6 +245,7 @@ echo ^| ^|
|
||||
echo ^| 已安装: ^|
|
||||
echo ^| [v] Node.js LTS — JavaScript 运行时 ^|
|
||||
echo ^| [v] Git — 版本控制与配置同步 ^|
|
||||
echo ^| [v] PowerShell 7 — 现代终端环境 ^|
|
||||
echo ^| [v] Claude Code — AI 编程助手 ^|
|
||||
echo ^| [v] Bookworm — 92 Skills / 18 Agents ^|
|
||||
echo ^| ^|
|
||||
@ -243,17 +266,15 @@ if %ERRORS% gtr 0 (
|
||||
echo 按任意键启动 Bookworm...
|
||||
pause > nul
|
||||
|
||||
:: 启动
|
||||
:: 启动 — 优先在 pwsh7 新窗口中运行
|
||||
cd /d "%INSTALL_DIR%"
|
||||
if exist "启动Bookworm.bat" (
|
||||
where pwsh >nul 2>nul
|
||||
if !errorlevel! equ 0 (
|
||||
start "Bookworm Smart Assistant" pwsh -NoLogo -ExecutionPolicy Bypass -File "%INSTALL_DIR%\install.ps1" -StartOnly -AutoAccept
|
||||
) else if exist "启动Bookworm.bat" (
|
||||
call "启动Bookworm.bat"
|
||||
) else (
|
||||
where pwsh >nul 2>nul
|
||||
if !errorlevel! equ 0 (
|
||||
pwsh -NoLogo -ExecutionPolicy Bypass -File install.ps1 -StartOnly -AutoAccept
|
||||
) else (
|
||||
powershell -NoLogo -ExecutionPolicy Bypass -File install.ps1 -StartOnly -AutoAccept
|
||||
)
|
||||
powershell -NoLogo -ExecutionPolicy Bypass -File "%INSTALL_DIR%\install.ps1" -StartOnly -AutoAccept
|
||||
)
|
||||
|
||||
endlocal
|
||||
|
||||
199
auto-setup.ps1
199
auto-setup.ps1
@ -261,9 +261,11 @@ Log-Phase 1 "环境检测 + 依赖自动安装"
|
||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
||||
|
||||
$deps = @(
|
||||
@{ Name = "Node.js"; Cmd = "node"; WingetId = "OpenJS.NodeJS.LTS"; NpmPkg = $null }
|
||||
@{ Name = "Git"; Cmd = "git"; WingetId = "Git.Git"; NpmPkg = $null }
|
||||
@{ Name = "Claude Code"; Cmd = "claude"; WingetId = $null; NpmPkg = "@anthropic-ai/claude-code" }
|
||||
@{ Name = "Node.js"; Cmd = "node"; WingetId = "OpenJS.NodeJS.LTS"; NpmPkg = $null; PipPkg = $null }
|
||||
@{ Name = "Git"; Cmd = "git"; WingetId = "Git.Git"; NpmPkg = $null; PipPkg = $null }
|
||||
@{ Name = "PowerShell 7"; Cmd = "pwsh"; WingetId = "Microsoft.PowerShell"; NpmPkg = $null; PipPkg = $null }
|
||||
@{ Name = "Python 3.12"; Cmd = "python"; WingetId = "Python.Python.3.12"; NpmPkg = $null; PipPkg = $null }
|
||||
@{ Name = "Claude Code"; Cmd = "claude"; WingetId = $null; NpmPkg = "@anthropic-ai/claude-code"; PipPkg = $null }
|
||||
)
|
||||
|
||||
$hasWinget = Test-Cmd "winget"
|
||||
@ -318,20 +320,72 @@ if (-not (Test-Cmd "claude") -and (Test-Cmd "npm")) {
|
||||
if (Test-Cmd "claude") { Log-OK "Claude Code 安装成功" } else { Log-Fail "Claude Code 安装失败" }
|
||||
}
|
||||
|
||||
# uv 依赖 Python, 需要在 Python 安装后再检查
|
||||
if (Test-Cmd "python") {
|
||||
if (Test-Cmd "uv") {
|
||||
$uvVer = try { & uv --version 2>$null | Select-Object -First 1 } catch { "installed" }
|
||||
Log-OK "uv $uvVer"
|
||||
} else {
|
||||
Log-Info "安装 uv (Python 包管理器)..."
|
||||
try {
|
||||
& python -m pip install uv --quiet 2>&1 | Select-Object -Last 2 | ForEach-Object { Write-Host " $_" -ForegroundColor Gray }
|
||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
||||
# pip install 的 Scripts 目录可能不在 PATH, 追加
|
||||
$pyScripts = Join-Path (Split-Path (& python -c "import sys; print(sys.executable)") -Parent) "Scripts"
|
||||
if (Test-Path $pyScripts) { $env:Path += ";$pyScripts" }
|
||||
if (Test-Cmd "uv") {
|
||||
Log-OK "uv 安装成功"
|
||||
$installed += "uv"
|
||||
} else {
|
||||
Log-Warn "uv 安装后未找到, 尝试 uvx 替代检查..."
|
||||
}
|
||||
} catch { Log-Warn "uv 安装失败: $_" }
|
||||
}
|
||||
} else {
|
||||
Log-Warn "Python 未安装, 跳过 uv (部分 MCP 不可用)"
|
||||
}
|
||||
|
||||
# OpenSSL (随 Git 安装)
|
||||
$opensslCmd = Find-OpenSSL
|
||||
if ($opensslCmd) { Log-OK "OpenSSL: $opensslCmd" } else { Log-Warn "OpenSSL 未找到 (凭证解密可能失败)" }
|
||||
|
||||
# 最终检查
|
||||
if (-not (Test-Cmd "node") -or -not (Test-Cmd "git") -or -not (Test-Cmd "claude")) {
|
||||
# 最终检查 (核心四件套必须)
|
||||
if (-not (Test-Cmd "node") -or -not (Test-Cmd "git") -or -not (Test-Cmd "claude") -or -not (Test-Cmd "pwsh")) {
|
||||
$missing = @()
|
||||
if (-not (Test-Cmd "node")) { $missing += "Node.js" }
|
||||
if (-not (Test-Cmd "git")) { $missing += "Git" }
|
||||
if (-not (Test-Cmd "pwsh")) { $missing += "PowerShell 7" }
|
||||
if (-not (Test-Cmd "claude")) { $missing += "Claude Code" }
|
||||
Show-MsgBox "以下依赖安装失败: $($missing -join ', ')`n`n请手动安装后重新运行。" "安装中断" "OK" "Error"
|
||||
Show-MsgBox "以下核心依赖安装失败: $($missing -join ', ')`n`n请手动安装后重新运行。" "安装中断" "OK" "Error"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 定位 pwsh.exe 完整路径 (供后续 settings.json 配置使用)
|
||||
$PwshPath = (Get-Command pwsh -ErrorAction SilentlyContinue).Source
|
||||
if (-not $PwshPath) {
|
||||
# winget 默认安装路径
|
||||
$defaultPaths = @(
|
||||
"$env:ProgramFiles\PowerShell\7\pwsh.exe",
|
||||
"${env:ProgramFiles(x86)}\PowerShell\7\pwsh.exe",
|
||||
"$env:LOCALAPPDATA\Microsoft\PowerShell\pwsh.exe"
|
||||
)
|
||||
$PwshPath = $defaultPaths | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
}
|
||||
if ($PwshPath) {
|
||||
Log-OK "PowerShell 7 路径: $PwshPath"
|
||||
} else {
|
||||
Log-Warn "pwsh 可执行但无法定位完整路径, 使用 'pwsh'"
|
||||
$PwshPath = "pwsh"
|
||||
}
|
||||
|
||||
# 可选依赖警告 (不阻断)
|
||||
$optionalMissing = @()
|
||||
if (-not (Test-Cmd "python")) { $optionalMissing += "Python 3.12" }
|
||||
if (-not (Test-Cmd "uv")) { $optionalMissing += "uv" }
|
||||
if ($optionalMissing.Count -gt 0) {
|
||||
Log-Warn "可选依赖未就绪: $($optionalMissing -join ', ') (部分 MCP 不可用)"
|
||||
}
|
||||
|
||||
if ($installed.Count -gt 0) {
|
||||
Log-OK "本次新安装: $($installed -join ', ')"
|
||||
}
|
||||
@ -530,7 +584,8 @@ if (Get-CachedSecrets) {
|
||||
Log-OK "从本日缓存加载凭证 (免密)"
|
||||
$secretsDecrypted = $true
|
||||
}
|
||||
# 再解密
|
||||
# 再解密 (缓存命中则跳过)
|
||||
if (-not $secretsDecrypted) {
|
||||
$cryptoHelper = Join-Path $ScriptDir "crypto-helper.js"
|
||||
$useNode = (Test-Cmd "node") -and (Test-Path $cryptoHelper)
|
||||
if (-not $useNode -and -not $opensslCmd) {
|
||||
@ -596,6 +651,7 @@ elseif (Test-Path $SecretsEnc) {
|
||||
elseif (-not (Test-Path $SecretsEnc)) {
|
||||
Log-Warn "secrets.enc 不存在, 跳过凭证解密"
|
||||
}
|
||||
} # end if (-not $secretsDecrypted)
|
||||
|
||||
# ========================================================================
|
||||
# Phase 5: 配置渲染
|
||||
@ -608,13 +664,16 @@ $settingsFile = Join-Path $ClaudeDir "settings.json"
|
||||
if (Test-Path $templateFile) {
|
||||
$claudeRoot = $ClaudeDir.Replace('\', '/')
|
||||
$homeDir = $env:USERPROFILE
|
||||
# pwsh 路径转正斜杠供 JSON 使用 (C:/Program Files/PowerShell/7/pwsh.exe)
|
||||
$pwshJsonPath = if ($PwshPath) { $PwshPath.Replace('\', '/') } else { "pwsh" }
|
||||
|
||||
$content = Get-Content $templateFile -Raw
|
||||
$content = $content -replace '\{\{CLAUDE_ROOT\}\}', $claudeRoot
|
||||
$content = $content -replace '\{\{HOME\}\}', ($homeDir -replace '\\', '\\')
|
||||
$content = $content -replace '\{\{PWSH_PATH\}\}', ($pwshJsonPath -replace '\\', '\\')
|
||||
|
||||
Set-Content $settingsFile -Value $content -Encoding UTF8
|
||||
Log-OK "settings.json 已渲染 (ROOT=$claudeRoot)"
|
||||
Log-OK "settings.json 已渲染 (ROOT=$claudeRoot, SHELL=$pwshJsonPath)"
|
||||
|
||||
# settings.local.template.json
|
||||
$localTpl = Join-Path $ClaudeDir "settings.local.template.json"
|
||||
@ -624,6 +683,7 @@ if (Test-Path $templateFile) {
|
||||
$lc = $lc -replace '\{\{CLAUDE_ROOT\}\}', $claudeRoot
|
||||
$lc = $lc -replace '\{\{HOME\}\}', ($homeDir -replace '\\', '\\')
|
||||
$lc = $lc -replace '\{\{USERNAME\}\}', $env:USERNAME
|
||||
$lc = $lc -replace '\{\{PWSH_PATH\}\}', ($pwshJsonPath -replace '\\', '\\')
|
||||
Set-Content $localSet -Value $lc -Encoding UTF8
|
||||
Log-OK "settings.local.json 已渲染"
|
||||
}
|
||||
@ -636,9 +696,9 @@ $env:CLAUDE_HOME = $ClaudeDir
|
||||
# ========================================================================
|
||||
# Phase 6: MCP 验证 + 自动安装
|
||||
# ========================================================================
|
||||
Log-Phase 6 "MCP 服务验证"
|
||||
Log-Phase 6 "MCP 服务验证 + 预安装"
|
||||
|
||||
# Bookworm 完整性
|
||||
# ── 6a: Bookworm 完整性检查 ──
|
||||
$skillCount = 0; $hookCount = 0
|
||||
$skillsDir = Join-Path $ClaudeDir "skills"
|
||||
$hooksDir = Join-Path $ClaudeDir "hooks"
|
||||
@ -670,44 +730,114 @@ foreach ($c in $checks) {
|
||||
if ($c.OK) { Log-OK $c.Name } else { Log-Fail $c.Name; $allOK = $false }
|
||||
}
|
||||
|
||||
# API Key 检查
|
||||
# ── 6b: API 凭证检查 ──
|
||||
Write-Host ""
|
||||
Log-Info "API 凭证检查..."
|
||||
if ($env:ANTHROPIC_API_KEY) { Log-OK "ANTHROPIC_API_KEY 已配置" } else { Log-Fail "ANTHROPIC_API_KEY 未配置" }
|
||||
if ($env:ANTHROPIC_BASE_URL) { Log-OK "ANTHROPIC_BASE_URL 已配置" } else { Log-Warn "ANTHROPIC_BASE_URL 未配置 (将使用默认)" }
|
||||
|
||||
# MCP 依赖自动安装
|
||||
# ── 6c: MCP npx 包预缓存 ──
|
||||
Write-Host ""
|
||||
Log-Info "MCP 依赖检查..."
|
||||
Log-Info "MCP 预安装 (npx 包预缓存)..."
|
||||
|
||||
# Playwright
|
||||
$hasPlaywright = $false
|
||||
try {
|
||||
$pwCheck = npm list -g @anthropic-ai/mcp-playwright 2>$null
|
||||
if ($pwCheck -and $pwCheck -notmatch 'empty') { $hasPlaywright = $true }
|
||||
} catch {}
|
||||
# Tier 1: 纯 npx, 无需 Key
|
||||
$npxPackages = @(
|
||||
@{ Name = "context7"; Pkg = "@upstash/context7-mcp@2.1.1" }
|
||||
@{ Name = "sequential-thinking"; Pkg = "@modelcontextprotocol/server-sequential-thinking@2025.12.18" }
|
||||
@{ Name = "playwright"; Pkg = "@playwright/mcp@0.0.68" }
|
||||
@{ Name = "session-continuity"; Pkg = "claude-session-continuity-mcp@1.13.0" }
|
||||
@{ Name = "notebooklm"; Pkg = "notebooklm-mcp@latest" }
|
||||
@{ Name = "cloudflare-docs"; Pkg = "mcp-remote" }
|
||||
@{ Name = "chrome-devtools"; Pkg = "chrome-devtools-mcp@0.18.1" }
|
||||
# Tier 2: npx + Key
|
||||
@{ Name = "github"; Pkg = "@modelcontextprotocol/server-github" }
|
||||
@{ Name = "slack"; Pkg = "@modelcontextprotocol/server-slack" }
|
||||
@{ Name = "firecrawl"; Pkg = "firecrawl-mcp" }
|
||||
@{ Name = "mcp-image"; Pkg = "mcp-image" }
|
||||
@{ Name = "google-drive"; Pkg = "@piotr-agier/google-drive-mcp" }
|
||||
)
|
||||
|
||||
if ($hasPlaywright) {
|
||||
Log-OK "Playwright MCP 已安装"
|
||||
} else {
|
||||
Log-Info "安装 Playwright MCP..."
|
||||
$mcpOK = 0; $mcpFail = 0
|
||||
foreach ($mcp in $npxPackages) {
|
||||
$idx = $mcpOK + $mcpFail + 1
|
||||
Write-Host " [$idx/$($npxPackages.Count)] $($mcp.Name) " -NoNewline -ForegroundColor Gray
|
||||
try {
|
||||
npm i -g @anthropic-ai/mcp-playwright 2>&1 | Select-Object -Last 2 | ForEach-Object { Write-Host " $_" -ForegroundColor Gray }
|
||||
Log-OK "Playwright MCP 安装完成"
|
||||
} catch { Log-Warn "Playwright MCP 安装失败 (不影响核心功能)" }
|
||||
# npm cache add 只下载到缓存, 不执行 (MCP 是 stdio 长驻进程, 不能用 --help)
|
||||
$proc = Start-Process npm.cmd -ArgumentList "cache", "add", $mcp.Pkg -NoNewWindow -PassThru -RedirectStandardOutput "NUL" -RedirectStandardError "NUL"
|
||||
$exited = $proc.WaitForExit(60000) # 60 秒超时
|
||||
if (-not $exited) { $proc.Kill(); throw "timeout" }
|
||||
if ($proc.ExitCode -eq 0) {
|
||||
Write-Host "[cached]" -ForegroundColor Green
|
||||
$mcpOK++
|
||||
} else { throw "exit $($proc.ExitCode)" }
|
||||
} catch {
|
||||
Write-Host "[FAIL: $_]" -ForegroundColor Red
|
||||
$mcpFail++
|
||||
}
|
||||
}
|
||||
Log-OK "npx 预缓存: $mcpOK 成功, $mcpFail 失败 (共 $($npxPackages.Count))"
|
||||
|
||||
# ── 6d: Playwright 浏览器安装 ──
|
||||
Write-Host ""
|
||||
Log-Info "Playwright 浏览器安装..."
|
||||
try {
|
||||
$pwBrowserPath = Join-Path $env:USERPROFILE "AppData\Local\ms-playwright"
|
||||
if (Test-Path (Join-Path $pwBrowserPath "chromium-*")) {
|
||||
Log-OK "Playwright Chromium 已存在"
|
||||
} else {
|
||||
Write-Host " 下载 Chromium (首次约 150MB, 最长等 5 分钟)..." -ForegroundColor Gray
|
||||
$pwProc = Start-Process npx.cmd -ArgumentList "-y", "playwright", "install", "chromium" -NoNewWindow -PassThru
|
||||
$pwExited = $pwProc.WaitForExit(300000) # 5 分钟超时
|
||||
if (-not $pwExited) { $pwProc.Kill(); Log-Warn "Playwright 下载超时, 跳过" }
|
||||
elseif (Test-Path (Join-Path $pwBrowserPath "chromium-*")) {
|
||||
Log-OK "Playwright Chromium 安装成功"
|
||||
} else {
|
||||
Log-Warn "Playwright Chromium 安装可能未完成"
|
||||
}
|
||||
}
|
||||
} catch { Log-Warn "Playwright 浏览器安装失败: $_ (不影响核心功能)" }
|
||||
|
||||
# ── 6e: Python MCP (uvx) 验证 ──
|
||||
Write-Host ""
|
||||
if (Test-Cmd "uvx") {
|
||||
Log-Info "Python MCP 验证 (uvx)..."
|
||||
|
||||
$uvxPackages = @(
|
||||
@{ Name = "windows-mcp"; Args = @("--python", "3.13", "windows-mcp") }
|
||||
@{ Name = "atlassian"; Args = @("mcp-atlassian") }
|
||||
)
|
||||
|
||||
foreach ($pkg in $uvxPackages) {
|
||||
Write-Host " $($pkg.Name) " -NoNewline -ForegroundColor Gray
|
||||
try {
|
||||
# uv tool install 只下载不启动 (MCP 是 stdio 长驻进程, --help 会挂起)
|
||||
$installArgs = @("tool", "install") + $pkg.Args
|
||||
$proc = Start-Process uv -ArgumentList $installArgs -NoNewWindow -PassThru -RedirectStandardOutput "NUL" -RedirectStandardError "NUL"
|
||||
$exited = $proc.WaitForExit(90000) # 90 秒超时 (Python 包较大)
|
||||
if (-not $exited) { $proc.Kill(); throw "timeout" }
|
||||
Write-Host "[ready]" -ForegroundColor Green
|
||||
} catch {
|
||||
Write-Host "[skip: $_]" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log-Warn "uvx 不可用, 跳过 Python MCP (windows-mcp, atlassian)"
|
||||
}
|
||||
|
||||
# 可选 API Key 提示
|
||||
# ── 6f: 可选 API Key 提示 ──
|
||||
$optional = @(
|
||||
@{ Key = "GITHUB_PERSONAL_ACCESS_TOKEN"; Name = "GitHub MCP" }
|
||||
@{ Key = "FIRECRAWL_API_KEY"; Name = "Firecrawl MCP" }
|
||||
@{ Key = "SLACK_BOT_TOKEN"; Name = "Slack MCP" }
|
||||
@{ Key = "BROWSERBASE_API_KEY"; Name = "Browserbase MCP" }
|
||||
@{ Key = "GEMINI_API_KEY"; Name = "MCP Image / Browserbase" }
|
||||
@{ Key = "ATLASSIAN_API_TOKEN"; Name = "Atlassian MCP" }
|
||||
)
|
||||
$missingOpt = $optional | Where-Object { -not [System.Environment]::GetEnvironmentVariable($_.Key, "Process") }
|
||||
if ($missingOpt.Count -gt 0) {
|
||||
Write-Host ""
|
||||
Write-Host " 可选 MCP (未配置, 不影响核心功能):" -ForegroundColor DarkGray
|
||||
foreach ($m in $missingOpt) { Write-Host " [-] $($m.Name)" -ForegroundColor DarkGray }
|
||||
Write-Host " 可选 MCP (Key 未配置, 不影响核心功能):" -ForegroundColor DarkGray
|
||||
foreach ($m in $missingOpt) { Write-Host " [-] $($m.Name) ($($m.Key))" -ForegroundColor DarkGray }
|
||||
}
|
||||
|
||||
# ========================================================================
|
||||
@ -733,8 +863,14 @@ if ($allOK -and $env:ANTHROPIC_API_KEY) {
|
||||
Write-Host ""
|
||||
Log-Info "正在启动 Claude Code..."
|
||||
Write-Host ""
|
||||
# 始终在独立 pwsh7 窗口中启动 (bat 调 pwsh 子进程时窗口仍属 cmd.exe)
|
||||
$pwshCmd = Get-Command pwsh -ErrorAction SilentlyContinue
|
||||
if ($pwshCmd) {
|
||||
Start-Process $pwshCmd.Source -ArgumentList "-NoLogo", "-NoExit", "-Command", "& claude" -WorkingDirectory $env:USERPROFILE -WindowStyle Normal
|
||||
} else {
|
||||
& claude
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Write-Host " +---------------------------------------------------+" -ForegroundColor Yellow
|
||||
Write-Host " | |" -ForegroundColor Yellow
|
||||
@ -749,6 +885,11 @@ if ($allOK -and $env:ANTHROPIC_API_KEY) {
|
||||
|
||||
$launchResult = Show-MsgBox "安装完成, 但存在以下问题:`n$issueText`n`n是否仍然启动 Claude Code?`n(将以受限模式运行)" "安装警告" "YesNo" "Warning"
|
||||
if ($launchResult -eq "Yes" -and -not $SkipLaunch) {
|
||||
$pwshCmd = Get-Command pwsh -ErrorAction SilentlyContinue
|
||||
if ($pwshCmd) {
|
||||
Start-Process $pwshCmd.Source -ArgumentList "-NoLogo", "-NoExit", "-Command", "& claude" -WorkingDirectory $env:USERPROFILE -WindowStyle Normal
|
||||
} else {
|
||||
& claude
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
24
install.ps1
24
install.ps1
@ -257,22 +257,26 @@ function Render-SettingsTemplate {
|
||||
}
|
||||
|
||||
$claudeRoot = $ClaudeTarget.Replace('\', '/')
|
||||
# HOME 保留反斜杠格式,与 Claude Code 原始行为一致
|
||||
$homeDir = $env:USERPROFILE
|
||||
$homeDir = $env:USERPROFILE.Replace('\', '/')
|
||||
# 定位 pwsh 路径 (正斜杠供 JSON)
|
||||
$pwshExe = (Get-Command pwsh -ErrorAction SilentlyContinue)
|
||||
$pwshJsonPath = if ($pwshExe) { $pwshExe.Source.Replace('\', '/') } else { "pwsh" }
|
||||
|
||||
$content = Get-Content $TemplateFile -Raw
|
||||
$content = $content -replace '\{\{CLAUDE_ROOT\}\}', $claudeRoot
|
||||
$content = $content -replace '\{\{HOME\}\}', ($homeDir -replace '\\', '\\')
|
||||
$content = $content -replace '\{\{HOME\}\}', $homeDir
|
||||
$content = $content -replace '\{\{PWSH_PATH\}\}', $pwshJsonPath
|
||||
|
||||
Set-Content $SettingsFile -Value $content -Encoding UTF8
|
||||
Write-Host " [OK] settings.json 已渲染 (ROOT=$claudeRoot)" -ForegroundColor Green
|
||||
Write-Host " [OK] settings.json 已渲染 (ROOT=$claudeRoot, SHELL=$pwshJsonPath)" -ForegroundColor Green
|
||||
|
||||
# 渲染 settings.local.template.json (如果存在)
|
||||
if (Test-Path $LocalTplFile) {
|
||||
$localContent = Get-Content $LocalTplFile -Raw
|
||||
$localContent = $localContent -replace '\{\{CLAUDE_ROOT\}\}', $claudeRoot
|
||||
$localContent = $localContent -replace '\{\{HOME\}\}', ($homeDir -replace '\\', '\\')
|
||||
$localContent = $localContent -replace '\{\{HOME\}\}', $homeDir
|
||||
$localContent = $localContent -replace '\{\{USERNAME\}\}', $env:USERNAME
|
||||
$localContent = $localContent -replace '\{\{PWSH_PATH\}\}', $pwshJsonPath
|
||||
Set-Content $LocalSetFile -Value $localContent -Encoding UTF8
|
||||
Write-Host " [OK] settings.local.json 已渲染" -ForegroundColor Green
|
||||
}
|
||||
@ -723,4 +727,12 @@ if (-not $StartOnly) {
|
||||
}
|
||||
}
|
||||
|
||||
& claude
|
||||
# 始终在独立 pwsh7 窗口中启动 Claude Code
|
||||
# (bat 调 pwsh 子进程时窗口仍属 cmd.exe, 必须 Start-Process 新建窗口)
|
||||
$pwshCmd = Get-Command pwsh -ErrorAction SilentlyContinue
|
||||
if ($pwshCmd) {
|
||||
Write-Host " [..] 正在启动 Claude Code (PowerShell 7)..." -ForegroundColor Cyan
|
||||
Start-Process $pwshCmd.Source -ArgumentList "-NoLogo", "-NoExit", "-Command", "& claude" -WorkingDirectory $env:USERPROFILE -WindowStyle Normal
|
||||
} else {
|
||||
& claude
|
||||
}
|
||||
|
||||
@ -1,25 +1,24 @@
|
||||
@echo off
|
||||
chcp 65001 > nul
|
||||
title Bookworm Portable - 启动
|
||||
cd /d "%~dp0"
|
||||
|
||||
:: 中转站在国内,不走代理
|
||||
set NO_PROXY=bww.letcareme.com,code.letcareme.com,letcareme.com,localhost,127.0.0.1
|
||||
set no_proxy=%NO_PROXY%
|
||||
|
||||
echo.
|
||||
echo ====================================
|
||||
echo Bookworm Portable - 快速启动
|
||||
echo ====================================
|
||||
echo.
|
||||
|
||||
:: 优先 pwsh7: 启动新 PowerShell 7 窗口, 退出 cmd
|
||||
where pwsh >nul 2>nul
|
||||
if %errorlevel% equ 0 (
|
||||
pwsh -ExecutionPolicy Bypass -File install.ps1 -StartOnly -AutoAccept
|
||||
) else (
|
||||
powershell -ExecutionPolicy Bypass -File install.ps1 -StartOnly -AutoAccept
|
||||
start "Bookworm Smart Assistant" pwsh -NoLogo -ExecutionPolicy Bypass -File "%~dp0install.ps1" -StartOnly -AutoAccept
|
||||
exit
|
||||
)
|
||||
|
||||
:: 回退 PowerShell 5.1
|
||||
title Bookworm Portable
|
||||
echo.
|
||||
echo [!] PowerShell 7 未安装, 使用 PowerShell 5.1
|
||||
echo.
|
||||
powershell -ExecutionPolicy Bypass -File install.ps1 -StartOnly -AutoAccept
|
||||
if %errorlevel% neq 0 (
|
||||
echo.
|
||||
echo 启动失败,按任意键退出...
|
||||
|
||||
@ -1,26 +1,24 @@
|
||||
@echo off
|
||||
chcp 65001 > nul
|
||||
title Bookworm Portable - 更新并启动
|
||||
cd /d "%~dp0"
|
||||
|
||||
:: 中转站在国内,不走代理
|
||||
set NO_PROXY=bww.letcareme.com,code.letcareme.com,letcareme.com,localhost,127.0.0.1
|
||||
set no_proxy=%NO_PROXY%
|
||||
|
||||
echo.
|
||||
echo ====================================
|
||||
echo Bookworm Portable - 更新并启动
|
||||
echo (同步最新 Skills/Hooks 后启动)
|
||||
echo ====================================
|
||||
echo.
|
||||
|
||||
:: 优先 pwsh7: 启动新 PowerShell 7 窗口, 退出 cmd
|
||||
where pwsh >nul 2>nul
|
||||
if %errorlevel% equ 0 (
|
||||
pwsh -ExecutionPolicy Bypass -File install.ps1 -AutoAccept
|
||||
) else (
|
||||
powershell -ExecutionPolicy Bypass -File install.ps1 -AutoAccept
|
||||
start "Bookworm - 更新并启动" pwsh -NoLogo -ExecutionPolicy Bypass -File "%~dp0install.ps1" -AutoAccept
|
||||
exit
|
||||
)
|
||||
|
||||
:: 回退 PowerShell 5.1
|
||||
title Bookworm Portable - 更新并启动
|
||||
echo.
|
||||
echo [!] PowerShell 7 未安装, 使用 PowerShell 5.1
|
||||
echo.
|
||||
powershell -ExecutionPolicy Bypass -File install.ps1 -AutoAccept
|
||||
if %errorlevel% neq 0 (
|
||||
echo.
|
||||
echo 启动失败,按任意键退出...
|
||||
|
||||
Loading…
Reference in New Issue
Block a user