From 4cbfbdb23222cfa2c289eab6b64b55b8a312aa79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moura?= Date: Mon, 22 Jun 2026 13:22:46 -0300 Subject: [PATCH] Keep JSON crew projects and deploy archives Python-free (#6228) * fix: scaffold deployable json crews * fix: keep json crew scaffolds python-free * fix: keep json deploy archives python-free * fix: tighten json crew deploy validation * fix: address json crew pr checks * fix: clear langsmith audit advisory --- conftest.py | 16 +- lib/cli/src/crewai_cli/create_json_crew.py | 2 +- lib/cli/src/crewai_cli/deploy/archive.py | 266 --------------------- lib/cli/src/crewai_cli/deploy/validate.py | 32 ++- lib/cli/tests/deploy/test_archive.py | 94 +++++--- lib/cli/tests/deploy/test_validate.py | 35 +++ lib/cli/tests/test_create_crew.py | 20 +- pyproject.toml | 16 +- uv.lock | 112 +++++---- 9 files changed, 226 insertions(+), 367 deletions(-) diff --git a/conftest.py b/conftest.py index 27bf03a86..5987d653f 100644 --- a/conftest.py +++ b/conftest.py @@ -134,17 +134,21 @@ def bedrock_host_matcher(r1: Request, r2: Request) -> bool: # type: ignore[no-a ) -def _patched_make_vcr_request(httpx_request: Any, **kwargs: Any) -> Any: +def _patched_make_vcr_request( + httpx_request: Any, real_request_body: Any = None, **kwargs: Any +) -> Any: """Patched version of VCR's _make_vcr_request that handles binary content. The original implementation fails on binary request bodies (like file uploads) because it assumes all content can be decoded as UTF-8. """ - raw_body = httpx_request.read() - try: - body = raw_body.decode("utf-8") - except UnicodeDecodeError: - body = base64.b64encode(raw_body).decode("ascii") + raw_body = real_request_body if real_request_body is not None else httpx_request.read() + body: Any = raw_body + if isinstance(raw_body, bytes): + try: + body = raw_body.decode("utf-8") + except UnicodeDecodeError: + body = base64.b64encode(raw_body).decode("ascii") uri = str(httpx_request.url) headers = dict(httpx_request.headers) return Request(httpx_request.method, uri, body, headers) diff --git a/lib/cli/src/crewai_cli/create_json_crew.py b/lib/cli/src/crewai_cli/create_json_crew.py index 1df9f0310..9cc0c3787 100644 --- a/lib/cli/src/crewai_cli/create_json_crew.py +++ b/lib/cli/src/crewai_cli/create_json_crew.py @@ -680,7 +680,7 @@ def _default_agents_and_tasks( ] crew_settings = { "process": "sequential", - "memory": False, + "memory": True, "inputs": {}, } return agents, tasks, crew_settings diff --git a/lib/cli/src/crewai_cli/deploy/archive.py b/lib/cli/src/crewai_cli/deploy/archive.py index 14835579d..38b733fe4 100644 --- a/lib/cli/src/crewai_cli/deploy/archive.py +++ b/lib/cli/src/crewai_cli/deploy/archive.py @@ -1,15 +1,11 @@ from __future__ import annotations from pathlib import Path -import re import shutil import tempfile -from typing import Any import zipfile from crewai_cli import git -from crewai_cli.deploy.validate import normalize_package_name -from crewai_cli.utils import parse_toml _EXCLUDED_DIRS = { @@ -38,8 +34,6 @@ _EXCLUDED_SUFFIXES = { ".pyc", ".pyo", } -_SCRIPT_KEY_PATTERN = re.compile(r"^\s*(?P[A-Za-z0-9_.-]+|\"[^\"]+\"|'[^']+')\s*=") -_SECTION_PATTERN = re.compile(r"^\s*\[[^\]]+\]\s*(?:#.*)?$") def create_project_zip( @@ -143,267 +137,7 @@ def _stage_project(root: Path, files: list[Path]) -> Path: destination = staging_root / relative_path destination.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(source, destination) - - if _is_json_crew_project(staging_root): - _add_json_crew_deploy_wrapper(staging_root) except Exception: shutil.rmtree(staging_root, ignore_errors=True) raise return staging_root - - -def _is_json_crew_project(root: Path) -> bool: - """Return True for JSON crew projects that need a Python deploy wrapper.""" - if not ((root / "crew.jsonc").is_file() or (root / "crew.json").is_file()): - return False - - project = _read_pyproject(root) - tool_config = project.get("tool") or {} - crewai_config = tool_config.get("crewai") if isinstance(tool_config, dict) else None - declared_type = ( - crewai_config.get("type") if isinstance(crewai_config, dict) else None - ) - if declared_type == "flow": - return False - - package_name = _package_name(root) - if package_name is None: - raise ValueError( - "Could not derive a valid Python package name from [project].name." - ) - - return not (root / "src" / package_name / "crew.py").is_file() - - -def _read_pyproject(root: Path) -> dict[str, Any]: - """Read pyproject.toml, returning an empty mapping on missing or invalid data.""" - pyproject_path = root / "pyproject.toml" - if not pyproject_path.is_file(): - return {} - try: - pyproject = parse_toml(pyproject_path.read_text()) - except Exception: - return {} - return pyproject if isinstance(pyproject, dict) else {} - - -def _package_name(root: Path) -> str | None: - """Return the normalized Python package name for the project.""" - project = _read_pyproject(root).get("project") - if not isinstance(project, dict): - return None - - name = project.get("name") - if not isinstance(name, str) or not name.strip(): - return None - - package_name = normalize_package_name(name) - return package_name or None - - -def _class_name(package_name: str) -> str: - """Return the generated wrapper class name for a package.""" - parts = [part for part in re.split(r"[^a-zA-Z0-9]+", package_name) if part] - class_name = "".join(part[:1].upper() + part[1:] for part in parts) - if not class_name: - return "JsonCrew" - if class_name[0].isdigit(): - return f"Crew{class_name}" - return class_name - - -def _add_json_crew_deploy_wrapper(root: Path) -> None: - """Add Python wrapper files required to deploy a JSON crew project.""" - package_name = _package_name(root) - if package_name is None: - raise ValueError( - "Could not derive a valid Python package name from [project].name." - ) - - package_dir = root / "src" / package_name - config_dir = package_dir / "config" - config_dir.mkdir(parents=True, exist_ok=True) - - class_name = _class_name(package_name) - crew_filename = "crew.jsonc" if (root / "crew.jsonc").is_file() else "crew.json" - - (package_dir / "__init__.py").write_text("", encoding="utf-8") - (config_dir / "agents.yaml").write_text("{}\n", encoding="utf-8") - (config_dir / "tasks.yaml").write_text("{}\n", encoding="utf-8") - (package_dir / "crew.py").write_text( - _json_crew_py(class_name, crew_filename), - encoding="utf-8", - ) - (package_dir / "main.py").write_text( - _json_main_py(package_name, class_name), - encoding="utf-8", - ) - _ensure_project_scripts(root, package_name) - - -def _json_crew_py(class_name: str, crew_filename: str) -> str: - """Render the generated crew.py module for a JSON crew.""" - return f'''from pathlib import Path - -from crewai import Crew -from crewai.project import CrewBase, crew -from crewai.project.crew_loader import load_crew - - -def _crew_path() -> Path: - return Path(__file__).resolve().parents[2] / "{crew_filename}" - - -@CrewBase -class {class_name}: - """Compatibility wrapper for a JSON-defined CrewAI project.""" - - @crew - def crew(self) -> Crew: - crew_instance, default_inputs = load_crew(_crew_path()) - self.default_inputs = default_inputs - return crew_instance -''' - - -def _json_main_py(package_name: str, class_name: str) -> str: - """Render the generated main.py entrypoints for a JSON crew.""" - return f"""#!/usr/bin/env python -import json -import sys - -from {package_name}.crew import {class_name} - - -def _load(): - wrapper = {class_name}() - crew = wrapper.crew() - return crew, getattr(wrapper, "default_inputs", {{}}) - - -def run(): - crew, inputs = _load() - return crew.kickoff(inputs=inputs) - - -def train(): - crew, inputs = _load() - return crew.train( - n_iterations=int(sys.argv[1]), - filename=sys.argv[2], - inputs=inputs, - ) - - -def replay(): - crew, _ = _load() - return crew.replay(task_id=sys.argv[1]) - - -def test(): - crew, inputs = _load() - return crew.test( - n_iterations=int(sys.argv[1]), - eval_llm=sys.argv[2], - inputs=inputs, - ) - - -def run_with_trigger(): - if len(sys.argv) < 2: - raise ValueError("No trigger payload provided.") - - crew, inputs = _load() - trigger_payload = json.loads(sys.argv[1]) - return crew.kickoff( - inputs={{**inputs, "crewai_trigger_payload": trigger_payload}} - ) -""" - - -def _ensure_project_scripts(root: Path, package_name: str) -> None: - """Ensure generated wrappers have project script entrypoints.""" - pyproject_path = root / "pyproject.toml" - if not pyproject_path.is_file(): - return - - content = pyproject_path.read_text(encoding="utf-8") - entries = _project_script_entries(package_name) - pyproject_path.write_text( - _update_project_scripts(content, entries), - encoding="utf-8", - ) - - -def _project_script_entries(package_name: str) -> dict[str, str]: - """Return script entrypoints required by the generated JSON wrapper.""" - return { - package_name: f"{package_name}.main:run", - "run_crew": f"{package_name}.main:run", - "train": f"{package_name}.main:train", - "replay": f"{package_name}.main:replay", - "test": f"{package_name}.main:test", - "run_with_trigger": f"{package_name}.main:run_with_trigger", - } - - -def _update_project_scripts(content: str, entries: dict[str, str]) -> str: - """Add or replace generated script entries in pyproject.toml content.""" - lines = content.rstrip().splitlines() - header_index = _project_scripts_header_index(lines) - if header_index is None: - return content.rstrip() + _project_scripts_block(entries) - - end_index = _section_end_index(lines, header_index + 1) - seen: set[str] = set() - for index in range(header_index + 1, end_index): - key = _script_key(lines[index]) - if key in entries: - lines[index] = _script_line(key, entries[key]) - seen.add(key) - - missing_lines = [ - _script_line(key, value) for key, value in entries.items() if key not in seen - ] - lines[end_index:end_index] = missing_lines - return "\n".join(lines).rstrip() + "\n" - - -def _project_scripts_header_index(lines: list[str]) -> int | None: - """Return the line index of the project scripts table, if present.""" - for index, line in enumerate(lines): - if line.strip() == "[project.scripts]": - return index - return None - - -def _section_end_index(lines: list[str], start_index: int) -> int: - """Return the exclusive end index for a TOML table section.""" - for index in range(start_index, len(lines)): - if _SECTION_PATTERN.match(lines[index]): - return index - return len(lines) - - -def _script_key(line: str) -> str | None: - """Return the script key for a pyproject script line.""" - match = _SCRIPT_KEY_PATTERN.match(line) - if not match: - return None - - key = match.group("key") - if key.startswith(("'", '"')) and key.endswith(("'", '"')): - return key[1:-1] - return key - - -def _script_line(key: str, value: str) -> str: - """Render a project script TOML entry.""" - return f'{key} = "{value}"' - - -def _project_scripts_block(entries: dict[str, str]) -> str: - """Render a project scripts TOML table.""" - lines = ["", "", "[project.scripts]"] - lines.extend(_script_line(key, value) for key, value in entries.items()) - return "\n".join(lines) + "\n" diff --git a/lib/cli/src/crewai_cli/deploy/validate.py b/lib/cli/src/crewai_cli/deploy/validate.py index 544ff20cf..b76303d56 100644 --- a/lib/cli/src/crewai_cli/deploy/validate.py +++ b/lib/cli/src/crewai_cli/deploy/validate.py @@ -212,8 +212,16 @@ class DeployValidator: if crew_path is None: return self.results + agents_dir = self.project_root / "agents" + + self._check_pyproject() + self._check_lockfile() + agents_dir_ok = self._check_json_agents_dir(agents_dir) + + project = None try: - project = validate_crew_project(crew_path, self.project_root / "agents") + if agents_dir_ok: + project = validate_crew_project(crew_path, agents_dir) except JSONProjectValidationError as e: self._add( Severity.ERROR, @@ -232,15 +240,27 @@ class DeployValidator: ) return self.results - agents_dir = self.project_root / "agents" - - self._check_pyproject() - self._check_lockfile() - self._check_env_vars_json(crew_path, agents_dir, project.agent_names) + if project is not None: + self._check_env_vars_json(crew_path, agents_dir, project.agent_names) self._check_version_vs_lockfile() return self.results + def _check_json_agents_dir(self, agents_dir: Path) -> bool: + if agents_dir.is_dir(): + return True + self._add( + Severity.ERROR, + "missing_agents_dir", + "Cannot find agents/ directory", + detail=( + "JSON crew projects load agent definitions from " + f"{agents_dir.relative_to(self.project_root)}/*.jsonc or *.json." + ), + hint="Create agents/ and add one JSON or JSONC file per agent.", + ) + return False + def _check_env_vars_json( self, crew_path: Path, agents_dir: Path, agent_names: list[str] ) -> None: diff --git a/lib/cli/tests/deploy/test_archive.py b/lib/cli/tests/deploy/test_archive.py index 1d0e2cc1a..dff77a29b 100644 --- a/lib/cli/tests/deploy/test_archive.py +++ b/lib/cli/tests/deploy/test_archive.py @@ -132,7 +132,7 @@ def test_create_project_zip_excludes_symlinked_files(tmp_path: Path): assert names == {"pyproject.toml"} -def test_create_project_zip_adds_json_project_wrapper(tmp_path: Path): +def test_create_project_zip_preserves_json_project_shape(tmp_path: Path): (tmp_path / "pyproject.toml").write_text( """ [project] @@ -157,8 +157,6 @@ type = "crew" try: with zipfile.ZipFile(archive_path) as archive: names = set(archive.namelist()) - crew_py = archive.read("src/json_crew/crew.py").decode() - main_py = archive.read("src/json_crew/main.py").decode() pyproject = archive.read("pyproject.toml").decode() finally: archive_path.unlink(missing_ok=True) @@ -166,18 +164,50 @@ type = "crew" assert "uv.lock" not in names assert "crew.jsonc" in names assert "agents/researcher.jsonc" in names - assert "src/json_crew/__init__.py" in names - assert "src/json_crew/crew.py" in names - assert "src/json_crew/main.py" in names - assert "src/json_crew/config/agents.yaml" in names - assert "src/json_crew/config/tasks.yaml" in names - assert "load_crew(_crew_path())" in crew_py - assert "JsonCrew" in crew_py - assert "from json_crew.crew import JsonCrew" in main_py - assert "run_crew = \"json_crew.main:run\"" in pyproject + assert all(not name.startswith("src/") for name in names) + assert "run_crew" not in pyproject + assert "json_crew =" not in pyproject + assert "[project.scripts]" not in pyproject -def test_create_project_zip_updates_existing_json_project_scripts(tmp_path: Path): +def test_create_project_zip_keeps_json_project_root_shape(tmp_path: Path): + (tmp_path / "pyproject.toml").write_text( + """ +[project] +name = "json_crew" +version = "0.1.0" +dependencies = ["crewai[tools]==1.14.8a1"] + +[tool.crewai] +type = "crew" +""".strip() + + "\n" + ) + (tmp_path / "uv.lock").write_text("# lock\n") + (tmp_path / "agents").mkdir() + (tmp_path / "agents" / "foo.jsonc").write_text("{}\n") + (tmp_path / "crew.jsonc").write_text("{}\n") + + archive_path = create_project_zip("json_crew", project_dir=tmp_path) + try: + with zipfile.ZipFile(archive_path) as archive: + names = set(archive.namelist()) + pyproject = archive.read("pyproject.toml").decode() + finally: + archive_path.unlink(missing_ok=True) + + assert names == { + "agents/foo.jsonc", + "crew.jsonc", + "pyproject.toml", + "uv.lock", + } + assert "run_crew" not in pyproject + assert "json_crew =" not in pyproject + assert "[project.scripts]" not in pyproject + + +def test_create_project_zip_does_not_rewrite_json_project_scripts(tmp_path: Path): (tmp_path / "pyproject.toml").write_text( """ [project] @@ -203,14 +233,10 @@ type = "crew" finally: archive_path.unlink(missing_ok=True) - assert 'json_crew = "json_crew.main:run"' in pyproject - assert 'run_crew = "json_crew.main:run"' in pyproject - assert 'train = "json_crew.main:train"' in pyproject - assert 'replay = "json_crew.main:replay"' in pyproject - assert 'test = "json_crew.main:test"' in pyproject - assert 'run_with_trigger = "json_crew.main:run_with_trigger"' in pyproject + assert 'json_crew = "old.module:run"' in pyproject + assert 'run_crew = "old.module:run"' in pyproject assert 'custom = "custom.module:main"' in pyproject - assert "old.module:run" not in pyproject + assert pyproject.count("[project.scripts]") == 1 assert "[tool.crewai]" in pyproject @@ -221,7 +247,7 @@ type = "crew" '[tool]\ncrewai = "invalid"\n', ], ) -def test_create_project_zip_adds_json_wrapper_for_malformed_tool_config( +def test_create_project_zip_preserves_json_project_with_malformed_tool_config( tmp_path: Path, tool_config: str ): (tmp_path / "pyproject.toml").write_text( @@ -244,12 +270,13 @@ version = "0.1.0" finally: archive_path.unlink(missing_ok=True) - assert "src/json_crew/crew.py" in names - assert "src/json_crew/main.py" in names - assert "run_crew = \"json_crew.main:run\"" in pyproject + assert names == {"crew.jsonc", "pyproject.toml"} + assert "run_crew" not in pyproject + assert "json_crew =" not in pyproject + assert "[project.scripts]" not in pyproject -def test_create_project_zip_rejects_empty_normalized_package_name(tmp_path: Path): +def test_create_project_zip_accepts_json_project_without_package_name(tmp_path: Path): (tmp_path / "pyproject.toml").write_text( """ [project] @@ -263,8 +290,15 @@ type = "crew" ) (tmp_path / "crew.jsonc").write_text("{}\n") - with pytest.raises( - ValueError, - match=r"Could not derive a valid Python package name", - ): - create_project_zip("invalid", project_dir=tmp_path) + archive_path = create_project_zip("invalid", project_dir=tmp_path) + try: + with zipfile.ZipFile(archive_path) as archive: + names = set(archive.namelist()) + pyproject = archive.read("pyproject.toml").decode() + finally: + archive_path.unlink(missing_ok=True) + + assert names == {"crew.jsonc", "pyproject.toml"} + assert "run_crew" not in pyproject + assert "json_crew =" not in pyproject + assert "[project.scripts]" not in pyproject diff --git a/lib/cli/tests/deploy/test_validate.py b/lib/cli/tests/deploy/test_validate.py index 07ceef14f..1176fbbdf 100644 --- a/lib/cli/tests/deploy/test_validate.py +++ b/lib/cli/tests/deploy/test_validate.py @@ -200,6 +200,41 @@ def test_json_runtime_fields_are_deploy_errors(tmp_path: Path) -> None: assert "runtime-only" in finding.detail +def test_json_crew_requires_agents_dir_without_classic_errors(tmp_path: Path) -> None: + _scaffold_json_crew(tmp_path) + for path in (tmp_path / "agents").iterdir(): + path.unlink() + (tmp_path / "agents").rmdir() + + v = DeployValidator(project_root=tmp_path) + v.run() + + codes = _codes(v) + assert "missing_agents_dir" in codes + assert "missing_src_dir" not in codes + assert "missing_crew_py" not in codes + assert "missing_agents_yaml" not in codes + assert "missing_tasks_yaml" not in codes + + +def test_json_crew_reports_project_metadata_before_invalid_json( + tmp_path: Path, +) -> None: + _scaffold_json_crew(tmp_path) + (tmp_path / "pyproject.toml").unlink() + (tmp_path / "uv.lock").unlink() + (tmp_path / "crew.jsonc").write_text('{"agents": ["researcher"], "tasks": []}\n') + + v = DeployValidator(project_root=tmp_path) + v.run() + + codes = _codes(v) + assert "missing_pyproject" in codes + assert "missing_lockfile" in codes + assert "invalid_crew_json" in codes + assert "missing_src_dir" not in codes + + def test_missing_pyproject_errors(tmp_path: Path) -> None: v = _run_without_import_check(tmp_path) assert "missing_pyproject" in _codes(v) diff --git a/lib/cli/tests/test_create_crew.py b/lib/cli/tests/test_create_crew.py index adfe1757f..5d87f8f3e 100644 --- a/lib/cli/tests/test_create_crew.py +++ b/lib/cli/tests/test_create_crew.py @@ -712,8 +712,26 @@ def test_json_create_provider_preselects_default_model(tmp_path, monkeypatch): default_llm="openai/gpt-5.5", ) assert (tmp_path / "json_crew" / "crew.jsonc").exists() + assert not (tmp_path / "json_crew" / "src").exists() assert not (tmp_path / "json_crew" / "tests").exists() assert not (tmp_path / "json_crew" / "config.jsonc").exists() + generated_paths = { + path.relative_to(tmp_path / "json_crew").as_posix() + for path in (tmp_path / "json_crew").rglob("*") + if path.is_file() + } + assert not any( + path.endswith("/crew.py") or path == "crew.py" for path in generated_paths + ) + assert not any( + path.endswith("/agents.yaml") or path == "agents.yaml" + for path in generated_paths + ) + assert not any( + path.endswith("/tasks.yaml") or path == "tasks.yaml" + for path in generated_paths + ) + assert not any(path.startswith("src/") for path in generated_paths) pyproject = tomli.loads((tmp_path / "json_crew" / "pyproject.toml").read_text()) dependency = pyproject["project"]["dependencies"][0] @@ -849,7 +867,7 @@ def test_json_create_dmn_mode_uses_non_interactive_defaults(tmp_path, monkeypatc crew_template = (project_root / "crew.jsonc").read_text() agent_template = (project_root / "agents" / "researcher.jsonc").read_text() - assert '"memory": false' in crew_template + assert '"memory": true' in crew_template assert '"description": "Research current AI trends and write a concise summary."' in ( crew_template ) diff --git a/pyproject.toml b/pyproject.toml index d36586f4a..845e365ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,7 @@ dev = [ "pytest==9.0.3", "pytest-asyncio==1.3.0", "pytest-subprocess==1.5.3", - "vcrpy==7.0.0", # pinned, less versions break pytest-recording + "vcrpy==8.2.1", # pinned, lower versions break pytest-recording "pytest-recording==0.13.4", "pytest-randomly==4.0.1", "pytest-timeout==2.4.0", @@ -171,8 +171,8 @@ info = "Commits must follow Conventional Commits 1.0.0." [tool.uv] exclude-newer = "3 days" -# pypdf 6.13.3 is a security fix newer than the global supply-chain cutoff. -exclude-newer-package = { pypdf = "2026-06-18T00:00:00Z" } +# These security fixes are newer than the global supply-chain cutoff. +exclude-newer-package = { pypdf = "2026-06-18T00:00:00Z", msgpack = "2026-06-20T00:00:00Z", pydantic-settings = "2026-06-20T00:00:00Z", langsmith = "2026-06-20T00:00:00Z" } # composio-core pins rich<14 but textual requires rich>=14. # onnxruntime 1.24+ dropped Python 3.10 wheels; cap it so qdrant[fastembed] resolves on 3.10. @@ -188,7 +188,8 @@ exclude-newer-package = { pypdf = "2026-06-18T00:00:00Z" } # python-multipart <0.0.27 has GHSA-pp6c-gr5w-3c5g (DoS via unbounded multipart headers). # gitpython <3.1.50 has GHSA-mv93-w799-cj2w (config_writer newline injection bypassing the 3.1.49 patch -> RCE via core.hooksPath). # urllib3 <2.7.0 has GHSA-qccp-gfcp-xxvc (ProxyManager cross-origin redirect leaks Authorization/Cookie) and GHSA-mf9v-mfxr-j63j (streaming decompression-bomb bypass); force 2.7.0+. -# langsmith <0.8.0 has GHSA-3644-q5cj-c5c7 (public prompt manifest deserialization, SSRF/secret disclosure); force 0.8.0+. +# langsmith <0.8.18 has GHSA-3644-q5cj-c5c7 (public prompt manifest deserialization, SSRF/secret disclosure) +# and GHSA-f4xh-w4cj-qxq8; force 0.8.18+. # authlib <1.6.12 has GHSA-jj8c-mmj3-mmgv (CSRF bypass in cache-based state storage) and PYSEC-2026-188. # pip 26.1.1 has PYSEC-2026-196; force 26.1.2+. # aiohttp <=3.13.x has GHSA-jg22-mg44-37j8, GHSA-hg6j-4rv6-33pg; fixed in 3.14.0; force 3.14.0+. @@ -196,6 +197,8 @@ exclude-newer-package = { pypdf = "2026-06-18T00:00:00Z" } # pip <26.1.1 has GHSA-58qw-9mgm-455v (archive handling); OSV considers 26.1.1 unaffected. # paramiko <5.0.0 has GHSA-r374-rxx8-8654 (SHA-1 in rsakey.py); OSV considers 5.0.0 unaffected. Transitive via composio-core. # starlette <1.3.1 has PYSEC-2026-161, GHSA-jp82-jpqv-5vv3, and GHSA-82w8-qh3p-5jfq. Transitive via fastapi. +# msgpack <1.2.1 has GHSA-6v7p-g79w-8964; transitive via pip-audit[filecache]. +# pydantic-settings <2.14.2 has GHSA-4xgf-cpjx-pc3j. # Keep OpenAI on the SDK range required by CrewAI when transitive dependencies # loosen or pin their own lower versions. override-dependencies = [ @@ -212,16 +215,17 @@ override-dependencies = [ "uv>=0.11.15,<1", "python-multipart>=0.0.27,<1", "gitpython>=3.1.50,<4", - "langsmith>=0.8.0,<1", + "langsmith>=0.8.18,<1", "authlib>=1.6.12", "pip>=26.1.2", "aiohttp>=3.14.0", # [chunking] carried here because override-dependencies replace the whole # requirement; without it the docling extra's chunking deps get stripped. "docling-core[chunking]>=2.74.1", - "pydantic-settings>=2.14.0", "paramiko>=5.0.0", "starlette>=1.3.1", + "msgpack>=1.2.1", + "pydantic-settings>=2.14.2", ] [tool.uv.workspace] diff --git a/uv.lock b/uv.lock index d8954d3ed..b623014c8 100644 --- a/uv.lock +++ b/uv.lock @@ -17,7 +17,10 @@ exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for exclude-newer-span = "P3D" [options.exclude-newer-package] +msgpack = "2026-06-20T00:00:00Z" +langsmith = "2026-06-20T00:00:00Z" pypdf = "2026-06-18T00:00:00Z" +pydantic-settings = "2026-06-20T00:00:00Z" [manifest] members = [ @@ -36,13 +39,14 @@ overrides = [ { name = "gitpython", specifier = ">=3.1.50,<4" }, { name = "langchain-core", specifier = ">=1.3.3,<2" }, { name = "langchain-text-splitters", specifier = ">=1.1.2,<2" }, - { name = "langsmith", specifier = ">=0.8.0,<1" }, + { name = "langsmith", specifier = ">=0.8.18,<1" }, + { name = "msgpack", specifier = ">=1.2.1" }, { name = "onnxruntime", marker = "python_full_version < '3.11'", specifier = "<1.24" }, { name = "openai", specifier = ">=2.30.0,<3" }, { name = "paramiko", specifier = ">=5.0.0" }, { name = "pillow", specifier = ">=12.1.1" }, { name = "pip", specifier = ">=26.1.2" }, - { name = "pydantic-settings", specifier = ">=2.14.0" }, + { name = "pydantic-settings", specifier = ">=2.14.2" }, { name = "pypdf", specifier = ">=6.13.3,<7" }, { name = "python-multipart", specifier = ">=0.0.27,<1" }, { name = "rich", specifier = ">=13.7.1" }, @@ -77,7 +81,7 @@ dev = [ { name = "types-redis", specifier = "~=4.6" }, { name = "types-regex", specifier = "==2026.1.15.*" }, { name = "types-requests", specifier = "~=2.31.0.6" }, - { name = "vcrpy", specifier = "==7.0.0" }, + { name = "vcrpy", specifier = "==8.2.1" }, ] [[package]] @@ -3946,7 +3950,7 @@ sdist = { url = "https://files.pythonhosted.org/packages/0e/72/a3add0e4eec4eb9e2 [[package]] name = "langsmith" -version = "0.8.11" +version = "0.8.18" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -3960,9 +3964,9 @@ dependencies = [ { name = "xxhash" }, { name = "zstandard" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ea/0d/082410ece26ff9f3ed4f87b014a8675be47cbd7d65f06b922045dfc21c47/langsmith-0.8.11.tar.gz", hash = "sha256:d9b3496f8f7ca63f4f2d1dfd368afd6c527923fff2ce4026c82ce85f37db3965", size = 4495842, upload-time = "2026-06-08T22:54:44.395Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/d9/a6681aa9847bbbc5ec21abe20a5e233b94e5edcfe39624db607ac7e8ccb4/langsmith-0.8.18.tar.gz", hash = "sha256:32dde9c0e67e053e0fb738921fc8ced768af7b8fa83d7a0e3fd63597cf8776dd", size = 4526988, upload-time = "2026-06-19T13:12:17.123Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b4/65/f9c9dc19b21a9076286fafdb0ab732c9019ddf71aa7e7d720a830a98fe2a/langsmith-0.8.11-py3-none-any.whl", hash = "sha256:08aa5e84b00703ecc11dbeafda78d84b92da4e8c6114e0be9b59df9e71afc59b", size = 478985, upload-time = "2026-06-08T22:54:42.349Z" }, + { url = "https://files.pythonhosted.org/packages/03/70/0e0cc80a3b064c8d6c8d697c3125ed86e39d5a7393ec6dc8b07cb1cf13c4/langsmith-0.8.18-py3-none-any.whl", hash = "sha256:3940183349993faef48e6c7d08e4822ee9cefd906b362d0e3c2d650314d2f282", size = 508108, upload-time = "2026-06-19T13:12:15.348Z" }, ] [[package]] @@ -4702,45 +4706,53 @@ wheels = [ [[package]] name = "msgpack" -version = "1.1.2" +version = "1.2.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4d/f2/bfb55a6236ed8725a96b0aa3acbd0ec17588e6a2c3b62a93eb513ed8783f/msgpack-1.1.2.tar.gz", hash = "sha256:3b60763c1373dd60f398488069bcdc703cd08a711477b5d480eecc9f9626f47e", size = 173581, upload-time = "2025-10-08T09:15:56.596Z" } +sdist = { url = "https://files.pythonhosted.org/packages/31/f9/c0a1c127f9049db9155afc316952ea571720dd01833ff5e4d7e8e6352dbb/msgpack-1.2.1.tar.gz", hash = "sha256:04c721c2c7448767e9e3f2520a475663d8ee0f09c31890f6d2bd70fd636a9647", size = 183960, upload-time = "2026-06-18T16:13:52.594Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f5/a2/3b68a9e769db68668b25c6108444a35f9bd163bb848c0650d516761a59c0/msgpack-1.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0051fffef5a37ca2cd16978ae4f0aef92f164df86823871b5162812bebecd8e2", size = 81318, upload-time = "2025-10-08T09:14:38.722Z" }, - { url = "https://files.pythonhosted.org/packages/5b/e1/2b720cc341325c00be44e1ed59e7cfeae2678329fbf5aa68f5bda57fe728/msgpack-1.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a605409040f2da88676e9c9e5853b3449ba8011973616189ea5ee55ddbc5bc87", size = 83786, upload-time = "2025-10-08T09:14:40.082Z" }, - { url = "https://files.pythonhosted.org/packages/71/e5/c2241de64bfceac456b140737812a2ab310b10538a7b34a1d393b748e095/msgpack-1.1.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b696e83c9f1532b4af884045ba7f3aa741a63b2bc22617293a2c6a7c645f251", size = 398240, upload-time = "2025-10-08T09:14:41.151Z" }, - { url = "https://files.pythonhosted.org/packages/b7/09/2a06956383c0fdebaef5aa9246e2356776f12ea6f2a44bd1368abf0e46c4/msgpack-1.1.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:365c0bbe981a27d8932da71af63ef86acc59ed5c01ad929e09a0b88c6294e28a", size = 406070, upload-time = "2025-10-08T09:14:42.821Z" }, - { url = "https://files.pythonhosted.org/packages/0e/74/2957703f0e1ef20637d6aead4fbb314330c26f39aa046b348c7edcf6ca6b/msgpack-1.1.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:41d1a5d875680166d3ac5c38573896453bbbea7092936d2e107214daf43b1d4f", size = 393403, upload-time = "2025-10-08T09:14:44.38Z" }, - { url = "https://files.pythonhosted.org/packages/a5/09/3bfc12aa90f77b37322fc33e7a8a7c29ba7c8edeadfa27664451801b9860/msgpack-1.1.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:354e81bcdebaab427c3df4281187edc765d5d76bfb3a7c125af9da7a27e8458f", size = 398947, upload-time = "2025-10-08T09:14:45.56Z" }, - { url = "https://files.pythonhosted.org/packages/4b/4f/05fcebd3b4977cb3d840f7ef6b77c51f8582086de5e642f3fefee35c86fc/msgpack-1.1.2-cp310-cp310-win32.whl", hash = "sha256:e64c8d2f5e5d5fda7b842f55dec6133260ea8f53c4257d64494c534f306bf7a9", size = 64769, upload-time = "2025-10-08T09:14:47.334Z" }, - { url = "https://files.pythonhosted.org/packages/d0/3e/b4547e3a34210956382eed1c85935fff7e0f9b98be3106b3745d7dec9c5e/msgpack-1.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:db6192777d943bdaaafb6ba66d44bf65aa0e9c5616fa1d2da9bb08828c6b39aa", size = 71293, upload-time = "2025-10-08T09:14:48.665Z" }, - { url = "https://files.pythonhosted.org/packages/2c/97/560d11202bcd537abca693fd85d81cebe2107ba17301de42b01ac1677b69/msgpack-1.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2e86a607e558d22985d856948c12a3fa7b42efad264dca8a3ebbcfa2735d786c", size = 82271, upload-time = "2025-10-08T09:14:49.967Z" }, - { url = "https://files.pythonhosted.org/packages/83/04/28a41024ccbd67467380b6fb440ae916c1e4f25e2cd4c63abe6835ac566e/msgpack-1.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:283ae72fc89da59aa004ba147e8fc2f766647b1251500182fac0350d8af299c0", size = 84914, upload-time = "2025-10-08T09:14:50.958Z" }, - { url = "https://files.pythonhosted.org/packages/71/46/b817349db6886d79e57a966346cf0902a426375aadc1e8e7a86a75e22f19/msgpack-1.1.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:61c8aa3bd513d87c72ed0b37b53dd5c5a0f58f2ff9f26e1555d3bd7948fb7296", size = 416962, upload-time = "2025-10-08T09:14:51.997Z" }, - { url = "https://files.pythonhosted.org/packages/da/e0/6cc2e852837cd6086fe7d8406af4294e66827a60a4cf60b86575a4a65ca8/msgpack-1.1.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:454e29e186285d2ebe65be34629fa0e8605202c60fbc7c4c650ccd41870896ef", size = 426183, upload-time = "2025-10-08T09:14:53.477Z" }, - { url = "https://files.pythonhosted.org/packages/25/98/6a19f030b3d2ea906696cedd1eb251708e50a5891d0978b012cb6107234c/msgpack-1.1.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7bc8813f88417599564fafa59fd6f95be417179f76b40325b500b3c98409757c", size = 411454, upload-time = "2025-10-08T09:14:54.648Z" }, - { url = "https://files.pythonhosted.org/packages/b7/cd/9098fcb6adb32187a70b7ecaabf6339da50553351558f37600e53a4a2a23/msgpack-1.1.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bafca952dc13907bdfdedfc6a5f579bf4f292bdd506fadb38389afa3ac5b208e", size = 422341, upload-time = "2025-10-08T09:14:56.328Z" }, - { url = "https://files.pythonhosted.org/packages/e6/ae/270cecbcf36c1dc85ec086b33a51a4d7d08fc4f404bdbc15b582255d05ff/msgpack-1.1.2-cp311-cp311-win32.whl", hash = "sha256:602b6740e95ffc55bfb078172d279de3773d7b7db1f703b2f1323566b878b90e", size = 64747, upload-time = "2025-10-08T09:14:57.882Z" }, - { url = "https://files.pythonhosted.org/packages/2a/79/309d0e637f6f37e83c711f547308b91af02b72d2326ddd860b966080ef29/msgpack-1.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:d198d275222dc54244bf3327eb8cbe00307d220241d9cec4d306d49a44e85f68", size = 71633, upload-time = "2025-10-08T09:14:59.177Z" }, - { url = "https://files.pythonhosted.org/packages/73/4d/7c4e2b3d9b1106cd0aa6cb56cc57c6267f59fa8bfab7d91df5adc802c847/msgpack-1.1.2-cp311-cp311-win_arm64.whl", hash = "sha256:86f8136dfa5c116365a8a651a7d7484b65b13339731dd6faebb9a0242151c406", size = 64755, upload-time = "2025-10-08T09:15:00.48Z" }, - { url = "https://files.pythonhosted.org/packages/ad/bd/8b0d01c756203fbab65d265859749860682ccd2a59594609aeec3a144efa/msgpack-1.1.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:70a0dff9d1f8da25179ffcf880e10cf1aad55fdb63cd59c9a49a1b82290062aa", size = 81939, upload-time = "2025-10-08T09:15:01.472Z" }, - { url = "https://files.pythonhosted.org/packages/34/68/ba4f155f793a74c1483d4bdef136e1023f7bcba557f0db4ef3db3c665cf1/msgpack-1.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:446abdd8b94b55c800ac34b102dffd2f6aa0ce643c55dfc017ad89347db3dbdb", size = 85064, upload-time = "2025-10-08T09:15:03.764Z" }, - { url = "https://files.pythonhosted.org/packages/f2/60/a064b0345fc36c4c3d2c743c82d9100c40388d77f0b48b2f04d6041dbec1/msgpack-1.1.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c63eea553c69ab05b6747901b97d620bb2a690633c77f23feb0c6a947a8a7b8f", size = 417131, upload-time = "2025-10-08T09:15:05.136Z" }, - { url = "https://files.pythonhosted.org/packages/65/92/a5100f7185a800a5d29f8d14041f61475b9de465ffcc0f3b9fba606e4505/msgpack-1.1.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:372839311ccf6bdaf39b00b61288e0557916c3729529b301c52c2d88842add42", size = 427556, upload-time = "2025-10-08T09:15:06.837Z" }, - { url = "https://files.pythonhosted.org/packages/f5/87/ffe21d1bf7d9991354ad93949286f643b2bb6ddbeab66373922b44c3b8cc/msgpack-1.1.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2929af52106ca73fcb28576218476ffbb531a036c2adbcf54a3664de124303e9", size = 404920, upload-time = "2025-10-08T09:15:08.179Z" }, - { url = "https://files.pythonhosted.org/packages/ff/41/8543ed2b8604f7c0d89ce066f42007faac1eaa7d79a81555f206a5cdb889/msgpack-1.1.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:be52a8fc79e45b0364210eef5234a7cf8d330836d0a64dfbb878efa903d84620", size = 415013, upload-time = "2025-10-08T09:15:09.83Z" }, - { url = "https://files.pythonhosted.org/packages/41/0d/2ddfaa8b7e1cee6c490d46cb0a39742b19e2481600a7a0e96537e9c22f43/msgpack-1.1.2-cp312-cp312-win32.whl", hash = "sha256:1fff3d825d7859ac888b0fbda39a42d59193543920eda9d9bea44d958a878029", size = 65096, upload-time = "2025-10-08T09:15:11.11Z" }, - { url = "https://files.pythonhosted.org/packages/8c/ec/d431eb7941fb55a31dd6ca3404d41fbb52d99172df2e7707754488390910/msgpack-1.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:1de460f0403172cff81169a30b9a92b260cb809c4cb7e2fc79ae8d0510c78b6b", size = 72708, upload-time = "2025-10-08T09:15:12.554Z" }, - { url = "https://files.pythonhosted.org/packages/c5/31/5b1a1f70eb0e87d1678e9624908f86317787b536060641d6798e3cf70ace/msgpack-1.1.2-cp312-cp312-win_arm64.whl", hash = "sha256:be5980f3ee0e6bd44f3a9e9dea01054f175b50c3e6cdb692bc9424c0bbb8bf69", size = 64119, upload-time = "2025-10-08T09:15:13.589Z" }, - { url = "https://files.pythonhosted.org/packages/6b/31/b46518ecc604d7edf3a4f94cb3bf021fc62aa301f0cb849936968164ef23/msgpack-1.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4efd7b5979ccb539c221a4c4e16aac1a533efc97f3b759bb5a5ac9f6d10383bf", size = 81212, upload-time = "2025-10-08T09:15:14.552Z" }, - { url = "https://files.pythonhosted.org/packages/92/dc/c385f38f2c2433333345a82926c6bfa5ecfff3ef787201614317b58dd8be/msgpack-1.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:42eefe2c3e2af97ed470eec850facbe1b5ad1d6eacdbadc42ec98e7dcf68b4b7", size = 84315, upload-time = "2025-10-08T09:15:15.543Z" }, - { url = "https://files.pythonhosted.org/packages/d3/68/93180dce57f684a61a88a45ed13047558ded2be46f03acb8dec6d7c513af/msgpack-1.1.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1fdf7d83102bf09e7ce3357de96c59b627395352a4024f6e2458501f158bf999", size = 412721, upload-time = "2025-10-08T09:15:16.567Z" }, - { url = "https://files.pythonhosted.org/packages/5d/ba/459f18c16f2b3fc1a1ca871f72f07d70c07bf768ad0a507a698b8052ac58/msgpack-1.1.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fac4be746328f90caa3cd4bc67e6fe36ca2bf61d5c6eb6d895b6527e3f05071e", size = 424657, upload-time = "2025-10-08T09:15:17.825Z" }, - { url = "https://files.pythonhosted.org/packages/38/f8/4398c46863b093252fe67368b44edc6c13b17f4e6b0e4929dbf0bdb13f23/msgpack-1.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fffee09044073e69f2bad787071aeec727183e7580443dfeb8556cbf1978d162", size = 402668, upload-time = "2025-10-08T09:15:19.003Z" }, - { url = "https://files.pythonhosted.org/packages/28/ce/698c1eff75626e4124b4d78e21cca0b4cc90043afb80a507626ea354ab52/msgpack-1.1.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5928604de9b032bc17f5099496417f113c45bc6bc21b5c6920caf34b3c428794", size = 419040, upload-time = "2025-10-08T09:15:20.183Z" }, - { url = "https://files.pythonhosted.org/packages/67/32/f3cd1667028424fa7001d82e10ee35386eea1408b93d399b09fb0aa7875f/msgpack-1.1.2-cp313-cp313-win32.whl", hash = "sha256:a7787d353595c7c7e145e2331abf8b7ff1e6673a6b974ded96e6d4ec09f00c8c", size = 65037, upload-time = "2025-10-08T09:15:21.416Z" }, - { url = "https://files.pythonhosted.org/packages/74/07/1ed8277f8653c40ebc65985180b007879f6a836c525b3885dcc6448ae6cb/msgpack-1.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:a465f0dceb8e13a487e54c07d04ae3ba131c7c5b95e2612596eafde1dccf64a9", size = 72631, upload-time = "2025-10-08T09:15:22.431Z" }, - { url = "https://files.pythonhosted.org/packages/e5/db/0314e4e2db56ebcf450f277904ffd84a7988b9e5da8d0d61ab2d057df2b6/msgpack-1.1.2-cp313-cp313-win_arm64.whl", hash = "sha256:e69b39f8c0aa5ec24b57737ebee40be647035158f14ed4b40e6f150077e21a84", size = 64118, upload-time = "2025-10-08T09:15:23.402Z" }, + { url = "https://files.pythonhosted.org/packages/5b/16/f70100614b69feb3ade7285f08c9c52d6cda0a5c03f3f5e2facd63acb211/msgpack-1.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8c7b398c56ff125feae96c2737abfec5595f1fa0aa186df60c56040b8accb95c", size = 82926, upload-time = "2026-06-18T16:12:31.531Z" }, + { url = "https://files.pythonhosted.org/packages/e4/3c/08ecd5cdfe4e2de43aec79062028ad0f7b2d9b1fea5430068c198ba570da/msgpack-1.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1548006a91aa93c5da81f3bdcebc1a0d10cea2d25969754fbe848da622b2b895", size = 82730, upload-time = "2026-06-18T16:12:32.894Z" }, + { url = "https://files.pythonhosted.org/packages/19/9f/a70c9cb1a04ecc134005149367dcfe35d167284e8f65035a1e4156ad17b5/msgpack-1.2.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1dabedcd0f23559f3596428c6589c1cd8c6eaed3a0d720795b07b0225d769203", size = 400729, upload-time = "2026-06-18T16:12:34.052Z" }, + { url = "https://files.pythonhosted.org/packages/fa/7f/5ce020168cf0439041526e95aa068c722c016aee21624e331aeabeee2e8e/msgpack-1.2.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:83efa1c898e0fc5380fc0cabbf75164c52e3b5cbb45973710d75821928380c73", size = 407625, upload-time = "2026-06-18T16:12:35.239Z" }, + { url = "https://files.pythonhosted.org/packages/79/70/fb7668ce0386819303047057aef6fc1da73b584291d9cff82b821744e2ef/msgpack-1.2.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:01e2dd6c9b19d333a00282330cc8a73d38d8dabc306dc5b42cd668c3ac82e833", size = 377891, upload-time = "2026-06-18T16:12:36.684Z" }, + { url = "https://files.pythonhosted.org/packages/3d/dc/9ebe654a73c3aed2e40aa6b52e3c2a02b5f53ef0085fa235a45d5b367f87/msgpack-1.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:350cb813d0af6e65d2f7ef0d729f7ff5be5a8bce03665892f43e5883d4ecc1b8", size = 391987, upload-time = "2026-06-18T16:12:37.839Z" }, + { url = "https://files.pythonhosted.org/packages/42/eb/b67cf64218a2fa25e1c671fe1d3dbb06cbeb973e71bc4b822da079862d0b/msgpack-1.2.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:ee1d9ed27d0497b848923746cf762ed2e7db24f4be7eec8e5cbe8c766aa707b7", size = 374603, upload-time = "2026-06-18T16:12:39.221Z" }, + { url = "https://files.pythonhosted.org/packages/a2/2e/9ee200cde32fd1a0101b4006202fde554c1860adfb9bf7bff31ea4c08df8/msgpack-1.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:633727297ed063441fd1cda2288865487f33ad14eeb8831afb5f0c396a62cfce", size = 405121, upload-time = "2026-06-18T16:12:40.524Z" }, + { url = "https://files.pythonhosted.org/packages/43/b6/f10117be7ca7a51e8feed699a907b8e663a8cd66e115ae6b4fb30cc7945c/msgpack-1.2.1-cp310-cp310-win32.whl", hash = "sha256:298872ecf9e61950f1c6af4ca969b859ee91783bb920ef6e6172697d0c8aad74", size = 64088, upload-time = "2026-06-18T16:12:41.762Z" }, + { url = "https://files.pythonhosted.org/packages/ba/93/89976c696fb0224662239d952c47b4d1661b34d79a332ef5584facaa8579/msgpack-1.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:2ff164c1b0bcb740b073b99e945234d0212852fa378e44a208c425379140dbeb", size = 70113, upload-time = "2026-06-18T16:12:42.78Z" }, + { url = "https://files.pythonhosted.org/packages/f4/6b/e9b1cdc042c4458801d2545ed782a95f3d6ba8e270cce8745b8603c7f748/msgpack-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:29a3f6e9667868429d8240dfd063ea5ffdc1321c13d783aa23827a38de0dcb22", size = 82812, upload-time = "2026-06-18T16:12:45.022Z" }, + { url = "https://files.pythonhosted.org/packages/0c/3a/dd518a1bf78ed1e9ad8afe57307c079a00eafe4b3068932a27ca1ea56b4f/msgpack-1.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:aded5bdf32609dc7987a49bbbd15a8ef096193f96dd8bbeb791de729e650acf5", size = 82739, upload-time = "2026-06-18T16:12:46.025Z" }, + { url = "https://files.pythonhosted.org/packages/70/e0/7ba9e1542bf0771a27b8b37c1316e3f95ae9d748fd765284655c476ad4ef/msgpack-1.2.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:146ee4e9ce80b365c6d4c47073da9da7bcec473e58194ceee5dd7620ace77e06", size = 414233, upload-time = "2026-06-18T16:12:47.029Z" }, + { url = "https://files.pythonhosted.org/packages/03/8d/671d81534ea0e2b0e8a121be100020da09eb78861fe3aa8f3ef7dcd3bed1/msgpack-1.2.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a28d076ca7c82b9c8728ad90b7147489449557038bed50e4241eb832395169b4", size = 423843, upload-time = "2026-06-18T16:12:48.19Z" }, + { url = "https://files.pythonhosted.org/packages/d2/b6/e5c737515ed1f166664b87601b532f58cbb73d8aa6a90b99f7c2c5037e8e/msgpack-1.2.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7d31c0ac0c640f877804c67cb2bc9f4e23dc2db97e96c2e67fa27d38283b41f8", size = 390772, upload-time = "2026-06-18T16:12:49.624Z" }, + { url = "https://files.pythonhosted.org/packages/a8/46/62ed8c2e87d7021eab19921594d961ef3aa3794eec76c716dc30f3bfd433/msgpack-1.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8ff92d7feeaf5bc26c51495b69e2f99ed97ab79346fb6555f44be7dd2ac6503b", size = 409559, upload-time = "2026-06-18T16:12:50.936Z" }, + { url = "https://files.pythonhosted.org/packages/70/ff/59aa3887b860bbf43532835e192b1c388a17590d6068ae4f8b2bc74c906e/msgpack-1.2.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:779197a6513bab3c3632265e3d0f7cb3227e62510841a6f34f1eaa37efbb345e", size = 387838, upload-time = "2026-06-18T16:12:52.161Z" }, + { url = "https://files.pythonhosted.org/packages/09/11/f8563e471093420cf6478cb3271a0175d8402b82d879783d4035d2d03360/msgpack-1.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:67f6dd22fa72a93752643f07889796d62739a13415ee630169a8ce764f86cf9f", size = 421732, upload-time = "2026-06-18T16:12:53.556Z" }, + { url = "https://files.pythonhosted.org/packages/57/cf/e673683c4c6c90c1022b24c65af4b03eda72b182a1176ef6449069d66acc/msgpack-1.2.1-cp311-cp311-win32.whl", hash = "sha256:91054a783328e0ea7954b8771095705c8d2243b814743fbaadf14552c9c52c5d", size = 64091, upload-time = "2026-06-18T16:12:54.821Z" }, + { url = "https://files.pythonhosted.org/packages/3f/07/ca212739d179f9083bff2c7c08c24101c3555a334fadc2b876b18768a3ae/msgpack-1.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2eda0b7ebb1283a98d3e4492ac933c8af6aff59fd3df1c3ed024f536af4b1dc8", size = 70462, upload-time = "2026-06-18T16:12:55.898Z" }, + { url = "https://files.pythonhosted.org/packages/6d/be/6798347b425e26f35db82e69dd83c09716c856a3714e7bffc4c0860fd830/msgpack-1.2.1-cp311-cp311-win_arm64.whl", hash = "sha256:6ee967f7c7e1df2890c671ff2ee51a28ded0efc95da3e507176dee881ce36c66", size = 65059, upload-time = "2026-06-18T16:12:57.053Z" }, + { url = "https://files.pythonhosted.org/packages/bc/dd/9e8cbd8f5582ca4b590336f2b91ee5662f6a6ca562b565abaf696a0f81ff/msgpack-1.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2ef59c659f289eddf8aa6623823f19fa2f40a4029266889eac7a2505dd210c35", size = 83531, upload-time = "2026-06-18T16:12:58.249Z" }, + { url = "https://files.pythonhosted.org/packages/50/2e/ebdb85a8da151397a2790363676b7ed7c125924fe618e4c6d8befb0cc62c/msgpack-1.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d3567748a5107cb40cdf66a275430c2f87c07777698f4bfd25c35f44d533258c", size = 82657, upload-time = "2026-06-18T16:12:59.396Z" }, + { url = "https://files.pythonhosted.org/packages/26/aa/753ad8b007b464e1d8aa0c8e650b9c5f4f725e658fc5ac8a7635c55b7f6e/msgpack-1.2.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:60926b75d00c8e816ef98f3034f484a8bc64242d66839cef4cf7e503142316a0", size = 410634, upload-time = "2026-06-18T16:13:00.383Z" }, + { url = "https://files.pythonhosted.org/packages/6a/fd/6adabd4f6d5e686f97dd02ce7fce3fe4cf672cbac36b8f67ff4040e8ad8b/msgpack-1.2.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:020e881a764b20d8d7ca1a54fc01b8175519d108e3c3f194fddc200bda95951a", size = 419989, upload-time = "2026-06-18T16:13:01.776Z" }, + { url = "https://files.pythonhosted.org/packages/5a/cc/85039b7b0eb168aaad7383a23c97e291a11f08351cb45a606ce865e4e3f1/msgpack-1.2.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4202c74688ca06591f78cb18988228bd4cca2cc75d57b60008372892d2f1e6e6", size = 377544, upload-time = "2026-06-18T16:13:03.637Z" }, + { url = "https://files.pythonhosted.org/packages/ed/bf/35963899493b32030c85fc513b723ae66144ac70c11ebc52e889e16e3d99/msgpack-1.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8b267ce94efb76fbd1b3373511420074ee3187f0f7811bf394531de13294735a", size = 400842, upload-time = "2026-06-18T16:13:05.012Z" }, + { url = "https://files.pythonhosted.org/packages/a6/df/8e2ac970c8f99264cd9997d1c73df5466bc19da3301d7dc5500862a9b089/msgpack-1.2.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:e4f1d0f8f98ade9634e01fb704a408f9336c0a8f1117b369f5db83dc7551d8b1", size = 374108, upload-time = "2026-06-18T16:13:06.232Z" }, + { url = "https://files.pythonhosted.org/packages/17/dd/fa8bd265110dfa51c20cb529f9e6d240a16fafe7e645004c6af2d01353ba/msgpack-1.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f02cf17a6ca1abe29b5f980644f7551f94d71f2011509b26d8625ce038f0df64", size = 414939, upload-time = "2026-06-18T16:13:07.478Z" }, + { url = "https://files.pythonhosted.org/packages/2e/b9/8377a5ad8953fc0437c70cc98d9ae29f27fe5ac5109fbec0812085865735/msgpack-1.2.1-cp312-cp312-win32.whl", hash = "sha256:0c0d9802354507bcba62af19c17918e3eb437cc25e6f50657d511b5856a77aac", size = 64504, upload-time = "2026-06-18T16:13:08.822Z" }, + { url = "https://files.pythonhosted.org/packages/57/7f/ce1e377df7e62461fefd9eb23bfb93a4a523f40a517b377b8f844d836828/msgpack-1.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:5c24aa15d5963051e1a5c62b12c50cd705992502b5ec1f3bece6046f33c9fc24", size = 71421, upload-time = "2026-06-18T16:13:09.828Z" }, + { url = "https://files.pythonhosted.org/packages/8f/32/ebfe84c9929f08f188d56c7a2fd913406a9ddad76a634697c1c43b8112e6/msgpack-1.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:4227224aaec8f7fbcbfbd4272319347b2bb4030366502600f8c45588c5187b07", size = 64775, upload-time = "2026-06-18T16:13:11.056Z" }, + { url = "https://files.pythonhosted.org/packages/b0/ac/dcddcab6f6c20ecb387ca5e980371cdb3f87ff69aeca388be97eebc4c074/msgpack-1.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0a70e3cf2804a300d921bb0940426e35f4e489a23adfb77a808892241db0a064", size = 83151, upload-time = "2026-06-18T16:13:12.173Z" }, + { url = "https://files.pythonhosted.org/packages/64/71/fbcfa83a1d6a9c6091942d1cfd070962244664b87427a9a49a6897b1b219/msgpack-1.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:491cc39455ca765fad51fb451bf2915eb2cf41192ab5801ce8d67c1d614fe056", size = 82351, upload-time = "2026-06-18T16:13:13.194Z" }, + { url = "https://files.pythonhosted.org/packages/e3/10/ddf7b06db879e8792d13934ddda09ff20bd2a583fd84c9b59aae9b0e650b/msgpack-1.2.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f310233ef7fb9c14e201c93639fe5f5260b005f56f0b29048e999c30935596cc", size = 407518, upload-time = "2026-06-18T16:13:14.233Z" }, + { url = "https://files.pythonhosted.org/packages/79/d3/36a46a8ed992b781acbc05928bd5bee3c810cb0c3563bf81a7b0c04a1a76/msgpack-1.2.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:787c9bebb5833e8f6fc8abca3c0597683d8d87f56a8842b6b89c75a5f3176e2d", size = 416405, upload-time = "2026-06-18T16:13:15.435Z" }, + { url = "https://files.pythonhosted.org/packages/f9/84/e8e9598b557c0ba6ddae901a73780a4c75ac667dddf59414b1e56a42fb34/msgpack-1.2.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dc871b997a9370d855b7394465f2f350e847a5b806dd38dcc9c989e7d87da155", size = 376257, upload-time = "2026-06-18T16:13:17.022Z" }, + { url = "https://files.pythonhosted.org/packages/40/16/738fe6d875ad7e2a9429c165322a4ec088f4f273cdfae63d96a89c467961/msgpack-1.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:85f57e960d877f2977f6430896191b04a21f8901b3b4baf2e4604329f4db5402", size = 397469, upload-time = "2026-06-18T16:13:18.287Z" }, + { url = "https://files.pythonhosted.org/packages/ca/be/6d5952df75a7f24f35833af764c3a6860780364cb3a0030beb8099e1b2b4/msgpack-1.2.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:1233ee2dd0cefba127583de50ea654677277047d238303521db35def3d7b2e7c", size = 372802, upload-time = "2026-06-18T16:13:19.685Z" }, + { url = "https://files.pythonhosted.org/packages/e1/39/e2ef7dbf0473bcb8dc7c50bf782a892d67414877b63e47fc88eb189ef5e6/msgpack-1.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e3dc2feb0876209d9c38aa56cb1de169bd6c4348f1aa48271f241226590993e6", size = 411273, upload-time = "2026-06-18T16:13:21.028Z" }, + { url = "https://files.pythonhosted.org/packages/ef/c5/133f4512a56e983a93445c836c9d94d88f3bc2e0980ff4b9e577bd8416ce/msgpack-1.2.1-cp313-cp313-win32.whl", hash = "sha256:6d09badf350af2be9d189184e04e64cf54ad93569ab3d96fca58bd3e84aad707", size = 64471, upload-time = "2026-06-18T16:13:22.293Z" }, + { url = "https://files.pythonhosted.org/packages/e2/98/577e10b055096a7dd40732358cabaf7180a20c79ed1dcdbb618e4b9deac7/msgpack-1.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:33f14fba63278b714efe6ad07e50ea5f03d91537aa6a1c5f1ceca4cf44013ca9", size = 71274, upload-time = "2026-06-18T16:13:23.455Z" }, + { url = "https://files.pythonhosted.org/packages/ba/ee/0c0048e7cfbef23c6a94791b8959ab28155232e7956de8a305b5ff588f05/msgpack-1.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:afc5febcd4c99effbc02b528e49d6fd0760b2b7d48c05239e345a5fa6e743d9a", size = 64795, upload-time = "2026-06-18T16:13:24.687Z" }, ] [[package]] @@ -6989,16 +7001,16 @@ wheels = [ [[package]] name = "pydantic-settings" -version = "2.14.1" +version = "2.14.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, { name = "python-dotenv" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/07/60/1d1e59c9c90d54591469ada7d268251f71c24bdb765f1a8a832cee8c6653/pydantic_settings-2.14.1.tar.gz", hash = "sha256:e874d3bec7e787b0c9958277956ed9b4dd5de6a80e162188fdaff7c5e26fd5fa", size = 235551, upload-time = "2026-05-08T13:40:06.542Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5c/b5/8f48e906c3e0205276e8bd8cb7512217a87b2685304d64be27cad5b3019f/pydantic_settings-2.14.2.tar.gz", hash = "sha256:c19dd64b19097f1de80184f0cc7b0272a13ae6e170cbf240a3e27e381ed14a5f", size = 237700, upload-time = "2026-06-19T13:44:56.324Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/8d/f1af3832f5e6eb13ba94ee809e72b8ecb5eef226d27ee0bef7d963d943c7/pydantic_settings-2.14.1-py3-none-any.whl", hash = "sha256:6e3c7edfd8277687cdc598f56e5cff0e9bfff0910a3749deaa8d4401c3a2b9de", size = 60964, upload-time = "2026-05-08T13:40:04.958Z" }, + { url = "https://files.pythonhosted.org/packages/77/c1/6e422f34e569cf8e18df68d1939c81c099d2b61e4f7d9621c8a77560799c/pydantic_settings-2.14.2-py3-none-any.whl", hash = "sha256:a20c97b37910b6550d5ea50fbcc2d4187defe58cd57070b73863d069419c9440", size = 61715, upload-time = "2026-06-19T13:44:55.02Z" }, ] [[package]] @@ -9698,17 +9710,15 @@ wheels = [ [[package]] name = "vcrpy" -version = "7.0.0" +version = "8.2.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pyyaml" }, - { name = "urllib3" }, { name = "wrapt" }, - { name = "yarl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/25/d3/856e06184d4572aada1dd559ddec3bedc46df1f2edc5ab2c91121a2cccdb/vcrpy-7.0.0.tar.gz", hash = "sha256:176391ad0425edde1680c5b20738ea3dc7fb942520a48d2993448050986b3a50", size = 85502, upload-time = "2024-12-31T00:07:57.894Z" } +sdist = { url = "https://files.pythonhosted.org/packages/08/db/08183b845b0040bb877dad2bd7e4e0976fc232bb3476d7ee369c6c4f8b5a/vcrpy-8.2.1.tar.gz", hash = "sha256:d73a6e4eb6dae8148e659764b7a00e68cc51ba29ba9e6a85e1f0790ad96b97df", size = 90511, upload-time = "2026-06-16T13:20:52.906Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/13/5d/1f15b252890c968d42b348d1e9b0aa12d5bf3e776704178ec37cceccdb63/vcrpy-7.0.0-py2.py3-none-any.whl", hash = "sha256:55791e26c18daa363435054d8b35bd41a4ac441b6676167635d1b37a71dbe124", size = 42321, upload-time = "2024-12-31T00:07:55.277Z" }, + { url = "https://files.pythonhosted.org/packages/f8/7c/0e812ab83f5289404c674f3461ba783250b967d34b5ab034d361236ec042/vcrpy-8.2.1-py3-none-any.whl", hash = "sha256:7ce58c9e2792b246f79d6f4b3e9660676cc6f853be17e1547305b4437ab1ff85", size = 44925, upload-time = "2026-06-16T13:20:51.734Z" }, ] [[package]]