-
Notifications
You must be signed in to change notification settings - Fork 82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mail channel first iteration #1620
Changes from all commits
04cdff8
02391b0
50fd4a1
fb4c4f6
19d3c88
0b3ec48
610a6cf
3443164
8f8ce73
8edbe0a
fed613e
124bbf2
67623e6
6a51ffe
b978fbe
b3e3901
1620374
fd49bf2
51642ca
d4eb5d0
d7d7128
10c39ea
fa135b8
64d6da5
8380bf6
d075337
97752a2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -43,6 +43,37 @@ async def chat( | |||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
return chat_response | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
@staticmethod | ||||||||||||||||||||||||||||||||||||||||||||||||||||
async def process_messages_via_bot( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
messages: [str], | ||||||||||||||||||||||||||||||||||||||||||||||||||||
account: int, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
bot: str, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
user: str, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
is_integration_user: bool = False, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
metadata: Dict = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
): | ||||||||||||||||||||||||||||||||||||||||||||||||||||
"""Process a list of messages through the bot. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
Args: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
messages: List of messages to process | ||||||||||||||||||||||||||||||||||||||||||||||||||||
account: Account ID | ||||||||||||||||||||||||||||||||||||||||||||||||||||
bot: Bot ID | ||||||||||||||||||||||||||||||||||||||||||||||||||||
user: User ID | ||||||||||||||||||||||||||||||||||||||||||||||||||||
is_integration_user: Flag indicating if user is integration user | ||||||||||||||||||||||||||||||||||||||||||||||||||||
metadata: Additional metadata | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
Returns: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
List of responses from the bot | ||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
responses = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||
uncached_model = AgentProcessor.get_agent_without_cache(bot, False) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
metadata = ChatUtils.get_metadata(account, bot, is_integration_user, metadata) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
for message in messages: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
msg = UserMessage(message, sender_id=user, metadata=metadata) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
chat_response = await uncached_model.handle_message(msg) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
responses.append(chat_response) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
return responses | ||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+67
to
+74
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling and input validation. Consider adding:
@staticmethod
async def process_messages_via_bot(
messages: [str],
account: int,
bot: str,
user: str,
is_integration_user: bool = False,
metadata: Dict = None,
):
"""Process a list of messages through the bot.
Args:
messages: List of messages to process
account: Account ID
bot: Bot ID
user: User ID
is_integration_user: Flag indicating if user is integration user
metadata: Additional metadata
Returns:
List of responses from the bot
"""
+ if not messages:
+ raise ValueError("Messages list cannot be empty")
+ if not all(isinstance(msg, str) for msg in messages):
+ raise ValueError("All messages must be strings")
responses = []
uncached_model = AgentProcessor.get_agent_without_cache(bot, False)
metadata = ChatUtils.get_metadata(account, bot, is_integration_user, metadata)
for message in messages:
+ try:
msg = UserMessage(message, sender_id=user, metadata=metadata)
chat_response = await uncached_model.handle_message(msg)
responses.append(chat_response)
+ except Exception as e:
+ logger.error(f"Error processing message '{message}': {str(e)}")
+ responses.append({"error": f"Failed to process message: {str(e)}"})
return responses 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
@staticmethod | ||||||||||||||||||||||||||||||||||||||||||||||||||||
def reload(bot: Text, user: Text): | ||||||||||||||||||||||||||||||||||||||||||||||||||||
exc = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import json | ||
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter | ||
from typing import List | ||
from rasa.cli import SubParsersAction | ||
|
||
from kairon.events.definitions.mail_channel import MailProcessEvent | ||
|
||
|
||
def process_channel_mails(args): | ||
mails = json.loads(args.mails) | ||
if not isinstance(mails, list): | ||
raise ValueError("Mails should be a list") | ||
MailProcessEvent(args.bot, args.user).execute(mails=mails) | ||
Comment on lines
+9
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add input validation and error handling The JSON parsing and validation needs additional safety measures:
Consider applying this improvement: def process_channel_mails(args):
+ if len(args.mails) > MAX_MAIL_JSON_SIZE:
+ raise ValueError(f"Mail JSON exceeds maximum size of {MAX_MAIL_JSON_SIZE} bytes")
+ try:
mails = json.loads(args.mails)
if not isinstance(mails, list):
raise ValueError("Mails should be a list")
+ for mail in mails:
+ if not isinstance(mail, dict) or not all(k in mail for k in REQUIRED_MAIL_FIELDS):
+ raise ValueError("Invalid mail format in list")
+ except json.JSONDecodeError as e:
+ raise ValueError(f"Invalid JSON format: {str(e)}")
|
||
|
||
|
||
def add_subparser(subparsers: SubParsersAction, parents: List[ArgumentParser]): | ||
mail_parser = subparsers.add_parser( | ||
"mail-channel-process", | ||
conflict_handler="resolve", | ||
formatter_class=ArgumentDefaultsHelpFormatter, | ||
parents=parents, | ||
help="Mail channel process mails" | ||
) | ||
mail_parser.add_argument('bot', | ||
type=str, | ||
help="Bot id for which command is executed", action='store') | ||
|
||
mail_parser.add_argument('user', | ||
type=str, | ||
help="Kairon user who is initiating the command", action='store') | ||
|
||
mail_parser.add_argument('mails', | ||
type=str, | ||
help="json representing List of mails to be processed", action='store') | ||
Comment on lines
+24
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add argument validation in CLI parser The CLI arguments need format validation to ensure they meet expected patterns:
Consider enhancing the argument definitions: mail_parser.add_argument('bot',
type=str,
+ pattern=r'^[a-f0-9]{24}$', # Assuming MongoDB ObjectId format
help="Bot id for which command is executed", action='store')
mail_parser.add_argument('user',
type=str,
+ pattern=r'^[a-f0-9]{24}$', # Assuming MongoDB ObjectId format
help="Kairon user who is initiating the command", action='store')
mail_parser.add_argument('mails',
type=str,
- help="json representing List of mails to be processed",
+ help="JSON array of mail objects. Each object must contain: subject, body, from_email",
action='store')
|
||
|
||
mail_parser.set_defaults(func=process_channel_mails) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter | ||
from typing import List | ||
from rasa.cli import SubParsersAction | ||
|
||
from kairon.events.definitions.mail_channel import MailReadEvent | ||
|
||
|
||
def read_channel_mails(args): | ||
MailReadEvent(args.bot, args.user).execute() | ||
Comment on lines
+8
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider adding error handling and logging The def read_channel_mails(args):
+ try:
MailReadEvent(args.bot, args.user).execute()
+ logging.info(f"Successfully executed mail read for bot: {args.bot}")
+ except Exception as e:
+ logging.error(f"Failed to read mail for bot {args.bot}: {str(e)}")
+ raise
|
||
|
||
|
||
def add_subparser(subparsers: SubParsersAction, parents: List[ArgumentParser]): | ||
mail_parser = subparsers.add_parser( | ||
"mail-channel-read", | ||
conflict_handler="resolve", | ||
formatter_class=ArgumentDefaultsHelpFormatter, | ||
parents=parents, | ||
help="Mail channel initiate reading" | ||
) | ||
mail_parser.add_argument('bot', | ||
type=str, | ||
help="Bot id for which command is executed", action='store') | ||
|
||
mail_parser.add_argument('user', | ||
type=str, | ||
help="Kairon user who is initiating the command", action='store') | ||
|
||
mail_parser.set_defaults(func=read_channel_mails) |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,98 @@ | ||||||||||||||
from typing import Text | ||||||||||||||
from loguru import logger | ||||||||||||||
from kairon import Utility | ||||||||||||||
from kairon.events.definitions.base import EventsBase | ||||||||||||||
from kairon.exceptions import AppException | ||||||||||||||
from kairon.shared.channels.mail.processor import MailProcessor | ||||||||||||||
from kairon.shared.constants import EventClass | ||||||||||||||
|
||||||||||||||
|
||||||||||||||
class MailProcessEvent(EventsBase): | ||||||||||||||
""" | ||||||||||||||
Event to start mail channel scheduler if not already running. | ||||||||||||||
""" | ||||||||||||||
|
||||||||||||||
def __init__(self, bot: Text, user: Text, **kwargs): | ||||||||||||||
""" | ||||||||||||||
Initialise event. | ||||||||||||||
""" | ||||||||||||||
self.bot = bot | ||||||||||||||
self.user = user | ||||||||||||||
|
||||||||||||||
def validate(self): | ||||||||||||||
""" | ||||||||||||||
validate mail channel exists | ||||||||||||||
""" | ||||||||||||||
return MailProcessor.validate_smtp_connection(self.bot) | ||||||||||||||
|
||||||||||||||
|
||||||||||||||
def enqueue(self, **kwargs): | ||||||||||||||
""" | ||||||||||||||
Send event to event server. | ||||||||||||||
""" | ||||||||||||||
try: | ||||||||||||||
mails: list = kwargs.get('mails', []) | ||||||||||||||
payload = {'bot': self.bot, 'user': self.user, 'mails': mails} | ||||||||||||||
Utility.request_event_server(EventClass.mail_channel_process_mails, payload) | ||||||||||||||
except Exception as e: | ||||||||||||||
logger.error(str(e)) | ||||||||||||||
raise AppException(e) | ||||||||||||||
Comment on lines
+37
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Use exception chaining when re-raising exceptions When re-raising an exception inside an Apply this diff to fix the issue: 37 except Exception as e:
38 logger.error(str(e))
-39 raise AppException(e)
+39 raise AppException(e) from e 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.8.0)39-39: Within an (B904) |
||||||||||||||
|
||||||||||||||
def execute(self, **kwargs): | ||||||||||||||
""" | ||||||||||||||
Execute the event. | ||||||||||||||
""" | ||||||||||||||
try: | ||||||||||||||
mails = kwargs.get('mails') | ||||||||||||||
if mails: | ||||||||||||||
MailProcessor.process_message_task(self.bot, mails) | ||||||||||||||
except Exception as e: | ||||||||||||||
logger.error(str(e)) | ||||||||||||||
raise AppException(e) | ||||||||||||||
Comment on lines
+49
to
+51
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Use exception chaining when re-raising exceptions When re-raising an exception inside an Apply this diff to fix the issue: 49 except Exception as e:
50 logger.error(str(e))
-51 raise AppException(e)
+51 raise AppException(e) from e 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.8.0)51-51: Within an (B904) |
||||||||||||||
|
||||||||||||||
|
||||||||||||||
|
||||||||||||||
class MailReadEvent(EventsBase): | ||||||||||||||
""" | ||||||||||||||
Event to read mails from mail channel and create events for each mail tp process them via bot | ||||||||||||||
""" | ||||||||||||||
|
||||||||||||||
def __init__(self, bot: Text, user: Text, **kwargs): | ||||||||||||||
""" | ||||||||||||||
Initialise event. | ||||||||||||||
""" | ||||||||||||||
self.bot = bot | ||||||||||||||
self.user = user | ||||||||||||||
|
||||||||||||||
def validate(self): | ||||||||||||||
""" | ||||||||||||||
validate mail channel exists | ||||||||||||||
""" | ||||||||||||||
return MailProcessor.validate_imap_connection(self.bot) | ||||||||||||||
|
||||||||||||||
def enqueue(self, **kwargs): | ||||||||||||||
""" | ||||||||||||||
Send event to event server. | ||||||||||||||
""" | ||||||||||||||
try: | ||||||||||||||
payload = {'bot': self.bot, 'user': self.user} | ||||||||||||||
Utility.request_event_server(EventClass.mail_channel_read_mails, payload) | ||||||||||||||
except Exception as e: | ||||||||||||||
logger.error(str(e)) | ||||||||||||||
raise AppException(e) | ||||||||||||||
|
||||||||||||||
Comment on lines
+81
to
+83
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Use exception chaining when re-raising exceptions When re-raising an exception inside an Apply this diff to fix the issue: 81 except Exception as e:
82 logger.error(str(e))
-83 raise AppException(e)
+83 raise AppException(e) from e 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.8.0)82-82: Within an (B904) |
||||||||||||||
def execute(self, **kwargs): | ||||||||||||||
""" | ||||||||||||||
Execute the event. | ||||||||||||||
""" | ||||||||||||||
try: | ||||||||||||||
vals = MailProcessor.read_mails(self.bot) | ||||||||||||||
print(vals) | ||||||||||||||
emails, _, _ = vals | ||||||||||||||
for email in emails: | ||||||||||||||
ev = MailProcessEvent(self.bot, self.user) | ||||||||||||||
ev.validate() | ||||||||||||||
ev.enqueue(mails=[email]) | ||||||||||||||
|
||||||||||||||
except Exception as e: | ||||||||||||||
raise AppException(f"Failed to schedule mail reading for bot {self.bot}. Error: {str(e)}") | ||||||||||||||
Comment on lines
+97
to
+98
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Use exception chaining when re-raising exceptions When re-raising an exception inside an Apply this diff to fix the issue: 97 except Exception as e:
-98 raise AppException(f"Failed to schedule mail reading for bot {self.bot}. Error: {str(e)}")
+98 raise AppException(f"Failed to schedule mail reading for bot {self.bot}. Error: {str(e)}") from e 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.8.0)98-98: Within an (B904) |
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -56,6 +56,7 @@ async def lifespan(app: FastAPI): | |||||||||||||||||
""" MongoDB is connected on the bot trainer startup """ | ||||||||||||||||||
config: dict = Utility.mongoengine_connection(Utility.environment['database']["url"]) | ||||||||||||||||||
connect(**config) | ||||||||||||||||||
EventUtility.reschedule_all_bots_channel_mail_reading() | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling for mail rescheduling during startup The mail rescheduling call during startup could fail silently. Consider wrapping it in a try-catch block to log any failures without preventing server startup. - EventUtility.reschedule_all_bots_channel_mail_reading()
+ try:
+ EventUtility.reschedule_all_bots_channel_mail_reading()
+ except Exception as e:
+ logger.error(f"Failed to reschedule mail reading during startup: {str(e)}") 📝 Committable suggestion
Suggested change
|
||||||||||||||||||
yield | ||||||||||||||||||
disconnect() | ||||||||||||||||||
|
||||||||||||||||||
|
@@ -144,3 +145,9 @@ def delete_scheduled_event(event_id: Text = Path(description="Event id")): | |||||||||||||||||
def dispatch_scheduled_event(event_id: Text = Path(description="Event id")): | ||||||||||||||||||
KScheduler().dispatch_event(event_id) | ||||||||||||||||||
return {"data": None, "message": "Scheduled event dispatch!"} | ||||||||||||||||||
|
||||||||||||||||||
|
||||||||||||||||||
@app.get('/api/mail/schedule/{bot}', response_model=Response) | ||||||||||||||||||
def request_epoch(bot: Text = Path(description="Bot id")): | ||||||||||||||||||
EventUtility.schedule_channel_mail_reading(bot) | ||||||||||||||||||
return {"data": None, "message": "Mail scheduler epoch request!"} | ||||||||||||||||||
Comment on lines
+150
to
+153
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add input validation for bot parameter The endpoint should validate the bot ID parameter to ensure it's not empty or malformed. @app.get('/api/mail/schedule/{bot}', response_model=Response)
-def request_epoch(bot: Text = Path(description="Bot id")):
+def request_epoch(bot: Text = Path(description="Bot id", min_length=1)):
EventUtility.schedule_channel_mail_reading(bot)
return {"data": None, "message": "Mail scheduler epoch request!"} 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.8.0)151-151: Do not perform function call (B008) |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -1,9 +1,14 @@ | ||||||||||
from typing import Dict, Text | ||||||||||
|
||||||||||
from uuid6 import uuid7 | ||||||||||
|
||||||||||
from kairon.events.executors.factory import ExecutorFactory | ||||||||||
from kairon.events.scheduler.kscheduler import KScheduler | ||||||||||
from kairon.exceptions import AppException | ||||||||||
from kairon.shared.chat.data_objects import Channels | ||||||||||
from kairon.shared.constants import EventClass, ChannelTypes | ||||||||||
from kairon.shared.data.constant import TASK_TYPE | ||||||||||
from loguru import logger | ||||||||||
|
||||||||||
|
||||||||||
class EventUtility: | ||||||||||
|
@@ -32,3 +37,36 @@ def update_job(event_type: Text, request_data: Dict, is_scheduled: bool): | |||||||||
KScheduler().update_job(event_class=event_type, event_id=event_id, task_type=TASK_TYPE.EVENT.value, | ||||||||||
**request_data) | ||||||||||
return None, 'Scheduled event updated!' | ||||||||||
|
||||||||||
@staticmethod | ||||||||||
def schedule_channel_mail_reading(bot: str): | ||||||||||
from kairon.shared.channels.mail.processor import MailProcessor | ||||||||||
|
||||||||||
try: | ||||||||||
mail_processor = MailProcessor(bot) | ||||||||||
interval = mail_processor.config.get("interval", 60) | ||||||||||
event_id = mail_processor.state.event_id | ||||||||||
if event_id: | ||||||||||
KScheduler().update_job(event_id, | ||||||||||
TASK_TYPE.EVENT, | ||||||||||
f"*/{interval} * * * *", | ||||||||||
EventClass.mail_channel_read_mails, {"bot": bot, "user": mail_processor.bot_settings.user}) | ||||||||||
else: | ||||||||||
event_id = uuid7().hex | ||||||||||
mail_processor.update_event_id(event_id) | ||||||||||
KScheduler().add_job(event_id, | ||||||||||
TASK_TYPE.EVENT, | ||||||||||
f"*/{interval} * * * *", | ||||||||||
EventClass.mail_channel_read_mails, {"bot": bot, "user": mail_processor.bot_settings.user}) | ||||||||||
except Exception as e: | ||||||||||
raise AppException(f"Failed to schedule mail reading for bot {bot}. Error: {str(e)}") | ||||||||||
Comment on lines
+61
to
+62
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Use exception chaining when re-raising exceptions When re-raising an exception inside an Apply this diff to fix the issue: 61 except Exception as e:
-62 raise AppException(f"Failed to schedule mail reading for bot {bot}. Error: {str(e)}")
+62 raise AppException(f"Failed to schedule mail reading for bot {bot}. Error: {str(e)}") from e 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.8.0)62-62: Within an (B904) |
||||||||||
|
||||||||||
@staticmethod | ||||||||||
def reschedule_all_bots_channel_mail_reading(): | ||||||||||
try: | ||||||||||
bots = list(Channels.objects(connector_type= ChannelTypes.MAIL.value).distinct("bot")) | ||||||||||
for bot in bots: | ||||||||||
logger.info(f"Rescheduling mail reading for bot {bot}") | ||||||||||
EventUtility.schedule_channel_mail_reading(bot) | ||||||||||
except Exception as e: | ||||||||||
raise AppException(f"Failed to reschedule mail reading events. Error: {str(e)}") | ||||||||||
Comment on lines
+71
to
+72
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Use exception chaining when re-raising exceptions When re-raising an exception inside an Apply this diff to fix the issue: 71 except Exception as e:
-72 raise AppException(f"Failed to reschedule mail reading events. Error: {str(e)}")
+72 raise AppException(f"Failed to reschedule mail reading events. Error: {str(e)}") from e 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.8.0)72-72: Within an (B904) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
|
||
|
||
class MailConstants: | ||
DEFAULT_SMTP_SERVER = 'smtp.gmail.com' | ||
DEFAULT_IMAP_SERVER = 'imap.gmail.com' | ||
DEFAULT_SMTP_PORT = 587 | ||
|
||
DEFAULT_TEMPLATE = "<p>{bot_response}</p> <br/><br/><span style='color:#999;'> Generated by kAIron AI.</span>\n" | ||
|
||
PROCESS_MESSAGE_BATCH_SIZE = 4 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add error handling and documentation to get_agent_without_cache method
reload()
and this method to reduce duplication.📝 Committable suggestion