Skip to content

Conversation

@ysmoradi
Copy link
Member

@ysmoradi ysmoradi commented Sep 9, 2025

closes #11362

Summary by CodeRabbit

  • New Features

    • Chat now suggests up to three follow-up prompts after assistant replies; tap to continue the conversation.
    • Auto-scroll pauses while you type and resumes when the input is cleared for smoother reading.
  • Improvements

    • Enhanced chatbot guidance for specific support scenarios to improve response quality.
    • Better request tracking in the background for more reliable troubleshooting.

@ysmoradi ysmoradi requested review from Copilot and msynk September 9, 2025 10:36
@coderabbitai
Copy link

coderabbitai bot commented Sep 9, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Implements follow-up suggestion generation and rendering in the AI chatbot: server now requests and emits JSON follow-up suggestions after streaming the assistant reply; client parses and displays clickable suggestions; adds DTO for suggestions; adjusts auto-scroll behavior; annotates tool parameters; logs RequestId; minor prompt seed edits.

Changes

Cohort / File(s) Summary
Client chat UI tweaks
.../Components/Layout/AppAiChatPanel.razor
Binds auto-scroll to string.IsNullOrEmpty(userInput). Adds conditional UI to render dynamic follow-up buttons from followUpSuggestions. Buttons call SendPromptMessage(suggestion).
Client chat logic & streaming handling
.../Components/Layout/AppAiChatPanel.razor.cs
Adds followUpSuggestions: List<string>. Clears it on defaults and before sending. In streaming, detects JSON follow-up payload, deserializes to list, and keeps separate from normal message assembly and counters. Adjusts success/error handling branches.
Shared DTO
.../Shared/Dtos/Chatbot/StartChatbotRequest.cs
Adds public class AiChatFollowUpList with List<string> FollowUpSuggestions = [];.
Server SignalR chatbot flow
.../Server/Boilerplate.Server.Api/SignalR/AppHub.Chatbot.cs
Adds validation attributes to tool inputs. After assistant streaming completes, requests JSON follow-ups via GetResponseAsync<AiChatFollowUpList> with response_format hints; serializes and emits follow-up JSON payload on the channel.
HTTP handler logging
.../Services/HttpMessageHandlers/ExceptionDelegatingHandler.cs
Captures Request-Id response header and adds to log scope data.
System prompt seed adjustments
.../Data/Configurations/Chatbot/SystemPromptConfiguration.cs
Formatting/indentation changes and a token/content tweak in ADS troubleshooting block within static markdown seed.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant U as User
  participant C as Client (AppAiChatPanel)
  participant H as Server (SignalR Hub)
  participant M as AI Model

  U->>C: Type message / click suggestion
  C->>H: Start chat (user message)
  H->>M: Request assistant reply (stream)
  M-->>H: Stream tokens
  H-->>C: Stream assistant tokens
  Note over C,H: Normal reply streaming completes

  H->>M: Request follow-ups (JSON format)
  M-->>H: { FollowUpSuggestions: [...] }
  H-->>C: Emit follow-up JSON payload

  C->>C: Parse payload → set followUpSuggestions
  C-->>U: Render suggestion buttons
  U->>C: Click suggestion (optional)
  C->>H: Send suggestion as new prompt
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Pre-merge checks (2 passed, 2 warnings, 1 inconclusive)

❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning This PR includes unrelated edits to ExceptionDelegatingHandler for diagnostic logging and formatting/content tweaks in SystemPromptConfiguration that do not pertain to generating chatbot follow-up items. Please remove or relocate the logging enhancements in ExceptionDelegatingHandler and the SystemPromptConfiguration adjustments into a separate PR so this one remains focused on follow-up suggestion generation.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description Check ❓ Inconclusive The description only contains “closes #11362,” which links the issue but provides no detail about the implemented functionality or its purpose, making it too vague for reviewers to grasp the scope. Please expand the description to include a brief summary of the key changes, such as the introduction of follow-up suggestion DTOs, backend JSON support, and dynamic UI rendering.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title “Generate follow up items in bit Boilerplate AI Chatbot (#11362)” concisely and accurately highlights the main change—enabling follow-up suggestion generation in the chatbot—and directly reflects the primary scope of the diff.
Linked Issues Check ✅ Passed The changes fully address issue #11362 by adding the AiChatFollowUpList DTO, extending the SignalR hub to emit JSON follow-up suggestions, updating client logic to handle them, and rendering dynamic suggestion buttons in the UI.

Poem

