npm package: @nuskin/chat-bot
Description: React Chat Bot component for GenAI interaction with Amazon Bedrock
Author: Paul Roberts
Latest version: 1.0.0

# @nuskin/chat-bot

A React Chat Bot component for GenAI interaction with Amazon Bedrock. This component provides a modern, user-friendly chat interface that connects to AI services
through Amazon Bedrock, making it easy to add conversational AI capabilities to your application. This component is written in a way that the api endpoint that it
will call can take the data passed to it and use that data to invoke a Amazon Bedrock Agent. The `apiHeaders` passed to this component should include Authorization
for the targeted api endpoint.

## Features

-   Clean, responsive UI with Material Design components
-   Support for markdown rendering in responses, including syntax highlighting for code blocks with copy functionality
-   Suggested example questions to help users get started
-   Seamless integration with Amazon Bedrock AI agents
-   Session management for conversational context with cookie-based persistence
-   Multiple LLM model selection via dropdown
-   Error handling with visual alerts
-   Multiline input support (Shift+Enter for new line, Enter to submit)
-   Easy to customize appearance and behavior
-   Works in both React applications and vanilla JavaScript environments
-   Customizable title bar with optional logo and "Clear Chat Session" button
-   Auto-scrolling chat container for smooth user experience

## Installation

Using npm:

```bash
npm install @nuskin/chat-bot
```

Using yarn:

```bash
yarn add @nuskin/chat-bot
```

### Peer Dependencies

This component requires the following peer dependencies:

```bash
yarn add @emotion/react@11.13.5 @emotion/styled@11.13.5 @mui/material@6.1.8 @mui/icons-material@6.1.8 react@18.3.1 react-dom@18.3.1
```

### Additional Dependencies

