diff --git a/src/crewai/agent.py b/src/crewai/agent.py index 11670d65a..63d5b5eee 100644 --- a/src/crewai/agent.py +++ b/src/crewai/agent.py @@ -303,9 +303,9 @@ class Agent(BaseModel): } if self._rpm_controller: - executor_args[ - "request_within_rpm_limit" - ] = self._rpm_controller.check_or_wait + executor_args["request_within_rpm_limit"] = ( + self._rpm_controller.check_or_wait + ) prompt = Prompts( i18n=self.i18n, diff --git a/src/crewai/cli/templates/tools/custom_tool.py b/src/crewai/cli/templates/tools/custom_tool.py index 4d60dc832..b12529303 100644 --- a/src/crewai/cli/templates/tools/custom_tool.py +++ b/src/crewai/cli/templates/tools/custom_tool.py @@ -3,7 +3,9 @@ from crewai_tools import BaseTool class MyCustomTool(BaseTool): name: str = "Name of my tool" - description: str = "Clear description for what this tool is useful for, you agent will need this information to use it." + description: str = ( + "Clear description for what this tool is useful for, you agent will need this information to use it." + ) def _run(self, argument: str) -> str: # Implementation goes here diff --git a/src/crewai/task.py b/src/crewai/task.py index 66d8ea6f2..5fd2b3367 100644 --- a/src/crewai/task.py +++ b/src/crewai/task.py @@ -1,8 +1,8 @@ +import os import re import threading import uuid from typing import Any, Dict, List, Optional, Type -import os from langchain_openai import ChatOpenAI from pydantic import UUID4, BaseModel, Field, field_validator, model_validator @@ -109,6 +109,14 @@ class Task(BaseModel): "may_not_set_field", "This field is not to be set by the user.", {} ) + @field_validator("output_file") + @classmethod + def output_file_validattion(cls, value: str) -> str: + """Validate the output file path by removing the / from the beginning of the path.""" + if value.startswith("/"): + return value[1:] + return value + @model_validator(mode="after") def set_attributes_based_on_config(self) -> "Task": """Set attributes based on the agent configuration.""" @@ -247,16 +255,16 @@ class Task(BaseModel): return exported_result.model_dump() return exported_result except Exception: - # sometimes the response contains valid JSON in the middle of text - match = re.search(r"({.*})", result, re.DOTALL) - if match: - try: - exported_result = model.model_validate_json(match.group(0)) - if self.output_json: - return exported_result.model_dump() - return exported_result - except Exception: - pass + # sometimes the response contains valid JSON in the middle of text + match = re.search(r"({.*})", result, re.DOTALL) + if match: + try: + exported_result = model.model_validate_json(match.group(0)) + if self.output_json: + return exported_result.model_dump() + return exported_result + except Exception: + pass llm = self.agent.function_calling_llm or self.agent.llm @@ -294,7 +302,7 @@ class Task(BaseModel): def _save_file(self, result: Any) -> None: directory = os.path.dirname(self.output_file) - if not os.path.exists(directory): + if directory and not os.path.exists(directory): os.makedirs(directory) with open(self.output_file, "w") as file: diff --git a/src/crewai/telemetry/telemetry.py b/src/crewai/telemetry/telemetry.py index 4d6f4a67f..067d1bb22 100644 --- a/src/crewai/telemetry/telemetry.py +++ b/src/crewai/telemetry/telemetry.py @@ -256,9 +256,11 @@ class Telemetry: "async_execution?": task.async_execution, "output": task.expected_output, "agent_role": task.agent.role if task.agent else "None", - "context": [task.description for task in task.context] - if task.context - else "None", + "context": ( + [task.description for task in task.context] + if task.context + else "None" + ), "tools_names": [ tool.name.casefold() for tool in task.tools ],