A whisker twitch, a message sent,
The stream completes—then hints are lent.
Three little hops of follow-up light,
Buttons bloom for the next delight.
With IDs logged and prompts anew,
This rabbit queues the chat for you. 🐇✨

✨ Finishing Touches
🧪 Generate unit tests
  • 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

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements follow-up suggestion functionality for the AI chatbot in bit Boilerplate. The feature generates contextual follow-up questions after each AI response to help users continue conversations naturally.

Key changes:

  • Adds server-side generation of follow-up suggestions using a secondary AI call
  • Implements client-side UI to display follow-up suggestions as clickable buttons
  • Enhances chat experience with auto-scroll improvements and logging enhancements

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
StartChatbotRequest.cs Adds AiChatFollowUpList DTO for follow-up suggestions
AppHub.Chatbot.cs Implements follow-up generation logic and adds required attributes to AI functions
SystemPromptConfiguration.cs Minor formatting fix removing extra space
ExceptionDelegatingHandler.cs Enhances logging by adding RequestId to log scope
AppAiChatPanel.razor.cs Adds client-side handling for follow-up suggestions
AppAiChatPanel.razor Updates UI to display follow-up buttons and improves auto-scroll behavior

Copy link

@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: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Services/HttpMessageHandlers/ExceptionDelegatingHandler.cs (1)

14-15: Avoid possible NRE when LogScopeData option is missing

Casting with null-forgiving may blow up if the option wasn’t populated upstream. Safeguard and initialize the scope dictionary when absent.

Apply:

-        var logScopeData = (Dictionary<string, object?>)request.Options.GetValueOrDefault(RequestOptionNames.LogScopeData)!;
+        var logScopeData = request.Options.GetValueOrDefault(RequestOptionNames.LogScopeData) as Dictionary<string, object?>;
+        if (logScopeData is null)
+        {
+            logScopeData = new();
+            request.Options.Set(new(RequestOptionNames.LogScopeData), logScopeData);
+        }
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/SignalR/AppHub.Chatbot.cs (2)

55-56: Dispose the scope used to resolve IChatClient

Creating a scope without disposing can leak scoped services for the lifetime of the conversation.

Apply:

-        var chatClient = serviceProvider.CreateAsyncScope().ServiceProvider.GetRequiredService<IChatClient>();
+        await using var chatClientScope = serviceProvider.CreateAsyncScope();
+        var chatClient = chatClientScope.ServiceProvider.GetRequiredService<IChatClient>();

91-104: Avoid logging PII (email and full conversation) to Error

This is highly sensitive; storing it in logs risks compliance issues. Prefer persisting to a secure store or redacting before logging; if logging at all, lower the level.

Apply:

-                                    scope.ServiceProvider.GetRequiredService<ILogger<IChatClient>>()
-                                        .LogError("Chat reported issue: User email: {emailAddress}, Conversation history: {conversationHistory}", emailAddress, conversationHistory);
+                                    var logger = scope.ServiceProvider.GetRequiredService<ILogger<IChatClient>>();
+                                    var redactedEmail = emailAddress?.Replace(@"/(^.).+(@.*$)/", "$1***$2"); // simplistic redaction or replace with a proper helper
+                                    logger.LogInformation("Chat reported issue: User email (redacted): {email}, Conversation captured (length): {length}", redactedEmail, conversationHistory?.Length ?? 0);
+                                    // TODO: persist securely instead of logging raw content.
🧹 Nitpick comments (7)
src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Services/HttpMessageHandlers/ExceptionDelegatingHandler.cs (1)

35-43: Broaden JSON content-type check to include +json problem payloads

Responses like application/problem+json won’t match Contains("application/json"). Accept any media type that ends with +json or json.

Apply:

-                if (isInternalRequest && /* The following exception handling mechanism applies exclusively to responses from our own server. */
-                    response.IsSuccessStatusCode is false &&
-                    string.IsNullOrEmpty(requestIdValue) is false &&
-                    response.Content.Headers.ContentType?.MediaType?.Contains("application/json", StringComparison.InvariantCultureIgnoreCase) is true)
+                var mediaType = response.Content.Headers.ContentType?.MediaType;
+                if (isInternalRequest &&
+                    response.IsSuccessStatusCode is false &&
+                    string.IsNullOrEmpty(requestIdValue) is false &&
+                    (mediaType?.EndsWith("json", StringComparison.OrdinalIgnoreCase) ?? false))
src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Dtos/Chatbot/StartChatbotRequest.cs (1)

