diff --git a/lib/crewai/src/crewai/files/__init__.py b/lib/crewai/src/crewai/files/__init__.py index 6fef629c6..d86767871 100644 --- a/lib/crewai/src/crewai/files/__init__.py +++ b/lib/crewai/src/crewai/files/__init__.py @@ -6,24 +6,25 @@ from crewai.files.cleanup import ( cleanup_uploaded_files, ) from crewai.files.content_types import ( - AudioContentType, AudioExtension, AudioFile, + AudioMimeType, BaseFile, File, + FileInput, FileMode, - ImageContentType, ImageExtension, ImageFile, + ImageMimeType, PDFContentType, PDFExtension, PDFFile, TextContentType, TextExtension, TextFile, - VideoContentType, VideoExtension, VideoFile, + VideoMimeType, ) from crewai.files.file import ( FileBytes, @@ -74,9 +75,6 @@ from crewai.files.upload_cache import ( from crewai.files.uploaders import FileUploader, UploadResult, get_uploader -FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile - - def wrap_file_source(source: FileSource) -> FileInput: """Wrap a FileSource in the appropriate typed FileInput wrapper. @@ -146,9 +144,9 @@ __all__ = [ "GEMINI_CONSTRAINTS", "OPENAI_CONSTRAINTS", "AudioConstraints", - "AudioContentType", "AudioExtension", "AudioFile", + "AudioMimeType", "BaseFile", "CachedUpload", "File", @@ -169,9 +167,9 @@ __all__ = [ "FileUploader", "FileValidationError", "ImageConstraints", - "ImageContentType", "ImageExtension", "ImageFile", + "ImageMimeType", "InlineBase64", "InlineBytes", "PDFConstraints", @@ -191,9 +189,9 @@ __all__ = [ "UploadResult", "UrlReference", "VideoConstraints", - "VideoContentType", "VideoExtension", "VideoFile", + "VideoMimeType", "cleanup_expired_files", "cleanup_provider_files", "cleanup_uploaded_files", diff --git a/lib/crewai/src/crewai/files/content_types.py b/lib/crewai/src/crewai/files/content_types.py index 711c9e134..ae5a96d97 100644 --- a/lib/crewai/src/crewai/files/content_types.py +++ b/lib/crewai/src/crewai/files/content_types.py @@ -70,9 +70,19 @@ FileMode = Literal["strict", "auto", "warn", "chunk"] ImageExtension = Literal[ - ".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp", ".tiff", ".tif", ".svg" + ".png", + ".jpg", + ".jpeg", + ".gif", + ".webp", + ".bmp", + ".tiff", + ".tif", + ".svg", + ".heic", + ".heif", ] -ImageContentType = Literal[ +ImageMimeType = Literal[ "image/png", "image/jpeg", "image/gif", @@ -80,6 +90,8 @@ ImageContentType = Literal[ "image/bmp", "image/tiff", "image/svg+xml", + "image/heic", + "image/heif", ] PDFExtension = Literal[".pdf"] @@ -116,13 +128,15 @@ TextContentType = Literal[ AudioExtension = Literal[ ".mp3", ".wav", ".ogg", ".flac", ".aac", ".m4a", ".wma", ".aiff", ".opus" ] -AudioContentType = Literal[ +AudioMimeType = Literal[ + "audio/mp3", "audio/mpeg", "audio/wav", "audio/x-wav", "audio/ogg", "audio/flac", "audio/aac", + "audio/m4a", "audio/mp4", "audio/x-ms-wma", "audio/aiff", @@ -132,15 +146,15 @@ AudioContentType = Literal[ VideoExtension = Literal[ ".mp4", ".avi", ".mkv", ".mov", ".webm", ".flv", ".wmv", ".m4v", ".mpeg", ".mpg" ] -VideoContentType = Literal[ +VideoMimeType = Literal[ "video/mp4", + "video/mpeg", + "video/webm", + "video/quicktime", "video/x-msvideo", "video/x-matroska", - "video/quicktime", - "video/webm", "video/x-flv", "video/x-ms-wmv", - "video/mpeg", ] @@ -265,3 +279,6 @@ class File(BaseFile): >>> image_file = File(source="./image.png") >>> bytes_file = File(source=b"file content") """ + + +FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile diff --git a/lib/crewai/src/crewai/files/processing/constraints.py b/lib/crewai/src/crewai/files/processing/constraints.py index 0f580e21e..adf7cca86 100644 --- a/lib/crewai/src/crewai/files/processing/constraints.py +++ b/lib/crewai/src/crewai/files/processing/constraints.py @@ -3,35 +3,12 @@ from dataclasses import dataclass from typing import Literal +from crewai.files.content_types import ( + AudioMimeType, + ImageMimeType, + VideoMimeType, +) -ImageFormat = Literal[ - "image/png", - "image/jpeg", - "image/gif", - "image/webp", - "image/heic", - "image/heif", -] - -AudioFormat = Literal[ - "audio/mp3", - "audio/mpeg", - "audio/wav", - "audio/ogg", - "audio/flac", - "audio/aac", - "audio/m4a", - "audio/opus", -] - -VideoFormat = Literal[ - "video/mp4", - "video/mpeg", - "video/webm", - "video/quicktime", - "video/x-msvideo", - "video/x-flv", -] ProviderName = Literal[ "anthropic", @@ -41,15 +18,14 @@ ProviderName = Literal[ "azure", ] -# Pre-typed format tuples for common combinations -DEFAULT_IMAGE_FORMATS: tuple[ImageFormat, ...] = ( +DEFAULT_IMAGE_FORMATS: tuple[ImageMimeType, ...] = ( "image/png", "image/jpeg", "image/gif", "image/webp", ) -GEMINI_IMAGE_FORMATS: tuple[ImageFormat, ...] = ( +GEMINI_IMAGE_FORMATS: tuple[ImageMimeType, ...] = ( "image/png", "image/jpeg", "image/gif", @@ -58,7 +34,7 @@ GEMINI_IMAGE_FORMATS: tuple[ImageFormat, ...] = ( "image/heif", ) -DEFAULT_AUDIO_FORMATS: tuple[AudioFormat, ...] = ( +DEFAULT_AUDIO_FORMATS: tuple[AudioMimeType, ...] = ( "audio/mp3", "audio/mpeg", "audio/wav", @@ -68,7 +44,7 @@ DEFAULT_AUDIO_FORMATS: tuple[AudioFormat, ...] = ( "audio/m4a", ) -GEMINI_AUDIO_FORMATS: tuple[AudioFormat, ...] = ( +GEMINI_AUDIO_FORMATS: tuple[AudioMimeType, ...] = ( "audio/mp3", "audio/mpeg", "audio/wav", @@ -79,14 +55,14 @@ GEMINI_AUDIO_FORMATS: tuple[AudioFormat, ...] = ( "audio/opus", ) -DEFAULT_VIDEO_FORMATS: tuple[VideoFormat, ...] = ( +DEFAULT_VIDEO_FORMATS: tuple[VideoMimeType, ...] = ( "video/mp4", "video/mpeg", "video/webm", "video/quicktime", ) -GEMINI_VIDEO_FORMATS: tuple[VideoFormat, ...] = ( +GEMINI_VIDEO_FORMATS: tuple[VideoMimeType, ...] = ( "video/mp4", "video/mpeg", "video/webm", @@ -112,7 +88,7 @@ class ImageConstraints: max_width: int | None = None max_height: int | None = None max_images_per_request: int | None = None - supported_formats: tuple[ImageFormat, ...] = DEFAULT_IMAGE_FORMATS + supported_formats: tuple[ImageMimeType, ...] = DEFAULT_IMAGE_FORMATS @dataclass(frozen=True) @@ -140,7 +116,7 @@ class AudioConstraints: max_size_bytes: int max_duration_seconds: int | None = None - supported_formats: tuple[AudioFormat, ...] = DEFAULT_AUDIO_FORMATS + supported_formats: tuple[AudioMimeType, ...] = DEFAULT_AUDIO_FORMATS @dataclass(frozen=True) @@ -155,7 +131,7 @@ class VideoConstraints: max_size_bytes: int max_duration_seconds: int | None = None - supported_formats: tuple[VideoFormat, ...] = DEFAULT_VIDEO_FORMATS + supported_formats: tuple[VideoMimeType, ...] = DEFAULT_VIDEO_FORMATS @dataclass(frozen=True) diff --git a/lib/crewai/src/crewai/files/processing/processor.py b/lib/crewai/src/crewai/files/processing/processor.py index 7ee020216..70c665334 100644 --- a/lib/crewai/src/crewai/files/processing/processor.py +++ b/lib/crewai/src/crewai/files/processing/processor.py @@ -7,6 +7,7 @@ import logging from crewai.files.content_types import ( AudioFile, File, + FileInput, ImageFile, PDFFile, TextFile, @@ -36,8 +37,6 @@ from crewai.files.processing.validators import validate_file logger = logging.getLogger(__name__) -FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile - class FileProcessor: """Processes files according to provider constraints and per-file mode mode. diff --git a/lib/crewai/src/crewai/files/processing/validators.py b/lib/crewai/src/crewai/files/processing/validators.py index d764e05d0..b76aeced6 100644 --- a/lib/crewai/src/crewai/files/processing/validators.py +++ b/lib/crewai/src/crewai/files/processing/validators.py @@ -6,7 +6,7 @@ import logging from crewai.files.content_types import ( AudioFile, - File, + FileInput, ImageFile, PDFFile, TextFile, @@ -28,8 +28,6 @@ from crewai.files.processing.exceptions import ( logger = logging.getLogger(__name__) -FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile - def _get_image_dimensions(content: bytes) -> tuple[int, int] | None: """Get image dimensions using Pillow if available. diff --git a/lib/crewai/src/crewai/files/resolver.py b/lib/crewai/src/crewai/files/resolver.py index c6fff5b3f..75464d289 100644 --- a/lib/crewai/src/crewai/files/resolver.py +++ b/lib/crewai/src/crewai/files/resolver.py @@ -6,14 +6,7 @@ from dataclasses import dataclass, field import hashlib import logging -from crewai.files.content_types import ( - AudioFile, - File, - ImageFile, - PDFFile, - TextFile, - VideoFile, -) +from crewai.files.content_types import FileInput from crewai.files.metrics import measure_operation from crewai.files.processing.constraints import ( AudioConstraints, @@ -36,8 +29,6 @@ from crewai.files.uploaders.base import FileUploader logger = logging.getLogger(__name__) -FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile - UPLOAD_MAX_RETRIES = 3 UPLOAD_RETRY_DELAY_BASE = 2 diff --git a/lib/crewai/src/crewai/files/upload_cache.py b/lib/crewai/src/crewai/files/upload_cache.py index 0dc0282ea..799621e8d 100644 --- a/lib/crewai/src/crewai/files/upload_cache.py +++ b/lib/crewai/src/crewai/files/upload_cache.py @@ -17,16 +17,7 @@ from aiocache.serializers import PickleSerializer # type: ignore[import-untyped if TYPE_CHECKING: - from crewai.files.content_types import ( - AudioFile, - File, - ImageFile, - PDFFile, - TextFile, - VideoFile, - ) - - FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile + from crewai.files.content_types import FileInput logger = logging.getLogger(__name__) diff --git a/lib/crewai/src/crewai/files/uploaders/anthropic.py b/lib/crewai/src/crewai/files/uploaders/anthropic.py index df61daf3f..bf778c53f 100644 --- a/lib/crewai/src/crewai/files/uploaders/anthropic.py +++ b/lib/crewai/src/crewai/files/uploaders/anthropic.py @@ -7,22 +7,13 @@ import logging import os from typing import Any -from crewai.files.content_types import ( - AudioFile, - File, - ImageFile, - PDFFile, - TextFile, - VideoFile, -) +from crewai.files.content_types import FileInput from crewai.files.processing.exceptions import classify_upload_error from crewai.files.uploaders.base import FileUploader, UploadResult logger = logging.getLogger(__name__) -FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile - class AnthropicFileUploader(FileUploader): """Uploader for Anthropic Files API. diff --git a/lib/crewai/src/crewai/files/uploaders/base.py b/lib/crewai/src/crewai/files/uploaders/base.py index 47e7a5af3..83b02f52a 100644 --- a/lib/crewai/src/crewai/files/uploaders/base.py +++ b/lib/crewai/src/crewai/files/uploaders/base.py @@ -6,17 +6,7 @@ from dataclasses import dataclass from datetime import datetime from typing import Any -from crewai.files.content_types import ( - AudioFile, - File, - ImageFile, - PDFFile, - TextFile, - VideoFile, -) - - -FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile +from crewai.files.content_types import FileInput @dataclass diff --git a/lib/crewai/src/crewai/files/uploaders/bedrock.py b/lib/crewai/src/crewai/files/uploaders/bedrock.py index 20ae7313a..f0c7f0cb7 100644 --- a/lib/crewai/src/crewai/files/uploaders/bedrock.py +++ b/lib/crewai/src/crewai/files/uploaders/bedrock.py @@ -8,14 +8,7 @@ import os from pathlib import Path from typing import Any -from crewai.files.content_types import ( - AudioFile, - File, - ImageFile, - PDFFile, - TextFile, - VideoFile, -) +from crewai.files.content_types import FileInput from crewai.files.file import FileBytes, FilePath from crewai.files.processing.exceptions import ( PermanentUploadError, @@ -26,8 +19,6 @@ from crewai.files.uploaders.base import FileUploader, UploadResult logger = logging.getLogger(__name__) -FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile - MULTIPART_THRESHOLD = 8 * 1024 * 1024 MULTIPART_CHUNKSIZE = 8 * 1024 * 1024 MAX_CONCURRENCY = 10 diff --git a/lib/crewai/src/crewai/files/uploaders/gemini.py b/lib/crewai/src/crewai/files/uploaders/gemini.py index 73b0087a0..ff43964ef 100644 --- a/lib/crewai/src/crewai/files/uploaders/gemini.py +++ b/lib/crewai/src/crewai/files/uploaders/gemini.py @@ -12,14 +12,7 @@ import random import time from typing import Any -from crewai.files.content_types import ( - AudioFile, - File, - ImageFile, - PDFFile, - TextFile, - VideoFile, -) +from crewai.files.content_types import FileInput from crewai.files.file import FilePath from crewai.files.processing.exceptions import ( PermanentUploadError, @@ -31,8 +24,6 @@ from crewai.files.uploaders.base import FileUploader, UploadResult logger = logging.getLogger(__name__) -FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile - GEMINI_FILE_TTL = timedelta(hours=48) BACKOFF_BASE_DELAY = 1.0 diff --git a/lib/crewai/src/crewai/files/uploaders/openai.py b/lib/crewai/src/crewai/files/uploaders/openai.py index fd63a47ee..d251094a4 100644 --- a/lib/crewai/src/crewai/files/uploaders/openai.py +++ b/lib/crewai/src/crewai/files/uploaders/openai.py @@ -8,14 +8,7 @@ import logging import os from typing import Any -from crewai.files.content_types import ( - AudioFile, - File, - ImageFile, - PDFFile, - TextFile, - VideoFile, -) +from crewai.files.content_types import FileInput from crewai.files.file import FileBytes, FilePath, FileStream from crewai.files.processing.exceptions import ( PermanentUploadError, @@ -27,8 +20,6 @@ from crewai.files.uploaders.base import FileUploader, UploadResult logger = logging.getLogger(__name__) -FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile - FILES_API_MAX_SIZE = 512 * 1024 * 1024 DEFAULT_UPLOAD_CHUNK_SIZE = 64 * 1024 * 1024