mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-04-15 23:42:37 +00:00
fix: deduplicate coerce_skill_paths and activate pre-loaded METADATA skills
This commit is contained in:
@@ -66,7 +66,7 @@ from crewai.mcp.tool_resolver import MCPToolResolver
|
||||
from crewai.rag.embeddings.types import EmbedderConfig
|
||||
from crewai.security.fingerprint import Fingerprint
|
||||
from crewai.skills.loader import activate_skill, discover_skills
|
||||
from crewai.skills.models import Skill as SkillModel
|
||||
from crewai.skills.models import DisclosureLevel, Skill as SkillModel
|
||||
from crewai.tools.agent_tools.agent_tools import AgentTools
|
||||
from crewai.utilities.agent_utils import (
|
||||
get_tool_names,
|
||||
@@ -296,11 +296,10 @@ class Agent(BaseAgent):
|
||||
raise ValueError(f"Invalid Knowledge Configuration: {e!s}") from e
|
||||
|
||||
def set_skills(self) -> None:
|
||||
"""Resolve skill paths into loaded Skill objects.
|
||||
"""Resolve skill paths and activate skills to INSTRUCTIONS level.
|
||||
|
||||
Path entries trigger discovery and activation. Skill entries pass through.
|
||||
Crew-level skill paths are merged in. Skips work when all items are
|
||||
already resolved and there are no crew-level paths to merge.
|
||||
Path entries trigger discovery and activation. Pre-loaded Skill objects
|
||||
below INSTRUCTIONS level are activated. Crew-level skills are merged in.
|
||||
"""
|
||||
from crewai.crew import Crew
|
||||
|
||||
@@ -313,8 +312,15 @@ class Agent(BaseAgent):
|
||||
if not self.skills and not crew_skills:
|
||||
return
|
||||
|
||||
has_unresolved = self.skills and any(isinstance(s, Path) for s in self.skills)
|
||||
if not has_unresolved and not crew_skills:
|
||||
needs_work = self.skills and any(
|
||||
isinstance(s, Path)
|
||||
or (
|
||||
isinstance(s, SkillModel)
|
||||
and s.disclosure_level < DisclosureLevel.INSTRUCTIONS
|
||||
)
|
||||
for s in self.skills
|
||||
)
|
||||
if not needs_work and not crew_skills:
|
||||
return
|
||||
|
||||
seen: set[str] = set()
|
||||
|
||||
@@ -31,6 +31,7 @@ from crewai.mcp.config import MCPServerConfig
|
||||
from crewai.rag.embeddings.types import EmbedderConfig
|
||||
from crewai.security.security_config import SecurityConfig
|
||||
from crewai.skills.models import Skill
|
||||
from crewai.skills.validation import coerce_skill_paths as _coerce_skill_paths
|
||||
from crewai.tools.base_tool import BaseTool, Tool
|
||||
from crewai.utilities.config import process_config
|
||||
from crewai.utilities.i18n import I18N, get_i18n
|
||||
@@ -225,9 +226,7 @@ class BaseAgent(BaseModel, ABC, metaclass=AgentMeta):
|
||||
@classmethod
|
||||
def coerce_skill_paths(cls, v: list[Any] | None) -> list[Path | Skill] | None:
|
||||
"""Coerce string entries to Path objects."""
|
||||
if not v:
|
||||
return v
|
||||
return [Path(item) if isinstance(item, str) else item for item in v]
|
||||
return _coerce_skill_paths(v)
|
||||
|
||||
@model_validator(mode="before")
|
||||
@classmethod
|
||||
|
||||
@@ -90,6 +90,7 @@ from crewai.rag.types import SearchResult
|
||||
from crewai.security.fingerprint import Fingerprint
|
||||
from crewai.security.security_config import SecurityConfig
|
||||
from crewai.skills.models import Skill
|
||||
from crewai.skills.validation import coerce_skill_paths as _coerce_skill_paths
|
||||
from crewai.task import Task
|
||||
from crewai.tasks.conditional_task import ConditionalTask
|
||||
from crewai.tasks.task_output import TaskOutput
|
||||
@@ -302,9 +303,7 @@ class Crew(FlowTrackable, BaseModel):
|
||||
@classmethod
|
||||
def coerce_skill_paths(cls, v: list[Any] | None) -> list[Path | Skill] | None:
|
||||
"""Coerce string entries to Path objects, pass through Skill instances."""
|
||||
if not v:
|
||||
return v
|
||||
return [Path(item) if isinstance(item, str) else item for item in v]
|
||||
return _coerce_skill_paths(v)
|
||||
|
||||
security_config: SecurityConfig = Field(
|
||||
default_factory=SecurityConfig,
|
||||
|
||||
@@ -16,6 +16,7 @@ from crewai.skills.models import (
|
||||
SkillFrontmatter,
|
||||
)
|
||||
from crewai.skills.parser import SkillParseError, parse_skill_md
|
||||
from crewai.skills.validation import coerce_skill_paths
|
||||
|
||||
|
||||
__all__ = [
|
||||
@@ -25,6 +26,7 @@ __all__ = [
|
||||
"SkillFrontmatter",
|
||||
"SkillParseError",
|
||||
"activate_skill",
|
||||
"coerce_skill_paths",
|
||||
"discover_skills",
|
||||
"format_skill_context",
|
||||
"load_resources",
|
||||
|
||||
@@ -6,6 +6,7 @@ Validates skill names and directory structures per the Agent Skills standard.
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
MAX_SKILL_NAME_LENGTH: int = 64
|
||||
@@ -13,6 +14,20 @@ MIN_SKILL_NAME_LENGTH: int = 1
|
||||
SKILL_NAME_PATTERN: str = r"^[a-z0-9]+(?:-[a-z0-9]+)*$"
|
||||
|
||||
|
||||
def coerce_skill_paths(v: list[Any] | None) -> list[Any] | None:
|
||||
"""Coerce string entries to Path objects, pass through other types.
|
||||
|
||||
Args:
|
||||
v: List of skill paths or Skill objects, or None.
|
||||
|
||||
Returns:
|
||||
The list with string entries converted to Path objects, or None.
|
||||
"""
|
||||
if not v:
|
||||
return v
|
||||
return [Path(item) if isinstance(item, str) else item for item in v]
|
||||
|
||||
|
||||
def validate_directory_name(skill_dir: Path, skill_name: str) -> None:
|
||||
"""Validate that a directory name matches the skill name.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user