Skip to content
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

WIP: clickable results #395

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open

WIP: clickable results #395

wants to merge 4 commits into from

Conversation

Bran18
Copy link
Contributor

@Bran18 Bran18 commented Feb 26, 2025

Summary by Sourcery

Implement clickable text functionality in chat messages to allow users to generate follow-up queries by clicking on key sections of the text. This includes identifying and handling clickable portions of text, such as headings, list items, and bolded text.

New Features:

  • Implement clickable text functionality within chat messages, allowing users to generate follow-up queries by clicking on key sections of the text.
  • Enhance user interaction by enabling clickable sections for headings, list items, and bolded text within chat messages, facilitating more detailed explorations of specific topics.
  • Improve content processing to identify and handle clickable portions of text, including headings, numbered sections, bullet points, and bold text, enhancing the interactive experience.

Summary by CodeRabbit

  • New Features
    • Introduced interactive text components that make clickable content in chat messages and other content areas more engaging.
  • Style
    • Enhanced visual styling of clickable text elements with improved hover effects, transitions, and focus outlines for better accessibility and consistency.

Copy link

sourcery-ai bot commented Feb 26, 2025

Reviewer's Guide by Sourcery

This pull request introduces clickable text functionality to the chat messages, allowing users to generate follow-up queries by clicking on specific parts of the text. It includes the implementation of ClickableText and EnhancedClickableText components, along with parsing logic, click handlers, and CSS styling. The changes also involve refactoring the ChatMessage component to use the new clickable text components.

Sequence diagram for generating follow-up queries from clickable text

sequenceDiagram
    participant User
    participant ChatMessage
    participant ClickableText
    participant sendMessageFromResponse

    User->>ChatMessage: Clicks on clickable text
    ChatMessage->>ClickableText: Handles click event with text
    ClickableText->>sendMessageFromResponse: Calls sendMessageFromResponse(text)
    sendMessageFromResponse-->>ChatMessage: Sends new query
    ChatMessage-->>User: Displays response
Loading

File-Level Changes

Change Details Files
Implements clickable text functionality to allow users to generate follow-up queries by clicking on specific parts of the chat message.
  • Added ClickableText component to make sections of text clickable.
  • Implemented logic to extract text from React nodes for both web and normal contexts.
  • Added parsing logic to identify clickable portions of text based on patterns like headings, list items, and bold text.
  • Implemented click handlers to send follow-up queries based on the clicked text.
  • Added CSS styling for clickable text elements to provide visual cues.
  • Added logic to handle nested lists and links in the clickable text component.
  • Added logic to handle strong/bold text within list items.
  • Added logic to handle unique phrases in the clickable text component.
apps/masterbots.ai/components/routes/chat/chat-clickable-text.tsx
apps/masterbots.ai/lib/clickable-results.ts
apps/masterbots.ai/app/globals.css
apps/masterbots.ai/components/routes/chat/chat-message.tsx
apps/masterbots.ai/lib/utils.ts
apps/masterbots.ai/types/types.ts
Introduces an enhanced clickable text component with improved content extraction and formatting.
  • Created EnhancedClickableText component to identify and make clickable section headings, list items with bold text, and text patterns with colons.
  • Implemented functions to extract text content, titles from headings, and context from text.
  • Added logic to format follow-up queries based on the clicked text and context.
  • Implemented hover states for clickable elements to provide visual cues.
  • Added utility function to safely invoke callbacks.
  • Refactored ChatMessage component to use EnhancedClickableText for rendering clickable content.
apps/masterbots.ai/components/routes/chat/chat-clickable-list.tsx
apps/masterbots.ai/lib/clickable-content-extraction.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!
  • Generate a plan of action for an issue: Comment @sourcery-ai plan on
    an issue to generate a plan of action for it.

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

vercel bot commented Feb 26, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
masterbots ❌ Failed (Inspect) Feb 26, 2025 8:12pm

Copy link
Contributor

coderabbitai bot commented Feb 26, 2025

Walkthrough

This pull request introduces extensive enhancements to the styling and interactivity of clickable text elements within the application. New CSS classes and hover/focus effects improve button and heading aesthetics. Several React components have been added or refactored—most notably, the EnhancedClickableText and EnhancedChatMessage components—to offer streamlined processing of AI-generated text. Additionally, new utility functions and updated type definitions help in more robust text extraction, parsing, and event handling.

