mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-20 06:35:46 +02:00
96 lines
3.3 KiB
Python
96 lines
3.3 KiB
Python
"""Resolve the LangGraph API version from CLI flags and langgraph.json."""
|
|
|
|
import json
|
|
import pathlib
|
|
import re
|
|
import urllib.request
|
|
|
|
import click
|
|
|
|
VERSION_MARKER_REPO = "langchain/langgraph-published-version-marker"
|
|
_PATCH_VERSION_RE = re.compile(r"^\d+\.\d+\.\d+$")
|
|
_SEMVER_RE = re.compile(r"^\d+\.\d+\.\d+")
|
|
|
|
|
|
def resolve_langgraph_api_version(
|
|
config_path: pathlib.Path,
|
|
api_version_cli_param: str | None,
|
|
) -> str:
|
|
"""Resolve the API version from the CLI flag and/or langgraph.json.
|
|
|
|
Returns the resolved patch-level version string. When neither source
|
|
provides a version, the latest published version is fetched from Docker Hub.
|
|
|
|
Raises `click.ClickException` when both sources specify a version, or
|
|
when a version cannot be resolved via Docker Hub.
|
|
"""
|
|
api_version_langgraph_json = _read_api_version_from_config(config_path)
|
|
|
|
if api_version_cli_param and api_version_langgraph_json:
|
|
raise click.ClickException(
|
|
"API version specified in both --api-version CLI flag "
|
|
f"({api_version_cli_param!r}) and langgraph.json "
|
|
f"({api_version_langgraph_json!r}). Please use only one."
|
|
)
|
|
|
|
preferred_api_version = api_version_cli_param or api_version_langgraph_json
|
|
|
|
if preferred_api_version and _PATCH_VERSION_RE.match(preferred_api_version):
|
|
return preferred_api_version
|
|
|
|
version_prefix = preferred_api_version or ""
|
|
if version_prefix:
|
|
click.secho(
|
|
f"Resolving API version matching {version_prefix!r} from Docker Hub...",
|
|
fg="cyan",
|
|
)
|
|
else:
|
|
click.secho(
|
|
"Resolving latest API version from Docker Hub...",
|
|
fg="cyan",
|
|
)
|
|
resolved = _fetch_matching_version(version_prefix)
|
|
click.secho(f"Resolved API version: {resolved}", fg="cyan")
|
|
return resolved
|
|
|
|
|
|
def _read_api_version_from_config(config_path: pathlib.Path) -> str | None:
|
|
"""Read the `api_version` field from langgraph.json (if present)."""
|
|
try:
|
|
with open(config_path) as f:
|
|
raw_config = json.load(f)
|
|
except (OSError, json.JSONDecodeError):
|
|
return None
|
|
return raw_config.get("api_version")
|
|
|
|
|
|
def _fetch_matching_version(version_prefix: str = "") -> str:
|
|
"""Query Docker Hub for the latest patch version matching *version_prefix*.
|
|
|
|
When *version_prefix* is empty, returns the latest published version.
|
|
"""
|
|
url = f"https://hub.docker.com/v2/repositories/{VERSION_MARKER_REPO}/tags/?page_size=10"
|
|
if version_prefix:
|
|
url += f"&name={version_prefix}"
|
|
try:
|
|
with urllib.request.urlopen(url, timeout=10) as resp:
|
|
data = json.loads(resp.read())
|
|
except Exception as exc:
|
|
raise click.ClickException(
|
|
f"Failed to fetch API version from {VERSION_MARKER_REPO}: {exc}\n"
|
|
"You can specify an exact version with --api-version (e.g. 0.7.67)."
|
|
) from exc
|
|
|
|
for tag in data.get("results", []):
|
|
name = tag.get("name", "")
|
|
if _SEMVER_RE.match(name):
|
|
return name
|
|
|
|
if version_prefix:
|
|
msg = f"Could not find a version matching {version_prefix!r} in {VERSION_MARKER_REPO}."
|
|
else:
|
|
msg = f"Could not find a published version in {VERSION_MARKER_REPO}."
|
|
raise click.ClickException(
|
|
f"{msg}\nYou can specify an exact version with --api-version (e.g. 0.7.67)."
|
|
)
|