The package uses these additional dependencies internally (you don't need to install them separately):

-   **@nuskin/axios-util**: For making HTTP requests with retry functionality
-   **@nuskin/uncle-buck**: For utility functions
-   **js-cookie**: For session management with cookie-based persistence
-   **uuid**: For generating unique session IDs
-   **tailwindcss**: For additional styling
-   **react-markdown**, **react-syntax-highlighter**, **rehype-raw**, **remark-gfm**, **remark-breaks**: For markdown rendering with code syntax highlighting

## Usage

### In a React Application

```jsx
import { ChatBotUI } from '@nuskin/chat-bot'
import '@nuskin/chat-bot/style.css'

function App() {
    return (
        <ChatBotUI.ChatBot
            title="My ChatBot"
            questions={['What is the capital of France?', 'What is GenAI?']}
            agentId="YOUR_BEDROCK_AGENT_ID"
            agentAliasId="YOUR_BEDROCK_AGENT_ALIAS_ID"
            apiEndpoint="YOUR_API_ENDPOINT"
            apiHeaders='{"Authorization": "YOUR_KEY_OR_TOKEN"}'
        />
    )
}
```

### With Multiple LLM Models and Hidden Title Bar

```jsx
import { ChatBotUI } from '@nuskin/chat-bot'
import '@nuskin/chat-bot/style.css'

function App() {
    // Define custom example questions
    const exampleQuestions = ['What products help with dry skin?', 'How can I reduce wrinkles?', 'What ingredients should I look for in anti-aging products?']
    const agents = [
        {
            agentId: 'YOUR_BEDROCK_AGENT_ID',
            agentAliasId: 'YOUR_BEDROCK_AGENT_ALIAS_ID',
            value: 'haiku',
            label: 'Haiku'
        },
        {
            agentId: 'YOUR_BEDROCK_AGENT_ID',
            agentAliasId: 'YOUR_BEDROCK_AGENT_ALIAS_ID',
            value: 'sonnet',
            label: 'Sonnet'
        }
    ]

    return (
        <ChatBotUI.ChatBot
            title="Beauty Assistant"
            questions={exampleQuestions}
            agents={agents}
            hideTitleBar={true}
            apiEndpoint="YOUR_API_ENDPOINT"
            apiHeaders='{"Authorization": "YOUR_KEY_OR_TOKEN"}'
        />
    )
}
```

The `value` and `label` properties represent the value and label for an Agent dropdown next to the search bar. In this example each agent represents using a different LLM.
Providing an array of agents will enable a dropdown that will provide the user the ability to choose between the different LLM options.

### In a Static HTML Page

```html
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>ChatBot Example</title>
        <!-- Required Dependencies -->
        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
        <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
        <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>

        <script crossorigin src="https://unpkg.com/react@18.3.1/umd/react.production.min.js"></script>
        <script crossorigin src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.production.min.js"></script>

        <!-- Process polyfill (required for UMD build) -->
        <script>
            window.process = { env: { NODE_ENV: 'production' } }
        </script>

        <!-- ChatBot Files -->
        <link rel="stylesheet" href="https://unpkg.com/@nuskin/chat-bot/dist/umd/style.css" />
        <script crossorigin defer src="https://unpkg.com/@nuskin/chat-bot/dist/umd/chat-bot.js"></script>
    </head>
    <body>
        <div id="chatbot-container"></div>
        <script>
            function checkDependencies() {
                const dependencies = {
                    React: window.React,
                    ReactDOM: window.ReactDOM,
                    ChatBotUI: window.ChatBotUI
                }

                console.log('Dependencies check:', dependencies)

                return Object.entries(dependencies).every(([name, dep]) => {
                    if (!dep) {
                        console.error(`Missing dependency: ${name}`)
                        return false
                    }
                    return true
                })
            }

            function initChatBot() {
                if (!checkDependencies()) {
                    console.error('Dependencies not loaded. Retrying in 100ms...')
                    setTimeout(initChatBot, 100)
                    return
                }

                try {
                    ChatBotUI.init('chatbot-container', {
                        title: 'Developer Portal Questions',
                        questions: ['How many APIs do we have?', 'How many Lambdas do we have?', 'How do I get sso access?', 'How do I generate auth tokens?'],
                        agentId: 'YOUR_BEDROCK_AGENT_ID',
                        agentAliasId: 'YOUR_BEDROCK_AGENT_ALIAS_ID',
                        apiEndpoint: 'YOUR_API_ENDPOINT',
                        apiHeaders: '{"Content-Type": "application/json", "Authorization": "YOUR_KEY_OR_TOKEN"}'
                    })
                } catch (error) {
                    console.error('Error initializing ChatBot:', error)
                }
            }

            // Wait for all scripts to load
            document.addEventListener('DOMContentLoaded', initChatBot)
        </script>
    </body>
</html>
```

The example above includes:

1. A process polyfill required for the UMD build to work properly in browsers
2. A dependency checking function that ensures all required libraries are loaded before initializing the ChatBot
3. Error handling for initialization failures

## Props API

The ChatBot component accepts the following props:

| Prop         | Type     | Required | Default                   | Description                                                                           |
| ------------ | -------- | -------- | ------------------------- | ------------------------------------------------------------------------------------- |
| title        | string   | No       | "Nu Skin Chatbot"         | The title displayed at the top of the chat window                                     |
| questions    | string[] | No       | [Example questions array] | Array of example questions to display                                                 |
| agentId      | string   | No\*     | -                         | Amazon Bedrock agent ID                                                               |
| agentAliasId | string   | No\*     | -                         | Amazon Bedrock agent alias ID                                                         |
| agents       | array    | No\*     | -                         | Array of objects {agentId, agentAliasId, value, label}                                |
| hideTitleBar | boolean  | No       | false                     | Hide the title bar, including the logo and "Clear Chat Session" button                |
| apiEndpoint  | string   | Yes      | -                         | API endpoint URL for the Bedrock service                                              |
| apiHeaders   | string   | Yes      | -                         | JSON string of headers for API requests, including Authorization for the api endpoint |

\*Note: You will need to either include `agentId` AND `agentAliasId` OR `agents` to properly connect with Amazon Bedrock AI services.

## Additional Features

### Input Handling

-   **Multiline Input**: Users can press Shift+Enter to add a new line in the input field, and Enter to submit the question
-   **Clear Chat Session**: When the title bar is visible, users can click the "Clear Chat Session" button to reset the conversation history
-   **Error Handling**: The component displays error alerts when API calls fail, providing feedback to the user
-   **Loading Indicator**: Shows a progress bar while waiting for AI responses
-   **Auto-scrolling**: The chat container automatically scrolls to the latest message for a smooth user experience

### Title Bar

When `hideTitleBar` is set to `false` (default), the title bar includes:
-   A customizable logo (using the `Logo` component)
-   The chat title (customizable via the `title` prop)
-   A "Clear Chat Session" button to reset the conversation

### LLM Selection

When multiple agents are provided via the `agents` prop, a dropdown menu appears next to the input field, allowing users to select different LLM models for their conversation.

### Code Block Features

-   **Syntax Highlighting**: Code blocks in markdown responses are rendered with syntax highlighting
-   **Copy Button**: Each code block includes a "Copy" button that copies the code to the clipboard
-   **Success Notification**: A snackbar notification appears when code is successfully copied

## Customization

### Styling

The ChatBot component includes default styling through the CSS file. You can customize its appearance by overriding CSS classes:

-   `.chatbot` - The main container div
-   `.ask-box` - The question input area
-   `.ask-wrapper` - Wrapper for input components
-   `.example-questions` - Container for example question chips
-   `.ask-form` - Form container for the input field
-   `.ask-question` - Container for the question text field
-   `.question` - The text input field itself
-   `.send-btn-wrapper` - Container for the send button
-   `.listed-question` - Container for each question/answer pair in the chat history
-   `.llm-selector` - Container for the LLM dropdown selector
-   `.copy-btn` - The copy button for code blocks

### Message Structure

The ChatBot maintains a conversation history as an array of message objects. Each message has the following structure:

```js
{
  question: "User's question text",
  answer: {
    value: "AI response text in markdown format"
  }
}
```

The `answer.value` field contains markdown-formatted text, which is rendered by the `RenderMarkdown` component. This supports:

-   Formatting (bold, italic, etc.)
-   Lists (ordered and unordered) with proper nesting
-   Code blocks with syntax highlighting and copy functionality
-   Tables
-   Links
-   Line breaks
-   Other standard markdown features

## API Integration

The ChatBot component communicates with Amazon Bedrock through a proxy API endpoint. The API integration includes:

-   **Retry Functionality**: Automatically retries failed API calls with exponential backoff
-   **Session Management**: Maintains conversation context using session cookies
-   **Error Handling**: Gracefully handles and displays API errors to users
-   **Timeout Configuration**: Configurable request timeouts

## TypeScript Support

This package includes built-in TypeScript support. TypeScript users can import the component and its types directly:

```typescript
import { ChatBotUI } from '@nuskin/chat-bot'
import type { ChatBotProps } from '@nuskin/chat-bot'
```

## Development

1. Clone the repository
2. Install dependencies:
    ```bash
    yarn
    ```
3. Run the development server:
    ```bash
    yarn dev
    ```
4. Run tests:
    ```bash
    yarn test
    ```
5. Run linting:
    ```bash
    yarn lint
    ```
6. Run Storybook for component development:
    ```bash
    yarn storybook
    ```
7. Build the package:
    ```bash
    yarn build:both
    ```

The build process creates two distributions:

-   ESM (ES Modules) build: `dist/esm/chat-bot.js`
-   UMD (Universal Module Definition) build: `dist/umd/chat-bot.js`

Note: The build process must be run locally before committing changes to ensure both ESM and UMD builds are properly generated.

### Testing

The project uses Jest for testing. Run the test suite with:

```bash
yarn test
```

This will run all tests and generate a coverage report. The project maintains high test coverage to ensure reliability.

### Storybook

The project includes Storybook for component development and testing. Run Storybook with:

```bash
yarn storybook
```

This will start a Storybook server at http://localhost:6060, where you can view and interact with the ChatBot component in various configurations.

## Resources

-   [Amazon Bedrock Documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/what-is-bedrock.html)
-   [Material-UI Documentation](https://mui.com/material-ui/getting-started/overview/)
-   [Material-UI Components API](https://mui.com/material-ui/api/alert/)
-   [Material-UI Icons](https://mui.com/material-ui/material-icons/)
-   [React Markdown](https://github.com/remarkjs/react-markdown)
-   [TailwindCSS Documentation](https://tailwindcss.com/docs)

## License

MIT