-
-
Notifications
You must be signed in to change notification settings - Fork 231
Nestbot AI Direct message implementation #2374
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
base: feature/nestbot-ai-assistant
Are you sure you want to change the base?
Nestbot AI Direct message implementation #2374
Conversation
Summary by CodeRabbit
WalkthroughAdds Slack DM support by subscribing to Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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.
Actionable comments posted: 2
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
backend/apps/slack/MANIFEST.yaml
(1 hunks)backend/apps/slack/admin/__init__.py
(1 hunks)backend/apps/slack/admin/chat.py
(1 hunks)backend/apps/slack/common/handlers/ai.py
(2 hunks)backend/apps/slack/events/message_posted.py
(3 hunks)backend/apps/slack/migrations/0020_chat.py
(1 hunks)backend/apps/slack/models/__init__.py
(1 hunks)backend/apps/slack/models/chat.py
(1 hunks)backend/tests/apps/slack/events/message_posted_test.py
(3 hunks)
🧰 Additional context used
🧬 Code graph analysis (7)
backend/apps/slack/common/handlers/ai.py (5)
backend/apps/slack/models/chat.py (4)
Chat
(11-90)update_data
(30-50)get_context
(70-90)add_to_context
(52-68)backend/apps/slack/models/member.py (1)
Member
(10-78)backend/apps/slack/models/workspace.py (1)
Workspace
(11-44)backend/apps/ai/agent/tools/rag/rag_tool.py (2)
query
(34-63)RagTool
(13-63)backend/apps/slack/blocks.py (1)
markdown
(21-34)
backend/apps/slack/admin/__init__.py (1)
backend/apps/slack/admin/chat.py (1)
ChatAdmin
(8-13)
backend/apps/slack/events/message_posted.py (3)
backend/apps/slack/common/handlers/ai.py (1)
get_dm_blocks
(50-66)backend/apps/slack/models/member.py (1)
Member
(10-78)backend/apps/slack/models/workspace.py (1)
Workspace
(11-44)
backend/apps/slack/models/__init__.py (1)
backend/apps/slack/models/chat.py (1)
Chat
(11-90)
backend/apps/slack/admin/chat.py (1)
backend/apps/slack/models/chat.py (1)
Chat
(11-90)
backend/tests/apps/slack/events/message_posted_test.py (1)
backend/apps/slack/events/message_posted.py (1)
handle_event
(27-79)
backend/apps/slack/models/chat.py (3)
backend/apps/common/models.py (1)
TimestampedModel
(37-46)backend/apps/slack/models/member.py (1)
Member
(10-78)backend/apps/slack/models/workspace.py (1)
Workspace
(11-44)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Run frontend unit tests
- GitHub Check: Run frontend e2e tests
- GitHub Check: Run backend tests
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.
Please use existing Slack app entities:
backend/apps/slack/models/chat.py
Outdated
from apps.slack.models.workspace import Workspace | ||
|
||
|
||
class Chat(TimestampedModel): |
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.
Isn't this redundant with Conversation
model we already have?
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.
the conversation is for the slack channel conversation -- this chat model is responsible for handling the human and bot interaction
this is a good approach becaue if we try to combine this with conversation -- unnecessary complexity will be added and it will be difficult for future developer to figure out what exactly is happening, as there would be a lot of conditions because the slack direct messages and the slack channel messages behave differently
let me know what do want to continue with
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.
If you check Slack conversation object you'll see that it covers more cases than just channel conversation. I don't want introduce new redundant models for each specific case we may have. Unless Slack splits it on their side.
Your perspective for future developer's complexity issues may be biased as it's your code, you wrote it and now need to defend your decisions. I suggest reconsidering it and not to multiply entities when you can keep it unified.
the slack direct messages and the slack channel messages behave differently
It'd be great to see some specific examples.
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.
I'll refactor my approach and use the conversation model
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.
refactored the code --- we are now using our existing conversation model
backend/apps/slack/models/chat.py
Outdated
|
||
return chat | ||
|
||
def add_to_context(self, user_message: str, bot_response: str | None = None) -> None: |
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.
These methods need to be migrated to conversation + message models we already have. Please don't +
strings in Python.
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.
this is the chat model responsible for human and bot conversation, so I think we should add and get the context from here
in case we want to migrate let me know the specific model conversation or message
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.
fixed
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.
Actionable comments posted: 1
♻️ Duplicate comments (1)
backend/apps/slack/events/message_posted.py (1)
83-92
: Fix workspace resolution and add error handling for API call.Two issues:
- Line 83:
event.get("team")
may returnNone
for IM conversations; Slack sometimes usesteam_id
,context_team_id
, oruser_team
instead. The previous review flagged this as a critical blocker.- Line 84:
client.conversations_info(channel=channel_id)
can fail with API errors (rate limits, permissions, etc.), but it's not in a try-except, so failures crash the handler.Apply the fix from the previous review to safely resolve
workspace_id
and wrap the API call:- workspace_id = event.get("team") - channel_info = client.conversations_info(channel=channel_id) + workspace_id = event.get("team") or event.get("team_id") or event.get("context_team_id") or event.get("user_team") + + if not workspace_id: + try: + channel_info = client.conversations_info(channel=channel_id) + channel_data = channel_info.get("channel", {}) + workspace_id = ( + channel_data.get("team") + or channel_data.get("context_team_id") + or channel_data.get("user_team") + ) + except Exception: + logger.exception("Failed to fetch workspace ID for DM.") + return + else: + try: + channel_info = client.conversations_info(channel=channel_id) + except Exception: + logger.exception("Failed to fetch channel info for DM.") + return + + if not workspace_id: + logger.error("Unable to determine workspace_id for DM channel %s.", channel_id) + return
🧹 Nitpick comments (2)
backend/apps/slack/common/handlers/ai.py (1)
97-98
: Handle None response before adding to context.If
rag_tool.query
returnsNone
, line 98 still callsadd_to_context(query, None)
, which stores a user message without a bot response. While the method handles this case, it clutters the context with unanswered questions.Only add to context if a response was generated:
response = rag_tool.query(question=enhanced_query) - conversation.add_to_context(query, response) + if response: + conversation.add_to_context(query, response) + else: + logger.warning("RAG query returned no response for DM: %s", query[:50]) return responsebackend/apps/slack/events/message_posted.py (1)
92-92
: Guard against missingid
inchannel_info["channel"]
. Ensurechannel_info.get("channel", {}).get("id")
is present before callingConversation.update_data
to avoid aKeyError
(e.g. bail or log if absent).
Location: backend/apps/slack/events/message_posted.py:92
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
backend/apps/slack/common/handlers/ai.py
(2 hunks)backend/apps/slack/constants.py
(1 hunks)backend/apps/slack/events/message_posted.py
(3 hunks)backend/apps/slack/migrations/0020_conversation_conversation_context.py
(1 hunks)backend/apps/slack/models/conversation.py
(2 hunks)backend/tests/apps/slack/models/conversation_test.py
(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
backend/tests/apps/slack/models/conversation_test.py (1)
backend/apps/slack/models/conversation.py (2)
add_to_context
(110-126)get_context
(128-148)
backend/apps/slack/events/message_posted.py (4)
backend/apps/slack/common/handlers/ai.py (1)
get_dm_blocks
(51-67)backend/apps/slack/models/conversation.py (2)
Conversation
(15-148)update_data
(86-108)backend/apps/slack/models/member.py (1)
Member
(10-78)backend/apps/slack/models/workspace.py (1)
Workspace
(11-44)
backend/apps/slack/common/handlers/ai.py (4)
backend/apps/slack/models/conversation.py (3)
Conversation
(15-148)get_context
(128-148)add_to_context
(110-126)backend/apps/slack/models/workspace.py (1)
Workspace
(11-44)backend/apps/ai/agent/tools/rag/rag_tool.py (2)
query
(34-63)RagTool
(13-63)backend/apps/slack/blocks.py (1)
markdown
(21-34)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Run frontend e2e tests
- GitHub Check: Run backend tests
- GitHub Check: Run frontend unit tests
🔇 Additional comments (3)
backend/apps/slack/models/conversation.py (2)
110-126
: LGTM! Context append logic is clean.The method correctly initializes empty context, formats messages with clear prefixes, and uses
update_fields
to avoid unintended changes.
128-148
: Assumption valid: exchanges remain two lines Verified all runtime calls toadd_to_context
supply bothuser_message
andbot_response
, ensuringget_context
slicing won’t split exchanges.backend/apps/slack/events/message_posted.py (1)
103-111
: LGTM! DM response handling is clean.The logic correctly retrieves DM blocks with context, posts the response, and preserves threading with
thread_ts
. The error handler at lines 113-122 ensures users receive feedback on failures.
|
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.
Actionable comments posted: 0
🧹 Nitpick comments (1)
backend/apps/slack/common/handlers/ai.py (1)
82-87
: Log identifiers when DM context lookup fails.We still emit a stack trace but lose the
workspace_id
/channel_id
needed to debug these failures (and.exception
is noisy for a handled condition). Switch tologger.error
and include the identifiers so ops can trace the failing DM.- except (Workspace.DoesNotExist, Conversation.DoesNotExist): - logger.exception("Workspace or conversation not found for DM processing") + except (Workspace.DoesNotExist, Conversation.DoesNotExist): + logger.error( + "Workspace or conversation not found for DM processing: workspace_id=%s channel_id=%s", + workspace_id, + channel_id, + )
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
backend/apps/slack/common/handlers/ai.py
(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
backend/apps/slack/common/handlers/ai.py (4)
backend/apps/slack/models/conversation.py (3)
Conversation
(15-148)get_context
(128-148)add_to_context
(110-126)backend/apps/slack/models/workspace.py (1)
Workspace
(11-44)backend/apps/ai/agent/tools/rag/rag_tool.py (2)
query
(34-63)RagTool
(13-63)backend/apps/slack/blocks.py (1)
markdown
(21-34)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Run frontend e2e tests
- GitHub Check: Run backend tests
- GitHub Check: Run frontend unit tests
- GitHub Check: CodeQL (javascript-typescript)
Proposed change
Resolves #2189
NOTE
message.im
to manifest fileis_nestbot_enabled
manually in the conversation model by going to django panelChecklist
make check-test
locally; all checks and tests passed.