mirror of
https://github.com/agent0ai/agent-zero.git
synced 2026-10-22 14:19:50 +00:00
Update LiteLLM to 1.104.0, OpenAI to 2.54.0, and python-dotenv to 1.2.2. Raise shared security floors for aiohttp, anyio, urllib3, filelock, fsspec, and multidict while retaining the compatible OpenAI 2.x SDK line. Use the existing startup_migration hook to apply the same requirements to v2.x Docker instances updating to v2.14. Read versions from requirements.txt, install only when requirements are unmet, and reuse restart_process() to load the upgraded SDKs before serving requests. Skip current and non-Docker environments, bound installation time, and propagate installation failures. Add installed-SDK HTTP tests for Chat Completions, Responses, streaming, tools, state, usage, fallback, embeddings, and Anthropic cache markers. Cover dependency migration, restart behavior, and installation failures. Validation: - 70 focused dependency, SDK, and self-update tests passed. - Docker startup upgraded the v2.0-v2.13 SDK pins and became healthy in 24 seconds, with exactly one dependency installation and process restart. - An already-current startup performed no installation or extra restart. - pip check passed; live Codex Responses and Moonshot Chat Completions tasks and follow-ups validated the upgraded SDK versions.
67 lines
2.3 KiB
Python
67 lines
2.3 KiB
Python
import importlib.metadata
|
|
from pathlib import Path
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
|
|
from packaging.requirements import Requirement
|
|
|
|
from helpers import files, process, runtime
|
|
from helpers.extension import Extension
|
|
from helpers.print_style import PrintStyle
|
|
|
|
|
|
_REQUIREMENTS_FILE = Path(files.get_abs_path("requirements.txt"))
|
|
_PACKAGES = {
|
|
"litellm", "openai", "python-dotenv", "aiohttp", "anyio", "urllib3",
|
|
"filelock", "fsspec", "multidict",
|
|
}
|
|
|
|
|
|
class FrameworkDependencies(Extension):
|
|
def execute(self, **kwargs):
|
|
if not runtime.is_dockerized():
|
|
return
|
|
requirements = _requirements()
|
|
outdated = _outdated(requirements)
|
|
if not outdated:
|
|
return
|
|
uv = shutil.which("uv")
|
|
if not uv:
|
|
raise RuntimeError("Framework dependency update requires 'uv'.")
|
|
PrintStyle.info("Updating framework dependencies:", ", ".join(outdated))
|
|
subprocess.check_call(
|
|
[uv, "pip", "install", "--python", sys.executable, *map(str, requirements)],
|
|
timeout=60,
|
|
)
|
|
outdated = _outdated(requirements)
|
|
if outdated:
|
|
raise RuntimeError(f"Framework dependencies still unavailable after installation: {outdated}")
|
|
# Models were imported before startup migrations; load the upgraded SDKs.
|
|
process.restart_process()
|
|
|
|
|
|
def _requirements() -> list[Requirement]:
|
|
requirements = []
|
|
for line in _REQUIREMENTS_FILE.read_text(encoding="utf-8").splitlines():
|
|
line = line.partition("#")[0].strip()
|
|
if line:
|
|
requirement = Requirement(line)
|
|
if requirement.name in _PACKAGES:
|
|
requirements.append(requirement)
|
|
missing = _PACKAGES - {requirement.name for requirement in requirements}
|
|
if missing:
|
|
raise RuntimeError(f"Framework requirements missing from {_REQUIREMENTS_FILE}: {sorted(missing)}")
|
|
return requirements
|
|
|
|
|
|
def _outdated(requirements: list[Requirement]) -> list[str]:
|
|
outdated = []
|
|
for requirement in requirements:
|
|
try:
|
|
installed = importlib.metadata.version(requirement.name)
|
|
except importlib.metadata.PackageNotFoundError:
|
|
installed = None
|
|
if installed is None or installed not in requirement.specifier:
|
|
outdated.append(str(requirement))
|
|
return outdated
|