feat: v1.3 full UX upgrade (6 improvements)

This commit is contained in:
leesu 2026-04-01 21:35:21 +08:00
parent 38da27b389
commit 0faadf531f
3 changed files with 222 additions and 9 deletions

View File

@ -48,9 +48,10 @@ if (-not $opensslCmd) {
function Write-Banner {
Write-Host ""
Write-Host " ╔══════════════════════════════════════════╗" -ForegroundColor Cyan
Write-Host " ║ Bookworm Portable Installer v1.1 ║" -ForegroundColor Cyan
Write-Host " ╚══════════════════════════════════════════╝" -ForegroundColor Cyan
Write-Host " +------------------------------------------+" -ForegroundColor Cyan
Write-Host " | Bookworm Portable Installer v1.3 |" -ForegroundColor Cyan
Write-Host " | 97 Skills / 18 Agents / 28 Hooks |" -ForegroundColor Cyan
Write-Host " +------------------------------------------+" -ForegroundColor Cyan
Write-Host ""
}
@ -58,6 +59,130 @@ function Test-Command($cmd) {
return [bool](Get-Command $cmd -ErrorAction SilentlyContinue)
}
# ─── 密码本日免输 (Windows Credential Manager) ──────
function Get-CachedSecrets {
try {
$cred = cmdkey /list 2>$null | Select-String "bookworm-secrets"
if ($cred) {
$stored = cmdkey /generic:bookworm-secrets 2>$null
# 从 Credential Manager 读取缓存的环境变量
$regPath = "HKCU:\Software\Bookworm\CachedEnv"
if (Test-Path $regPath) {
$props = Get-ItemProperty $regPath -ErrorAction SilentlyContinue
$loaded = 0
foreach ($p in $props.PSObject.Properties) {
if ($p.Name -match '^[A-Z_]+$') {
[System.Environment]::SetEnvironmentVariable($p.Name, $p.Value, "Process")
$loaded++
}
}
if ($loaded -gt 0 -and $env:ANTHROPIC_API_KEY) {
Write-Host " [OK] 从本日缓存加载 $loaded 个凭证 (免密)" -ForegroundColor Green
return $true
}
}
}
} catch {}
return $false
}
function Save-SecretsToCache {
try {
# 用 Credential Manager 标记缓存存在
cmdkey /generic:bookworm-secrets /user:bw /pass:cached 2>$null | Out-Null
# 用 HKCU 注册表存凭证值 (DPAPI 保护, 仅当前用户可读)
$regPath = "HKCU:\Software\Bookworm\CachedEnv"
if (-not (Test-Path $regPath)) { New-Item $regPath -Force | Out-Null }
$envKeys = @("ANTHROPIC_API_KEY", "ANTHROPIC_BASE_URL", "GITHUB_PERSONAL_ACCESS_TOKEN",
"SLACK_BOT_TOKEN", "ATLASSIAN_API_TOKEN", "BROWSERBASE_API_KEY", "FIRECRAWL_API_KEY")
foreach ($k in $envKeys) {
$v = [System.Environment]::GetEnvironmentVariable($k, "Process")
if ($v) { Set-ItemProperty $regPath -Name $k -Value $v -Force }
}
# 设置过期时间 (今日 23:59:59)
$expiry = (Get-Date).Date.AddDays(1).ToString("o")
Set-ItemProperty $regPath -Name "_expiry" -Value $expiry -Force
Write-Host " [OK] 凭证已缓存至今日 23:59 (下次免密)" -ForegroundColor Green
} catch {}
}
function Clear-SecretsCache {
cmdkey /delete:bookworm-secrets 2>$null | Out-Null
Remove-Item "HKCU:\Software\Bookworm" -Recurse -Force -ErrorAction SilentlyContinue
}
# ─── 依赖自动安装 ────────────────────────────────────
function Install-MissingDeps {
$missing = @()
if (-not (Test-Command "node")) { $missing += "Node.js" }
if (-not (Test-Command "git")) { $missing += "Git" }
if (-not (Test-Command "claude")) { $missing += "Claude Code" }
if ($missing.Count -eq 0) { return }
$hasWinget = Test-Command "winget"
Write-Host ""
Write-Host " 缺少以下软件: $($missing -join ', ')" -ForegroundColor Yellow
if ($hasWinget) {
$auto = Read-Host " 是否用 winget 自动安装? (y/n)"
if ($auto -eq 'y') {
if ($missing -contains "Node.js") {
Write-Host " 安装 Node.js..." -ForegroundColor Gray
winget install OpenJS.NodeJS.LTS --accept-source-agreements --accept-package-agreements 2>&1 | Select-Object -Last 3 | ForEach-Object { Write-Host " $_" }
# 刷新 PATH
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
}
if ($missing -contains "Git") {
Write-Host " 安装 Git..." -ForegroundColor Gray
winget install Git.Git --accept-source-agreements --accept-package-agreements 2>&1 | Select-Object -Last 3 | ForEach-Object { Write-Host " $_" }
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
}
if ($missing -contains "Claude Code" -and (Test-Command "npm")) {
Write-Host " 安装 Claude Code..." -ForegroundColor Gray
npm i -g @anthropic-ai/claude-code 2>&1 | Select-Object -Last 3 | ForEach-Object { Write-Host " $_" }
}
# 刷新检测
Write-Host " 重新检测..." -ForegroundColor Gray
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
}
} else {
Write-Host " 请手动安装后重新运行本脚本:" -ForegroundColor Yellow
if ($missing -contains "Node.js") { Write-Host " Node.js: https://nodejs.org" -ForegroundColor Gray }
if ($missing -contains "Git") { Write-Host " Git: https://git-scm.com" -ForegroundColor Gray }
if ($missing -contains "Claude Code") { Write-Host " Claude: npm i -g @anthropic-ai/claude-code" -ForegroundColor Gray }
exit 1
}
}
# ─── 桌面快捷方式 ────────────────────────────────────
function Create-DesktopShortcuts {
$desktop = [System.Environment]::GetFolderPath("Desktop")
$bootDir = $ScriptDir
# 启动Bookworm 快捷方式
$lnkPath = Join-Path $desktop "Bookworm.lnk"
if (-not (Test-Path $lnkPath)) {
try {
$shell = New-Object -ComObject WScript.Shell
$shortcut = $shell.CreateShortcut($lnkPath)
$batFile = Join-Path $bootDir "启动Bookworm.bat"
if (Test-Path $batFile) {
$shortcut.TargetPath = $batFile
} else {
$shortcut.TargetPath = "pwsh.exe"
$shortcut.Arguments = "-ExecutionPolicy Bypass -File `"$(Join-Path $bootDir 'install.ps1')`" -StartOnly"
}
$shortcut.WorkingDirectory = $bootDir
$shortcut.Description = "Bookworm Smart Assistant"
$shortcut.Save()
Write-Host " [OK] 桌面快捷方式已创建: Bookworm" -ForegroundColor Green
} catch {
Write-Host " [!] 桌面快捷方式创建失败 (不影响使用)" -ForegroundColor Gray
}
}
}
function Decrypt-Secrets {
if ($SkipSecrets -or -not (Test-Path $SecretsEnc)) {
Write-Host " [!] 跳过凭证解密 (无 secrets.enc)" -ForegroundColor Yellow
@ -222,12 +347,17 @@ foreach ($c in $checks) {
$color = if ($c.OK) { "Green" } else { "Red" }
Write-Host " $icon $($c.Name)" -ForegroundColor $color
}
if (-not (Test-Command "claude") -or -not (Test-Command "node") -or -not (Test-Command "git")) {
Install-MissingDeps
}
# 再次验证
if (-not (Test-Command "claude")) {
Write-Host "`n [ABORT] Claude Code 未安装,请先安装后重试" -ForegroundColor Red
Write-Host "`n [ABORT] Claude Code 未安装" -ForegroundColor Red
Write-Host " 安装: npm i -g @anthropic-ai/claude-code" -ForegroundColor Gray
exit 1
}
if (-not (Test-Command "node")) {
Write-Host "`n [ABORT] Node.js 未安装Bookworm Hooks 无法运行" -ForegroundColor Red
Write-Host "`n [ABORT] Node.js 未安装" -ForegroundColor Red
exit 1
}
@ -235,9 +365,29 @@ if (-not (Test-Command "node")) {
Write-Host "`n[2/6] 代理检测..." -ForegroundColor White
Detect-SystemProxy
# 步骤 3: 解密凭证 (进程级环境变量,不写磁盘)
# 步骤 3: 解密凭证 (优先使用本日缓存)
Write-Host "`n[3/6] 解密凭证..." -ForegroundColor White
Decrypt-Secrets
# 检查缓存是否过期
$cacheExpiry = $null
try {
$cacheExpiry = Get-ItemProperty "HKCU:\Software\Bookworm\CachedEnv" -Name "_expiry" -ErrorAction SilentlyContinue
} catch {}
$cacheValid = $false
if ($cacheExpiry -and $cacheExpiry._expiry) {
try { $cacheValid = [datetime]$cacheExpiry._expiry -gt (Get-Date) } catch {}
}
if ($cacheValid -and (Get-CachedSecrets)) {
# 缓存有效,跳过解密
} else {
Clear-SecretsCache
Decrypt-Secrets
# 解密成功后询问是否缓存
if ($env:ANTHROPIC_API_KEY) {
$cache = Read-Host " 今日内免密启动? (y/n)"
if ($cache -eq 'y') { Save-SecretsToCache }
}
}
# 自动配置 git credential helper (避免 clone 时反复要密码)
$prevEAP = $ErrorActionPreference
@ -536,4 +686,14 @@ if ($allOK) {
}
Write-Host ""
# 首次安装: 创建桌面快捷方式 + 打开使用教程
if (-not $StartOnly) {
Create-DesktopShortcuts
$guidePath = Join-Path $ScriptDir "guide.html"
if (Test-Path $guidePath) {
Start-Process $guidePath
Write-Host " [OK] 使用教程已在浏览器打开" -ForegroundColor Gray
}
}
& claude

View File

@ -55,8 +55,14 @@ foreach ($v in $envVars) {
}
Write-Host " [OK] 环境变量已清除" -ForegroundColor Green
# 3. 清除 Git 凭证缓存
Write-Host "[3/5] 清除 Git 凭证缓存..." -ForegroundColor White
# 3. 清除凭证缓存 (Credential Manager + 注册表)
Write-Host "[3/5] 清除凭证缓存..." -ForegroundColor White
cmdkey /delete:bookworm-secrets 2>$null | Out-Null
Remove-Item "HKCU:\Software\Bookworm" -Recurse -Force -ErrorAction SilentlyContinue
Write-Host " 清除: Bookworm 本日免密缓存" -ForegroundColor Gray
# 4. 清除 Git 凭证缓存
Write-Host "[4/5] 清除 Git 凭证缓存..." -ForegroundColor White
$gitCredTargets = @("git:https://code.letcareme.com", "git:http://8.138.11.105", "git:https://8.138.11.105")
foreach ($target in $gitCredTargets) {
$exists = cmdkey /list 2>$null | Select-String $target

47
卸载Bookworm.bat Normal file
View File

@ -0,0 +1,47 @@
@echo off
chcp 65001 > nul
title Bookworm Portable - 卸载
cd /d "%~dp0"
echo.
echo ====================================
echo Bookworm Portable - 完整卸载
echo ====================================
echo.
echo 将执行:
echo - 终止 Claude Code 进程
echo - 清除所有环境变量和凭证缓存
echo - 恢复原始 .claude 目录
echo - 清除 PowerShell 历史和 Git 凭证
echo - 删除桌面快捷方式
echo.
set /p confirm=" 确认卸载? (y/n): "
if /i not "%confirm%"=="y" (
echo 已取消
pause
exit /b
)
echo.
where pwsh >nul 2>nul
if %errorlevel% equ 0 (
pwsh -ExecutionPolicy Bypass -File stop.ps1 -Restore -Deep
) else (
powershell -ExecutionPolicy Bypass -File stop.ps1 -Restore -Deep
)
:: 删除桌面快捷方式
del "%USERPROFILE%\Desktop\Bookworm.lnk" 2>nul
:: 清除凭证缓存注册表
reg delete "HKCU\Software\Bookworm" /f 2>nul
echo.
echo ====================================
echo Bookworm 已完全卸载
echo 可安全删除 bookworm-boot 文件夹
echo ====================================
echo.
pause