Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .env

This file was deleted.

2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@

# production
/build
/dist

# misc
.DS_Store
.env
.env.local
.env.development.local
.env.test.local
Expand Down
14 changes: 0 additions & 14 deletions .whitesource

This file was deleted.

85 changes: 85 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# EDDI Chat UI β€” AI Agent Guidelines

> **This file is loaded by AI coding assistants. Follow ALL rules below.**

## 1. Project Context

**eddi-chat-ui** is a standalone React 19 chat widget for [EDDI](https://github.com/labsai/EDDI) agents. Built with Vite + TypeScript 5.7, vanilla CSS with CSS custom properties, and `react-markdown` for rich message rendering.

### Tech Stack

| Technology | Version | Purpose |
| -------------- | ------- | ------------------------------ |
| React | 19 | UI framework |
| TypeScript | 5.7 | Type safety |
| Vite | 6 | Build tool + dev server |
| Vitest | 3.x | Unit testing (jsdom) |
| react-markdown | 9.x | Markdown rendering in messages |

### Ecosystem

- **EDDI backend** β€” Quarkus REST API at `/agents/{env}/{agentId}`, serves chat UI from `META-INF/resources/`
- **EDDI Manager** β€” Admin UI with embedded chat panel, shares API patterns
- All repos at `c:\dev\git\`

---

## 2. Project Structure

```
src/
β”œβ”€β”€ api/ # API layer
β”‚ β”œβ”€β”€ chat-api.ts # Pure fetch functions (start, read, send, stream, undo, redo)
β”‚ └── demo-api.ts # Mock API for demo mode
β”œβ”€β”€ components/ # UI components
β”‚ β”œβ”€β”€ ChatWidget.tsx # Main orchestrator (lifecycle, SSE, query params)
β”‚ β”œβ”€β”€ ChatHeader.tsx # Logo/title, undo/redo, theme toggle, new conversation
β”‚ β”œβ”€β”€ MessageBubble.tsx # User/agent messages with markdown
β”‚ β”œβ”€β”€ ChatInput.tsx # Auto-grow textarea, Enter/Shift+Enter
β”‚ β”œβ”€β”€ QuickReplies.tsx # Pill buttons for suggested replies
β”‚ β”œβ”€β”€ Indicators.tsx # Typing (dots) + Thinking (brain) indicators
β”‚ └── ScrollToAgenttom.tsx # Floating scroll button
β”œβ”€β”€ hooks/
β”‚ └── useTheme.ts # Dark/light/system theme with localStorage
β”œβ”€β”€ store/
β”‚ └── chat-store.tsx # Context + useReducer state management
β”œβ”€β”€ styles/
β”‚ β”œβ”€β”€ variables.css # CSS custom properties (dark/light tokens)
β”‚ └── chat.css # All component styles (BEM naming)
└── types.ts # Shared TypeScript types
```

---

## 3. Key Conventions

1. **CSS** β€” BEM naming: `.chat-header__logo`, `.message--user`, `.quick-replies__btn`. No Tailwind.
2. **State** β€” `ChatProvider` β†’ `useChatState()` / `useChatDispatch()`. No prop drilling.
3. **API** β€” Pure `fetch` in `chat-api.ts`. SSE streaming uses `AsyncGenerator`.
4. **Testing** β€” Wrap components in `<ChatProvider>`. Mock `window.matchMedia` in `test-setup.ts`.
5. **Demo mode** β€” `/chat/demo/showcase` uses `demo-api.ts`. Check with `isDemoMode()`.
6. **Query params** β€” `hideUndo`, `hideRedo`, `hideNewConversation`, `hideLogo`, `theme`, `title`.

---

## 4. Build & Deploy

Production build goes to **EDDI backend** at `src/main/resources/META-INF/resources/`:

```bash
npm run build # Outputs to EDDI backend resources
```

---

## 5. Mandatory Workflow

1. **Before work**: `git status`, read this file + any `changelog.md`
2. **During work**: Commit with `feat(chat-ui):` / `fix(chat-ui):`. Each commit must build.
3. **After work**: Update `changelog.md`

### DO NOT

- Add external state libraries (zustand, redux) β€” use Context + useReducer
- Add CSS frameworks β€” use CSS custom properties
- Duplicate logic from `demo-api.ts` into components
170 changes: 100 additions & 70 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,70 +1,100 @@
# Getting Started with EDDI Chat UI

This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).

## Available Scripts

In the project directory, you can run:

### `npm start`

Runs the app in the development mode.\
Open `http://localhost:3000/chat/managedbots/:intent/:userId` or `http://localhost:3000/chat/:environment/:botId?userId=:userId` to view it in your browser.

The page will reload when you make changes.\
You may also see any lint errors in the console.

### `npm test`

Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.

### `npm run build`

Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.

The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!

See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.

### `npm run eject`

**Note: this is a one-way operation. Once you `eject`, you can't go back!**

If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.

Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.

You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.

## Learn More

You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).