Changes

File(s) Change Summary
apps/masterbots.ai/app/globals.css Added new CSS classes (.clickable-text, .section-title.clickable-text, etc.) and hover, focus, and transition effects to enhance clickable text elements and buttons.
apps/masterbots.ai/components/routes/chat/chat-clickable-list.tsx
apps/masterbots.ai/components/routes/chat/chat-clickable-text.tsx
apps/masterbots.ai/components/routes/chat/chat-message.tsx
Introduced the EnhancedClickableText component and refactored clickable text logic. Renamed ChatMessage to EnhancedChatMessage with enhanced content rendering using the new component and improved click event handling.
apps/masterbots.ai/lib/clickable-content-extraction.ts Added utility functions (extractTextContent, extractTitleFromHeading, extractContextFromText, formatFollowUpQuery, and safeInvoke) for extracting and formatting text from React nodes.
apps/masterbots.ai/lib/clickable-results.ts Refactored text parsing functionality including an updated ParsedText interface and added functions (cleanClickableText, isTextClickable, extractClickablePortion) for robust text extraction and cleaning.
apps/masterbots.ai/lib/utils.ts Removed the old ParsedText interface and added a new constant UNIQUE_PHRASES for categorizing unique text patterns.
apps/masterbots.ai/types/types.ts Updated the ClickableTextProps interface (renamed parameters and added a new node property) and introduced a new ParsedText interface with an additional fullContext property.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant ECT as EnhancedClickableText
    participant UF as Utility Functions
    participant CB as Callback (sendMessageFromResponse)
    
    U->>ECT: Clicks on a text element
    ECT->>UF: Processes text & extracts clickable portion
    UF-->>ECT: Returns processed text data
    ECT->>CB: Invokes callback with formatted query
    CB-->>ECT: Acknowledges the response
Loading

Possibly related PRs

Suggested labels

enhancement, feature

Suggested reviewers

  • AndlerRL

Poem

In a garden of code I hop with glee,
New clickable styles set my spirit free.
Buttons and headings now dance in the light,
With smooth transitions from day to night.
I'm a rabbit in code, joyful and spry—
Hopping through changes as time flies by! 🐇

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

apps/masterbots.ai/app/globals.css

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the config "next/core-web-vitals" to extend from. Please check that the name of the config is correct.

The config "next/core-web-vitals" was referenced from the config file in "/apps/masterbots.ai/.eslintrc.json".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.

apps/masterbots.ai/components/routes/chat/chat-clickable-list.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the config "next/core-web-vitals" to extend from. Please check that the name of the config is correct.

The config "next/core-web-vitals" was referenced from the config file in "/apps/masterbots.ai/.eslintrc.json".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.

apps/masterbots.ai/components/routes/chat/chat-clickable-text.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the config "next/core-web-vitals" to extend from. Please check that the name of the config is correct.

The config "next/core-web-vitals" was referenced from the config file in "/apps/masterbots.ai/.eslintrc.json".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.

  • 5 others
✨ Finishing Touches
  • 📝 Generate Docstrings

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @Bran18 - I've reviewed your changes - here's some feedback:

Overall Comments:

  • Consider adding a fallback mechanism to processContent to handle unexpected React element types gracefully.
  • The UNIQUE_PHRASES constant is duplicated in lib/utils.ts and lib/clickable-results.ts; consolidate it into a single source of truth.
Here's what I looked at during the review
  • 🟢 General issues: all looks good
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟡 Complexity: 2 issues found
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

const contentText =
typeof children === 'string'
? children
: extractTextFromReactNodeNormal(children)

Copy link

Choose a reason for hiding this comment

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

issue (complexity): Consider using a lookup table to map element types to processors to reduce nested conditionals in processContent.

It looks like you still have many helper functions and deeply nested conditionals scattered throughout the code. To reduce complexity, consider consolidating similar processing rules into a lookup table that maps element types to their corresponding processors. This can clean up the main processContent function and lower the depth of nested conditionals.

For example, you could extract this mapping:

const elementProcessors: Record<string, (elem: React.ReactElement) => React.ReactNode> = {
  // Headings
  'h1': processHeading,
  'h2': processHeading,
  'h3': processHeading,
  'h4': processHeading,
  'h5': processHeading,
  'h6': processHeading,
  // Emphasis
  'strong': processEmphasis,
  'b': processEmphasis,
  // List item
  'li': processListItem,
  // Links
  'a': processLink,
};

