Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

Dishant1804
Copy link
Collaborator

@Dishant1804 Dishant1804 commented Oct 6, 2025

Proposed change

Resolves #2189

  • added slack direct message feature

NOTE

  • add this message.im to manifest file
  • enable the agent or assistant feature in nestbot settings in slack website
  • make sure you turn on the is_nestbot_enabled manually in the conversation model by going to django panel
  • make sure you re-install the nestbot

Checklist

  • I've read and followed the contributing guidelines.
  • I've run make check-test locally; all checks and tests passed.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 6, 2025

Summary by CodeRabbit

  • New Features

    • Chat with the assistant via Slack direct messages (DMs).
    • The assistant now uses recent conversation context for more coherent DM replies.
  • Bug Fixes

    • Improved reliability when tracking and updating threaded replies in channels.
    • Clearer, user-friendly fallback messages in DMs when an error occurs.

Walkthrough

Adds Slack DM support by subscribing to message.im, implements DM-specific AI processing and response blocks, persists and retrieves conversation context with a configurable limit, updates event routing to handle DMs, and includes migration and tests for the new model field and behaviors.

Changes

Cohort / File(s) Summary
Slack manifest updates
backend/apps/slack/MANIFEST.yaml
Adds settings.event_subscriptions.bot_events: message.im to enable DM event subscription.
AI handler enhancements (DM support)
backend/apps/slack/common/handlers/ai.py
Adds process_dm_ai_query and get_dm_blocks; integrates Workspace/Conversation context retrieval and update, prepends recent context (bounded by new constant), queries RagTool, and returns DM-formatted blocks or error blocks.
Slack message event handling (DM path)
backend/apps/slack/events/message_posted.py
Routes channel_type == "im" to new handle_dm; resolves workspace/member/conversation for DMs, updates conversation context, posts DM replies (preserving thread_ts when present), and adds DM-specific error handling and logging.
Conversation model, constants, migration
backend/apps/slack/models/conversation.py, backend/apps/slack/constants.py, backend/apps/slack/migrations/0020_conversation_conversation_context.py
Adds conversation_context TextField, methods add_to_context and get_context(conversation_context_limit), introduces CONVERSATION_CONTEXT_LIMIT = 20, and migration to add the field.
Event handler tests
backend/tests/apps/slack/events/message_posted_test.py
Adjusts tests to use filter-based lookup for thread messages, adds/uses django_rq mocking and assertions, and updates test signatures to include the mock_django_rq fixture.
Conversation model tests
backend/tests/apps/slack/models/conversation_test.py
Adds tests covering add_to_context and get_context behaviors, including save calls, formatting of "User:"/"Bot:" lines, and limit-based truncation edge cases.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Nestbot MVP #2113 — Prior Slack AI changes touching the same AI handlers, event routing, and conversation context codepaths; likely the most directly related.

Suggested reviewers

  • arkid15r
  • kasya

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title Check ✅ Passed The title clearly describes the primary enhancement introduced by this changeset—adding direct message handling for the NestBot AI in Slack—using concise and specific wording that allows a reviewer to quickly understand the main focus.
Linked Issues Check ✅ Passed The pull request delivers on the primary coding requirements of issue #2189 by adding the Slack direct message interface—through manifest inclusion of message.im, DM-specific AI handlers, and DM routing in the event flow—while preserving existing channel mention handling, and by introducing conversation context management to support stateful interactions.
Out of Scope Changes Check ✅ Passed All modifications in this pull request directly support the implementation of Slack direct messages or enhance underlying conversation context management and testing, with no unrelated or extraneous code changes detected.
Description Check ✅ Passed The pull request description clearly outlines the addition of the Slack direct message feature, references issue #2189, and provides relevant setup instructions and checklist items, making it directly pertinent to the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

📥 Commits

Reviewing files that changed from the base of the PR and between 0f839b9 and 10cda99.

📒 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

Copy link
Collaborator

@arkid15r arkid15r left a 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:

from apps.slack.models.workspace import Workspace


class Chat(TimestampedModel):
Copy link
Collaborator

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?

Copy link
Collaborator Author

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

Copy link
Collaborator

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.

Copy link
Collaborator Author

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

Copy link
Collaborator Author

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


return chat

def add_to_context(self, user_message: str, bot_response: str | None = None) -> None:
Copy link
Collaborator

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.

Copy link
Collaborator Author

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed

@Dishant1804 Dishant1804 requested a review from arkid15r October 8, 2025 10:02
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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:

  1. Line 83: event.get("team") may return None for IM conversations; Slack sometimes uses team_id, context_team_id, or user_team instead. The previous review flagged this as a critical blocker.
  2. 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 returns None, line 98 still calls add_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 response
backend/apps/slack/events/message_posted.py (1)

92-92: Guard against missing id in channel_info["channel"]. Ensure channel_info.get("channel", {}).get("id") is present before calling Conversation.update_data to avoid a KeyError (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

📥 Commits

Reviewing files that changed from the base of the PR and between 10cda99 and 08afea2.

📒 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 to add_to_context supply both user_message and bot_response, ensuring get_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.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Oct 8, 2025

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 to logger.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

📥 Commits

Reviewing files that changed from the base of the PR and between 08afea2 and cb202a6.

📒 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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants