Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions src/praisonai/praisonai/bots/_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -836,3 +836,57 @@ def active_sessions(self) -> int:
def get_user_ids(self) -> List[str]:
"""List user IDs with active sessions."""
return list(self._histories.keys())


def build_session_manager(config, platform: str, *, run_control=None) -> BotSessionManager:
"""Build a BotSessionManager with standard configuration from a BotConfig.

This helper extracts the common session manager setup logic that's duplicated
across all bot adapters, including:
- Session store acquisition
- Reset policy extraction
- Backward-compatible max_history resolution

Args:
config: BotConfig instance with session configuration
platform: Platform identifier (e.g., "telegram", "slack")
run_control: Optional run control for Telegram (keyword-only)

Returns:
Configured BotSessionManager instance
"""
# Try to get the default session store
try:
from praisonaiagents.session import get_default_session_store
except ImportError:
# Module not available, fallback to in-memory
store = None
Comment on lines +859 to +863

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid silent fallback when default session-store initialization fails.

Line 824 currently swallows all store-init failures and silently switches to in-memory sessions, which can cause unnoticed loss of persisted history across all adapters. Keep the fallback, but log non-import failures so operators can detect misconfiguration/outages.

Proposed fix
-    try:
-        from praisonaiagents.session import get_default_session_store
-        store = get_default_session_store()
-    except Exception:
-        store = None
+    try:
+        from praisonaiagents.session import get_default_session_store
+    except ImportError:
+        store = None
+    else:
+        try:
+            store = get_default_session_store()
+        except Exception as exc:
+            logger.warning(
+                "Default session store unavailable; falling back to in-memory store: %s",
+                exc,
+            )
+            store = None
🧰 Tools
🪛 Ruff (0.15.17)

[warning] 824-824: Do not catch blind exception: Exception