To learn React, check out the [React documentation](https://reactjs.org/).

### Code Splitting

This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)

### Analyzing the Bundle Size

This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)

### Making a Progressive Web App

This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)

### Advanced Configuration

This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)

### Deployment

This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)

### `npm run build` fails to minify

This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
# EDDI Chat UI

A standalone, configurable chat widget for [EDDI](https://github.com/labsai/EDDI) conversational AI agents. Built with React 19, TypeScript, and Vite.

## Features

- πŸ’¬ **Rich markdown** β€” Tables, code blocks, bold/italic, links, lists
- 🌊 **SSE streaming** β€” Real-time token-by-token agent responses with thinking indicator
- 🎨 **Dark/Light themes** β€” Toggle via UI or query parameters
- ⚑ **Quick replies** β€” Pill buttons for suggested responses
- ↩β†ͺ **Undo/Redo** β€” Step through conversation history
- πŸ”§ **Configurable** β€” All features togglable via URL query parameters
- πŸ“± **Responsive** β€” Mobile-first design with adaptive breakpoints
- 🎭 **Demo mode** β€” Full showcase without a running backend

## Quick Start

```bash
npm install
npm run dev # http://localhost:5174
```

### URL Patterns

| URL | Description |
| ------------------------------------- | --------------------------- |
| `/chat/:environment/:agentId` | Connect to a specific agent |
| `/chat/demo/showcase` | Demo mode with mock data |
| `/chat/managedagents/:intent/:userId` | Managed agent mode |

### Query Parameters

| Parameter | Example | Effect |
| --------------------- | --------------------------- | ---------------------------------- |
| `hideUndo` | `?hideUndo=true` | Hide undo button |
| `hideRedo` | `?hideRedo=true` | Hide redo button |
| `hideNewConversation` | `?hideNewConversation=true` | Hide restart button |
| `hideLogo` | `?hideLogo=true` | Show text title instead of logo |
| `hideQuickReplies` | `?hideQuickReplies=true` | Hide quick reply buttons |
| `theme` | `?theme=light` | Set initial theme (`dark`/`light`) |
| `title` | `?title=My%20Agent` | Override header title |

## Development

```bash
npm run dev # Dev server (port 5174) with proxy to EDDI backend
npm run build # Production build
npx vitest run # Run tests (42 tests)
npx tsc --noEmit # Type check
```

### Project Structure

```
src/
β”œβ”€β”€ api/ # API layer (fetch + SSE streaming)
β”‚ β”œβ”€β”€ chat-api.ts # Real EDDI backend API
β”‚ └── demo-api.ts # Mock API for demo mode
β”œβ”€β”€ components/ # React components
β”‚ β”œβ”€β”€ ChatWidget.tsx # Main orchestrator
β”‚ β”œβ”€β”€ ChatHeader.tsx # Logo, actions, theme toggle
β”‚ β”œβ”€β”€ MessageBubble.tsx # Message rendering with Markdown
β”‚ β”œβ”€β”€ ChatInput.tsx # Auto-grow textarea + send
β”‚ β”œβ”€β”€ QuickReplies.tsx # Suggested reply pills
β”‚ β”œβ”€β”€ Indicators.tsx # Typing + Thinking indicators
β”‚ └── ScrollToAgenttom.tsx
β”œβ”€β”€ hooks/
β”‚ └── useTheme.ts # Theme management
β”œβ”€β”€ store/
β”‚ └── chat-store.tsx # Context + useReducer
β”œβ”€β”€ styles/
β”‚ β”œβ”€β”€ variables.css # CSS custom properties (design tokens)
β”‚ └── chat.css # Component styles (BEM naming)
└── types.ts # Shared types
```

## Embedding

The chat UI can be embedded in any HTML page via iframe:

```html
<iframe
src="https://your-eddi-server/chat/production/your-agent-id?hideNewConversation=true&theme=dark"
style="width: 400px; height: 600px; border: none; border-radius: 12px;"
></iframe>
```

## Backend Integration

The production build is deployed into the EDDI Quarkus backend at:

```
EDDI/src/main/resources/META-INF/resources/
```

This makes the chat UI available at `http://your-eddi-server/chat.html`.

## License

Part of the EDDI project β€” see [EDDI License](https://github.com/labsai/EDDI/blob/master/LICENSE).
44 changes: 44 additions & 0 deletions chat.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Remove zoom-blocking viewport restrictions.

On Line 5, maximum-scale=1.0 and user-scalable=no prevent zooming, which is an accessibility blocker on mobile.

β™Ώ Suggested fix
-  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
πŸ€– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@chat.html` at line 5, The meta viewport tag currently includes
accessibility-blocking attributes (maximum-scale=1.0 and user-scalable=no); edit
the meta tag that sets the viewport to remove those attributes (or set them to
allow zoom, e.g., omit maximum-scale and user-scalable or set user-scalable=yes
and a reasonable maximum-scale) so mobile users can pinch-zoom β€” locate the meta
name="viewport" tag in chat.html and update its attributes accordingly.

<meta name="theme-color" content="#1a1a1a" />
<link rel="icon" href="/img/favicon.ico" />
<title>EDDI Chat</title>
<meta name="description" content="EDDI β€” Open Source Conversational AI" />
<meta property="og:title" content="EDDI Chat" />
<meta property="og:description" content="Open Source Conversational AI" />
<meta property="og:image" content="/img/logo_eddi.png" />
<style>
@font-face {
font-display: swap;
font-family: 'Noto Sans';
font-style: normal;
font-weight: 200;
src: url('/fonts/noto-sans-v36-cyrillic_cyrillic-ext_devanagari_greek_greek-ext_latin_latin-ext_vietnamese-200.woff2') format('woff2'),
url('/fonts/noto-sans-v36-cyrillic_cyrillic-ext_devanagari_greek_greek-ext_latin_latin-ext_vietnamese-200.ttf') format('truetype');
}
@font-face {
font-display: swap;
font-family: 'Noto Sans';
font-style: normal;
font-weight: 400;
src: url('/fonts/noto-sans-v36-cyrillic_cyrillic-ext_devanagari_greek_greek-ext_latin_latin-ext_vietnamese-regular.woff2') format('woff2'),
url('/fonts/noto-sans-v36-cyrillic_cyrillic-ext_devanagari_greek_greek-ext_latin_latin-ext_vietnamese-regular.ttf') format('truetype');
}
@font-face {
font-display: swap;
font-family: 'Noto Sans';
font-style: normal;
font-weight: 500;
src: url('/fonts/noto-sans-v36-cyrillic_cyrillic-ext_devanagari_greek_greek-ext_latin_latin-ext_vietnamese-500.woff2') format('woff2'),
url('/fonts/noto-sans-v36-cyrillic_cyrillic-ext_devanagari_greek_greek-ext_latin_latin-ext_vietnamese-500.ttf') format('truetype');
}
</style>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading