fix: Protect desktop plugin installs with core lock#7872
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a mechanism to manage desktop-specific core dependency locks by adding desktop_core_lock.py, which parses a JSON lock file defined by an environment variable. These locked constraints are integrated into the core constraint provider, and the pip installer is updated to exclude these modules from plugin dependency preference logic. Feedback suggests refactoring the distribution name canonicalization to use an existing utility to avoid duplication and ensuring that requirement pins use canonicalized names to guarantee correct deduplication when merging constraints.
| import re | ||
| from functools import lru_cache | ||
| from typing import Any | ||
|
|
||
| from astrbot.core.utils.runtime_env import is_packaged_desktop_runtime | ||
|
|
||
| logger = logging.getLogger("astrbot") | ||
|
|
||
| DESKTOP_CORE_LOCK_PATH_ENV = "ASTRBOT_DESKTOP_CORE_LOCK_PATH" | ||
|
|
||
|
|
||
| def _canonicalize_distribution_name(name: str) -> str: | ||
| return re.sub(r"[-_.]+", "-", name).strip("-").lower() |
There was a problem hiding this comment.
The function _canonicalize_distribution_name is identical to canonicalize_distribution_name in requirements_utils.py. To avoid code duplication and maintain consistency, it is recommended to import the existing utility. This also allows for the removal of the import re statement as it is not used elsewhere in this module.
from functools import lru_cache
from typing import Any
from astrbot.core.utils.runtime_env import is_packaged_desktop_runtime
from astrbot.core.utils.requirements_utils import (
canonicalize_distribution_name as _canonicalize_distribution_name,
)
logger = logging.getLogger("astrbot")
DESKTOP_CORE_LOCK_PATH_ENV = "ASTRBOT_DESKTOP_CORE_LOCK_PATH"References
- When implementing similar functionality for different cases, refactor the logic into a shared helper function to avoid code duplication.
| pin = _safe_requirement_pin(name, version) | ||
| if not pin: | ||
| continue | ||
| constraints.setdefault(_canonicalize_distribution_name(name), pin) |
There was a problem hiding this comment.
In get_desktop_core_lock_constraints, the requirement pin should use the canonicalized distribution name. This ensures that when these constraints are merged with core constraints in core_constraints.py, the dict.fromkeys deduplication works correctly even if the lock file uses different casing or separators for the package name compared to the core metadata.
| pin = _safe_requirement_pin(name, version) | |
| if not pin: | |
| continue | |
| constraints.setdefault(_canonicalize_distribution_name(name), pin) | |
| canonical_name = _canonicalize_distribution_name(name) | |
| pin = _safe_requirement_pin(canonical_name, version) | |
| if not pin: | |
| continue | |
| constraints.setdefault(canonical_name, pin) |
Summary
Adds packaged desktop support for consuming a runtime core dependency lock exposed by AstrBot Desktop. The pip installer now merges locked desktop runtime packages into its constraints file and skips locked top-level modules during post-install dependency preference. This prevents plugin installs from replacing already-loaded backend runtime packages such as OpenAI, Pydantic, FastAPI, NumPy, or platform-native bridge modules.
Why
Desktop plugin installs currently target
data/site-packagesand then try to prefer those modules in the live backend process. Heavy plugins can install alternate versions of packages already used by the core runtime, which can corrupt module identity and break streaming/model calls until restart. The lock turns that into either a compatible install using the bundled versions or an explicit dependency conflict.Tests
uv run pytest tests/test_pip_installer.py -quv run ruff check astrbot/core/utils/desktop_core_lock.py astrbot/core/utils/core_constraints.py astrbot/core/utils/pip_installer.py tests/test_pip_installer.pyuv run ruff format --check astrbot/core/utils/desktop_core_lock.py astrbot/core/utils/core_constraints.py astrbot/core/utils/pip_installer.py tests/test_pip_installer.pySummary by Sourcery
Integrate desktop runtime core lock data into plugin installation to avoid overriding bundled desktop dependencies.
Enhancements:
Tests: