Encountered the same issue; looks like distutils
is deprecated from python 3.11 onwards. This is the workaround I’ve employed, which builds the distutils/strtobool
functionality directly into your project eliminating any dependency:
Within your project directory, edit the following file:
~/.venv/lib/python3.12/site-packages/crewai_tools/tools/file_writer_tool/file_writer_tool.py
Overwrite the contents of file_writer_tool.py
with:
import os
# from distutils.util import strtobool
# from setuptools._distutils.util import strtobool
def strtobool(val: str) -> bool:
"""Convert a string representation of truth to true (1) or false (0).
True values are 'y', 'yes', 't', 'true', 'on', and '1';
False values are 'n', 'no', 'f', 'false', 'off', and '0'.
Raises ValueError if 'val' is anything else.
"""
val = val.lower()
if val in ("y", "yes", "t", "true", "on", "1"):
return True
elif val in ("n", "no", "f", "false", "off", "0"):
return False
else:
raise ValueError(f"Invalid truth value: {val}")
from typing import Any, Optional, Type
from crewai.tools import BaseTool
from pydantic import BaseModel
class FileWriterToolInput(BaseModel):
filename: str
directory: Optional[str] = "./"
overwrite: str = "False"
content: str
class FileWriterTool(BaseTool):
name: str = "File Writer Tool"
description: str = "A tool to write content to a specified file. Accepts filename, content, and optionally a directory path and overwrite flag as input."
args_schema: Type[BaseModel] = FileWriterToolInput
def _run(self, **kwargs: Any) -> str:
try:
# Create the directory if it doesn't exist
if kwargs.get("directory") and not os.path.exists(kwargs["directory"]):
os.makedirs(kwargs["directory"])
# Construct the full path
filepath = os.path.join(kwargs.get("directory") or "", kwargs["filename"])
# Convert overwrite to boolean
kwargs["overwrite"] = bool(strtobool(kwargs["overwrite"]))
# Check if file exists and overwrite is not allowed
if os.path.exists(filepath) and not kwargs["overwrite"]:
return f"File {filepath} already exists and overwrite option was not passed."
# Write content to the file
mode = "w" if kwargs["overwrite"] else "x"
with open(filepath, mode) as file:
file.write(kwargs["content"])
return f"Content successfully written to {filepath}"
except FileExistsError:
return (
f"File {filepath} already exists and overwrite option was not passed."
)
except KeyError as e:
return f"An error occurred while accessing key: {str(e)}"
except Exception as e:
return f"An error occurred while writing to the file: {str(e)}"
Run crewai run
again and you should be good to go. If you’re using OpenAI, make sure you have billing turned on for your API usage and a payment method added (this is independent of ChatGPT billing).