bookworm-smart-assistant/scripts/sync/1-pack-and-serve.ps1

137 lines
4.9 KiB
PowerShell
Raw Permalink Normal View History

# =============================================================================
# Bookworm .claude 同步 - 阶段 1: 本机打包 + HTTP 服务
# 在源机器 (leesu) 上运行
# =============================================================================
[CmdletBinding()]
param(
[string]$SourceUser = $env:USERNAME,
[int]$Port = 8765,
[switch]$NoServe # 加这个开关只打包不起服务
)
$ErrorActionPreference = 'Stop'
$src = "C:\Users\$SourceUser\.claude"
$staging = "$env:TEMP\claude-sync-staging"
$zip = "$env:TEMP\claude-sync.zip"
if (-not (Test-Path $src)) {
Write-Host "❌ 源目录不存在: $src" -ForegroundColor Red
exit 1
}
Write-Host "==================== 阶段 1: 打包 ====================" -ForegroundColor Cyan
Write-Host "源: $src"
Write-Host "目标 zip: $zip"
Write-Host ""
# ---------- 1) 清理旧暂存 ----------
Write-Host "[1/5] 清理旧暂存..." -ForegroundColor Yellow
Remove-Item $staging, $zip -Recurse -Force -ErrorAction SilentlyContinue
New-Item $staging -ItemType Directory -Force | Out-Null
# ---------- 2) 构建排除列表 ----------
Write-Host "[2/5] 构建排除列表..." -ForegroundColor Yellow
# 必排除目录 (顶层)
$excludeTopDirs = @(
"$src\.git",
"$src\node_modules",
"$src\.skill-cache"
)
# 排除每个 mcp-server 下的 .venv / __pycache__ / node_modules (保留源码)
$mcpExcludes = @()
if (Test-Path "$src\mcp-servers") {
Get-ChildItem "$src\mcp-servers" -Directory | ForEach-Object {
$mcpExcludes += "$($_.FullName)\.venv"
$mcpExcludes += "$($_.FullName)\__pycache__"
$mcpExcludes += "$($_.FullName)\node_modules"
}
}
# 排除每个 skill 下的 node_modules / dist / .git (保留源码)
$skillExcludes = @()
if (Test-Path "$src\skills") {
Get-ChildItem "$src\skills" -Directory | ForEach-Object {
$skillExcludes += "$($_.FullName)\node_modules"
$skillExcludes += "$($_.FullName)\dist"
$skillExcludes += "$($_.FullName)\.git"
}
}
# 排除文件类型
$excludeFiles = @(
'*.dpapi.json', # DPAPI 机器绑定,无法跨机器解密
'*.bak.*', # 临时备份文件
'Thumbs.db','desktop.ini' # OS 残留
)
$xdArgs = $excludeTopDirs + $mcpExcludes + $skillExcludes
# ---------- 3) robocopy 复制 ----------
Write-Host "[3/5] 复制中(约 1-3 分钟)..." -ForegroundColor Yellow
$rcArgs = @($src, $staging, '/E', '/XD') + $xdArgs + @('/XF') + $excludeFiles + @('/NFL','/NDL','/NJH','/NJS','/NC','/NS','/NP','/R:1','/W:1')
$rcExit = (Start-Process robocopy -ArgumentList $rcArgs -NoNewWindow -Wait -PassThru).ExitCode
# robocopy exit code < 8 都是成功
if ($rcExit -ge 8) {
Write-Host "❌ robocopy 失败 (exit=$rcExit)" -ForegroundColor Red
exit 1
}
# 排除 hooks 测试 / 归档 / 废弃
Remove-Item "$staging\hooks\__tests__","$staging\hooks\archive","$staging\hooks\deprecated" -Recurse -Force -ErrorAction SilentlyContinue
# 统计
$stat = Get-ChildItem $staging -Recurse -File -ErrorAction SilentlyContinue | Measure-Object Length -Sum
Write-Host " 暂存: $([Math]::Round($stat.Sum / 1MB, 1)) MB / $($stat.Count) 文件"
# ---------- 4) 压缩 ----------
Write-Host "[4/5] 压缩中(文件多时 2-5 分钟)..." -ForegroundColor Yellow
Compress-Archive -Path "$staging\*" -DestinationPath $zip -Force -CompressionLevel Optimal
$zipSize = [Math]::Round((Get-Item $zip).Length / 1MB, 1)
Write-Host "$zip ($zipSize MB)" -ForegroundColor Green
# ---------- 5) 起 HTTP 服务 ----------
if ($NoServe) {
Write-Host "[5/5] 跳过 HTTP 服务(-NoServe 已指定)" -ForegroundColor Yellow
Write-Host ""
Write-Host "✅ 打包完成。手动传输 $zip 到目标机器即可。" -ForegroundColor Green
exit 0
}
Write-Host "[5/5] 启动 HTTP 服务..." -ForegroundColor Yellow
# 获取本机 LAN IP
$lanIP = (Get-NetIPAddress -AddressFamily IPv4 |
Where-Object {
$_.IPAddress -notlike '169.254.*' -and
$_.IPAddress -ne '127.0.0.1' -and
$_.IPAddress -notlike '198.18.*' -and
$_.IPAddress -notlike '172.*'
} |
Select-Object -First 1).IPAddress
Write-Host ""
Write-Host "================ 服务就绪 ================" -ForegroundColor Green
Write-Host " 目标机器请运行 2-pull-and-rebuild.ps1"
Write-Host " 或手动下载: " -NoNewline
Write-Host "http://${lanIP}:${Port}/claude-sync.zip" -ForegroundColor Cyan
Write-Host ""
Write-Host " 传输完成后回到此窗口按 Ctrl+C 停止服务" -ForegroundColor Yellow
Write-Host "==========================================" -ForegroundColor Green
Write-Host ""
# 切到 TEMP 目录起服务
Push-Location $env:TEMP
try {
python -m http.server $Port
} finally {
Pop-Location
Write-Host ""
Write-Host "🧹 清理暂存..." -ForegroundColor Yellow
Remove-Item $staging -Recurse -Force -ErrorAction SilentlyContinue
Write-Host "✅ 暂存已清。zip 保留在: $zip" -ForegroundColor Green
}