fix(pm): a lazily installed extra swaps into the running process

ensure_import synced the extra into a new generation and then always
raised "restart Hermes to activate", so choosing a provider whose SDK is an
opt-in extra (anthropic, bedrock, ...) failed the first message in every
fresh install or worktree even though the install had succeeded.

adopt_selected() already knows when swapping a live process onto a new
generation is safe (it was on the generation selected before the sync, and
nothing it imported changed version). Call it after the sync; raise only
when adoption was refused, naming restart_needed()'s reason.
This commit is contained in:
ethernet
2026-09-24 23:44:25 -04:00
parent 5d39ddd28b
commit 86e01ba3ed

View File

@@ -220,17 +220,22 @@ def ensure_import(extra: str) -> None:
from pm.client import sync_venv
sync_venv([extra])
# Activation is a process-boot operation. Never mix a newly resolved
# dependency tree with libraries already imported by this process.
# The sync published a new generation. Swap this process onto it when nothing
# already imported would change underneath it (adopt_selected); otherwise only
# a restart can load it.
from pm.environments import selected_venv, site_packages
from pm.environments_adopt import adopt_selected, restart_needed
from pm.paths import repo_root, runtime_facts_path
import sys
from pathlib import Path
if runtime_facts_path().is_file():
selected = site_packages(selected_venv(repo_root())).resolve()
root = repo_root()
adopt_selected(root)
selected = site_packages(selected_venv(root)).resolve()
if selected not in {Path(entry).resolve() for entry in sys.path}:
raise InstallError("venv", f"{extra} installed; restart Hermes to activate the new dependency environment")
reason = restart_needed(root) or "this process does not run from the install's dependency environment"
raise InstallError("venv", f"{extra} installed; restart Hermes to activate it ({reason})")
def ensure_and_bind(extra, importer, target_globals) -> bool: