mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-05-03 00:02:36 +00:00
fix: remove FilteredStream stdout/stderr wrapper
Wrapping sys.stdout and sys.stderr at import time with a threading.Lock is not fork-safe and adds overhead to every print call. litellm.suppress_debug_info already silences the noisy output this was designed to filter.
This commit is contained in:
@@ -3,18 +3,14 @@ from __future__ import annotations
|
||||
from collections import defaultdict
|
||||
from collections.abc import Callable
|
||||
from datetime import datetime
|
||||
import io
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import threading
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
Final,
|
||||
Literal,
|
||||
TextIO,
|
||||
TypedDict,
|
||||
cast,
|
||||
)
|
||||
@@ -102,72 +98,6 @@ if LITELLM_AVAILABLE:
|
||||
litellm.suppress_debug_info = True
|
||||
|
||||
|
||||
class FilteredStream(io.TextIOBase):
|
||||
_lock = None
|
||||
|
||||
def __init__(self, original_stream: TextIO):
|
||||
self._original_stream = original_stream
|
||||
self._lock = threading.Lock()
|
||||
|
||||
def write(self, s: str) -> int:
|
||||
if not self._lock:
|
||||
self._lock = threading.Lock()
|
||||
|
||||
with self._lock:
|
||||
lower_s = s.lower()
|
||||
|
||||
# Skip common noisy LiteLLM banners and any other lines that contain "litellm"
|
||||
if (
|
||||
"litellm.info:" in lower_s
|
||||
or "Consider using a smaller input or implementing a text splitting strategy"
|
||||
in lower_s
|
||||
):
|
||||
return 0
|
||||
|
||||
return self._original_stream.write(s)
|
||||
|
||||
def flush(self) -> None:
|
||||
if self._lock:
|
||||
with self._lock:
|
||||
return self._original_stream.flush()
|
||||
return None
|
||||
|
||||
def __getattr__(self, name: str) -> Any:
|
||||
"""Delegate attribute access to the wrapped original stream.
|
||||
|
||||
This ensures compatibility with libraries (e.g., Rich) that rely on
|
||||
attributes such as `encoding`, `isatty`, `buffer`, etc., which may not
|
||||
be explicitly defined on this proxy class.
|
||||
"""
|
||||
return getattr(self._original_stream, name)
|
||||
|
||||
# Delegate common properties/methods explicitly so they aren't shadowed by
|
||||
# the TextIOBase defaults (e.g., .encoding returns None by default, which
|
||||
# confuses Rich). These explicit pass-throughs ensure the wrapped Console
|
||||
# still sees a fully-featured stream.
|
||||
@property
|
||||
def encoding(self) -> str | Any: # type: ignore[override]
|
||||
return getattr(self._original_stream, "encoding", "utf-8")
|
||||
|
||||
def isatty(self) -> bool:
|
||||
return self._original_stream.isatty()
|
||||
|
||||
def fileno(self) -> int:
|
||||
return self._original_stream.fileno()
|
||||
|
||||
def writable(self) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
# Apply the filtered stream globally so that any subsequent writes containing the filtered
|
||||
# keywords (e.g., "litellm") are hidden from terminal output. We guard against double
|
||||
# wrapping to ensure idempotency in environments where this module might be reloaded.
|
||||
if not isinstance(sys.stdout, FilteredStream):
|
||||
sys.stdout = FilteredStream(sys.stdout)
|
||||
if not isinstance(sys.stderr, FilteredStream):
|
||||
sys.stderr = FilteredStream(sys.stderr)
|
||||
|
||||
|
||||
MIN_CONTEXT: Final[int] = 1024
|
||||
MAX_CONTEXT: Final[int] = 2097152 # Current max from gemini-1.5-pro
|
||||
ANTHROPIC_PREFIXES: Final[tuple[str, str, str]] = ("anthropic/", "claude-", "claude/")
|
||||
|
||||
Reference in New Issue
Block a user