And then refactor your processContent function like so:

if (React.isValidElement(content) && typeof content.type === 'string') {
  const processor = elementProcessors[content.type];
  if (processor) {
    return processor(content);
  }
  // If element has children, process them recursively.
  if (content.props?.children) {
    return React.cloneElement(content, {
      ...content.props,
      children: processContent(content.props.children),
    });
  }
}

This change reduces the number of direct if/else checks, making the logic easier to follow while keeping functionality intact.

}

// Process React elements
if (React.isValidElement(content)) {
Copy link

Choose a reason for hiding this comment

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

issue (complexity): Consider using a configurable transformation list to handle different element types, reducing nested conditionals in processContent.

Consider abstracting the conditional branching into a configurable transformation list so that you avoid writing separate deep branches. For example, you could create an array of transformation objects that encapsulates the conditions and transformation functions. Then in your recursive processContent, check if any transformation applies before processing children. This keeps the recursion logic flatter and more declarative.

For instance, you can refactor like this:

// List your processors
const processors: {
  check: (element: React.ReactElement) => boolean;
  transform: (element: React.ReactElement) => React.ReactElement;
}[] = [
  {
    check: (element) => isHeading(element),
    transform: (element) => processSectionHeading(element),
  },
  {
    check: (element) => isListItem(element),
    transform: (element) => processListItemWithBold(element),
  },
  // add more processors as needed
];

const processContent = (content: React.ReactNode): React.ReactNode => {
  if (typeof content === 'string' || typeof content !== 'object' || content === null)
    return content;

  if (Array.isArray(content))
    return content.map((item, index) => (
      <React.Fragment key={`content-item-${index}`}>
        {processContent(item)}
      </React.Fragment>
    ));

  if (React.isValidElement(content)) {
    // Find the first matching processor
    for (const { check, transform } of processors) {
      if (check(content)) {
        return transform(content);
      }
    }

    // Process children if available
    if (content.props?.children) {
      return React.cloneElement(content, {
        ...content.props,
        children: processContent(content.props.children),
      });
    }
  }
  return content;
};

This approach maintains functionality while reducing nested conditional logic.

// Process standard text nodes (paragraphs, plain text)
const processTextContent = (text: string) => {
// Don't process empty or very short text
if (!text || text.length < 3) return text
Copy link

Choose a reason for hiding this comment

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

suggestion (code-quality): Use block braces for ifs, whiles, etc. (use-braces)

Suggested change
if (!text || text.length < 3) return text
if (!text || text.length < 3) {


ExplanationIt is recommended to always use braces and create explicit statement blocks.

Using the allowed syntax to just write a single statement can lead to very confusing
situations, especially where subsequently a developer might add another statement
while forgetting to add the braces (meaning that this wouldn't be included in the condition).

* Extracts text content from React nodes
*/
export function extractTextContent(node: ReactNode): string {
if (typeof node === 'string') return node
Copy link

Choose a reason for hiding this comment

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

suggestion (code-quality): Use block braces for ifs, whiles, etc. (use-braces)

Suggested change
if (typeof node === 'string') return node
if (typeof node === 'string') {


ExplanationIt is recommended to always use braces and create explicit statement blocks.

Using the allowed syntax to just write a single statement can lead to very confusing
situations, especially where subsequently a developer might add another statement
while forgetting to add the braces (meaning that this wouldn't be included in the condition).

*/
export function extractTextContent(node: ReactNode): string {
if (typeof node === 'string') return node
if (typeof node === 'number') return node.toString()
Copy link

Choose a reason for hiding this comment

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

suggestion (code-quality): Use block braces for ifs, whiles, etc. (use-braces)

Suggested change
if (typeof node === 'number') return node.toString()
if (typeof node === 'number') {


ExplanationIt is recommended to always use braces and create explicit statement blocks.

Using the allowed syntax to just write a single statement can lead to very confusing
situations, especially where subsequently a developer might add another statement
while forgetting to add the braces (meaning that this wouldn't be included in the condition).

export function extractClickablePortion(text: string): string {
// For markdown headings
const headingMatch = text.match(/^(#+\s+[^:\n]+)/)
if (headingMatch) return headingMatch[1].trim()
Copy link

Choose a reason for hiding this comment

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

suggestion (code-quality): Use block braces for ifs, whiles, etc. (use-braces)

Suggested change
if (headingMatch) return headingMatch[1].trim()
if (headingMatch) {


ExplanationIt is recommended to always use braces and create explicit statement blocks.

Using the allowed syntax to just write a single statement can lead to very confusing
situations, especially where subsequently a developer might add another statement
while forgetting to add the braces (meaning that this wouldn't be included in the condition).


// For numbered sections
const numberedMatch = text.match(/^(\d+\.\s+[^:\n]+)/)
if (numberedMatch) return numberedMatch[1].trim()
Copy link

Choose a reason for hiding this comment

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

suggestion (code-quality): Use block braces for ifs, whiles, etc. (use-braces)

Suggested change
if (numberedMatch) return numberedMatch[1].trim()
if (numberedMatch) {


ExplanationIt is recommended to always use braces and create explicit statement blocks.

Using the allowed syntax to just write a single statement can lead to very confusing
situations, especially where subsequently a developer might add another statement
while forgetting to add the braces (meaning that this wouldn't be included in the condition).


// For sections with colons (Title: Description)
const colonMatch = text.match(/^([^:]+):/)
if (colonMatch) return colonMatch[1].trim()
Copy link

Choose a reason for hiding this comment

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

suggestion (code-quality): Use block braces for ifs, whiles, etc. (use-braces)

Suggested change
if (colonMatch) return colonMatch[1].trim()
if (colonMatch) {


ExplanationIt is recommended to always use braces and create explicit statement blocks.

Using the allowed syntax to just write a single statement can lead to very confusing
situations, especially where subsequently a developer might add another statement
while forgetting to add the braces (meaning that this wouldn't be included in the condition).


// For bullet points
const bulletMatch = text.match(/^([•-]\s+[^:\n]+)/)
if (bulletMatch) return bulletMatch[1].trim()
Copy link

Choose a reason for hiding this comment

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

suggestion (code-quality): Use block braces for ifs, whiles, etc. (use-braces)

Suggested change
if (bulletMatch) return bulletMatch[1].trim()
if (bulletMatch) {


ExplanationIt is recommended to always use braces and create explicit statement blocks.

Using the allowed syntax to just write a single statement can lead to very confusing
situations, especially where subsequently a developer might add another statement
while forgetting to add the braces (meaning that this wouldn't be included in the condition).


// For bold text
const boldMatch = text.match(/^\*\*([^*]+)\*\*/)
if (boldMatch) return boldMatch[1].trim()
Copy link

Choose a reason for hiding this comment

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

suggestion (code-quality): Use block braces for ifs, whiles, etc. (use-braces)

Suggested change
if (boldMatch) return boldMatch[1].trim()
if (boldMatch) {


ExplanationIt is recommended to always use braces and create explicit statement blocks.

Using the allowed syntax to just write a single statement can lead to very confusing
situations, especially where subsequently a developer might add another statement
while forgetting to add the braces (meaning that this wouldn't be included in the condition).

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 (16)
apps/masterbots.ai/lib/utils.ts (1)

340-355: Consider externalizing or documenting phrase usage.

The new UNIQUE_PHRASES array is straightforward. However, if these phrases influence broader application logic or user-facing text, consider externalizing them into a config or an i18n file. This keeps the codebase tidier and the usage more discoverable.

apps/masterbots.ai/components/routes/chat/chat-message.tsx (1)

91-131: Ensure performance with large Markdown content.

Replacing direct rendering with <EnhancedContent> across paragraphs, headings, and strong tags effectively injects clickable features. However, watch for potential performance hits if messages become very large, as nested React elements can grow in complexity.

apps/masterbots.ai/lib/clickable-content-extraction.ts (2)

22-32: Regex heading extraction looks good.

extractTitleFromHeading uses a concise regex to strip numeric prefixes. For headings lacking a trailing period, the function falls back to the original text. This is a suitable fallback; just be mindful of variant heading formats.


34-52: Evaluate case sensitivity for context extraction.

extractContextFromText pinpoints text from the first occurrence of the keyword until the colon. If you need a case-insensitive match or a different delimiter, consider expanding the logic.

apps/masterbots.ai/types/types.ts (1)

91-92: Consider replacing any with a more specific type.

Using any here could mask potential type issues. Defining a more precise type (e.g., number or a union of acceptable types) will improve type safety and clarity.

     // biome-ignore lint/suspicious/noExplicitAny: <explanation>
-    meter: any
+    // TODO: Provide a more specific type, for example:
+    meter: number | null
apps/masterbots.ai/components/routes/chat/chat-clickable-list.tsx (2)

53-53: Avoid using any for contextText.

Currently, contextText is typed as any, which could lead to losing valuable typing information. Consider switching to a well-defined type or a more generic structure if the shape is unknown.

- const handleClick = (text: string, contextText: any = '') => {
+ interface ContextData {
+   // Provide fields for the context if known
+   details?: string;
+ }
+ 
+ const handleClick = (text: string, contextText: ContextData = {}) => {

169-224: Consider short-circuit returns in processContent for large nested structures.

This recursive logic is fine for moderate nesting, but deep or invalid structures could cause performance issues. Early checks or short-circuit conditions can improve resiliency.

apps/masterbots.ai/components/routes/chat/chat-clickable-text.tsx (3)

38-38: Parameterize the follow-up prompt.

Currently, the prompt text is hardcoded to “Explain more in-depth and in detail about…”. For flexibility and maintainability, consider externalizing or parameterizing this phrase.

- sendMessageFromResponse(`Explain more in-depth and in detail about ${cleanedText}`)
+ const followUpPrompt = `Explain more in-depth and in detail about ${cleanedText}`
+ sendMessageFromResponse(followUpPrompt)

48-83: Centralize content-type checks.

getContentTypeClass uses multiple regex matches and conditionals. If the checks expand, consider moving them into a separate helper function or object map for clarity and maintainability.


304-306: Clarify the node prop usage.

When node is present, the code delegates to processContent(children). If node can contain its own logic or differ from children, consider clarifying or renaming to avoid confusion.

apps/masterbots.ai/lib/clickable-results.ts (5)

6-41: Consider React.cloneElement or alternative approach for React element transformation.

Reconstructing the React element with a spread operator might lose some metadata (e.g., key, ref handling). A safer approach is to use React.cloneElement or a dedicated utility that preserves all element properties unless a full recreation is intentionally desired.


43-67: DRY opportunity with extractTextFromReactNodeWeb.

This function closely mirrors the logic in extractTextFromReactNodeWeb; consider consolidating both into a shared utility to reduce code duplication and possible maintenance burdens.


69-81: Include other punctuation in cleanClickableText.

Only a narrow set of trailing characters is stripped. If you want to remove “?”, “!”, etc., expand the character class.

You could do:

-    .replace(/[,.()[\]]$/, '') // Remove trailing punctuation
+    .replace(/[,.()[\]?!]$/, '') // Also remove question marks, exclamation marks

105-130: Unify similar pattern checks in extractClickablePortion.

Multiple sequential regex checks make the function straightforward but somewhat repetitive. Storing them as a list of patterns and iterating might simplify future extensions and improve maintainability.


132-256: Refactor large parseClickableText function.

The multi-pattern matching logic can be extracted into smaller helper functions or a config-driven approach. This will reduce complexity and streamline updates.

apps/masterbots.ai/app/globals.css (1)

266-280: Ensure consistent styling across .text-link and .clickable-text.

Defining button styles for both .text-link and .clickable-text classes in tandem is good for reusability, but check if you need to unify them or use a single class to avoid CSS bloat or conflicting rules over time.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 037e41e and 0e1466b.

📒 Files selected for processing (8)
  • apps/masterbots.ai/app/globals.css (3 hunks)
  • apps/masterbots.ai/components/routes/chat/chat-clickable-list.tsx (1 hunks)
  • apps/masterbots.ai/components/routes/chat/chat-clickable-text.tsx (2 hunks)
  • apps/masterbots.ai/components/routes/chat/chat-message.tsx (4 hunks)
  • apps/masterbots.ai/lib/clickable-content-extraction.ts (1 hunks)
  • apps/masterbots.ai/lib/clickable-results.ts (1 hunks)
  • apps/masterbots.ai/lib/utils.ts (1 hunks)
  • apps/masterbots.ai/types/types.ts (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
apps/masterbots.ai/lib/clickable-results.ts (1)
Learnt from: AndlerRL
PR: bitcashorg/masterbots#388
File: apps/masterbots.ai/lib/clickable-results.ts:148-149
Timestamp: 2025-02-24T20:46:17.229Z
Learning: Issue #389 is tracking potential improvements and refactoring needs for the ClickableText component, including the evaluation of using context objects instead of multiple parameters.
🔇 Additional comments (19)
apps/masterbots.ai/components/routes/chat/chat-message.tsx (7)

10-17: Doc comment aligns well with the new naming.

Renaming to EnhancedChatMessage and adding the descriptive JSDoc is coherent with the new functionality. Clear documentation helps maintainers understand the purpose of this enhanced version.


19-40: Validate the references for assistant vs user roles.

In EnhancedChatMessage, you're now cleaning the content and managing references. Verify that references are only relevant to non-user roles and that undefined references don't break the rendering.


71-83: EnhancedContent wrapper preserves user text behavior.

Wrapping children with EnhancedClickableText is a neat approach to selectively enable click handling for assistant messages only. This ensures the user’s own text isn't inadvertently made clickable.


133-149: List handling is clear.

Applying the <EnhancedContent> logic to list elements is consistent. The condition to detect nested lists is a good safeguard. This code segment looks solid.


153-166: Link rendering is correct and secure.

Providing target="_blank" and rel="noopener noreferrer" is a good practice to prevent security vulnerabilities. This safeguards your users when opening external links.


168-197: Code block handling is well-structured.

Integrating CodeBlock for multi-line code snippets is a robust approach. The check for inline vs block code, along with language extraction, appears correctly implemented.


202-206: Conditional rendering of ChatMessageActions.

Conditionally displaying actions with actionRequired is a clean design choice. It ensures clarity of when user actions are required, keeping the UI minimal otherwise.

apps/masterbots.ai/lib/clickable-content-extraction.ts (4)

1-3: Imports and setup confirmed.

The import of React, ReactNode types, and usage match the file’s purpose. No issues are detected here.


4-20: Handle React fragments if needed.

extractTextContent works well for common node types. If fragment usage is expected (<></>), consider a fallback to handle them explicitly, though your current checks likely suffice.


58-63: Consider validating or escaping the query inputs.

formatFollowUpQuery is straightforward, but if the user can supply arbitrary keyword or context, consider sanitizing or validating them to avoid potential injection or formatting issues.


65-75: Safe invoke pattern is neat.

safeInvoke neatly prevents runtime errors by checking if the callback is a function. This is a clean defensive coding practice.

apps/masterbots.ai/types/types.ts (1)

361-366: Nice addition of ParsedText interface!

The fields are well-labeled, making it clear how processed text is structured. No issues found here.

apps/masterbots.ai/components/routes/chat/chat-clickable-list.tsx (2)

63-96: processSectionHeading logic looks good!

Gracefully handles the click event on headings and applies hover styling & accessibility attributes. No concerns here.


98-167: Validate strongText extraction in processListItemWithBold.

Ensure that strongText doesn't remain empty if the node is unexpectedly empty or malformed. You might guard the re-cloning logic with a check for valid text to prevent potential runtime issues.

apps/masterbots.ai/components/routes/chat/chat-clickable-text.tsx (1)

141-178: Smooth handling of emphasized text with colons.

The logic for splitting on the first colon is clear and covers common AI-generated subsection headings. No issues found.

apps/masterbots.ai/lib/clickable-results.ts (2)

4-4: UNIQUE_PHRASES import is preserved—verify necessity.

The import statement remains present despite references suggesting prior removal. Confirm that UNIQUE_PHRASES is indeed required to avoid unused imports or inconsistencies across the codebase.


82-103: Clarify URL matching logic.

This function discards URLs but may inadvertently skip other link-like patterns (e.g., relative or protocol-less URLs). Verify whether that is acceptable for your usage scenario.

apps/masterbots.ai/app/globals.css (2)

281-326: Hover and focus interactions look good.

The addition of transitions, hover underlines, and focus outlines provides a clear interactive experience. Keep an eye on potential layering issues if other components introduce additional focus or hover states.


603-653: Verify broader browser compatibility and test style overrides.

The specialized heading, bullet, and unique phrase styling significantly improves readability and clarity. Ensure that older or less common browsers correctly handle the ::after underline transition and data attributes (data-section-title).

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.

1 participant