(BLE001)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/praisonai/praisonai/bots/_session.py` around lines 821 - 825, The
try-except block in the get_default_session_store initialization silently
catches all exceptions without logging, masking real configuration or runtime
failures. Modify the exception handling to distinguish between ImportError
(which should silently fall back to in-memory store) and other exceptions (which
should be logged as warnings or errors with the exception details) so operators
can detect misconfiguration or outages in the session store initialization.

Source: Linters/SAST tools

else:
try:
store = get_default_session_store()
except Exception as exc:
logger.warning(
"Default session store unavailable; falling back to in-memory store: %s",
exc,
)
store = None

# Extract reset policy from config
reset_policy = None
if getattr(config, "session", None) and getattr(config.session, "reset", None):
reset_policy = SessionResetPolicy.from_dict(config.session.reset.model_dump())

# Support backward compatibility with max_history at channel level
max_history = 100
if getattr(config, "max_history", None) is not None:
max_history = config.max_history
elif getattr(config, "session", None) and getattr(config.session, "max_history", None) is not None:
max_history = config.session.max_history

return BotSessionManager(
max_history=max_history,
store=store,
platform=platform,
reset_policy=reset_policy,
run_control=run_control,
)
Comment thread
greptile-apps[bot] marked this conversation as resolved.
10 changes: 3 additions & 7 deletions src/praisonai/praisonai/bots/agentmail.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
HealthResult,
)

from ._session import BotSessionManager
from ._email_utils import is_auto_reply, is_blocked_sender, extract_email_address

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -115,12 +114,9 @@ def __init__(
# Initialize allow_silence from config
self._allow_silence = getattr(self.config, 'allow_silence', False)

try:
from praisonaiagents.session import get_default_session_store
_store = get_default_session_store()
except Exception:
_store = None
self._session = BotSessionManager(store=_store, platform="agentmail")
# Use helper to build session manager
from ._session import build_session_manager
self._session = build_session_manager(self.config, platform="agentmail")

# Resolve mode: explicit param > config > default
if mode:
Expand Down
30 changes: 5 additions & 25 deletions src/praisonai/praisonai/bots/discord.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,31 +89,11 @@ def __init__(
self._message_handlers: List[Callable] = []
self._command_handlers: Dict[str, Callable] = {}
self._started_at: Optional[float] = None
try:
from praisonaiagents.session import get_default_session_store
_store = get_default_session_store()
except Exception:
_store = None
# Extract reset policy from config
reset_policy = None
if hasattr(self.config, 'session') and self.config.session:
if hasattr(self.config.session, 'reset') and self.config.session.reset:
from ._reset_policy import SessionResetPolicy
reset_policy = SessionResetPolicy.from_dict(self.config.session.reset.model_dump())

# Support backward compatibility with max_history at channel level
max_history = 100
if hasattr(self.config, 'max_history') and self.config.max_history is not None:
max_history = self.config.max_history
elif hasattr(self.config, 'session') and self.config.session:
if hasattr(self.config.session, 'max_history') and self.config.session.max_history is not None:
max_history = self.config.session.max_history

self._session: BotSessionManager = BotSessionManager(
max_history=max_history,
store=_store,
platform="discord",
reset_policy=reset_policy,
# Use helper to build session manager
from ._session import build_session_manager
self._session: BotSessionManager = build_session_manager(
self.config,
platform="discord"
)
self._debouncer: InboundDebouncer = InboundDebouncer(
debounce_ms=self.config.debounce_ms,
Expand Down
13 changes: 5 additions & 8 deletions src/praisonai/praisonai/bots/email.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,11 @@ def __init__(
self._started_at: Optional[float] = None
self._processed_uids: set = set() # Track processed email UIDs

try:
from praisonaiagents.session import get_default_session_store
_store = get_default_session_store()
except Exception:
_store = None
self._session: BotSessionManager = BotSessionManager(
store=_store,
platform="email",
# Use helper to build session manager
from ._session import build_session_manager
self._session: BotSessionManager = build_session_manager(
self.config,
platform="email"
)

self._stop_event: Optional[asyncio.Event] = None
Expand Down
15 changes: 5 additions & 10 deletions src/praisonai/praisonai/bots/linear.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
)

from ._commands import format_status, format_help
from ._session import BotSessionManager
from ._rate_limit import RateLimiter
from ._ack import AckReactor

Expand Down Expand Up @@ -91,15 +90,11 @@ def __init__(
self._started_at: Optional[float] = None
self._bot_user: Optional[BotUser] = None

try:
from praisonaiagents.session import get_default_session_store
_store = get_default_session_store()
except Exception:
_store = None

self._session_mgr = BotSessionManager(
store=_store,
platform="linear",
# Use helper to build session manager
from ._session import build_session_manager
self._session_mgr = build_session_manager(
self.config,
platform="linear"
)
self._message_handlers: List[Callable] = []
self._runner: Any = None
Expand Down
31 changes: 6 additions & 25 deletions src/praisonai/praisonai/bots/slack.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,31 +101,12 @@ def __init__(
self._message_handlers: List[Callable] = []
self._command_handlers: Dict[str, Callable] = {}
self._started_at: Optional[float] = None
try:
from praisonaiagents.session import get_default_session_store
_store = get_default_session_store()
except Exception:
_store = None
# Extract reset policy from config
reset_policy = None
if hasattr(self.config, 'session') and self.config.session:
if hasattr(self.config.session, 'reset') and self.config.session.reset:
from ._reset_policy import SessionResetPolicy
reset_policy = SessionResetPolicy.from_dict(self.config.session.reset.model_dump())

# Support backward compatibility with max_history at channel level
max_history = 100
if hasattr(self.config, 'max_history') and self.config.max_history is not None:
max_history = self.config.max_history
elif hasattr(self.config, 'session') and self.config.session:
if hasattr(self.config.session, 'max_history') and self.config.session.max_history is not None:
max_history = self.config.session.max_history

self._session: BotSessionManager = BotSessionManager(
max_history=max_history,
store=_store,
platform="slack",
reset_policy=reset_policy,

# Use helper to build session manager
from ._session import build_session_manager
self._session: BotSessionManager = build_session_manager(
self.config,
platform="slack"
)
self._debouncer: InboundDebouncer = InboundDebouncer(
debounce_ms=self.config.debounce_ms,
Expand Down
31 changes: 6 additions & 25 deletions src/praisonai/praisonai/bots/telegram.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,7 @@ def __init__(
self._message_handlers: List[Callable] = []
self._command_handlers: Dict[str, Callable] = {}
self._started_at: Optional[float] = None
try:
from praisonaiagents.session import get_default_session_store
_store = get_default_session_store()
except Exception:
_store = None

# Create run control if busy mode is configured
run_control = None
if hasattr(self.config, 'busy_mode') and self.config.busy_mode != "queue":
Expand All @@ -134,27 +130,12 @@ def __init__(
except ImportError:
logger.warning("Run control not available, falling back to basic session management")

# Extract reset policy from config
reset_policy = None
if hasattr(self.config, 'session') and self.config.session:
if hasattr(self.config.session, 'reset') and self.config.session.reset:
from ._reset_policy import SessionResetPolicy
reset_policy = SessionResetPolicy.from_dict(self.config.session.reset.model_dump())

# Support backward compatibility with max_history at channel level
max_history = 100
if hasattr(self.config, 'max_history') and self.config.max_history is not None:
max_history = self.config.max_history
elif hasattr(self.config, 'session') and self.config.session:
if hasattr(self.config.session, 'max_history') and self.config.session.max_history is not None:
max_history = self.config.session.max_history

self._session: BotSessionManager = BotSessionManager(
max_history=max_history,
store=_store,
# Use helper to build session manager
from ._session import build_session_manager
self._session: BotSessionManager = build_session_manager(
self.config,
platform="telegram",
run_control=run_control,
reset_policy=reset_policy,
run_control=run_control
)
self._debouncer: InboundDebouncer = InboundDebouncer(
debounce_ms=self.config.debounce_ms,
Expand Down
30 changes: 5 additions & 25 deletions src/praisonai/praisonai/bots/whatsapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,31 +134,11 @@ def __init__(
self._is_running = False
self._started_at: Optional[float] = None
self._bot_user: Optional[BotUser] = None
try:
from praisonaiagents.session import get_default_session_store
_store = get_default_session_store()
except Exception:
_store = None
# Extract reset policy from config
reset_policy = None
if hasattr(self.config, 'session') and self.config.session:
if hasattr(self.config.session, 'reset') and self.config.session.reset:
from ._reset_policy import SessionResetPolicy
reset_policy = SessionResetPolicy.from_dict(self.config.session.reset.model_dump())

# Support backward compatibility with max_history at channel level
max_history = 100
if hasattr(self.config, 'max_history') and self.config.max_history is not None:
max_history = self.config.max_history
elif hasattr(self.config, 'session') and self.config.session:
if hasattr(self.config.session, 'max_history') and self.config.session.max_history is not None:
max_history = self.config.session.max_history

self._session_mgr = BotSessionManager(
max_history=max_history,
store=_store,
platform="whatsapp",
reset_policy=reset_policy,
# Use helper to build session manager
from ._session import build_session_manager
self._session_mgr = build_session_manager(
self.config,
platform="whatsapp"
)
self._message_handlers: List[Callable] = []
self._runner: Any = None
Expand Down
Loading