From ab20a3ac618a22d9a3f90662c82d806d95702e66 Mon Sep 17 00:00:00 2001 From: alex-clawd Date: Tue, 19 May 2026 12:45:40 -0700 Subject: [PATCH] style: ruff format + autofix remaining lint errors --- lib/cli/src/crewai_cli/cli.py | 2 +- lib/cli/src/crewai_cli/git.py | 2 +- lib/cli/src/crewai_cli/skills/main.py | 31 +++++++++++++-------- lib/crewai-core/src/crewai_core/plus_api.py | 4 ++- lib/crewai/src/crewai/agent/core.py | 7 ++++- lib/crewai/src/crewai/skills/cache.py | 18 +++++++++--- lib/crewai/src/crewai/skills/registry.py | 20 +++++++++---- 7 files changed, 59 insertions(+), 25 deletions(-) diff --git a/lib/cli/src/crewai_cli/cli.py b/lib/cli/src/crewai_cli/cli.py index 5d812e317..e2369970e 100644 --- a/lib/cli/src/crewai_cli/cli.py +++ b/lib/cli/src/crewai_cli/cli.py @@ -26,9 +26,9 @@ from crewai_cli.replay_from_task import replay_task_command from crewai_cli.reset_memories_command import reset_memories_command from crewai_cli.run_crew import run_crew from crewai_cli.settings.main import SettingsCommand +from crewai_cli.skills.main import SkillCommand from crewai_cli.task_outputs import load_task_outputs from crewai_cli.tools.main import ToolCommand -from crewai_cli.skills.main import SkillCommand from crewai_cli.train_crew import train_crew from crewai_cli.triggers.main import TriggersCommand from crewai_cli.update_crew import update_crew diff --git a/lib/cli/src/crewai_cli/git.py b/lib/cli/src/crewai_cli/git.py index 0b7600a76..b43e4d3cb 100644 --- a/lib/cli/src/crewai_cli/git.py +++ b/lib/cli/src/crewai_cli/git.py @@ -40,7 +40,7 @@ class Repository: encoding="utf-8", ).strip() - @cached_property # noqa: B019 + @cached_property def is_git_repo(self) -> bool: """Check if the current directory is a git repository.""" try: diff --git a/lib/cli/src/crewai_cli/skills/main.py b/lib/cli/src/crewai_cli/skills/main.py index 9aa6f6a31..a844f24ed 100644 --- a/lib/cli/src/crewai_cli/skills/main.py +++ b/lib/cli/src/crewai_cli/skills/main.py @@ -6,8 +6,8 @@ import base64 import io import json import os -import tarfile from pathlib import Path +import tarfile import zipfile from rich.console import Console @@ -71,9 +71,7 @@ class SkillCommand(BaseCommand, PlusAPIMixin): console.print( f"[green]Created skill [bold]{name}[/bold] at [bold]{skill_dir}[/bold].[/green]" ) - console.print( - f"Edit [bold]{skill_md}[/bold] to define the skill instructions." - ) + console.print(f"Edit [bold]{skill_md}[/bold] to define the skill instructions.") # ------------------------------------------------------------------ # install @@ -138,12 +136,16 @@ class SkillCommand(BaseCommand, PlusAPIMixin): f"[green]Installed [bold]{ref}[/bold]{' (' + version + ')' if version else ''} to [bold]{dest}[/bold].[/green]" ) else: - from crewai_core.plus_api import PlusAPI as _ # noqa: F401 (ensure crewai_core present) + from crewai_core.plus_api import ( + PlusAPI as _, # noqa: F401 (ensure crewai_core present) + ) + cache_dir = Path.home() / ".crewai" / "skills" / org / name cache_dir.mkdir(parents=True, exist_ok=True) self._unpack_archive(archive_bytes, cache_dir) - import json as _json from datetime import datetime, timezone + import json as _json + meta = { "org": org, "name": name, @@ -181,7 +183,9 @@ class SkillCommand(BaseCommand, PlusAPIMixin): description = frontmatter.get("description") if not name: - console.print("[red]SKILL.md frontmatter must include a 'name' field.[/red]") + console.print( + "[red]SKILL.md frontmatter must include a 'name' field.[/red]" + ) raise SystemExit(1) if not version: @@ -204,10 +208,9 @@ class SkillCommand(BaseCommand, PlusAPIMixin): ) archive_bytes = self._build_skill_zip() - encoded_file = ( - "data:application/zip;base64," - + base64.b64encode(archive_bytes).decode("utf-8") - ) + encoded_file = "data:application/zip;base64," + base64.b64encode( + archive_bytes + ).decode("utf-8") response = self.plus_api_client.publish_skill( org=effective_org, @@ -271,7 +274,9 @@ class SkillCommand(BaseCommand, PlusAPIMixin): str(skill_dir), ) except (json.JSONDecodeError, KeyError): - console.print(f"[yellow]Warning: skipping malformed cache entry at {meta_file}[/yellow]") + console.print( + f"[yellow]Warning: skipping malformed cache entry at {meta_file}[/yellow]" + ) console.print(table) @@ -312,11 +317,13 @@ class SkillCommand(BaseCommand, PlusAPIMixin): def _parse_frontmatter(self, content: str) -> dict[str, str]: """Extract YAML frontmatter fields from a SKILL.md string.""" import re + match = re.match(r"^---\n(.*?)\n---", content, re.DOTALL) if not match: raise ValueError("No YAML frontmatter block found") try: import yaml + return yaml.safe_load(match.group(1)) or {} except ImportError: # Minimal fallback: parse key: value lines diff --git a/lib/crewai-core/src/crewai_core/plus_api.py b/lib/crewai-core/src/crewai_core/plus_api.py index eccd69b24..c6ecf1a2a 100644 --- a/lib/crewai-core/src/crewai_core/plus_api.py +++ b/lib/crewai-core/src/crewai_core/plus_api.py @@ -229,7 +229,9 @@ class PlusAPI: } return self._make_request("POST", f"{self.TOOLS_RESOURCE}", json=params) - def get_skill(self, org: str, name: str, version: str | None = None) -> httpx.Response: + def get_skill( + self, org: str, name: str, version: str | None = None + ) -> httpx.Response: params: dict[str, str] = {} if version is not None: params["version"] = version diff --git a/lib/crewai/src/crewai/agent/core.py b/lib/crewai/src/crewai/agent/core.py index 1dc0ffc57..6ae09a581 100644 --- a/lib/crewai/src/crewai/agent/core.py +++ b/lib/crewai/src/crewai/agent/core.py @@ -462,7 +462,12 @@ class Agent(BaseAgent): for item in items: if isinstance(item, str): - from crewai.skills.registry import is_registry_ref, parse_registry_ref, resolve_registry_ref + from crewai.skills.registry import ( + is_registry_ref, + parse_registry_ref, + resolve_registry_ref, + ) + if is_registry_ref(item): skill = resolve_registry_ref(item, source=self) org, _ = parse_registry_ref(item) diff --git a/lib/crewai/src/crewai/skills/cache.py b/lib/crewai/src/crewai/skills/cache.py index 231ab93b1..d2cc6fe9a 100644 --- a/lib/crewai/src/crewai/skills/cache.py +++ b/lib/crewai/src/crewai/skills/cache.py @@ -6,13 +6,14 @@ One version is stored per skill (last install wins). from __future__ import annotations +from datetime import datetime, timezone import json import logging -import tarfile -from datetime import datetime, timezone from pathlib import Path +import tarfile from typing import TypedDict + _logger = logging.getLogger(__name__) @@ -44,7 +45,9 @@ class SkillCacheManager: return skill_dir return None - def store(self, org: str, name: str, version: str | None, archive_bytes: bytes) -> Path: + def store( + self, org: str, name: str, version: str | None, archive_bytes: bytes + ) -> Path: """Unpack an archive into the cache and write metadata. Uses tarfile with filter='data' for path-traversal protection. @@ -62,10 +65,12 @@ class SkillCacheManager: # Wipe any previous version if skill_dir.exists(): import shutil + shutil.rmtree(skill_dir) skill_dir.mkdir(parents=True, exist_ok=True) import io + with tarfile.open(fileobj=io.BytesIO(archive_bytes), mode="r:gz") as tf: try: tf.extractall(skill_dir, filter="data") @@ -96,7 +101,11 @@ class SkillCacheManager: try: results.append(json.loads(meta_file.read_text())) except (json.JSONDecodeError, KeyError): - _logger.debug("Skipping malformed cache entry: %s", meta_file, exc_info=True) + _logger.debug( + "Skipping malformed cache entry: %s", + meta_file, + exc_info=True, + ) return results def invalidate(self, org: str, name: str) -> bool: @@ -108,6 +117,7 @@ class SkillCacheManager: skill_dir = self._skill_dir(org, name) if skill_dir.exists(): import shutil + shutil.rmtree(skill_dir) return True return False diff --git a/lib/crewai/src/crewai/skills/registry.py b/lib/crewai/src/crewai/skills/registry.py index 5daa23138..965243ab7 100644 --- a/lib/crewai/src/crewai/skills/registry.py +++ b/lib/crewai/src/crewai/skills/registry.py @@ -7,12 +7,13 @@ via the CrewAI+ API with a global cache at ~/.crewai/skills/. from __future__ import annotations import logging -import sys from pathlib import Path +import sys from typing import Any from crewai.skills.cache import SkillCacheManager + _logger = logging.getLogger(__name__) @@ -62,6 +63,7 @@ def parse_registry_ref(ref: str) -> tuple[str, str]: def _is_noninteractive() -> bool: """Return True in CI or explicitly non-interactive environments.""" import os + return ( os.environ.get("CI") == "1" or os.environ.get("CREWAI_NONINTERACTIVE") == "1" @@ -72,7 +74,7 @@ def _is_noninteractive() -> bool: def resolve_registry_ref( ref: str, source: Any = None, -) -> "Skill": # type: ignore[name-defined] # noqa: F821 +) -> Skill: # type: ignore[name-defined] # noqa: F821 """Resolve a registry reference to a Skill object. Resolution order: @@ -112,7 +114,9 @@ def resolve_registry_ref( skill = load_skill_metadata(cached_path) return activate_skill(skill, source=source) except Exception: - _logger.debug("Failed to load cached skill at %s", cached_path, exc_info=True) + _logger.debug( + "Failed to load cached skill at %s", cached_path, exc_info=True + ) # 3. Download if _is_noninteractive(): @@ -125,7 +129,7 @@ def download_skill( org: str, name: str, source: Any = None, -) -> "Skill": # type: ignore[name-defined] # noqa: F821 +) -> Skill: # type: ignore[name-defined] # noqa: F821 """Download a skill from the registry and store it in the cache. Args: @@ -143,7 +147,11 @@ def download_skill( try: from crewai.events.event_bus import crewai_event_bus - from crewai.events.types.skill_events import SkillDownloadStartedEvent, SkillDownloadCompletedEvent + from crewai.events.types.skill_events import ( + SkillDownloadCompletedEvent, + SkillDownloadStartedEvent, + ) + _has_events = True except ImportError: _has_events = False @@ -158,6 +166,7 @@ def download_skill( try: from crewai_core.plus_api import PlusAPI + api = PlusAPI() response = api.get_skill(org, name) response.raise_for_status() @@ -168,6 +177,7 @@ def download_skill( ) from exc import base64 + encoded = data.get("file", "") # Strip data URI prefix if present if "," in encoded: