fix(slack): NestBot deferred replies format without a second LLM call#4320
fix(slack): NestBot deferred replies format without a second LLM call#4320rajnisk wants to merge 1 commit intoOWASP:feature/nestbot-ai-assistantfrom
Conversation
Add format_blocks() for pre-rendered text, chunk mrkdwn under Slack limits, align chat.postMessage fallback text with formatting, dedupe link conversion via markdown(), and guard empty/YES/NO outputs. Update tests. Made-with: Cursor
Summary by CodeRabbitRelease Notes
WalkthroughThis PR refactors Slack AI response formatting by introducing a Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
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.
🧹 Nitpick comments (1)
backend/tests/apps/slack/common/handlers/ai_test.py (1)
196-205: Consider using the constant for consistency.The assertion
len(block_text) <= 3001hardcodes the Slack limit whileMAX_BLOCK_TEXT_LENGTH(3000) is the production target. For clarity, consider either using<= MAX_BLOCK_TEXT_LENGTHto match the production guarantee, or adding a brief comment explaining that 3001 is Slack's actual limit while 3000 is the safety margin.♻️ Suggested change
for block in blocks: block_text = block["text"]["text"] - assert len(block_text) <= 3001 # Slack mrkdwn section limit + assert len(block_text) <= MAX_BLOCK_TEXT_LENGTH # production safety limit🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/tests/apps/slack/common/handlers/ai_test.py` around lines 196 - 205, The test test_format_blocks_splits_long_text uses a hardcoded 3001 in the assertion; update it to use the constant MAX_BLOCK_TEXT_LENGTH (or assert <= MAX_BLOCK_TEXT_LENGTH + 1 with a clarifying comment if you intend to document Slack's absolute limit) so the test aligns with the production target and references the same limit used by format_blocks and the MAX_BLOCK_TEXT_LENGTH constant.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@backend/tests/apps/slack/common/handlers/ai_test.py`:
- Around line 196-205: The test test_format_blocks_splits_long_text uses a
hardcoded 3001 in the assertion; update it to use the constant
MAX_BLOCK_TEXT_LENGTH (or assert <= MAX_BLOCK_TEXT_LENGTH + 1 with a clarifying
comment if you intend to document Slack's absolute limit) so the test aligns
with the production target and references the same limit used by format_blocks
and the MAX_BLOCK_TEXT_LENGTH constant.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: a83bbe0b-ceff-40e6-a584-bf03dfbd384e
📒 Files selected for processing (5)
backend/apps/slack/common/handlers/ai.pybackend/apps/slack/services/message_auto_reply.pybackend/apps/slack/utils.pybackend/tests/apps/slack/common/handlers/ai_test.pybackend/tests/apps/slack/services/message_auto_reply_test.py
|
Superseded: equivalent changes (deferred reply formatting without re-running the model, Slack block limits, fallback text, link handling, YES/NO + empty guards, tests) are merged into the #4319 |



Proposed change
Resolves #3693
This PR implements reply handling fixes for NestBot’s delayed auto-reply path (
generate_ai_reply_if_unanswered): how answers are formatted and posted to Slack after the question-detector pipeline, without overlapping the Gemini provider, multi-agent orchestration, or interaction-UX PRs.What changed
generate_ai_reply_if_unansweredno longer callsget_blocks(ai_response_text, …), which incorrectly ranprocess_ai_queryagain on the model’s answer. It now usesformat_blocks(), which only formats pre-rendered text.format_blocks()splits long answers into multiple Slack section blocks so mrkdwn stays under Slack’s per-block limit (~3001 characters; we target 3000).chat.postMessagetext: fallback/notification text is derived fromformat_ai_response_for_slack, truncated with an ellipsis when needed, and aligned with block formatting (not raw model output only).format_ai_response_for_slack: stops callingformat_links_for_slackdirectly; link conversion happens once viamarkdown()/format_links_for_slackper block (avoids double processing).YES/NOoutputs from the pipeline inprocess_ai_query; treat empty/whitespace-only formatted output as error blocks instead of posting an empty block list.Files touched
backend/apps/slack/common/handlers/ai.pybackend/apps/slack/services/message_auto_reply.pybackend/apps/slack/utils.pybackend/tests/apps/slack/common/handlers/ai_test.pybackend/tests/apps/slack/services/message_auto_reply_test.pyChecklist
make check-testlocally: all warnings addressed, tests passed