mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-18 04:41:56 +00:00
fix(install.ps1): pin uv sync to venv\, verify baseline imports on Windows (#25755)
* fix(cli): allow rotating broken OpenRouter / AI Gateway key in `hermes model` flow Before: when `OPENROUTER_API_KEY` (or `AI_GATEWAY_API_KEY`) was already set in ~/.hermes/.env, `hermes model openrouter` / `hermes model ai-gateway` skipped the API-key prompt entirely and jumped straight to the model picker. Users with a broken / expired / wrong key had no way to replace it without editing ~/.hermes/.env by hand or re-running `hermes setup` from scratch. Both flows now route through the existing `_prompt_api_key()` helper, which surfaces [K]eep / [R]eplace / [C]lear when a key is already configured — the same UX the generic API-key providers (z.ai, MiniMax, Gemini, etc.) and the Daytona setup already use. * fix(install.ps1): pin uv sync target to venv\, verify baseline imports Two related Windows-installer bugs that produce a broken venv with `ModuleNotFoundError: No module named 'dotenv'` on first `hermes` run. ## Bug 1: uv sync ignores VIRTUAL_ENV, syncs into .venv\ instead of venv\ `Install-Dependencies` creates the venv at `venv\` via `uv venv venv`, sets `$env:VIRTUAL_ENV = "$InstallDir\venv"`, then runs `uv sync --extra all --locked`. Modern uv (>=0.5) ignores `VIRTUAL_ENV` for the `sync` subcommand and uses the project default `.venv\` instead. Result: deps land in `$InstallDir\.venv\`, `venv\` stays empty except for the python.exe stub from the earlier `uv venv` call, `hermes.exe` ends up wired to the wrong site-packages. The bash installer (`scripts/install.sh`) already worked around this in `install_deps()` line 1127 by passing `UV_PROJECT_ENVIRONMENT` — that flag tells uv exactly where to put the project env regardless of `VIRTUAL_ENV`. Port the same fix to PowerShell. ## Bug 2: no post-install verification If the sync still misdirects for any other reason (uv version drift, filesystem quirk, user re-run scenarios), the installer reports success and the user only finds out by running `hermes` and getting an unhelpful traceback. Add a baseline-import probe that runs the venv's own python against the four packages every `hermes` invocation needs (`dotenv`, `openai`, `rich`, `prompt_toolkit`). On failure, throw with a recovery command tailored to whether a sibling `.venv\` exists. User report (Windows 11, Python 3.13.5, Hermes v0.13.0): manual repro steps were exactly this — `uv sync` landed in `.venv\`, recovered by junctioning `venv\` → `.venv\` to bridge the path mismatch.
This commit is contained in:
parent
17e0e9d174
commit
524490a409
1 changed files with 33 additions and 0 deletions
|
|
@ -813,6 +813,14 @@ function Install-Dependencies {
|
|||
# needs `make` to build from sdist) and the
|
||||
# install fails.
|
||||
# --extra all = just the [all] extra's contents (curated).
|
||||
#
|
||||
# UV_PROJECT_ENVIRONMENT pins the sync target to our venv\.
|
||||
# Without it, modern uv (>=0.5) ignores VIRTUAL_ENV for `sync`
|
||||
# and creates a sibling .venv\ inside the repo — leaving venv\
|
||||
# empty and producing the broken state where `hermes.exe` exists
|
||||
# in the wrong directory and imports fail with ModuleNotFoundError.
|
||||
# (Mirrors the same flag in scripts/install.sh::install_deps.)
|
||||
$env:UV_PROJECT_ENVIRONMENT = "$InstallDir\venv"
|
||||
& $UvCmd sync --extra all --locked
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Success "Main package installed (hash-verified via uv.lock)"
|
||||
|
|
@ -902,6 +910,31 @@ except Exception:
|
|||
throw "Failed to install hermes-agent package even with no extras. Inspect the uv pip install output above."
|
||||
}
|
||||
|
||||
# Baseline-import gate. Even if a tier reported success above, the
|
||||
# actual deps may have landed somewhere other than $InstallDir\venv\
|
||||
# (e.g. uv 0.5+ syncing into a sibling .venv\ when UV_PROJECT_ENVIRONMENT
|
||||
# isn't set, leaving venv\ empty and hermes.exe broken with
|
||||
# `ModuleNotFoundError: No module named 'dotenv'` on first run).
|
||||
# We probe via the venv's own python so a misdirected sync is caught
|
||||
# here, not 30 seconds later when the user runs `hermes`.
|
||||
if (-not $NoVenv) {
|
||||
$venvPython = "$InstallDir\venv\Scripts\python.exe"
|
||||
if (-not (Test-Path $venvPython)) {
|
||||
throw "Install reported success but $venvPython does not exist. The dependency sync likely landed in a sibling .venv\ directory. Re-run the installer; if it persists, manually: cd '$InstallDir'; Remove-Item -Recurse -Force venv,.venv; uv venv venv --python $PythonVersion; `$env:UV_PROJECT_ENVIRONMENT='$InstallDir\venv'; uv sync --extra all --locked"
|
||||
}
|
||||
& $venvPython -c "import dotenv, openai, rich, prompt_toolkit" 2>&1 | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
$sibling = "$InstallDir\.venv"
|
||||
$hint = if (Test-Path $sibling) {
|
||||
"Detected sibling .venv\ at $sibling — uv synced there instead of venv\. Recover with: cd '$InstallDir'; Remove-Item -Recurse -Force venv; Move-Item .venv venv"
|
||||
} else {
|
||||
"Recover with: cd '$InstallDir'; `$env:UV_PROJECT_ENVIRONMENT='$InstallDir\venv'; uv sync --extra all --locked"
|
||||
}
|
||||
throw "Baseline imports failed in $InstallDir\venv (dotenv/openai/rich/prompt_toolkit). The install completed but dependencies are not in the venv. $hint"
|
||||
}
|
||||
Write-Success "Baseline imports verified in venv"
|
||||
}
|
||||
|
||||
# Verify the dashboard deps specifically — they're the most common thing
|
||||
# users hit and lazy-import errors from `hermes dashboard` are confusing.
|
||||
# If tier 1 failed (the common case), [web] was still picked up by tiers
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue