@aiassist-secure/react 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,40 @@
1
+ AiAssist Commercial Use License
2
+
3
+ Copyright (c) 2025 AiAssist. All rights reserved.
4
+
5
+ TERMS AND CONDITIONS
6
+
7
+ 1. PERMITTED USE
8
+ You are granted a non-exclusive, non-transferable license to:
9
+ - Use this software for personal or commercial purposes
10
+ - Integrate this software into your own applications and products
11
+ - Modify this software for your own use
12
+
13
+ 2. RESTRICTIONS
14
+ You may NOT:
15
+ - Sell, sublicense, or distribute this software as a standalone product
16
+ - Reproduce, copy, or redistribute this software for profit
17
+ - Offer this software as a service to third parties without prior written permission
18
+ - Remove or alter any copyright notices or this license
19
+
20
+ 3. REDISTRIBUTION
21
+ If you distribute applications or products that incorporate this software,
22
+ you must include this license file and the following attribution:
23
+ "Powered by AiAssist - https://aiassist.net" unless you are a subscriber,
24
+ then the attribution is not required
25
+
26
+ 4. COMMERCIAL RESALE
27
+ Commercial resale, white-labeling, or redistribution of this software
28
+ requires a separate commercial license agreement. Contact the copyright
29
+ holder for licensing inquiries.
30
+
31
+ 5. NO WARRANTY
32
+ THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
33
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
34
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
35
+
36
+ 6. LIMITATION OF LIABILITY
37
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM,
38
+ DAMAGES OR OTHER LIABILITY ARISING FROM THE USE OF THIS SOFTWARE.
39
+
40
+ For licensing inquiries: dev@interchained.org
package/README.md ADDED
@@ -0,0 +1,409 @@
1
+ # @aiassist-secure/react
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@aiassist-secure/react.svg)](https://www.npmjs.com/package/@aiassist-secure/react)
4
+ [![React](https://img.shields.io/badge/React-17+-61DAFB.svg)](https://reactjs.org/)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ **Production-ready React components for AiAssist Secure** - Add enterprise AI chat to your React app in minutes. Includes shadow mode, human-in-the-loop detection, theming, and more.
9
+
10
+ ---
11
+
12
+ ## Features
13
+
14
+ - **Floating Widget** - One-line integration, bottom-right chat bubble
15
+ - **Embedded Chat** - Full control, embed anywhere in your layout
16
+ - **Shadow Mode UI** - Visual indicators for pending approvals
17
+ - **Human Handoff** - Automatic UI updates when humans take over
18
+ - **Typing Indicators** - Real-time "AI is typing..." animation
19
+ - **Full Theming** - Match your brand with custom themes
20
+ - **Dark/Light Mode** - Built-in theme switching
21
+ - **TypeScript** - Complete type definitions
22
+
23
+ ---
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ npm install @aiassist-secure/react
29
+ # or
30
+ yarn add @aiassist-secure/react
31
+ # or
32
+ pnpm add @aiassist-secure/react
33
+ ```
34
+
35
+ ---
36
+
37
+ ## Quick Start: Floating Widget
38
+
39
+ Add a chat widget to your app with just one component:
40
+
41
+ ```tsx
42
+ import { AiAssistChatWidget } from '@aiassist-secure/react';
43
+
44
+ function App() {
45
+ return (
46
+ <div>
47
+ <h1>My App</h1>
48
+
49
+ {/* That's it! A floating chat bubble appears */}
50
+ <AiAssistChatWidget
51
+ config={{
52
+ apiKey: 'your-api-key',
53
+ greeting: 'Hey there! How can I help you today?',
54
+ systemPrompt: 'You are a friendly support agent for Acme Inc.'
55
+ }}
56
+ position="bottom-right"
57
+ />
58
+ </div>
59
+ );
60
+ }
61
+ ```
62
+
63
+ ---
64
+
65
+ ## Embedded Chat
66
+
67
+ For full control, embed the chat directly in your layout:
68
+
69
+ ```tsx
70
+ import { AiAssistChat } from '@aiassist-secure/react';
71
+
72
+ function SupportPage() {
73
+ return (
74
+ <div className="support-container">
75
+ <h1>Customer Support</h1>
76
+
77
+ <div style={{ height: '600px', width: '400px' }}>
78
+ <AiAssistChat
79
+ config={{
80
+ apiKey: 'your-api-key',
81
+ systemPrompt: 'You are a helpful customer support agent.',
82
+ context: {
83
+ user_id: 'user_123',
84
+ plan: 'enterprise'
85
+ }
86
+ }}
87
+ showHeader={true}
88
+ showSuggestions={true}
89
+ suggestions={[
90
+ 'Track my order',
91
+ 'Request a refund',
92
+ 'Talk to a human'
93
+ ]}
94
+ onClose={() => navigate('/home')}
95
+ />
96
+ </div>
97
+ </div>
98
+ );
99
+ }
100
+ ```
101
+
102
+ ---
103
+
104
+ ## Shadow Mode (Enterprise)
105
+
106
+ Handle AI drafts that require human approval:
107
+
108
+ ```tsx
109
+ import { AiAssistChat } from '@aiassist-secure/react';
110
+
111
+ function EnterpriseSupport() {
112
+ return (
113
+ <AiAssistChat
114
+ config={{
115
+ apiKey: 'your-api-key',
116
+ onMessage: (message) => {
117
+ // Shadow mode: AI drafted a response awaiting approval
118
+ if (message.pending_approval) {
119
+ console.log('Draft pending approval:', message.content);
120
+ // Show visual indicator that message is pending
121
+ }
122
+ },
123
+ onModeChange: (mode) => {
124
+ switch (mode) {
125
+ case 'ai':
126
+ console.log('AI is handling conversation');
127
+ break;
128
+ case 'shadow':
129
+ console.log('Shadow mode: AI drafts require approval');
130
+ // Update UI to show "Supervisor reviewing..."
131
+ break;
132
+ case 'takeover':
133
+ console.log('Human agent has taken control');
134
+ // Show "Speaking with Agent Sarah"
135
+ break;
136
+ }
137
+ }
138
+ }}
139
+ />
140
+ );
141
+ }
142
+ ```
143
+
144
+ ---
145
+
146
+ ## Human-in-the-Loop Detection
147
+
148
+ Automatically detect when a human takes over:
149
+
150
+ ```tsx
151
+ import { useState } from 'react';
152
+ import { AiAssistChat, Mode } from '@aiassist-secure/react';
153
+
154
+ function SmartChat() {
155
+ const [mode, setMode] = useState<Mode>('ai');
156
+ const [agentName, setAgentName] = useState<string | null>(null);
157
+
158
+ return (
159
+ <div>
160
+ {/* Dynamic header based on who's responding */}
161
+ <header className="chat-header">
162
+ {mode === 'ai' && <span>AI Assistant</span>}
163
+ {mode === 'shadow' && <span>AI Assistant (Supervised)</span>}
164
+ {mode === 'takeover' && <span>Agent {agentName || 'Support'}</span>}
165
+ </header>
166
+
167
+ <AiAssistChat
168
+ config={{
169
+ apiKey: 'your-api-key',
170
+ onModeChange: (newMode, details) => {
171
+ setMode(newMode);
172
+ if (details?.agent_name) {
173
+ setAgentName(details.agent_name);
174
+ }
175
+ }
176
+ }}
177
+ />
178
+ </div>
179
+ );
180
+ }
181
+ ```
182
+
183
+ ---
184
+
185
+ ## Custom Theming
186
+
187
+ Match your brand with a custom theme:
188
+
189
+ ```tsx
190
+ import { AiAssistChatWidget, AiAssistTheme } from '@aiassist-secure/react';
191
+
192
+ const darkPurpleTheme: AiAssistTheme = {
193
+ primary: '#8B5CF6', // Violet accent
194
+ background: '#0F0F1A', // Dark background
195
+ surface: '#1A1A2E', // Card/header background
196
+ text: '#FFFFFF', // Main text
197
+ textMuted: '#9CA3AF', // Secondary text
198
+ border: '#2D2D44', // Border color
199
+ radius: '16px', // Rounded corners
200
+ fontFamily: '"Inter", system-ui, sans-serif',
201
+ };
202
+
203
+ function App() {
204
+ return (
205
+ <AiAssistChatWidget
206
+ config={{ apiKey: 'your-api-key' }}
207
+ theme={darkPurpleTheme}
208
+ position="bottom-right"
209
+ />
210
+ );
211
+ }
212
+ ```
213
+
214
+ ---
215
+
216
+ ## Theme Provider
217
+
218
+ Share theme across multiple components:
219
+
220
+ ```tsx
221
+ import {
222
+ AiAssistThemeProvider,
223
+ AiAssistChat,
224
+ useAiAssistTheme
225
+ } from '@aiassist-secure/react';
226
+
227
+ function ChatHeader() {
228
+ const { theme } = useAiAssistTheme();
229
+
230
+ return (
231
+ <div style={{
232
+ backgroundColor: theme.surface,
233
+ color: theme.text,
234
+ padding: '16px',
235
+ borderRadius: theme.radius
236
+ }}>
237
+ <h2>Support Chat</h2>
238
+ </div>
239
+ );
240
+ }
241
+
242
+ function App() {
243
+ return (
244
+ <AiAssistThemeProvider theme={{ primary: '#10B981' }}>
245
+ <ChatHeader />
246
+ <AiAssistChat config={{ apiKey: 'your-api-key' }} />
247
+ </AiAssistThemeProvider>
248
+ );
249
+ }
250
+ ```
251
+
252
+ ---
253
+
254
+ ## Direct API Access
255
+
256
+ Use the API client for custom implementations:
257
+
258
+ ```tsx
259
+ import { AiAssistAPI } from '@aiassist-secure/react';
260
+
261
+ const api = new AiAssistAPI({
262
+ apiKey: 'your-api-key',
263
+ });
264
+
265
+ // Create workspace with system prompt
266
+ const { workspace, messages } = await api.createWorkspace({
267
+ initialMessage: 'Hello!',
268
+ systemPrompt: 'Be helpful and concise.',
269
+ context: { user_tier: 'premium' }
270
+ });
271
+
272
+ // Send a follow-up message
273
+ const response = await api.sendMessage(workspace.id, 'What can you do?');
274
+
275
+ // Check for shadow mode
276
+ if (response.pending_approval) {
277
+ console.log('Message pending approval');
278
+ }
279
+
280
+ // Get full history
281
+ const history = await api.getMessages(workspace.id);
282
+
283
+ // End conversation
284
+ await api.endConversation(workspace.id);
285
+ ```
286
+
287
+ ---
288
+
289
+ ## Event Callbacks
290
+
291
+ Track everything happening in your chat:
292
+
293
+ ```tsx
294
+ <AiAssistChat
295
+ config={{
296
+ apiKey: 'your-api-key',
297
+
298
+ // New message received
299
+ onMessage: (message) => {
300
+ analytics.track('chat_message', {
301
+ role: message.role,
302
+ pending: message.pending_approval,
303
+ mode: message.mode
304
+ });
305
+ },
306
+
307
+ // Mode changed (AI/Shadow/Human)
308
+ onModeChange: (mode) => {
309
+ if (mode === 'takeover') {
310
+ analytics.track('human_takeover');
311
+ }
312
+ },
313
+
314
+ // Error occurred
315
+ onError: (error) => {
316
+ Sentry.captureException(error);
317
+ },
318
+
319
+ // Conversation ended
320
+ onConversationEnd: () => {
321
+ showFeedbackModal();
322
+ }
323
+ }}
324
+ />
325
+ ```
326
+
327
+ ---
328
+
329
+ ## Configuration Reference
330
+
331
+ ### AiAssistConfig
332
+
333
+ | Property | Type | Required | Description |
334
+ |----------|------|----------|-------------|
335
+ | `apiKey` | `string` | Yes | Your AiAssist API key |
336
+ | `endpoint` | `string` | No | Custom API endpoint |
337
+ | `greeting` | `string` | No | Initial greeting message |
338
+ | `systemPrompt` | `string` | No | System prompt for AI behavior |
339
+ | `context` | `object` | No | Additional context for AI |
340
+ | `onMessage` | `(msg) => void` | No | New message callback |
341
+ | `onModeChange` | `(mode) => void` | No | Mode change callback |
342
+ | `onError` | `(err) => void` | No | Error callback |
343
+ | `onConversationEnd` | `() => void` | No | Conversation ended callback |
344
+
345
+ ### AiAssistChatProps
346
+
347
+ | Property | Type | Default | Description |
348
+ |----------|------|---------|-------------|
349
+ | `config` | `AiAssistConfig` | Required | Configuration object |
350
+ | `theme` | `AiAssistTheme` | Default | Custom theme |
351
+ | `showHeader` | `boolean` | `true` | Show header bar |
352
+ | `showSuggestions` | `boolean` | `true` | Show suggestion buttons |
353
+ | `suggestions` | `string[]` | Default | Custom suggestions |
354
+ | `placeholder` | `string` | Auto | Input placeholder |
355
+ | `title` | `string` | `"AiAssist"` | Header title |
356
+ | `subtitle` | `string` | Auto | Header subtitle |
357
+ | `onClose` | `() => void` | - | Close handler |
358
+
359
+ ### AiAssistChatWidgetProps
360
+
361
+ All `AiAssistChatProps` plus:
362
+
363
+ | Property | Type | Default | Description |
364
+ |----------|------|---------|-------------|
365
+ | `position` | `"bottom-right"` \| `"bottom-left"` \| `"top-right"` \| `"top-left"` | `"bottom-right"` | Widget position |
366
+ | `bubbleIcon` | `ReactNode` | Default | Custom bubble icon |
367
+ | `defaultOpen` | `boolean` | `false` | Start with chat open |
368
+
369
+ ---
370
+
371
+ ## TypeScript Types
372
+
373
+ ```tsx
374
+ import type {
375
+ // Configuration
376
+ AiAssistConfig,
377
+ AiAssistTheme,
378
+ AiAssistChatProps,
379
+ AiAssistChatWidgetProps,
380
+
381
+ // Data types
382
+ Message,
383
+ Workspace,
384
+ Mode, // 'ai' | 'shadow' | 'takeover'
385
+ } from '@aiassist-secure/react';
386
+ ```
387
+
388
+ ---
389
+
390
+ ## Related Packages
391
+
392
+ | Package | Description |
393
+ |---------|-------------|
394
+ | [@aiassist-secure/core](https://www.npmjs.com/package/@aiassist-secure/core) | Framework-agnostic TypeScript client |
395
+ | [@aiassist-secure/vanilla](https://www.npmjs.com/package/@aiassist-secure/vanilla) | Drop-in widget for any website |
396
+
397
+ ---
398
+
399
+ ## Links
400
+
401
+ - [Documentation](https://aiassist.net/developer-docs/react)
402
+ - [Live Demo](https://aiassist.net/demo)
403
+ - [GitHub](https://github.com/aiassistsecure/aiassist-react)
404
+
405
+ ---
406
+
407
+ ## License
408
+
409
+ MIT License - [Interchained LLC](https://interchained.com)
@@ -0,0 +1,114 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React$1 from 'react';
3
+
4
+ interface Message {
5
+ id: string;
6
+ role: "user" | "ai" | "human" | "system";
7
+ content: string;
8
+ workspace_id?: string;
9
+ created_at?: string;
10
+ }
11
+ interface LeadInfo {
12
+ leadId: string;
13
+ email: string;
14
+ }
15
+ interface AiAssistConfig {
16
+ apiKey: string;
17
+ endpoint?: string;
18
+ greeting?: string;
19
+ systemPrompt?: string;
20
+ context?: Record<string, unknown>;
21
+ requireEmail?: boolean;
22
+ onModeChange?: (mode: "ai" | "human") => void;
23
+ onMessage?: (message: Message) => void;
24
+ onError?: (error: Error) => void;
25
+ onLeadCapture?: (lead: LeadInfo) => void;
26
+ }
27
+ interface AiAssistTheme {
28
+ primary?: string;
29
+ background?: string;
30
+ surface?: string;
31
+ text?: string;
32
+ textMuted?: string;
33
+ border?: string;
34
+ radius?: string;
35
+ fontFamily?: string;
36
+ }
37
+ interface AiAssistChatProps {
38
+ config: AiAssistConfig;
39
+ theme?: AiAssistTheme;
40
+ onClose?: () => void;
41
+ className?: string;
42
+ showHeader?: boolean;
43
+ showSuggestions?: boolean;
44
+ suggestions?: string[];
45
+ placeholder?: string;
46
+ title?: string;
47
+ subtitle?: string;
48
+ }
49
+ interface AiAssistChatWidgetProps extends AiAssistChatProps {
50
+ position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
51
+ bubbleIcon?: React.ReactNode;
52
+ defaultOpen?: boolean;
53
+ }
54
+ type Mode = "ai" | "human";
55
+
56
+ declare function AiAssistChat(props: AiAssistChatProps): react_jsx_runtime.JSX.Element;
57
+
58
+ declare function AiAssistChatWidget(props: AiAssistChatWidgetProps): react_jsx_runtime.JSX.Element;
59
+
60
+ declare const DEFAULT_THEME: Required<AiAssistTheme>;
61
+ interface ThemeContextValue {
62
+ theme: Required<AiAssistTheme>;
63
+ cssVars: Record<string, string>;
64
+ }
65
+ declare function AiAssistThemeProvider({ theme, children, }: {
66
+ theme?: AiAssistTheme;
67
+ children: React$1.ReactNode;
68
+ }): react_jsx_runtime.JSX.Element;
69
+ declare function useAiAssistTheme(): ThemeContextValue;
70
+
71
+ declare class AiAssistAPI {
72
+ private apiKey;
73
+ private endpoint;
74
+ constructor(config: AiAssistConfig);
75
+ private request;
76
+ createWorkspace(options: {
77
+ initialMessage: string;
78
+ systemPrompt?: string;
79
+ context?: Record<string, unknown>;
80
+ clientId?: string;
81
+ }): Promise<{
82
+ workspace: {
83
+ id: string;
84
+ mode: string;
85
+ };
86
+ messages: Message[];
87
+ }>;
88
+ sendMessage(workspaceId: string, content: string): Promise<{
89
+ user_message: Message;
90
+ responses: Message[];
91
+ mode: string;
92
+ pending_approval?: boolean;
93
+ }>;
94
+ getWorkspace(workspaceId: string): Promise<{
95
+ id: string;
96
+ mode: string;
97
+ }>;
98
+ getMessages(workspaceId: string): Promise<Message[]>;
99
+ sendTypingPreview(workspaceId: string, text: string): Promise<void>;
100
+ endConversation(workspaceId: string): Promise<void>;
101
+ getWorkspaceByClientId(clientId: string): Promise<{
102
+ workspace: {
103
+ id: string;
104
+ mode: string;
105
+ } | null;
106
+ messages: Message[];
107
+ exists: boolean;
108
+ }>;
109
+ }
110
+
111
+ declare function useThrottle<T extends (...args: any[]) => void>(fn: T, delay: number): T;
112
+ declare function normalizeRole(role: string): "user" | "ai" | "human" | "system";
113
+
114
+ export { AiAssistAPI, AiAssistChat, type AiAssistChatProps, AiAssistChatWidget, type AiAssistChatWidgetProps, type AiAssistConfig, type AiAssistTheme, AiAssistThemeProvider, DEFAULT_THEME, type Message, type Mode, normalizeRole, useAiAssistTheme, useThrottle };
@@ -0,0 +1,114 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React$1 from 'react';
3
+
4
+ interface Message {
5
+ id: string;
6
+ role: "user" | "ai" | "human" | "system";
7
+ content: string;
8
+ workspace_id?: string;
9
+ created_at?: string;
10
+ }
11
+ interface LeadInfo {
12
+ leadId: string;
13
+ email: string;
14
+ }
15
+ interface AiAssistConfig {
16
+ apiKey: string;
17
+ endpoint?: string;
18
+ greeting?: string;
19
+ systemPrompt?: string;
20
+ context?: Record<string, unknown>;
21
+ requireEmail?: boolean;
22
+ onModeChange?: (mode: "ai" | "human") => void;
23
+ onMessage?: (message: Message) => void;
24
+ onError?: (error: Error) => void;
25
+ onLeadCapture?: (lead: LeadInfo) => void;
26
+ }
27
+ interface AiAssistTheme {
28
+ primary?: string;
29
+ background?: string;
30
+ surface?: string;
31
+ text?: string;
32
+ textMuted?: string;
33
+ border?: string;
34
+ radius?: string;
35
+ fontFamily?: string;
36
+ }
37
+ interface AiAssistChatProps {
38
+ config: AiAssistConfig;
39
+ theme?: AiAssistTheme;
40
+ onClose?: () => void;
41
+ className?: string;
42
+ showHeader?: boolean;
43
+ showSuggestions?: boolean;
44
+ suggestions?: string[];
45
+ placeholder?: string;
46
+ title?: string;
47
+ subtitle?: string;
48
+ }
49
+ interface AiAssistChatWidgetProps extends AiAssistChatProps {
50
+ position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
51
+ bubbleIcon?: React.ReactNode;
52
+ defaultOpen?: boolean;
53
+ }
54
+ type Mode = "ai" | "human";
55
+
56
+ declare function AiAssistChat(props: AiAssistChatProps): react_jsx_runtime.JSX.Element;
57
+
58
+ declare function AiAssistChatWidget(props: AiAssistChatWidgetProps): react_jsx_runtime.JSX.Element;
59
+
60
+ declare const DEFAULT_THEME: Required<AiAssistTheme>;
61
+ interface ThemeContextValue {
62
+ theme: Required<AiAssistTheme>;
63
+ cssVars: Record<string, string>;
64
+ }
65
+ declare function AiAssistThemeProvider({ theme, children, }: {
66
+ theme?: AiAssistTheme;
67
+ children: React$1.ReactNode;
68
+ }): react_jsx_runtime.JSX.Element;
69
+ declare function useAiAssistTheme(): ThemeContextValue;
70
+
71
+ declare class AiAssistAPI {
72
+ private apiKey;
73
+ private endpoint;
74
+ constructor(config: AiAssistConfig);
75
+ private request;
76
+ createWorkspace(options: {
77
+ initialMessage: string;
78
+ systemPrompt?: string;
79
+ context?: Record<string, unknown>;
80
+ clientId?: string;
81
+ }): Promise<{
82
+ workspace: {
83
+ id: string;
84
+ mode: string;
85
+ };
86
+ messages: Message[];
87
+ }>;
88
+ sendMessage(workspaceId: string, content: string): Promise<{
89
+ user_message: Message;
90
+ responses: Message[];
91
+ mode: string;
92
+ pending_approval?: boolean;
93
+ }>;
94
+ getWorkspace(workspaceId: string): Promise<{
95
+ id: string;
96
+ mode: string;
97
+ }>;
98
+ getMessages(workspaceId: string): Promise<Message[]>;
99
+ sendTypingPreview(workspaceId: string, text: string): Promise<void>;
100
+ endConversation(workspaceId: string): Promise<void>;
101
+ getWorkspaceByClientId(clientId: string): Promise<{
102
+ workspace: {
103
+ id: string;
104
+ mode: string;
105
+ } | null;
106
+ messages: Message[];
107
+ exists: boolean;
108
+ }>;
109
+ }
110
+
111
+ declare function useThrottle<T extends (...args: any[]) => void>(fn: T, delay: number): T;
112
+ declare function normalizeRole(role: string): "user" | "ai" | "human" | "system";
113
+
114
+ export { AiAssistAPI, AiAssistChat, type AiAssistChatProps, AiAssistChatWidget, type AiAssistChatWidgetProps, type AiAssistConfig, type AiAssistTheme, AiAssistThemeProvider, DEFAULT_THEME, type Message, type Mode, normalizeRole, useAiAssistTheme, useThrottle };