96 lines
6.7 KiB
PowerShell
96 lines
6.7 KiB
PowerShell
# Python bootstrap shared by the Windows launcher and its isolated checks.
|
|
# Save as UTF-8 with BOM so Windows PowerShell 5.1 reads Chinese messages correctly.
|
|
|
|
function Get-BootstrapText {
|
|
param([string]$English, [string]$Chinese)
|
|
if ($env:ARTEMIS_LAUNCH_LANG -eq 'zh-CN') { return $Chinese }
|
|
return $English
|
|
}
|
|
|
|
function Initialize-ArtemisPython {
|
|
param([Parameter(Mandatory=$true)][string]$ProjectRoot, [switch]$RuntimeOnly)
|
|
|
|
$ProjectRoot = (Resolve-Path -LiteralPath $ProjectRoot -ErrorAction Stop).Path
|
|
if (-not (Test-Path -LiteralPath (Join-Path $ProjectRoot 'pyproject.toml'))) {
|
|
throw (Get-BootstrapText 'pyproject.toml is missing. Extract the complete source archive first.' '缺少 pyproject.toml;请重新解压完整源码包。')
|
|
}
|
|
if (-not (Test-Path -LiteralPath (Join-Path $ProjectRoot 'uv.lock'))) {
|
|
throw (Get-BootstrapText 'uv.lock is missing. Extract the complete source archive first.' '缺少 uv.lock;请重新解压完整源码包。')
|
|
}
|
|
|
|
if (-not (Test-CommandExists 'uv')) {
|
|
if ($ArtemisDownloads -and $ArtemisDownloads.python_index) {
|
|
Write-Host (Get-BootstrapText ' [INSTALL] Installing uv from the selected Python mirror...' ' [安装] 正在从选定的 Python 镜像安装 uv...') -ForegroundColor Cyan
|
|
Install-ArtemisUvFromIndex -IndexUrl $ArtemisDownloads.python_index
|
|
} else {
|
|
Write-Host (Get-BootstrapText ' [INSTALL] uv was not found. Installing from the configured installer...' ' [安装] 未找到 uv,正在下载安装...') -ForegroundColor Cyan
|
|
$installer = Join-Path ([IO.Path]::GetTempPath()) ('artemis-uv-' + [guid]::NewGuid().ToString('N') + '.ps1')
|
|
try {
|
|
$installerUrl = if ($ArtemisDownloads) { $ArtemisDownloads.uv_installer_url } else { 'https://astral.sh/uv/install.ps1' }
|
|
if (-not (Invoke-DownloadFile -Uri $installerUrl -OutFile $installer)) {
|
|
throw (Get-BootstrapText 'Could not download uv. Check your network/proxy and retry.' 'uv 下载失败;请检查网络、代理或镜像后重试。')
|
|
}
|
|
& powershell.exe -NoProfile -ExecutionPolicy Bypass -File $installer | Out-Host
|
|
if ($LASTEXITCODE -ne 0) { throw (Get-BootstrapText "uv installation failed (exit $LASTEXITCODE)." "uv 安装失败(退出码 $LASTEXITCODE)。") }
|
|
} finally {
|
|
Remove-Item -LiteralPath $installer -Force -ErrorAction SilentlyContinue
|
|
}
|
|
}
|
|
Update-EnvironmentPath
|
|
} else {
|
|
Write-Host (Get-BootstrapText ' [SKIP] uv is already installed.' ' [复用] uv 已安装,跳过下载。') -ForegroundColor Green
|
|
}
|
|
if (-not (Test-CommandExists 'uv')) { throw (Get-BootstrapText 'uv is still unavailable. Install it from https://astral.sh/uv/ and retry.' '仍无法运行 uv;请检查安装并重试。') }
|
|
& uv --version | Out-Host
|
|
if ($LASTEXITCODE -ne 0) { throw (Get-BootstrapText 'The installed uv could not run. Repair its installation and retry.' '已安装的 uv 无法运行;请修复安装后重试。') }
|
|
|
|
$venvDir = Join-Path $ProjectRoot '.venv'
|
|
$pythonExe = Join-Path $venvDir 'Scripts\python.exe'
|
|
$previousEnvironment = $env:UV_PROJECT_ENVIRONMENT
|
|
$env:UV_PROJECT_ENVIRONMENT = $venvDir
|
|
Push-Location -LiteralPath $ProjectRoot
|
|
try {
|
|
if (-not (Test-Path -LiteralPath $venvDir)) {
|
|
Write-Host (Get-BootstrapText ' [INSTALL] Creating .venv with Python 3.12 (downloaded automatically if needed)...' ' [安装] 正在创建 Python 3.12 虚拟环境 .venv;缺少 Python 时自动下载...') -ForegroundColor Cyan
|
|
& uv venv --python 3.12 $venvDir | Out-Host
|
|
if ($LASTEXITCODE -ne 0) { throw (Get-BootstrapText 'Could not create .venv. Check the download errors above and retry.' '.venv 创建失败;请查看上方下载错误并重试。') }
|
|
} else {
|
|
Write-Host (Get-BootstrapText ' [SKIP] Reusing the existing project .venv.' ' [复用] 已有项目 .venv,跳过创建。') -ForegroundColor Green
|
|
}
|
|
if (-not (Test-Path -LiteralPath $pythonExe)) {
|
|
throw (Get-BootstrapText 'The existing .venv is incomplete. Rename it as a backup, then rerun start.bat.' '已有 .venv 不完整。先重命名备份,再运行 start-cn.bat。')
|
|
}
|
|
& $pythonExe -c 'import sys; sys.exit(0 if sys.version_info >= (3, 12) and sys.prefix != sys.base_prefix else 1)' | Out-Host
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw (Get-BootstrapText 'The existing .venv is unusable or older than Python 3.12. Rename it as a backup, then rerun start.bat.' '已有 .venv 无法使用或 Python 低于 3.12。先重命名备份,再运行 start-cn.bat。')
|
|
}
|
|
|
|
# The frozen source updater uses only Python's standard library. Install
|
|
# project dependencies once, from the new lock file AFTER the fast-forward.
|
|
if ($RuntimeOnly) { return $pythonExe }
|
|
|
|
# A cheap check skips installation when the lock and installed packages agree.
|
|
# --inexact preserves any optional development tools already installed.
|
|
$lockOption = if ($ArtemisDownloads -and $ArtemisDownloads.python_index) { '--frozen' } else { '--locked' }
|
|
& uv sync --check $lockOption --no-dev --inexact --quiet 2>$null | Out-Host
|
|
if ($LASTEXITCODE -eq 0) {
|
|
Write-Host (Get-BootstrapText ' [SKIP] Python dependencies are already ready.' ' [复用] Python 依赖已就绪。') -ForegroundColor Green
|
|
} else {
|
|
Write-Host (Get-BootstrapText ' [INSTALL] Synchronizing dependencies from uv.lock...' ' [安装] 正在按 uv.lock 同步 Python 依赖...') -ForegroundColor Cyan
|
|
if ($ArtemisDownloads -and $ArtemisDownloads.python_index) {
|
|
Install-ArtemisLockedDependencies -PythonExe $pythonExe -IndexUrl $ArtemisDownloads.python_index
|
|
} else {
|
|
& uv sync --locked --no-dev --inexact | Out-Host
|
|
if ($LASTEXITCODE -ne 0) { throw (Get-BootstrapText 'Dependency installation failed. Fix the error above and rerun start.bat.' '依赖安装失败;请处理上方错误,再运行 start-cn.bat。') }
|
|
}
|
|
}
|
|
& $pythonExe -c 'import artemis, uvicorn, fastapi, langchain_openai' | Out-Host
|
|
if ($LASTEXITCODE -ne 0) { throw (Get-BootstrapText 'Python dependency verification failed. The UI will not be started.' 'Python 依赖验证失败,网页不会启动。') }
|
|
Write-Host (Get-BootstrapText ' [OK] Python environment is ready.' ' [完成] Python 环境已就绪。') -ForegroundColor Green
|
|
return $pythonExe
|
|
} finally {
|
|
Pop-Location
|
|
$env:UV_PROJECT_ENVIRONMENT = $previousEnvironment
|
|
}
|
|
}
|