34-37: Freeze the JSON contract for follow-ups

Make the wire name explicit to avoid future serializer policy drift; keep the list non-null.

Apply:

-public class AiChatFollowUpList
+public sealed class AiChatFollowUpList
 {
-    public List<string> FollowUpSuggestions { get; set; } = [];
+    [JsonPropertyName("FollowUpSuggestions")]
+    public List<string> FollowUpSuggestions { get; set; } = [];
 }
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Data/Configurations/Chatbot/SystemPromptConfiguration.cs (1)

25-27: Grammar nit: “You are a assistant” → “You are an assistant”

Tiny polish in the very first sentence of the seed prompt.

Apply:

-        return @"You are a assistant for the Boilerplate app. Below, you will find a markdown document containing information about the app, followed by the user's query.
+        return @"You are an assistant for the Boilerplate app. Below, you will find a markdown document containing information about the app, followed by the user's query.
src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Layout/AppAiChatPanel.razor (2)

102-118: Gate follow-up chips behind not-loading to avoid flicker

They usually arrive after success, but add an explicit guard to prevent edge flicker during stream completion.

Apply:

-                @if (followUpSuggestions.Any())
+                @if (!isLoading && followUpSuggestions.Any())
                 {
                     <BitStack Alignment=" BitAlignment.Center" FitHeight FillContent Class="default-prompt-container">

75-99: Minor markup cleanup

There’s an extra leading space in Alignment=" BitAlignment.Center".

Apply:

-                    <BitStack Alignment=" BitAlignment.Center" FitHeight FillContent Class="default-prompt-container">
+                    <BitStack Alignment="BitAlignment.Center" FitHeight FillContent Class="default-prompt-container">
src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Layout/AppAiChatPanel.razor.cs (2)

94-100: Optional: avoid extra render before sending

You call StateHasChanged() right before SendMessage(), which immediately clears userInput. This causes a brief flash. Consider removing this render.

Apply:

-        followUpSuggestions = [];
-        userInput = message;
-        StateHasChanged();
-        await SendMessage();
+        followUpSuggestions = [];
+        userInput = message;
+        await SendMessage();

186-193: Indexing on error path is fragile—add bounds check

chatMessages[responseCounter * 2] assumes ideal interleaving. Guard to avoid OOR during reconnection/races.

Apply:

-                    chatMessages[responseCounter * 2].Successful = false;
+                    var idx = responseCounter * 2;
+                    if ((uint)idx < (uint)chatMessages.Count)
+                        chatMessages[idx].Successful = false;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Knowledge Base: Disabled due to Reviews > Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between cab38b1 and 8c244f3.

📒 Files selected for processing (6)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Layout/AppAiChatPanel.razor (2 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Layout/AppAiChatPanel.razor.cs (4 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Services/HttpMessageHandlers/ExceptionDelegatingHandler.cs (1 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Data/Configurations/Chatbot/SystemPromptConfiguration.cs (2 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/SignalR/AppHub.Chatbot.cs (3 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Dtos/Chatbot/StartChatbotRequest.cs (1 hunks)
⏰ 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). (1)
  • GitHub Check: build and test
🔇 Additional comments (5)
src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Layout/AppAiChatPanel.razor (1)

43-45: Auto-scroll tweak looks good

Binding AutoScroll to empty userInput is a sensible UX improvement while typing.

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Layout/AppAiChatPanel.razor.cs (3)

130-143: Good: follow-up suggestions reset on ClearChat

Resetting both chat state and followUpSuggestions avoids stale chips after clearing.


180-201: Streaming append gating looks correct

Appending only when (responseCounter + 1) == expectedResponsesCount prevents interleaving with older canceled turns.


172-177: Verify serializer policy alignment with server

If the server starts using camelCase serialization, client-side deserialization without options will fail. Consider centralizing JsonSerializerOptions and using them here.

Would you like me to scan the repo for any global JsonSerializerOptions (e.g., JsonSerializerDefaults.Web or PropertyNamingPolicy = JsonNamingPolicy.CamelCase) and produce a small alignment patch?

src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/SignalR/AppHub.Chatbot.cs (1)

88-138: Tool signatures updates look good

Annotating parameters with [Required]/[Description] improves validation and model guidance.

@ysmoradi ysmoradi merged commit 0879354 into bitfoundation:develop Sep 10, 2025
3 checks passed
@ysmoradi ysmoradi deleted the 11362 branch September 10, 2025 11:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bit Boilerplate AI Chatbot doesn't generate follow up items

1 participant