fix quickstart guide for windows (#6264)
* fix(windows): verify uv is runnable before launch * fix(windows): use validated uv path for kimi health check * fix(windows): dedupe uv discovery and keep quickstart scoped * chore: refresh uv lockfile
This commit is contained in:
committed by
GitHub
parent
36dcf2025b
commit
4a4f17ed40
@@ -10,6 +10,9 @@
|
|||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
|
||||||
|
$UvHelperPath = Join-Path $ScriptDir "scripts\uv-discovery.ps1"
|
||||||
|
|
||||||
|
. $UvHelperPath
|
||||||
|
|
||||||
# ── Validate project directory ──────────────────────────────────────
|
# ── Validate project directory ──────────────────────────────────────
|
||||||
|
|
||||||
@@ -30,16 +33,12 @@ if (-not (Test-Path (Join-Path $ScriptDir ".venv"))) {
|
|||||||
|
|
||||||
# ── Ensure uv is available ──────────────────────────────────────────
|
# ── Ensure uv is available ──────────────────────────────────────────
|
||||||
|
|
||||||
if (-not (Get-Command uv -ErrorAction SilentlyContinue)) {
|
$uvInfo = Get-WorkingUvInfo
|
||||||
# Check default install location before giving up
|
if (-not $uvInfo) {
|
||||||
$uvExe = Join-Path $env:USERPROFILE ".local\bin\uv.exe"
|
Write-Error "uv is not installed or is not runnable. Run .\quickstart.ps1 first."
|
||||||
if (Test-Path $uvExe) {
|
|
||||||
$env:Path = (Split-Path $uvExe) + ";" + $env:Path
|
|
||||||
} else {
|
|
||||||
Write-Error "uv is not installed. Run .\quickstart.ps1 first."
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
$uvExe = $uvInfo.Path
|
||||||
|
|
||||||
# ── Load environment variables from Windows Registry ────────────────
|
# ── Load environment variables from Windows Registry ────────────────
|
||||||
# Windows stores User-level env vars in the registry. New terminal
|
# Windows stores User-level env vars in the registry. New terminal
|
||||||
@@ -80,4 +79,4 @@ if (-not $env:HIVE_CREDENTIAL_KEY) {
|
|||||||
# ── Run the Hive CLI ────────────────────────────────────────────────
|
# ── Run the Hive CLI ────────────────────────────────────────────────
|
||||||
# PYTHONUTF8=1: use UTF-8 for default encoding (fixes charmap decode errors on Windows)
|
# PYTHONUTF8=1: use UTF-8 for default encoding (fixes charmap decode errors on Windows)
|
||||||
$env:PYTHONUTF8 = "1"
|
$env:PYTHONUTF8 = "1"
|
||||||
& uv run hive @args
|
& $uvExe run hive @args
|
||||||
|
|||||||
+26
-26
@@ -18,6 +18,10 @@
|
|||||||
# Use "Continue" so stderr from external tools (uv, python) does not
|
# Use "Continue" so stderr from external tools (uv, python) does not
|
||||||
# terminate the script. Errors are handled via $LASTEXITCODE checks.
|
# terminate the script. Errors are handled via $LASTEXITCODE checks.
|
||||||
$ErrorActionPreference = "Continue"
|
$ErrorActionPreference = "Continue"
|
||||||
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
|
||||||
|
$UvHelperPath = Join-Path $ScriptDir "scripts\uv-discovery.ps1"
|
||||||
|
|
||||||
|
. $UvHelperPath
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Colors / helpers
|
# Colors / helpers
|
||||||
@@ -95,7 +99,6 @@ function Prompt-Choice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Windows Defender Exclusion Functions
|
# Windows Defender Exclusion Functions
|
||||||
# ============================================================
|
# ============================================================
|
||||||
@@ -276,9 +279,6 @@ function Add-DefenderExclusions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get the directory where this script lives
|
|
||||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Banner
|
# Banner
|
||||||
# ============================================================
|
# ============================================================
|
||||||
@@ -352,10 +352,10 @@ Write-Host ""
|
|||||||
# Check / install uv
|
# Check / install uv
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
$uvCmd = Get-Command uv -ErrorAction SilentlyContinue
|
$uvInfo = Get-WorkingUvInfo
|
||||||
|
|
||||||
# If uv not in PATH, check if it exists in default location
|
# If uv not in PATH, check if it exists in default location
|
||||||
if (-not $uvCmd) {
|
if (-not $uvInfo) {
|
||||||
$uvDir = Join-Path $env:USERPROFILE ".local\bin"
|
$uvDir = Join-Path $env:USERPROFILE ".local\bin"
|
||||||
$uvExePath = Join-Path $uvDir "uv.exe"
|
$uvExePath = Join-Path $uvDir "uv.exe"
|
||||||
|
|
||||||
@@ -371,16 +371,16 @@ if (-not $uvCmd) {
|
|||||||
|
|
||||||
# Refresh PATH for current session
|
# Refresh PATH for current session
|
||||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "User") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "Machine")
|
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "User") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "Machine")
|
||||||
$uvCmd = Get-Command uv -ErrorAction SilentlyContinue
|
$uvInfo = Get-WorkingUvInfo
|
||||||
|
|
||||||
if ($uvCmd) {
|
if ($uvInfo) {
|
||||||
Write-Ok "uv is now in PATH"
|
Write-Ok "uv is now in PATH"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# If still not found, install it
|
# If still not found, install it
|
||||||
if (-not $uvCmd) {
|
if (-not $uvInfo) {
|
||||||
Write-Warn "uv not found. Installing..."
|
Write-Warn "uv not found. Installing..."
|
||||||
try {
|
try {
|
||||||
# Official uv installer for Windows
|
# Official uv installer for Windows
|
||||||
@@ -397,13 +397,13 @@ if (-not $uvCmd) {
|
|||||||
|
|
||||||
# Refresh PATH for current session
|
# Refresh PATH for current session
|
||||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "User") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "Machine")
|
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "User") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "Machine")
|
||||||
$uvCmd = Get-Command uv -ErrorAction SilentlyContinue
|
$uvInfo = Get-WorkingUvInfo
|
||||||
} catch {
|
} catch {
|
||||||
Write-Color -Text "Error: uv installation failed" -Color Red
|
Write-Color -Text "Error: uv installation failed" -Color Red
|
||||||
Write-Host "Please install uv manually from https://astral.sh/uv/"
|
Write-Host "Please install uv manually from https://astral.sh/uv/"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
if (-not $uvCmd) {
|
if (-not $uvInfo) {
|
||||||
Write-Color -Text "Error: uv not found after installation" -Color Red
|
Write-Color -Text "Error: uv not found after installation" -Color Red
|
||||||
Write-Host "Please close and reopen PowerShell, then run this script again."
|
Write-Host "Please close and reopen PowerShell, then run this script again."
|
||||||
Write-Host "Or install uv manually from https://astral.sh/uv/"
|
Write-Host "Or install uv manually from https://astral.sh/uv/"
|
||||||
@@ -412,8 +412,8 @@ if (-not $uvCmd) {
|
|||||||
Write-Ok "uv installed successfully"
|
Write-Ok "uv installed successfully"
|
||||||
}
|
}
|
||||||
|
|
||||||
$uvVersion = & uv --version
|
$UvCmd = $uvInfo.Path
|
||||||
Write-Ok "uv detected: $uvVersion"
|
Write-Ok "uv detected: $($uvInfo.Version)"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
|
|
||||||
# Check for Node.js (needed for frontend dashboard)
|
# Check for Node.js (needed for frontend dashboard)
|
||||||
@@ -503,7 +503,7 @@ try {
|
|||||||
if (Test-Path "pyproject.toml") {
|
if (Test-Path "pyproject.toml") {
|
||||||
Write-Host " Installing workspace packages... " -NoNewline
|
Write-Host " Installing workspace packages... " -NoNewline
|
||||||
|
|
||||||
$syncOutput = & uv sync 2>&1
|
$syncOutput = & $UvCmd sync 2>&1
|
||||||
$syncExitCode = $LASTEXITCODE
|
$syncExitCode = $LASTEXITCODE
|
||||||
|
|
||||||
if ($syncExitCode -eq 0) {
|
if ($syncExitCode -eq 0) {
|
||||||
@@ -518,9 +518,9 @@ try {
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check for Chrome/Edge (required for GCU browser tools)
|
# Keep browser setup scoped to detecting the system browser used by GCU.
|
||||||
Write-Host " Checking for Chrome/Edge browser... " -NoNewline
|
Write-Host " Checking for Chrome/Edge browser... " -NoNewline
|
||||||
$null = & uv run python -c "from gcu.browser.chrome_finder import find_chrome; assert find_chrome()" 2>&1
|
$null = & $UvCmd run python -c "from gcu.browser.chrome_finder import find_chrome; assert find_chrome()" 2>&1
|
||||||
$chromeCheckExit = $LASTEXITCODE
|
$chromeCheckExit = $LASTEXITCODE
|
||||||
if ($chromeCheckExit -eq 0) {
|
if ($chromeCheckExit -eq 0) {
|
||||||
Write-Ok "ok"
|
Write-Ok "ok"
|
||||||
@@ -720,7 +720,7 @@ $imports = @(
|
|||||||
$modulesToCheck = @("framework", "aden_tools", "litellm")
|
$modulesToCheck = @("framework", "aden_tools", "litellm")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$checkOutput = & uv run python scripts/check_requirements.py @modulesToCheck 2>&1 | Out-String
|
$checkOutput = & $UvCmd run python scripts/check_requirements.py @modulesToCheck 2>&1 | Out-String
|
||||||
$resultJson = $null
|
$resultJson = $null
|
||||||
|
|
||||||
# Try to parse JSON result
|
# Try to parse JSON result
|
||||||
@@ -1091,7 +1091,7 @@ switch ($num) {
|
|||||||
Write-Warn "Codex credentials not found. Starting OAuth login..."
|
Write-Warn "Codex credentials not found. Starting OAuth login..."
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
try {
|
try {
|
||||||
& uv run python (Join-Path $ScriptDir "core\codex_oauth.py") 2>&1
|
& $UvCmd run python (Join-Path $ScriptDir "core\codex_oauth.py") 2>&1
|
||||||
if ($LASTEXITCODE -eq 0) {
|
if ($LASTEXITCODE -eq 0) {
|
||||||
$CodexCredDetected = $true
|
$CodexCredDetected = $true
|
||||||
} else {
|
} else {
|
||||||
@@ -1164,7 +1164,7 @@ switch ($num) {
|
|||||||
# Health check the new key
|
# Health check the new key
|
||||||
Write-Host " Verifying API key... " -NoNewline
|
Write-Host " Verifying API key... " -NoNewline
|
||||||
try {
|
try {
|
||||||
$hcResult = & uv run python (Join-Path $ScriptDir "scripts/check_llm_key.py") $SelectedProviderId $apiKey 2>$null
|
$hcResult = & $UvCmd run python (Join-Path $ScriptDir "scripts/check_llm_key.py") $SelectedProviderId $apiKey 2>$null
|
||||||
$hcJson = $hcResult | ConvertFrom-Json
|
$hcJson = $hcResult | ConvertFrom-Json
|
||||||
if ($hcJson.valid -eq $true) {
|
if ($hcJson.valid -eq $true) {
|
||||||
Write-Color -Text "ok" -Color Green
|
Write-Color -Text "ok" -Color Green
|
||||||
@@ -1239,7 +1239,7 @@ if ($SubscriptionMode -eq "zai_code") {
|
|||||||
# Health check the new key
|
# Health check the new key
|
||||||
Write-Host " Verifying ZAI API key... " -NoNewline
|
Write-Host " Verifying ZAI API key... " -NoNewline
|
||||||
try {
|
try {
|
||||||
$hcResult = & uv run python (Join-Path $ScriptDir "scripts/check_llm_key.py") "zai" $apiKey "https://api.z.ai/api/coding/paas/v4" 2>$null
|
$hcResult = & $UvCmd run python (Join-Path $ScriptDir "scripts/check_llm_key.py") "zai" $apiKey "https://api.z.ai/api/coding/paas/v4" 2>$null
|
||||||
$hcJson = $hcResult | ConvertFrom-Json
|
$hcJson = $hcResult | ConvertFrom-Json
|
||||||
if ($hcJson.valid -eq $true) {
|
if ($hcJson.valid -eq $true) {
|
||||||
Write-Color -Text "ok" -Color Green
|
Write-Color -Text "ok" -Color Green
|
||||||
@@ -1307,7 +1307,7 @@ if ($SubscriptionMode -eq "kimi_code") {
|
|||||||
# Health check the new key
|
# Health check the new key
|
||||||
Write-Host " Verifying Kimi API key... " -NoNewline
|
Write-Host " Verifying Kimi API key... " -NoNewline
|
||||||
try {
|
try {
|
||||||
$hcResult = & uv run python (Join-Path $ScriptDir "scripts/check_llm_key.py") "kimi" $apiKey "https://api.kimi.com/coding" 2>$null
|
$hcResult = & $UvCmd run python (Join-Path $ScriptDir "scripts/check_llm_key.py") "kimi" $apiKey "https://api.kimi.com/coding" 2>$null
|
||||||
$hcJson = $hcResult | ConvertFrom-Json
|
$hcJson = $hcResult | ConvertFrom-Json
|
||||||
if ($hcJson.valid -eq $true) {
|
if ($hcJson.valid -eq $true) {
|
||||||
Write-Color -Text "ok" -Color Green
|
Write-Color -Text "ok" -Color Green
|
||||||
@@ -1459,7 +1459,7 @@ if ($credKey) {
|
|||||||
} else {
|
} else {
|
||||||
Write-Host " Generating encryption key... " -NoNewline
|
Write-Host " Generating encryption key... " -NoNewline
|
||||||
try {
|
try {
|
||||||
$generatedKey = & uv run python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" 2>$null
|
$generatedKey = & $UvCmd run python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" 2>$null
|
||||||
if ($LASTEXITCODE -eq 0 -and $generatedKey) {
|
if ($LASTEXITCODE -eq 0 -and $generatedKey) {
|
||||||
Write-Ok "ok"
|
Write-Ok "ok"
|
||||||
$generatedKey = $generatedKey.Trim()
|
$generatedKey = $generatedKey.Trim()
|
||||||
@@ -1508,7 +1508,7 @@ if ($credKey) {
|
|||||||
Write-Ok "Credential store initialized at ~/.hive/credentials/"
|
Write-Ok "Credential store initialized at ~/.hive/credentials/"
|
||||||
|
|
||||||
Write-Host " Verifying credential store... " -NoNewline
|
Write-Host " Verifying credential store... " -NoNewline
|
||||||
$verifyOut = & uv run python -c "from framework.credentials.storage import EncryptedFileStorage; storage = EncryptedFileStorage(); print('ok')" 2>$null
|
$verifyOut = & $UvCmd run python -c "from framework.credentials.storage import EncryptedFileStorage; storage = EncryptedFileStorage(); print('ok')" 2>$null
|
||||||
if ($verifyOut -match "ok") {
|
if ($verifyOut -match "ok") {
|
||||||
Write-Ok "ok"
|
Write-Ok "ok"
|
||||||
} else {
|
} else {
|
||||||
@@ -1529,7 +1529,7 @@ $verifyErrors = 0
|
|||||||
$verifyModules = @("framework", "aden_tools")
|
$verifyModules = @("framework", "aden_tools")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$verifyOutput = & uv run python scripts/check_requirements.py @verifyModules 2>&1 | Out-String
|
$verifyOutput = & $UvCmd run python scripts/check_requirements.py @verifyModules 2>&1 | Out-String
|
||||||
$verifyJson = $null
|
$verifyJson = $null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -1539,7 +1539,7 @@ try {
|
|||||||
# Fall back to basic checks if JSON parsing fails
|
# Fall back to basic checks if JSON parsing fails
|
||||||
foreach ($mod in $verifyModules) {
|
foreach ($mod in $verifyModules) {
|
||||||
Write-Host " $([char]0x2B21) $mod... " -NoNewline
|
Write-Host " $([char]0x2B21) $mod... " -NoNewline
|
||||||
$null = & uv run python -c "import $mod" 2>&1
|
$null = & $UvCmd run python -c "import $mod" 2>&1
|
||||||
if ($LASTEXITCODE -eq 0) { Write-Ok "ok" }
|
if ($LASTEXITCODE -eq 0) { Write-Ok "ok" }
|
||||||
else { Write-Fail "failed"; $verifyErrors++ }
|
else { Write-Fail "failed"; $verifyErrors++ }
|
||||||
}
|
}
|
||||||
@@ -1559,7 +1559,7 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Write-Host " $([char]0x2B21) litellm... " -NoNewline
|
Write-Host " $([char]0x2B21) litellm... " -NoNewline
|
||||||
$null = & uv run python -c "import litellm" 2>&1
|
$null = & $UvCmd run python -c "import litellm" 2>&1
|
||||||
if ($LASTEXITCODE -eq 0) { Write-Ok "ok" } else { Write-Warn "skipped" }
|
if ($LASTEXITCODE -eq 0) { Write-Ok "ok" } else { Write-Warn "skipped" }
|
||||||
|
|
||||||
Write-Host " $([char]0x2B21) MCP config... " -NoNewline
|
Write-Host " $([char]0x2B21) MCP config... " -NoNewline
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
function Get-WorkingUvInfo {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Find a runnable uv executable, not just a PATH entry named "uv"
|
||||||
|
.OUTPUTS
|
||||||
|
Hashtable with Path and Version, or $null if no working uv is found
|
||||||
|
#>
|
||||||
|
# pyenv-win can expose a uv shim that exists on PATH but fails at runtime.
|
||||||
|
# Verify each candidate with `uv --version` before trusting it.
|
||||||
|
$candidates = @()
|
||||||
|
|
||||||
|
$commands = @(Get-Command uv -All -ErrorAction SilentlyContinue)
|
||||||
|
foreach ($cmd in $commands) {
|
||||||
|
if ($cmd.Source) {
|
||||||
|
$candidates += $cmd.Source
|
||||||
|
} elseif ($cmd.Definition) {
|
||||||
|
$candidates += $cmd.Definition
|
||||||
|
} elseif ($cmd.Name) {
|
||||||
|
$candidates += $cmd.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$defaultUvExe = Join-Path $env:USERPROFILE ".local\bin\uv.exe"
|
||||||
|
if (Test-Path $defaultUvExe) {
|
||||||
|
$candidates += $defaultUvExe
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($candidate in ($candidates | Where-Object { $_ } | Select-Object -Unique)) {
|
||||||
|
try {
|
||||||
|
$versionOutput = & $candidate --version 2>$null
|
||||||
|
$version = ($versionOutput | Out-String).Trim()
|
||||||
|
if ($LASTEXITCODE -eq 0 -and -not [string]::IsNullOrWhiteSpace($version)) {
|
||||||
|
return @{
|
||||||
|
Path = $candidate
|
||||||
|
Version = $version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
# Try the next candidate.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $null
|
||||||
|
}
|
||||||
@@ -832,7 +832,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "framework"
|
name = "framework"
|
||||||
version = "0.5.1"
|
version = "0.7.1"
|
||||||
source = { editable = "core" }
|
source = { editable = "core" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "anthropic" },
|
{ name = "anthropic" },
|
||||||
|
|||||||
Reference in New Issue
Block a user