ai-site-pilot 0.1.0 → 0.2.1
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/CLAUDE.md +486 -0
- package/README.md +10 -1
- package/dist/api/index.d.mts +1 -1
- package/dist/api/index.d.ts +1 -1
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +18 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +18 -4
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +2 -2
- package/dist/{types-DAvVRuXd.d.mts → types-2ZpUTVRN.d.mts} +16 -2
- package/dist/{types-DAvVRuXd.d.ts → types-2ZpUTVRN.d.ts} +16 -2
- package/package.json +3 -2
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
# AI Instructions for ai-site-pilot
|
|
2
|
+
|
|
3
|
+
This file provides instructions for AI coding assistants (Claude, GPT, Copilot, etc.) on how to integrate ai-site-pilot into projects.
|
|
4
|
+
|
|
5
|
+
## What is ai-site-pilot?
|
|
6
|
+
|
|
7
|
+
A drop-in AI chat widget that can **control and navigate websites**. It's not just a chatbot - the AI can execute tools to filter content, open modals, navigate sections, and more.
|
|
8
|
+
|
|
9
|
+
## ⚠️ IMPORTANT: How the AI Learns Your Site
|
|
10
|
+
|
|
11
|
+
The package provides chat UI and streaming. **The AI doesn't automatically know your site structure.** You must:
|
|
12
|
+
|
|
13
|
+
1. **Tell it what exists** - In the system prompt, list your sections, data, categories
|
|
14
|
+
2. **Define tools** - Create tools that match your site's DOM and state
|
|
15
|
+
3. **Write handlers** - Client-side code that executes the actual actions
|
|
16
|
+
|
|
17
|
+
### Example: Teaching the AI About Your Site
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
// In your API route - this is the MOST IMPORTANT part
|
|
21
|
+
const SYSTEM_PROMPT = `You are an AI assistant for MyStore.
|
|
22
|
+
|
|
23
|
+
## SITE STRUCTURE
|
|
24
|
+
The page has these sections (use navigate_to_section tool):
|
|
25
|
+
- hero: Top of page with tagline
|
|
26
|
+
- products: Product grid (id="products")
|
|
27
|
+
- about: About us section (id="about")
|
|
28
|
+
- contact: Contact form (id="contact")
|
|
29
|
+
|
|
30
|
+
## AVAILABLE DATA
|
|
31
|
+
Products on this site:
|
|
32
|
+
- Electronics: laptops, phones, tablets
|
|
33
|
+
- Clothing: shirts, pants, shoes
|
|
34
|
+
- Home: furniture, decor, kitchen
|
|
35
|
+
|
|
36
|
+
Categories for filtering: electronics, clothing, home, all
|
|
37
|
+
|
|
38
|
+
## YOUR TOOLS
|
|
39
|
+
- navigate_to_section: Scroll to a section by ID
|
|
40
|
+
- filter_products: Filter the product grid by category
|
|
41
|
+
- open_product_modal: Show details for a specific product (use product slug)
|
|
42
|
+
- open_contact: Open the contact modal
|
|
43
|
+
|
|
44
|
+
## BEHAVIOR
|
|
45
|
+
- When users ask about products, use filter_products to show relevant category
|
|
46
|
+
- When users want details, use open_product_modal
|
|
47
|
+
- When users want to buy/contact, use open_contact
|
|
48
|
+
- Always be helpful and proactively use tools to show relevant content`;
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The system prompt teaches the AI:
|
|
52
|
+
- What sections exist and their IDs
|
|
53
|
+
- What data/content is available
|
|
54
|
+
- What tools it can use and when
|
|
55
|
+
- How to behave (proactively use tools)
|
|
56
|
+
|
|
57
|
+
## Quick Setup (Copy-Paste Ready)
|
|
58
|
+
|
|
59
|
+
### 1. Install the package
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npm install ai-site-pilot
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 2. Create the API route
|
|
66
|
+
|
|
67
|
+
Create `app/api/chat/route.ts` (Next.js App Router):
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import { streamText } from 'ai';
|
|
71
|
+
import { google } from '@ai-sdk/google';
|
|
72
|
+
// Or use any Vercel AI SDK provider:
|
|
73
|
+
// import { openai } from '@ai-sdk/openai';
|
|
74
|
+
// import { anthropic } from '@ai-sdk/anthropic';
|
|
75
|
+
|
|
76
|
+
const SYSTEM_PROMPT = `You are a helpful AI assistant for this website. You can help users navigate and find information.
|
|
77
|
+
|
|
78
|
+
## YOUR CAPABILITIES
|
|
79
|
+
You have access to tools that control the website:
|
|
80
|
+
- navigate_to_section: Scroll to different sections
|
|
81
|
+
- open_modal: Open detail modals
|
|
82
|
+
- filter_content: Filter displayed content
|
|
83
|
+
- search: Search the site
|
|
84
|
+
|
|
85
|
+
Use these tools proactively when relevant to the user's request.`;
|
|
86
|
+
|
|
87
|
+
export async function POST(req: Request) {
|
|
88
|
+
const { messages } = await req.json();
|
|
89
|
+
|
|
90
|
+
const result = streamText({
|
|
91
|
+
model: google('gemini-2.0-flash'),
|
|
92
|
+
system: SYSTEM_PROMPT,
|
|
93
|
+
messages,
|
|
94
|
+
tools: {
|
|
95
|
+
// Define your site-specific tools here
|
|
96
|
+
navigate_to_section: {
|
|
97
|
+
description: 'Scroll to a section of the page',
|
|
98
|
+
parameters: {
|
|
99
|
+
type: 'object',
|
|
100
|
+
properties: {
|
|
101
|
+
section: { type: 'string', enum: ['hero', 'features', 'pricing', 'contact'] }
|
|
102
|
+
},
|
|
103
|
+
required: ['section']
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
// Add more tools as needed
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
return result.toDataStreamResponse();
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 3. Add the chat widget
|
|
115
|
+
|
|
116
|
+
In your layout or page component:
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
'use client';
|
|
120
|
+
|
|
121
|
+
import { SitePilot } from 'ai-site-pilot';
|
|
122
|
+
import 'ai-site-pilot/styles.css';
|
|
123
|
+
|
|
124
|
+
export function ChatWidget() {
|
|
125
|
+
const handleToolCall = (name: string, args: Record<string, unknown>) => {
|
|
126
|
+
// Handle tool execution - this runs on the client
|
|
127
|
+
switch (name) {
|
|
128
|
+
case 'navigate_to_section':
|
|
129
|
+
document.getElementById(args.section as string)?.scrollIntoView({ behavior: 'smooth' });
|
|
130
|
+
break;
|
|
131
|
+
case 'open_modal':
|
|
132
|
+
// Your modal logic
|
|
133
|
+
break;
|
|
134
|
+
// Handle other tools
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<SitePilot
|
|
140
|
+
apiEndpoint="/api/chat"
|
|
141
|
+
onToolCall={handleToolCall}
|
|
142
|
+
suggestions={[
|
|
143
|
+
{ text: 'Show me features', icon: '✨' },
|
|
144
|
+
{ text: 'How does pricing work?', icon: '💰' },
|
|
145
|
+
{ text: 'Contact sales', icon: '📞' },
|
|
146
|
+
]}
|
|
147
|
+
welcomeMessage="Hi! I can help you explore this site. What would you like to know?"
|
|
148
|
+
theme={{
|
|
149
|
+
accentColor: '#3b82f6', // Your brand color
|
|
150
|
+
backgroundColor: '#0f172a', // Dark background
|
|
151
|
+
// See full theme options below
|
|
152
|
+
}}
|
|
153
|
+
/>
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Theme Customization
|
|
159
|
+
|
|
160
|
+
All colors accept any CSS color value (hex, rgb, hsl, etc.):
|
|
161
|
+
|
|
162
|
+
```tsx
|
|
163
|
+
<SitePilot
|
|
164
|
+
theme={{
|
|
165
|
+
// Position
|
|
166
|
+
position: 'bottom-right', // 'bottom-left', 'top-right', 'top-left'
|
|
167
|
+
borderRadius: 24, // pixels
|
|
168
|
+
|
|
169
|
+
// Colors
|
|
170
|
+
accentColor: '#f59e0b', // Primary accent (buttons, highlights)
|
|
171
|
+
accentColorDark: '#d97706', // Gradient end color
|
|
172
|
+
backgroundColor: '#0F0720', // Panel background
|
|
173
|
+
textColor: '#ffffff', // Primary text
|
|
174
|
+
textMutedColor: '#a1a1aa', // Secondary text
|
|
175
|
+
borderColor: 'rgba(255,255,255,0.1)',
|
|
176
|
+
|
|
177
|
+
// Message bubbles
|
|
178
|
+
userMessageBg: 'linear-gradient(135deg, #f59e0b, #d97706)',
|
|
179
|
+
assistantMessageBg: 'rgba(255,255,255,0.05)',
|
|
180
|
+
}}
|
|
181
|
+
/>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Feature Toggles
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
<SitePilot
|
|
188
|
+
features={{
|
|
189
|
+
speech: true, // Voice input (microphone)
|
|
190
|
+
tts: true, // Text-to-speech for responses
|
|
191
|
+
fullscreen: true, // Fullscreen toggle button
|
|
192
|
+
suggestions: true, // Show suggestion chips
|
|
193
|
+
}}
|
|
194
|
+
/>
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Tool System
|
|
198
|
+
|
|
199
|
+
Define tools that the AI can call to control your site:
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
// Using the defineTool helper (optional, for type safety)
|
|
203
|
+
import { defineTool } from 'ai-site-pilot/tools';
|
|
204
|
+
|
|
205
|
+
const filterProductsTool = defineTool({
|
|
206
|
+
name: 'filter_products',
|
|
207
|
+
description: 'Filter products by category',
|
|
208
|
+
parameters: {
|
|
209
|
+
type: 'object',
|
|
210
|
+
properties: {
|
|
211
|
+
category: {
|
|
212
|
+
type: 'string',
|
|
213
|
+
description: 'Product category',
|
|
214
|
+
enum: ['electronics', 'clothing', 'home', 'all']
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
required: ['category']
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Environment Variables
|
|
223
|
+
|
|
224
|
+
For the API route, you'll need your AI provider's API key:
|
|
225
|
+
|
|
226
|
+
```env
|
|
227
|
+
# For Google Gemini
|
|
228
|
+
GOOGLE_GENERATIVE_AI_API_KEY=your-key-here
|
|
229
|
+
|
|
230
|
+
# Or for OpenAI
|
|
231
|
+
OPENAI_API_KEY=your-key-here
|
|
232
|
+
|
|
233
|
+
# Or for Anthropic
|
|
234
|
+
ANTHROPIC_API_KEY=your-key-here
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Complete Real-World Example
|
|
238
|
+
|
|
239
|
+
Here's a full implementation for a portfolio site showing all three parts:
|
|
240
|
+
|
|
241
|
+
### Part 1: System Prompt (teaches the AI what exists)
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
// app/api/chat/route.ts
|
|
245
|
+
const PROJECTS = `
|
|
246
|
+
Available projects (use open_project_modal with these IDs):
|
|
247
|
+
- acme-dashboard: Acme Dashboard (SaaS, Live) - Analytics platform
|
|
248
|
+
- mobile-app: FitTrack (Mobile, Live) - Fitness tracking app
|
|
249
|
+
- ecommerce: ShopFlow (E-commerce, In Progress) - Online store template
|
|
250
|
+
- api-service: DataSync API (Backend, Live) - Data synchronization service
|
|
251
|
+
|
|
252
|
+
Categories: All, SaaS, Mobile, E-commerce, Backend
|
|
253
|
+
Statuses: Live, In Progress, Concept
|
|
254
|
+
`;
|
|
255
|
+
|
|
256
|
+
const SYSTEM_PROMPT = `You are a portfolio assistant for Jane Developer.
|
|
257
|
+
|
|
258
|
+
## SITE SECTIONS
|
|
259
|
+
- hero: Landing section with intro (id="hero")
|
|
260
|
+
- projects: Project showcase grid (id="projects")
|
|
261
|
+
- about: About section (id="about")
|
|
262
|
+
- contact: Contact form (id="contact")
|
|
263
|
+
|
|
264
|
+
## PROJECT DATA
|
|
265
|
+
${PROJECTS}
|
|
266
|
+
|
|
267
|
+
## YOUR TOOLS
|
|
268
|
+
- navigate_to_section: Scroll to hero, projects, about, or contact
|
|
269
|
+
- filter_by_category: Filter projects (SaaS, Mobile, E-commerce, Backend, All)
|
|
270
|
+
- filter_by_status: Filter by status (Live, In Progress, Concept)
|
|
271
|
+
- open_project_modal: Open project details (use project ID like "acme-dashboard")
|
|
272
|
+
- highlight_project: Pulse animation on a project card
|
|
273
|
+
- open_contact: Open contact/hire modal
|
|
274
|
+
|
|
275
|
+
## WHEN TO USE TOOLS
|
|
276
|
+
- "Show me your work" → navigate_to_section("projects")
|
|
277
|
+
- "Any mobile apps?" → filter_by_category("Mobile")
|
|
278
|
+
- "What's live?" → filter_by_status("Live")
|
|
279
|
+
- "Tell me about Acme" → open_project_modal("acme-dashboard")
|
|
280
|
+
- "I want to hire you" → open_contact()
|
|
281
|
+
|
|
282
|
+
Be conversational but proactively use tools to make the site interactive.`;
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Part 2: Tool Definitions (what the AI can call)
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
// app/api/chat/route.ts (continued)
|
|
289
|
+
export async function POST(req: Request) {
|
|
290
|
+
const { messages } = await req.json();
|
|
291
|
+
|
|
292
|
+
const result = streamText({
|
|
293
|
+
model: google('gemini-2.0-flash'),
|
|
294
|
+
system: SYSTEM_PROMPT,
|
|
295
|
+
messages,
|
|
296
|
+
tools: {
|
|
297
|
+
navigate_to_section: {
|
|
298
|
+
description: 'Scroll to a page section',
|
|
299
|
+
parameters: {
|
|
300
|
+
type: 'object',
|
|
301
|
+
properties: {
|
|
302
|
+
section: { type: 'string', enum: ['hero', 'projects', 'about', 'contact'] }
|
|
303
|
+
},
|
|
304
|
+
required: ['section']
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
filter_by_category: {
|
|
308
|
+
description: 'Filter projects by category',
|
|
309
|
+
parameters: {
|
|
310
|
+
type: 'object',
|
|
311
|
+
properties: {
|
|
312
|
+
category: { type: 'string', enum: ['All', 'SaaS', 'Mobile', 'E-commerce', 'Backend'] }
|
|
313
|
+
},
|
|
314
|
+
required: ['category']
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
open_project_modal: {
|
|
318
|
+
description: 'Open project detail modal',
|
|
319
|
+
parameters: {
|
|
320
|
+
type: 'object',
|
|
321
|
+
properties: {
|
|
322
|
+
projectId: { type: 'string', description: 'Project ID like acme-dashboard' }
|
|
323
|
+
},
|
|
324
|
+
required: ['projectId']
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
open_contact: {
|
|
328
|
+
description: 'Open the contact/hire modal',
|
|
329
|
+
parameters: { type: 'object', properties: {}, required: [] }
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
return result.toDataStreamResponse();
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Part 3: Client Handler (executes the actions)
|
|
339
|
+
|
|
340
|
+
```tsx
|
|
341
|
+
// components/ChatWidget.tsx
|
|
342
|
+
'use client';
|
|
343
|
+
|
|
344
|
+
import { SitePilot } from 'ai-site-pilot';
|
|
345
|
+
import 'ai-site-pilot/styles.css';
|
|
346
|
+
|
|
347
|
+
export function ChatWidget() {
|
|
348
|
+
const handleToolCall = (name: string, args: Record<string, unknown>) => {
|
|
349
|
+
switch (name) {
|
|
350
|
+
case 'navigate_to_section':
|
|
351
|
+
document.getElementById(args.section as string)?.scrollIntoView({
|
|
352
|
+
behavior: 'smooth'
|
|
353
|
+
});
|
|
354
|
+
break;
|
|
355
|
+
|
|
356
|
+
case 'filter_by_category':
|
|
357
|
+
// Dispatch custom event for your page to handle
|
|
358
|
+
window.dispatchEvent(new CustomEvent('filter-projects', {
|
|
359
|
+
detail: { category: args.category }
|
|
360
|
+
}));
|
|
361
|
+
break;
|
|
362
|
+
|
|
363
|
+
case 'open_project_modal':
|
|
364
|
+
window.dispatchEvent(new CustomEvent('open-project', {
|
|
365
|
+
detail: { projectId: args.projectId }
|
|
366
|
+
}));
|
|
367
|
+
break;
|
|
368
|
+
|
|
369
|
+
case 'open_contact':
|
|
370
|
+
window.dispatchEvent(new CustomEvent('open-contact'));
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
return (
|
|
376
|
+
<SitePilot
|
|
377
|
+
apiEndpoint="/api/chat"
|
|
378
|
+
onToolCall={handleToolCall}
|
|
379
|
+
suggestions={[
|
|
380
|
+
{ text: "Show me your work", icon: "💼" },
|
|
381
|
+
{ text: "What's live?", icon: "🚀" },
|
|
382
|
+
{ text: "I want to hire you", icon: "💡" },
|
|
383
|
+
]}
|
|
384
|
+
theme={{
|
|
385
|
+
accentColor: '#8b5cf6',
|
|
386
|
+
backgroundColor: '#0f0f23',
|
|
387
|
+
}}
|
|
388
|
+
/>
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Part 4: Page Listens for Events
|
|
394
|
+
|
|
395
|
+
```tsx
|
|
396
|
+
// app/page.tsx or components/HomePage.tsx
|
|
397
|
+
'use client';
|
|
398
|
+
|
|
399
|
+
import { useEffect, useState } from 'react';
|
|
400
|
+
|
|
401
|
+
export function HomePage() {
|
|
402
|
+
const [filter, setFilter] = useState('All');
|
|
403
|
+
const [selectedProject, setSelectedProject] = useState(null);
|
|
404
|
+
const [showContact, setShowContact] = useState(false);
|
|
405
|
+
|
|
406
|
+
useEffect(() => {
|
|
407
|
+
const handleFilter = (e: CustomEvent) => setFilter(e.detail.category);
|
|
408
|
+
const handleProject = (e: CustomEvent) => setSelectedProject(e.detail.projectId);
|
|
409
|
+
const handleContact = () => setShowContact(true);
|
|
410
|
+
|
|
411
|
+
window.addEventListener('filter-projects', handleFilter as EventListener);
|
|
412
|
+
window.addEventListener('open-project', handleProject as EventListener);
|
|
413
|
+
window.addEventListener('open-contact', handleContact);
|
|
414
|
+
|
|
415
|
+
return () => {
|
|
416
|
+
window.removeEventListener('filter-projects', handleFilter as EventListener);
|
|
417
|
+
window.removeEventListener('open-project', handleProject as EventListener);
|
|
418
|
+
window.removeEventListener('open-contact', handleContact);
|
|
419
|
+
};
|
|
420
|
+
}, []);
|
|
421
|
+
|
|
422
|
+
// Your page components use filter, selectedProject, showContact state...
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
## Common Patterns
|
|
427
|
+
|
|
428
|
+
### E-commerce Site
|
|
429
|
+
```tsx
|
|
430
|
+
const tools = {
|
|
431
|
+
search_products: { /* search inventory */ },
|
|
432
|
+
filter_by_category: { /* filter product grid */ },
|
|
433
|
+
add_to_cart: { /* add item to cart */ },
|
|
434
|
+
open_product: { /* show product details */ },
|
|
435
|
+
};
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### Documentation Site
|
|
439
|
+
```tsx
|
|
440
|
+
const tools = {
|
|
441
|
+
search_docs: { /* search documentation */ },
|
|
442
|
+
navigate_to_page: { /* go to specific doc page */ },
|
|
443
|
+
show_code_example: { /* display code snippet */ },
|
|
444
|
+
};
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### Portfolio Site
|
|
448
|
+
```tsx
|
|
449
|
+
const tools = {
|
|
450
|
+
filter_projects: { /* filter by category/status */ },
|
|
451
|
+
open_project_modal: { /* show project details */ },
|
|
452
|
+
navigate_to_section: { /* scroll to section */ },
|
|
453
|
+
open_contact: { /* open contact form */ },
|
|
454
|
+
};
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
## Troubleshooting
|
|
458
|
+
|
|
459
|
+
**Chat not appearing?**
|
|
460
|
+
- Make sure you imported the CSS: `import 'ai-site-pilot/styles.css'`
|
|
461
|
+
- Check that the component is rendered (use React DevTools)
|
|
462
|
+
|
|
463
|
+
**Tools not executing?**
|
|
464
|
+
- Verify `onToolCall` is passed to SitePilot
|
|
465
|
+
- Check browser console for the tool calls
|
|
466
|
+
- Make sure tool names match between API and client
|
|
467
|
+
|
|
468
|
+
**Styling issues?**
|
|
469
|
+
- CSS variables can be overridden in your global CSS
|
|
470
|
+
- The component uses `z-index: 200` - adjust if needed
|
|
471
|
+
|
|
472
|
+
## Full Props Reference
|
|
473
|
+
|
|
474
|
+
```typescript
|
|
475
|
+
interface SitePilotProps {
|
|
476
|
+
apiEndpoint: string; // Required: Your chat API endpoint
|
|
477
|
+
theme?: SitePilotTheme; // Theme customization
|
|
478
|
+
suggestions?: Suggestion[]; // Suggestion chips
|
|
479
|
+
features?: SitePilotFeatures; // Feature toggles
|
|
480
|
+
onToolCall?: (name: string, args: Record<string, unknown>) => void;
|
|
481
|
+
defaultOpen?: boolean; // Start with chat open
|
|
482
|
+
placeholder?: string; // Input placeholder
|
|
483
|
+
welcomeMessage?: string; // Initial greeting
|
|
484
|
+
className?: string; // Additional CSS class
|
|
485
|
+
}
|
|
486
|
+
```
|
package/README.md
CHANGED
|
@@ -101,9 +101,18 @@ Main chat widget component.
|
|
|
101
101
|
|
|
102
102
|
```typescript
|
|
103
103
|
interface SitePilotTheme {
|
|
104
|
-
accent?: string; // 'amber', 'blue', or CSS color
|
|
105
104
|
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
106
105
|
borderRadius?: number;
|
|
106
|
+
|
|
107
|
+
// Colors - all accept CSS color values (hex, rgb, hsl)
|
|
108
|
+
accentColor?: string; // Primary accent '#f59e0b'
|
|
109
|
+
accentColorDark?: string; // Gradient end '#d97706'
|
|
110
|
+
backgroundColor?: string; // Panel background '#0F0720'
|
|
111
|
+
textColor?: string; // Primary text '#ffffff'
|
|
112
|
+
textMutedColor?: string; // Secondary text '#a1a1aa'
|
|
113
|
+
borderColor?: string; // Border 'rgba(255,255,255,0.1)'
|
|
114
|
+
userMessageBg?: string; // User message bubble
|
|
115
|
+
assistantMessageBg?: string; // Assistant message bubble
|
|
107
116
|
}
|
|
108
117
|
```
|
|
109
118
|
|
package/dist/api/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LanguageModel } from 'ai';
|
|
2
2
|
import { T as ToolDefinition } from '../types--7jDyUM6.mjs';
|
|
3
|
-
import { S as StreamEvent } from '../types-
|
|
3
|
+
import { S as StreamEvent } from '../types-2ZpUTVRN.mjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Factory for creating Next.js API route handlers
|
package/dist/api/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LanguageModel } from 'ai';
|
|
2
2
|
import { T as ToolDefinition } from '../types--7jDyUM6.js';
|
|
3
|
-
import { S as StreamEvent } from '../types-
|
|
3
|
+
import { S as StreamEvent } from '../types-2ZpUTVRN.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Factory for creating Next.js API route handlers
|
package/dist/hooks/index.d.mts
CHANGED
package/dist/hooks/index.d.ts
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { a as SitePilotProps, C as ChatMessage$1, b as Suggestion } from './types-
|
|
3
|
-
export { d as SitePilotFeatures, c as SitePilotTheme, S as StreamEvent, T as ToolExecution } from './types-
|
|
2
|
+
import { a as SitePilotProps, C as ChatMessage$1, b as Suggestion } from './types-2ZpUTVRN.mjs';
|
|
3
|
+
export { d as SitePilotFeatures, c as SitePilotTheme, S as StreamEvent, T as ToolExecution } from './types-2ZpUTVRN.mjs';
|
|
4
4
|
export { useChat, useSpeech } from './hooks/index.mjs';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { a as SitePilotProps, C as ChatMessage$1, b as Suggestion } from './types-
|
|
3
|
-
export { d as SitePilotFeatures, c as SitePilotTheme, S as StreamEvent, T as ToolExecution } from './types-
|
|
2
|
+
import { a as SitePilotProps, C as ChatMessage$1, b as Suggestion } from './types-2ZpUTVRN.js';
|
|
3
|
+
export { d as SitePilotFeatures, c as SitePilotTheme, S as StreamEvent, T as ToolExecution } from './types-2ZpUTVRN.js';
|
|
4
4
|
export { useChat, useSpeech } from './hooks/index.js';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/index.js
CHANGED
|
@@ -400,9 +400,16 @@ function SitePilot({
|
|
|
400
400
|
className = ""
|
|
401
401
|
}) {
|
|
402
402
|
const {
|
|
403
|
-
accent = "amber",
|
|
404
403
|
position = "bottom-right",
|
|
405
|
-
borderRadius = 24
|
|
404
|
+
borderRadius = 24,
|
|
405
|
+
accentColor,
|
|
406
|
+
accentColorDark,
|
|
407
|
+
backgroundColor,
|
|
408
|
+
textColor,
|
|
409
|
+
textMutedColor,
|
|
410
|
+
borderColor,
|
|
411
|
+
userMessageBg,
|
|
412
|
+
assistantMessageBg
|
|
406
413
|
} = theme;
|
|
407
414
|
const {
|
|
408
415
|
speech = true,
|
|
@@ -479,8 +486,15 @@ function SitePilot({
|
|
|
479
486
|
"top-left": "top-6 left-6 md:left-8"
|
|
480
487
|
};
|
|
481
488
|
const cssVars = {
|
|
482
|
-
"--pilot-
|
|
483
|
-
"--pilot-
|
|
489
|
+
"--pilot-radius": `${borderRadius}px`,
|
|
490
|
+
...accentColor && { "--pilot-accent": accentColor },
|
|
491
|
+
...accentColorDark && { "--pilot-accent-dark": accentColorDark },
|
|
492
|
+
...backgroundColor && { "--pilot-bg": backgroundColor, "--pilot-bg-95": `${backgroundColor}f2` },
|
|
493
|
+
...textColor && { "--pilot-text": textColor },
|
|
494
|
+
...textMutedColor && { "--pilot-text-muted": textMutedColor },
|
|
495
|
+
...borderColor && { "--pilot-border": borderColor },
|
|
496
|
+
...userMessageBg && { "--pilot-user-bg": userMessageBg },
|
|
497
|
+
...assistantMessageBg && { "--pilot-assistant-bg": assistantMessageBg }
|
|
484
498
|
};
|
|
485
499
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `pilot-container ${className}`, style: cssVars, children: [
|
|
486
500
|
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: isOpen && /* @__PURE__ */ jsxRuntime.jsxs(
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks/useChat.ts","../src/hooks/useSpeech.ts","../src/components/ChatMessage.tsx","../src/components/ChatInput.tsx","../src/components/Suggestions.tsx","../src/components/SitePilot.tsx"],"names":["useState","useRef","useCallback","useEffect","jsx","motion","jsxs","ReactMarkdown","MicOff","Mic","Send","AnimatePresence","Zap","Sparkles","Volume2","VolumeX","Minimize2","Maximize2","X","MessageCircle"],"mappings":"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","file":"index.js","sourcesContent":["'use client';\n\nimport { useState, useCallback, useRef } from 'react';\nimport type { ChatMessage, ToolExecution, StreamEvent } from '../types';\n\nexport interface UseChatOptions {\n /** API endpoint for chat */\n apiEndpoint: string;\n /** Initial messages */\n initialMessages?: ChatMessage[];\n /** Callback when a tool is called */\n onToolCall?: (toolName: string, args: Record<string, unknown>) => void | Promise<void>;\n /** Callback when streaming starts */\n onStreamStart?: () => void;\n /** Callback when streaming ends */\n onStreamEnd?: () => void;\n}\n\nexport interface UseChatReturn {\n /** All messages in the conversation */\n messages: ChatMessage[];\n /** Current input value */\n input: string;\n /** Set the input value */\n setInput: (value: string) => void;\n /** Whether the assistant is currently responding */\n isLoading: boolean;\n /** ID of the currently streaming message */\n streamingMessageId: string | null;\n /** Send a message */\n sendMessage: (content?: string) => Promise<void>;\n /** Clear all messages */\n clearMessages: () => void;\n /** Add a message manually */\n addMessage: (message: Omit<ChatMessage, 'id' | 'timestamp'>) => void;\n}\n\n/**\n * Hook for managing chat state and streaming\n */\nexport function useChat(options: UseChatOptions): UseChatReturn {\n const { apiEndpoint, initialMessages = [], onToolCall, onStreamStart, onStreamEnd } = options;\n\n const [messages, setMessages] = useState<ChatMessage[]>(initialMessages);\n const [input, setInput] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [streamingMessageId, setStreamingMessageId] = useState<string | null>(null);\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const addMessage = useCallback((message: Omit<ChatMessage, 'id' | 'timestamp'>) => {\n const newMessage: ChatMessage = {\n ...message,\n id: Date.now().toString(),\n timestamp: new Date(),\n };\n setMessages((prev) => [...prev, newMessage]);\n return newMessage;\n }, []);\n\n const clearMessages = useCallback(() => {\n setMessages(initialMessages);\n }, [initialMessages]);\n\n const sendMessage = useCallback(\n async (content?: string) => {\n const messageContent = content || input;\n if (!messageContent.trim() || isLoading) return;\n\n // Cancel any ongoing request\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n abortControllerRef.current = new AbortController();\n\n // Add user message\n const userMessage: ChatMessage = {\n id: Date.now().toString(),\n role: 'user',\n content: messageContent,\n timestamp: new Date(),\n };\n setMessages((prev) => [...prev, userMessage]);\n setInput('');\n setIsLoading(true);\n onStreamStart?.();\n\n // Add placeholder for assistant message\n const assistantMessageId = (Date.now() + 1).toString();\n const assistantMessage: ChatMessage = {\n id: assistantMessageId,\n role: 'assistant',\n content: '',\n timestamp: new Date(),\n toolCalls: [],\n };\n setMessages((prev) => [...prev, assistantMessage]);\n setStreamingMessageId(assistantMessageId);\n\n let fullText = '';\n const toolCalls: ToolExecution[] = [];\n\n try {\n // Prepare messages for API (convert to format expected by API)\n const apiMessages = messages.concat(userMessage).map((m) => ({\n role: m.role,\n content: m.content,\n }));\n\n const response = await fetch(apiEndpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ messages: apiMessages }),\n signal: abortControllerRef.current.signal,\n });\n\n if (!response.ok) {\n throw new Error('Failed to get response');\n }\n\n const reader = response.body?.getReader();\n if (!reader) throw new Error('No reader available');\n\n const decoder = new TextDecoder();\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n const text = decoder.decode(value);\n const lines = text.split('\\n');\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n try {\n const data = JSON.parse(line.slice(6)) as StreamEvent;\n\n if (data.type === 'text') {\n fullText += data.content;\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantMessageId ? { ...m, content: fullText } : m\n )\n );\n } else if (data.type === 'tool') {\n const toolCall = { name: data.name, args: data.args };\n toolCalls.push(toolCall);\n\n // Execute tool call callback\n if (onToolCall) {\n try {\n await onToolCall(data.name, data.args);\n } catch (e) {\n console.error('Tool execution error:', e);\n }\n }\n } else if (data.type === 'done') {\n // Update message with tool calls\n if (toolCalls.length > 0) {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantMessageId ? { ...m, toolCalls } : m\n )\n );\n }\n\n // If no text, show default message\n if (!fullText) {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantMessageId\n ? { ...m, content: \"I've made some changes. Take a look!\" }\n : m\n )\n );\n }\n } else if (data.type === 'error') {\n throw new Error(data.message);\n }\n } catch {\n // Skip invalid JSON lines\n }\n }\n }\n }\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n // Request was cancelled, ignore\n return;\n }\n\n console.error('Chat error:', error);\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantMessageId\n ? { ...m, content: 'Sorry, I encountered an error. Please try again.' }\n : m\n )\n );\n } finally {\n setIsLoading(false);\n setStreamingMessageId(null);\n onStreamEnd?.();\n }\n },\n [apiEndpoint, input, isLoading, messages, onToolCall, onStreamStart, onStreamEnd]\n );\n\n return {\n messages,\n input,\n setInput,\n isLoading,\n streamingMessageId,\n sendMessage,\n clearMessages,\n addMessage,\n };\n}\n","'use client';\n\nimport { useState, useRef, useEffect, useCallback } from 'react';\n\n// Web Speech API types\ninterface SpeechRecognitionEvent extends Event {\n results: SpeechRecognitionResultList;\n}\n\ninterface SpeechRecognitionInstance {\n continuous: boolean;\n interimResults: boolean;\n lang: string;\n start(): void;\n stop(): void;\n onresult: ((event: SpeechRecognitionEvent) => void) | null;\n onend: (() => void) | null;\n onerror: (() => void) | null;\n}\n\nexport interface UseSpeechOptions {\n /** Language for speech recognition */\n lang?: string;\n /** Callback when speech is recognized */\n onResult?: (transcript: string, isFinal: boolean) => void;\n}\n\nexport interface UseSpeechReturn {\n /** Whether speech recognition is supported */\n isSupported: boolean;\n /** Whether currently listening */\n isListening: boolean;\n /** Toggle listening on/off */\n toggleListening: () => void;\n /** Start listening */\n startListening: () => void;\n /** Stop listening */\n stopListening: () => void;\n /** Speak text using TTS */\n speak: (text: string) => void;\n /** Whether TTS is enabled */\n ttsEnabled: boolean;\n /** Toggle TTS on/off */\n setTtsEnabled: (enabled: boolean) => void;\n /** Cancel current speech */\n cancelSpeech: () => void;\n}\n\n/**\n * Hook for speech recognition and text-to-speech\n */\nexport function useSpeech(options: UseSpeechOptions = {}): UseSpeechReturn {\n const { lang = 'en-US', onResult } = options;\n\n const [isSupported, setIsSupported] = useState(false);\n const [isListening, setIsListening] = useState(false);\n const [ttsEnabled, setTtsEnabled] = useState(false);\n\n const recognitionRef = useRef<SpeechRecognitionInstance | null>(null);\n\n // Initialize speech recognition\n useEffect(() => {\n if (typeof window === 'undefined') return;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const windowWithSpeech = window as any;\n const SpeechRecognitionAPI =\n windowWithSpeech.SpeechRecognition || windowWithSpeech.webkitSpeechRecognition;\n\n if (SpeechRecognitionAPI) {\n setIsSupported(true);\n recognitionRef.current = new SpeechRecognitionAPI() as SpeechRecognitionInstance;\n recognitionRef.current.continuous = false;\n recognitionRef.current.interimResults = true;\n recognitionRef.current.lang = lang;\n\n recognitionRef.current.onresult = (event) => {\n const result = event.results[0];\n const transcript = result[0].transcript;\n onResult?.(transcript, result.isFinal);\n\n if (result.isFinal) {\n setIsListening(false);\n }\n };\n\n recognitionRef.current.onend = () => setIsListening(false);\n recognitionRef.current.onerror = () => setIsListening(false);\n }\n }, [lang, onResult]);\n\n const startListening = useCallback(() => {\n if (!recognitionRef.current) return;\n try {\n recognitionRef.current.start();\n setIsListening(true);\n } catch (e) {\n console.error('Speech recognition error:', e);\n }\n }, []);\n\n const stopListening = useCallback(() => {\n if (!recognitionRef.current) return;\n recognitionRef.current.stop();\n setIsListening(false);\n }, []);\n\n const toggleListening = useCallback(() => {\n if (isListening) {\n stopListening();\n } else {\n startListening();\n }\n }, [isListening, startListening, stopListening]);\n\n const speak = useCallback(\n (text: string) => {\n if (!ttsEnabled || typeof window === 'undefined' || !('speechSynthesis' in window)) {\n return;\n }\n\n speechSynthesis.cancel();\n const utterance = new SpeechSynthesisUtterance(text);\n utterance.rate = 1.0;\n utterance.pitch = 1.0;\n\n // Try to find a good voice\n const voices = speechSynthesis.getVoices();\n const preferredVoice = voices.find(\n (v) => v.name.includes('Google') || v.name.includes('Samantha') || v.name.includes('Alex')\n );\n if (preferredVoice) {\n utterance.voice = preferredVoice;\n }\n\n speechSynthesis.speak(utterance);\n },\n [ttsEnabled]\n );\n\n const cancelSpeech = useCallback(() => {\n if (typeof window !== 'undefined' && 'speechSynthesis' in window) {\n speechSynthesis.cancel();\n }\n }, []);\n\n return {\n isSupported,\n isListening,\n toggleListening,\n startListening,\n stopListening,\n speak,\n ttsEnabled,\n setTtsEnabled,\n cancelSpeech,\n };\n}\n","'use client';\n\nimport React from 'react';\nimport { motion } from 'framer-motion';\nimport ReactMarkdown from 'react-markdown';\nimport type { ChatMessage as ChatMessageType } from '../types';\n\nexport interface ChatMessageProps {\n message: ChatMessageType;\n isStreaming?: boolean;\n isFullscreen?: boolean;\n}\n\nexport function ChatMessage({ message, isStreaming, isFullscreen }: ChatMessageProps) {\n const isUser = message.role === 'user';\n\n return (\n <motion.div\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n className={`flex ${isUser ? 'justify-end' : 'justify-start'}`}\n >\n <div\n className={`px-4 py-3 rounded-2xl text-sm leading-relaxed ${\n isFullscreen ? 'max-w-[70%]' : 'max-w-[85%]'\n } ${\n isUser\n ? 'pilot-message-user rounded-br-md'\n : 'pilot-message-assistant rounded-bl-md'\n }`}\n >\n {isUser ? (\n message.content\n ) : (\n <div className=\"pilot-prose\">\n <ReactMarkdown>{message.content}</ReactMarkdown>\n {isStreaming && (\n <span className=\"inline-block w-2 h-4 pilot-cursor ml-0.5 animate-pulse\" />\n )}\n </div>\n )}\n </div>\n </motion.div>\n );\n}\n","'use client';\n\nimport React from 'react';\nimport { Send, Mic, MicOff } from 'lucide-react';\n\nexport interface ChatInputProps {\n value: string;\n onChange: (value: string) => void;\n onSubmit: () => void;\n disabled?: boolean;\n placeholder?: string;\n isListening?: boolean;\n onToggleListening?: () => void;\n showMic?: boolean;\n}\n\nexport function ChatInput({\n value,\n onChange,\n onSubmit,\n disabled = false,\n placeholder = 'Type a message...',\n isListening = false,\n onToggleListening,\n showMic = false,\n}: ChatInputProps) {\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (value.trim() && !disabled) {\n onSubmit();\n }\n };\n\n return (\n <form onSubmit={handleSubmit} className=\"p-4 pilot-border-top\">\n <div className=\"flex items-center gap-2 pilot-input-container px-4 py-3 transition-colors\">\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n className=\"bg-transparent flex-1 outline-none text-sm pilot-input\"\n placeholder={isListening ? 'Listening...' : placeholder}\n disabled={disabled}\n />\n {showMic && onToggleListening && (\n <button\n type=\"button\"\n onClick={onToggleListening}\n disabled={disabled}\n className={`p-2 rounded-xl transition-all ${\n isListening ? 'pilot-mic-active' : 'pilot-mic-inactive'\n }`}\n >\n {isListening ? <MicOff className=\"w-4 h-4\" /> : <Mic className=\"w-4 h-4\" />}\n </button>\n )}\n <button\n type=\"submit\"\n disabled={!value.trim() || disabled}\n className={`p-2 rounded-xl transition-all ${\n value.trim() && !disabled ? 'pilot-send-active' : 'pilot-send-inactive'\n }`}\n >\n <Send className=\"w-4 h-4\" />\n </button>\n </div>\n </form>\n );\n}\n","'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport { Zap } from 'lucide-react';\nimport type { Suggestion } from '../types';\n\nexport interface SuggestionsProps {\n suggestions: Suggestion[];\n onSelect: (text: string) => void;\n isVisible?: boolean;\n isFullscreen?: boolean;\n suggestionsToShow?: number;\n rotationInterval?: number;\n}\n\nexport function Suggestions({\n suggestions,\n onSelect,\n isVisible = true,\n isFullscreen = false,\n suggestionsToShow = 3,\n rotationInterval = 5000,\n}: SuggestionsProps) {\n const [currentIndex, setCurrentIndex] = useState(0);\n\n // Rotate suggestions\n useEffect(() => {\n if (!isVisible || suggestions.length <= suggestionsToShow) return;\n\n const interval = setInterval(() => {\n setCurrentIndex((prev) => (prev + 1) % Math.ceil(suggestions.length / suggestionsToShow));\n }, rotationInterval);\n\n return () => clearInterval(interval);\n }, [isVisible, suggestions.length, suggestionsToShow, rotationInterval]);\n\n // Get current suggestions to display\n const currentSuggestions = suggestions.slice(\n currentIndex * suggestionsToShow,\n currentIndex * suggestionsToShow + suggestionsToShow\n );\n\n const totalPages = Math.ceil(suggestions.length / suggestionsToShow);\n\n if (!isVisible || suggestions.length === 0) return null;\n\n return (\n <AnimatePresence>\n <motion.div\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -10 }}\n transition={{ duration: 0.3 }}\n className=\"pt-2\"\n >\n <div className=\"flex items-center justify-between mb-3\">\n <div className=\"flex items-center gap-1.5 pilot-text-muted\">\n <Zap className=\"w-3 h-3\" />\n <span className=\"text-[10px] uppercase tracking-wider font-medium\">Try asking</span>\n </div>\n {/* Pagination dots */}\n {totalPages > 1 && (\n <div className=\"flex gap-1\">\n {Array.from({ length: totalPages }).map((_, i) => (\n <button\n key={i}\n onClick={() => setCurrentIndex(i)}\n className={`h-1.5 rounded-full transition-all ${\n i === currentIndex\n ? 'pilot-dot-active w-3'\n : 'pilot-dot-inactive w-1.5 hover:opacity-75'\n }`}\n />\n ))}\n </div>\n )}\n </div>\n <AnimatePresence mode=\"wait\">\n <motion.div\n key={currentIndex}\n initial={{ opacity: 0, x: 20 }}\n animate={{ opacity: 1, x: 0 }}\n exit={{ opacity: 0, x: -20 }}\n transition={{ duration: 0.3 }}\n className={`flex gap-2 ${isFullscreen ? 'flex-row flex-wrap' : 'flex-col'}`}\n >\n {currentSuggestions.map((suggestion, index) => (\n <motion.button\n key={suggestion.text}\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ delay: index * 0.1 }}\n onClick={() => onSelect(suggestion.text)}\n className=\"pilot-suggestion group flex items-center gap-2 px-3 py-2 rounded-xl text-xs text-left transition-all duration-200\"\n >\n {suggestion.icon && <span className=\"text-base\">{suggestion.icon}</span>}\n <span>{suggestion.text}</span>\n </motion.button>\n ))}\n </motion.div>\n </AnimatePresence>\n </motion.div>\n </AnimatePresence>\n );\n}\n","'use client';\n\nimport React, { useState, useRef, useEffect, useCallback } from 'react';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport { X, MessageCircle, Sparkles, Volume2, VolumeX, Maximize2, Minimize2 } from 'lucide-react';\nimport { useChat } from '../hooks/useChat';\nimport { useSpeech } from '../hooks/useSpeech';\nimport { ChatMessage } from './ChatMessage';\nimport { ChatInput } from './ChatInput';\nimport { Suggestions } from './Suggestions';\nimport type { SitePilotProps, ChatMessage as ChatMessageType } from '../types';\n\n/**\n * SitePilot - AI chat widget that can control and navigate your website\n *\n * @example\n * ```tsx\n * import { SitePilot } from 'ai-site-pilot';\n *\n * <SitePilot\n * apiEndpoint=\"/api/chat\"\n * suggestions={[\n * { text: 'Show me products', icon: '🛍️' },\n * { text: 'Help me find...', icon: '🔍' },\n * ]}\n * onToolCall={(name, args) => {\n * // Handle tool execution\n * }}\n * />\n * ```\n */\nexport function SitePilot({\n apiEndpoint,\n theme = {},\n suggestions = [],\n features = {},\n onToolCall,\n defaultOpen = false,\n placeholder = 'Type a message...',\n welcomeMessage = \"Hi! I'm here to help you navigate and explore. What would you like to know?\",\n className = '',\n}: SitePilotProps) {\n const {\n accent = 'amber',\n position = 'bottom-right',\n borderRadius = 24,\n } = theme;\n\n const {\n speech = true,\n tts = true,\n fullscreen = true,\n suggestions: showSuggestionsFeature = true,\n } = features;\n\n const [isOpen, setIsOpen] = useState(defaultOpen);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const [showSuggestions, setShowSuggestions] = useState(true);\n\n const messagesEndRef = useRef<HTMLDivElement>(null);\n\n // Initial welcome message\n const initialMessages: ChatMessageType[] = welcomeMessage\n ? [\n {\n id: 'init',\n role: 'assistant',\n content: welcomeMessage,\n timestamp: new Date(),\n },\n ]\n : [];\n\n const {\n messages,\n input,\n setInput,\n isLoading,\n streamingMessageId,\n sendMessage,\n } = useChat({\n apiEndpoint,\n initialMessages,\n onToolCall,\n onStreamStart: () => setShowSuggestions(false),\n });\n\n const {\n isSupported: speechSupported,\n isListening,\n toggleListening,\n speak,\n ttsEnabled,\n setTtsEnabled,\n } = useSpeech({\n onResult: (transcript, isFinal) => {\n setInput(transcript);\n if (isFinal) {\n // Could auto-submit here if desired\n }\n },\n });\n\n // Scroll to bottom when messages change\n useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n }, [messages, isOpen]);\n\n // Speak assistant messages when TTS is enabled\n useEffect(() => {\n if (!ttsEnabled) return;\n\n const lastMessage = messages[messages.length - 1];\n if (\n lastMessage?.role === 'assistant' &&\n lastMessage.id !== streamingMessageId &&\n lastMessage.content\n ) {\n speak(lastMessage.content);\n }\n }, [messages, streamingMessageId, ttsEnabled, speak]);\n\n const handleSuggestionSelect = useCallback(\n (text: string) => {\n sendMessage(text);\n },\n [sendMessage]\n );\n\n const handleSubmit = useCallback(() => {\n sendMessage();\n }, [sendMessage]);\n\n // Position classes\n const positionClasses = {\n 'bottom-right': 'bottom-24 right-6 md:right-8',\n 'bottom-left': 'bottom-24 left-6 md:left-8',\n 'top-right': 'top-24 right-6 md:right-8',\n 'top-left': 'top-24 left-6 md:left-8',\n };\n\n const buttonPositionClasses = {\n 'bottom-right': 'bottom-6 right-6 md:right-8',\n 'bottom-left': 'bottom-6 left-6 md:left-8',\n 'top-right': 'top-6 right-6 md:right-8',\n 'top-left': 'top-6 left-6 md:left-8',\n };\n\n // CSS custom properties for theming\n const cssVars = {\n '--pilot-accent': accent,\n '--pilot-radius': `${borderRadius}px`,\n } as React.CSSProperties;\n\n return (\n <div className={`pilot-container ${className}`} style={cssVars}>\n {/* Chat Panel */}\n <AnimatePresence>\n {isOpen && (\n <motion.div\n initial={{ opacity: 0, y: 20, scale: 0.95 }}\n animate={{ opacity: 1, y: 0, scale: 1 }}\n exit={{ opacity: 0, y: 20, scale: 0.95 }}\n transition={{ type: 'spring', stiffness: 400, damping: 30 }}\n layout\n className={`fixed pilot-panel flex flex-col shadow-2xl z-[200] transition-all duration-300 ${\n isFullscreen\n ? 'inset-4 md:inset-8'\n : `${positionClasses[position]} w-[calc(100%-48px)] md:w-[400px] h-[520px]`\n }`}\n style={{ borderRadius: `${borderRadius}px` }}\n >\n {/* Header */}\n <div className=\"px-5 py-4 pilot-border-bottom flex justify-between items-center\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 pilot-avatar rounded-xl flex items-center justify-center shadow-lg\">\n <Sparkles className=\"w-5 h-5 text-white\" />\n </div>\n <div>\n <div className=\"font-semibold pilot-text text-sm\">AI Assistant</div>\n <div className=\"flex items-center gap-1.5\">\n <span className=\"w-1.5 h-1.5 pilot-status-dot rounded-full animate-pulse\" />\n <span className=\"text-[10px] pilot-text-muted\">Ready to help</span>\n </div>\n </div>\n </div>\n <div className=\"flex items-center gap-1\">\n {tts && (\n <button\n onClick={() => setTtsEnabled(!ttsEnabled)}\n className={`p-2 rounded-lg transition-colors ${\n ttsEnabled ? 'pilot-button-active' : 'pilot-button-inactive'\n }`}\n title={ttsEnabled ? 'Disable voice' : 'Enable voice'}\n >\n {ttsEnabled ? (\n <Volume2 className=\"w-4 h-4\" />\n ) : (\n <VolumeX className=\"w-4 h-4\" />\n )}\n </button>\n )}\n {fullscreen && (\n <button\n onClick={() => setIsFullscreen(!isFullscreen)}\n className=\"p-2 rounded-lg transition-colors pilot-button-inactive\"\n title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}\n >\n {isFullscreen ? (\n <Minimize2 className=\"w-4 h-4\" />\n ) : (\n <Maximize2 className=\"w-4 h-4\" />\n )}\n </button>\n )}\n <button\n onClick={() => setIsOpen(false)}\n className=\"p-2 hover:bg-white/5 rounded-lg transition-colors\"\n >\n <X className=\"w-4 h-4 pilot-text-muted\" />\n </button>\n </div>\n </div>\n\n {/* Messages Area */}\n <div className=\"flex-1 overflow-y-auto p-4 space-y-4 scrollbar-thin scrollbar-thumb-white/10 scrollbar-track-transparent\">\n {messages.map((msg) => (\n <ChatMessage\n key={msg.id}\n message={msg}\n isStreaming={streamingMessageId === msg.id}\n isFullscreen={isFullscreen}\n />\n ))}\n\n {/* Loading indicator */}\n {isLoading && !streamingMessageId && (\n <div className=\"flex justify-start\">\n <div className=\"pilot-loading px-4 py-3 rounded-2xl rounded-bl-md\">\n <div className=\"flex gap-1.5\">\n {[0, 0.15, 0.3].map((delay, i) => (\n <motion.span\n key={i}\n className=\"w-2 h-2 pilot-loading-dot rounded-full\"\n animate={{ y: [0, -4, 0] }}\n transition={{ duration: 0.6, repeat: Infinity, delay }}\n />\n ))}\n </div>\n </div>\n </div>\n )}\n\n {/* Suggestions */}\n {showSuggestionsFeature && suggestions.length > 0 && (\n <Suggestions\n suggestions={suggestions}\n onSelect={handleSuggestionSelect}\n isVisible={showSuggestions && !isLoading}\n isFullscreen={isFullscreen}\n />\n )}\n\n <div ref={messagesEndRef} />\n </div>\n\n {/* Input Area */}\n <ChatInput\n value={input}\n onChange={setInput}\n onSubmit={handleSubmit}\n disabled={isLoading}\n placeholder={placeholder}\n isListening={isListening}\n onToggleListening={toggleListening}\n showMic={speech && speechSupported}\n />\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* Toggle Button */}\n {!isOpen && (\n <motion.button\n onClick={() => setIsOpen(true)}\n initial={{ opacity: 0, scale: 0.8 }}\n animate={{ opacity: 1, scale: 1 }}\n whileHover={{ scale: 1.05 }}\n whileTap={{ scale: 0.95 }}\n className={`fixed ${buttonPositionClasses[position]} flex items-center gap-2 pilot-toggle-button px-5 py-3.5 rounded-2xl font-medium shadow-xl transition-shadow z-[200]`}\n >\n <MessageCircle className=\"w-5 h-5\" />\n <span className=\"text-sm hidden sm:inline\">Ask AI</span>\n <span className=\"w-2 h-2 bg-white/80 rounded-full animate-pulse\" />\n </motion.button>\n )}\n </div>\n );\n}\n\nexport default SitePilot;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/hooks/useChat.ts","../src/hooks/useSpeech.ts","../src/components/ChatMessage.tsx","../src/components/ChatInput.tsx","../src/components/Suggestions.tsx","../src/components/SitePilot.tsx"],"names":["useState","useRef","useCallback","useEffect","jsx","motion","jsxs","ReactMarkdown","MicOff","Mic","Send","AnimatePresence","Zap","Sparkles","Volume2","VolumeX","Minimize2","Maximize2","X","MessageCircle"],"mappings":"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","file":"index.js","sourcesContent":["'use client';\n\nimport { useState, useCallback, useRef } from 'react';\nimport type { ChatMessage, ToolExecution, StreamEvent } from '../types';\n\nexport interface UseChatOptions {\n /** API endpoint for chat */\n apiEndpoint: string;\n /** Initial messages */\n initialMessages?: ChatMessage[];\n /** Callback when a tool is called */\n onToolCall?: (toolName: string, args: Record<string, unknown>) => void | Promise<void>;\n /** Callback when streaming starts */\n onStreamStart?: () => void;\n /** Callback when streaming ends */\n onStreamEnd?: () => void;\n}\n\nexport interface UseChatReturn {\n /** All messages in the conversation */\n messages: ChatMessage[];\n /** Current input value */\n input: string;\n /** Set the input value */\n setInput: (value: string) => void;\n /** Whether the assistant is currently responding */\n isLoading: boolean;\n /** ID of the currently streaming message */\n streamingMessageId: string | null;\n /** Send a message */\n sendMessage: (content?: string) => Promise<void>;\n /** Clear all messages */\n clearMessages: () => void;\n /** Add a message manually */\n addMessage: (message: Omit<ChatMessage, 'id' | 'timestamp'>) => void;\n}\n\n/**\n * Hook for managing chat state and streaming\n */\nexport function useChat(options: UseChatOptions): UseChatReturn {\n const { apiEndpoint, initialMessages = [], onToolCall, onStreamStart, onStreamEnd } = options;\n\n const [messages, setMessages] = useState<ChatMessage[]>(initialMessages);\n const [input, setInput] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [streamingMessageId, setStreamingMessageId] = useState<string | null>(null);\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const addMessage = useCallback((message: Omit<ChatMessage, 'id' | 'timestamp'>) => {\n const newMessage: ChatMessage = {\n ...message,\n id: Date.now().toString(),\n timestamp: new Date(),\n };\n setMessages((prev) => [...prev, newMessage]);\n return newMessage;\n }, []);\n\n const clearMessages = useCallback(() => {\n setMessages(initialMessages);\n }, [initialMessages]);\n\n const sendMessage = useCallback(\n async (content?: string) => {\n const messageContent = content || input;\n if (!messageContent.trim() || isLoading) return;\n\n // Cancel any ongoing request\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n abortControllerRef.current = new AbortController();\n\n // Add user message\n const userMessage: ChatMessage = {\n id: Date.now().toString(),\n role: 'user',\n content: messageContent,\n timestamp: new Date(),\n };\n setMessages((prev) => [...prev, userMessage]);\n setInput('');\n setIsLoading(true);\n onStreamStart?.();\n\n // Add placeholder for assistant message\n const assistantMessageId = (Date.now() + 1).toString();\n const assistantMessage: ChatMessage = {\n id: assistantMessageId,\n role: 'assistant',\n content: '',\n timestamp: new Date(),\n toolCalls: [],\n };\n setMessages((prev) => [...prev, assistantMessage]);\n setStreamingMessageId(assistantMessageId);\n\n let fullText = '';\n const toolCalls: ToolExecution[] = [];\n\n try {\n // Prepare messages for API (convert to format expected by API)\n const apiMessages = messages.concat(userMessage).map((m) => ({\n role: m.role,\n content: m.content,\n }));\n\n const response = await fetch(apiEndpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ messages: apiMessages }),\n signal: abortControllerRef.current.signal,\n });\n\n if (!response.ok) {\n throw new Error('Failed to get response');\n }\n\n const reader = response.body?.getReader();\n if (!reader) throw new Error('No reader available');\n\n const decoder = new TextDecoder();\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n const text = decoder.decode(value);\n const lines = text.split('\\n');\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n try {\n const data = JSON.parse(line.slice(6)) as StreamEvent;\n\n if (data.type === 'text') {\n fullText += data.content;\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantMessageId ? { ...m, content: fullText } : m\n )\n );\n } else if (data.type === 'tool') {\n const toolCall = { name: data.name, args: data.args };\n toolCalls.push(toolCall);\n\n // Execute tool call callback\n if (onToolCall) {\n try {\n await onToolCall(data.name, data.args);\n } catch (e) {\n console.error('Tool execution error:', e);\n }\n }\n } else if (data.type === 'done') {\n // Update message with tool calls\n if (toolCalls.length > 0) {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantMessageId ? { ...m, toolCalls } : m\n )\n );\n }\n\n // If no text, show default message\n if (!fullText) {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantMessageId\n ? { ...m, content: \"I've made some changes. Take a look!\" }\n : m\n )\n );\n }\n } else if (data.type === 'error') {\n throw new Error(data.message);\n }\n } catch {\n // Skip invalid JSON lines\n }\n }\n }\n }\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n // Request was cancelled, ignore\n return;\n }\n\n console.error('Chat error:', error);\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantMessageId\n ? { ...m, content: 'Sorry, I encountered an error. Please try again.' }\n : m\n )\n );\n } finally {\n setIsLoading(false);\n setStreamingMessageId(null);\n onStreamEnd?.();\n }\n },\n [apiEndpoint, input, isLoading, messages, onToolCall, onStreamStart, onStreamEnd]\n );\n\n return {\n messages,\n input,\n setInput,\n isLoading,\n streamingMessageId,\n sendMessage,\n clearMessages,\n addMessage,\n };\n}\n","'use client';\n\nimport { useState, useRef, useEffect, useCallback } from 'react';\n\n// Web Speech API types\ninterface SpeechRecognitionEvent extends Event {\n results: SpeechRecognitionResultList;\n}\n\ninterface SpeechRecognitionInstance {\n continuous: boolean;\n interimResults: boolean;\n lang: string;\n start(): void;\n stop(): void;\n onresult: ((event: SpeechRecognitionEvent) => void) | null;\n onend: (() => void) | null;\n onerror: (() => void) | null;\n}\n\nexport interface UseSpeechOptions {\n /** Language for speech recognition */\n lang?: string;\n /** Callback when speech is recognized */\n onResult?: (transcript: string, isFinal: boolean) => void;\n}\n\nexport interface UseSpeechReturn {\n /** Whether speech recognition is supported */\n isSupported: boolean;\n /** Whether currently listening */\n isListening: boolean;\n /** Toggle listening on/off */\n toggleListening: () => void;\n /** Start listening */\n startListening: () => void;\n /** Stop listening */\n stopListening: () => void;\n /** Speak text using TTS */\n speak: (text: string) => void;\n /** Whether TTS is enabled */\n ttsEnabled: boolean;\n /** Toggle TTS on/off */\n setTtsEnabled: (enabled: boolean) => void;\n /** Cancel current speech */\n cancelSpeech: () => void;\n}\n\n/**\n * Hook for speech recognition and text-to-speech\n */\nexport function useSpeech(options: UseSpeechOptions = {}): UseSpeechReturn {\n const { lang = 'en-US', onResult } = options;\n\n const [isSupported, setIsSupported] = useState(false);\n const [isListening, setIsListening] = useState(false);\n const [ttsEnabled, setTtsEnabled] = useState(false);\n\n const recognitionRef = useRef<SpeechRecognitionInstance | null>(null);\n\n // Initialize speech recognition\n useEffect(() => {\n if (typeof window === 'undefined') return;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const windowWithSpeech = window as any;\n const SpeechRecognitionAPI =\n windowWithSpeech.SpeechRecognition || windowWithSpeech.webkitSpeechRecognition;\n\n if (SpeechRecognitionAPI) {\n setIsSupported(true);\n recognitionRef.current = new SpeechRecognitionAPI() as SpeechRecognitionInstance;\n recognitionRef.current.continuous = false;\n recognitionRef.current.interimResults = true;\n recognitionRef.current.lang = lang;\n\n recognitionRef.current.onresult = (event) => {\n const result = event.results[0];\n const transcript = result[0].transcript;\n onResult?.(transcript, result.isFinal);\n\n if (result.isFinal) {\n setIsListening(false);\n }\n };\n\n recognitionRef.current.onend = () => setIsListening(false);\n recognitionRef.current.onerror = () => setIsListening(false);\n }\n }, [lang, onResult]);\n\n const startListening = useCallback(() => {\n if (!recognitionRef.current) return;\n try {\n recognitionRef.current.start();\n setIsListening(true);\n } catch (e) {\n console.error('Speech recognition error:', e);\n }\n }, []);\n\n const stopListening = useCallback(() => {\n if (!recognitionRef.current) return;\n recognitionRef.current.stop();\n setIsListening(false);\n }, []);\n\n const toggleListening = useCallback(() => {\n if (isListening) {\n stopListening();\n } else {\n startListening();\n }\n }, [isListening, startListening, stopListening]);\n\n const speak = useCallback(\n (text: string) => {\n if (!ttsEnabled || typeof window === 'undefined' || !('speechSynthesis' in window)) {\n return;\n }\n\n speechSynthesis.cancel();\n const utterance = new SpeechSynthesisUtterance(text);\n utterance.rate = 1.0;\n utterance.pitch = 1.0;\n\n // Try to find a good voice\n const voices = speechSynthesis.getVoices();\n const preferredVoice = voices.find(\n (v) => v.name.includes('Google') || v.name.includes('Samantha') || v.name.includes('Alex')\n );\n if (preferredVoice) {\n utterance.voice = preferredVoice;\n }\n\n speechSynthesis.speak(utterance);\n },\n [ttsEnabled]\n );\n\n const cancelSpeech = useCallback(() => {\n if (typeof window !== 'undefined' && 'speechSynthesis' in window) {\n speechSynthesis.cancel();\n }\n }, []);\n\n return {\n isSupported,\n isListening,\n toggleListening,\n startListening,\n stopListening,\n speak,\n ttsEnabled,\n setTtsEnabled,\n cancelSpeech,\n };\n}\n","'use client';\n\nimport React from 'react';\nimport { motion } from 'framer-motion';\nimport ReactMarkdown from 'react-markdown';\nimport type { ChatMessage as ChatMessageType } from '../types';\n\nexport interface ChatMessageProps {\n message: ChatMessageType;\n isStreaming?: boolean;\n isFullscreen?: boolean;\n}\n\nexport function ChatMessage({ message, isStreaming, isFullscreen }: ChatMessageProps) {\n const isUser = message.role === 'user';\n\n return (\n <motion.div\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n className={`flex ${isUser ? 'justify-end' : 'justify-start'}`}\n >\n <div\n className={`px-4 py-3 rounded-2xl text-sm leading-relaxed ${\n isFullscreen ? 'max-w-[70%]' : 'max-w-[85%]'\n } ${\n isUser\n ? 'pilot-message-user rounded-br-md'\n : 'pilot-message-assistant rounded-bl-md'\n }`}\n >\n {isUser ? (\n message.content\n ) : (\n <div className=\"pilot-prose\">\n <ReactMarkdown>{message.content}</ReactMarkdown>\n {isStreaming && (\n <span className=\"inline-block w-2 h-4 pilot-cursor ml-0.5 animate-pulse\" />\n )}\n </div>\n )}\n </div>\n </motion.div>\n );\n}\n","'use client';\n\nimport React from 'react';\nimport { Send, Mic, MicOff } from 'lucide-react';\n\nexport interface ChatInputProps {\n value: string;\n onChange: (value: string) => void;\n onSubmit: () => void;\n disabled?: boolean;\n placeholder?: string;\n isListening?: boolean;\n onToggleListening?: () => void;\n showMic?: boolean;\n}\n\nexport function ChatInput({\n value,\n onChange,\n onSubmit,\n disabled = false,\n placeholder = 'Type a message...',\n isListening = false,\n onToggleListening,\n showMic = false,\n}: ChatInputProps) {\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (value.trim() && !disabled) {\n onSubmit();\n }\n };\n\n return (\n <form onSubmit={handleSubmit} className=\"p-4 pilot-border-top\">\n <div className=\"flex items-center gap-2 pilot-input-container px-4 py-3 transition-colors\">\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n className=\"bg-transparent flex-1 outline-none text-sm pilot-input\"\n placeholder={isListening ? 'Listening...' : placeholder}\n disabled={disabled}\n />\n {showMic && onToggleListening && (\n <button\n type=\"button\"\n onClick={onToggleListening}\n disabled={disabled}\n className={`p-2 rounded-xl transition-all ${\n isListening ? 'pilot-mic-active' : 'pilot-mic-inactive'\n }`}\n >\n {isListening ? <MicOff className=\"w-4 h-4\" /> : <Mic className=\"w-4 h-4\" />}\n </button>\n )}\n <button\n type=\"submit\"\n disabled={!value.trim() || disabled}\n className={`p-2 rounded-xl transition-all ${\n value.trim() && !disabled ? 'pilot-send-active' : 'pilot-send-inactive'\n }`}\n >\n <Send className=\"w-4 h-4\" />\n </button>\n </div>\n </form>\n );\n}\n","'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport { Zap } from 'lucide-react';\nimport type { Suggestion } from '../types';\n\nexport interface SuggestionsProps {\n suggestions: Suggestion[];\n onSelect: (text: string) => void;\n isVisible?: boolean;\n isFullscreen?: boolean;\n suggestionsToShow?: number;\n rotationInterval?: number;\n}\n\nexport function Suggestions({\n suggestions,\n onSelect,\n isVisible = true,\n isFullscreen = false,\n suggestionsToShow = 3,\n rotationInterval = 5000,\n}: SuggestionsProps) {\n const [currentIndex, setCurrentIndex] = useState(0);\n\n // Rotate suggestions\n useEffect(() => {\n if (!isVisible || suggestions.length <= suggestionsToShow) return;\n\n const interval = setInterval(() => {\n setCurrentIndex((prev) => (prev + 1) % Math.ceil(suggestions.length / suggestionsToShow));\n }, rotationInterval);\n\n return () => clearInterval(interval);\n }, [isVisible, suggestions.length, suggestionsToShow, rotationInterval]);\n\n // Get current suggestions to display\n const currentSuggestions = suggestions.slice(\n currentIndex * suggestionsToShow,\n currentIndex * suggestionsToShow + suggestionsToShow\n );\n\n const totalPages = Math.ceil(suggestions.length / suggestionsToShow);\n\n if (!isVisible || suggestions.length === 0) return null;\n\n return (\n <AnimatePresence>\n <motion.div\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -10 }}\n transition={{ duration: 0.3 }}\n className=\"pt-2\"\n >\n <div className=\"flex items-center justify-between mb-3\">\n <div className=\"flex items-center gap-1.5 pilot-text-muted\">\n <Zap className=\"w-3 h-3\" />\n <span className=\"text-[10px] uppercase tracking-wider font-medium\">Try asking</span>\n </div>\n {/* Pagination dots */}\n {totalPages > 1 && (\n <div className=\"flex gap-1\">\n {Array.from({ length: totalPages }).map((_, i) => (\n <button\n key={i}\n onClick={() => setCurrentIndex(i)}\n className={`h-1.5 rounded-full transition-all ${\n i === currentIndex\n ? 'pilot-dot-active w-3'\n : 'pilot-dot-inactive w-1.5 hover:opacity-75'\n }`}\n />\n ))}\n </div>\n )}\n </div>\n <AnimatePresence mode=\"wait\">\n <motion.div\n key={currentIndex}\n initial={{ opacity: 0, x: 20 }}\n animate={{ opacity: 1, x: 0 }}\n exit={{ opacity: 0, x: -20 }}\n transition={{ duration: 0.3 }}\n className={`flex gap-2 ${isFullscreen ? 'flex-row flex-wrap' : 'flex-col'}`}\n >\n {currentSuggestions.map((suggestion, index) => (\n <motion.button\n key={suggestion.text}\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ delay: index * 0.1 }}\n onClick={() => onSelect(suggestion.text)}\n className=\"pilot-suggestion group flex items-center gap-2 px-3 py-2 rounded-xl text-xs text-left transition-all duration-200\"\n >\n {suggestion.icon && <span className=\"text-base\">{suggestion.icon}</span>}\n <span>{suggestion.text}</span>\n </motion.button>\n ))}\n </motion.div>\n </AnimatePresence>\n </motion.div>\n </AnimatePresence>\n );\n}\n","'use client';\n\nimport React, { useState, useRef, useEffect, useCallback } from 'react';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport { X, MessageCircle, Sparkles, Volume2, VolumeX, Maximize2, Minimize2 } from 'lucide-react';\nimport { useChat } from '../hooks/useChat';\nimport { useSpeech } from '../hooks/useSpeech';\nimport { ChatMessage } from './ChatMessage';\nimport { ChatInput } from './ChatInput';\nimport { Suggestions } from './Suggestions';\nimport type { SitePilotProps, ChatMessage as ChatMessageType } from '../types';\n\n/**\n * SitePilot - AI chat widget that can control and navigate your website\n *\n * @example\n * ```tsx\n * import { SitePilot } from 'ai-site-pilot';\n *\n * <SitePilot\n * apiEndpoint=\"/api/chat\"\n * suggestions={[\n * { text: 'Show me products', icon: '🛍️' },\n * { text: 'Help me find...', icon: '🔍' },\n * ]}\n * onToolCall={(name, args) => {\n * // Handle tool execution\n * }}\n * />\n * ```\n */\nexport function SitePilot({\n apiEndpoint,\n theme = {},\n suggestions = [],\n features = {},\n onToolCall,\n defaultOpen = false,\n placeholder = 'Type a message...',\n welcomeMessage = \"Hi! I'm here to help you navigate and explore. What would you like to know?\",\n className = '',\n}: SitePilotProps) {\n const {\n position = 'bottom-right',\n borderRadius = 24,\n accentColor,\n accentColorDark,\n backgroundColor,\n textColor,\n textMutedColor,\n borderColor,\n userMessageBg,\n assistantMessageBg,\n } = theme;\n\n const {\n speech = true,\n tts = true,\n fullscreen = true,\n suggestions: showSuggestionsFeature = true,\n } = features;\n\n const [isOpen, setIsOpen] = useState(defaultOpen);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const [showSuggestions, setShowSuggestions] = useState(true);\n\n const messagesEndRef = useRef<HTMLDivElement>(null);\n\n // Initial welcome message\n const initialMessages: ChatMessageType[] = welcomeMessage\n ? [\n {\n id: 'init',\n role: 'assistant',\n content: welcomeMessage,\n timestamp: new Date(),\n },\n ]\n : [];\n\n const {\n messages,\n input,\n setInput,\n isLoading,\n streamingMessageId,\n sendMessage,\n } = useChat({\n apiEndpoint,\n initialMessages,\n onToolCall,\n onStreamStart: () => setShowSuggestions(false),\n });\n\n const {\n isSupported: speechSupported,\n isListening,\n toggleListening,\n speak,\n ttsEnabled,\n setTtsEnabled,\n } = useSpeech({\n onResult: (transcript, isFinal) => {\n setInput(transcript);\n if (isFinal) {\n // Could auto-submit here if desired\n }\n },\n });\n\n // Scroll to bottom when messages change\n useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n }, [messages, isOpen]);\n\n // Speak assistant messages when TTS is enabled\n useEffect(() => {\n if (!ttsEnabled) return;\n\n const lastMessage = messages[messages.length - 1];\n if (\n lastMessage?.role === 'assistant' &&\n lastMessage.id !== streamingMessageId &&\n lastMessage.content\n ) {\n speak(lastMessage.content);\n }\n }, [messages, streamingMessageId, ttsEnabled, speak]);\n\n const handleSuggestionSelect = useCallback(\n (text: string) => {\n sendMessage(text);\n },\n [sendMessage]\n );\n\n const handleSubmit = useCallback(() => {\n sendMessage();\n }, [sendMessage]);\n\n // Position classes\n const positionClasses = {\n 'bottom-right': 'bottom-24 right-6 md:right-8',\n 'bottom-left': 'bottom-24 left-6 md:left-8',\n 'top-right': 'top-24 right-6 md:right-8',\n 'top-left': 'top-24 left-6 md:left-8',\n };\n\n const buttonPositionClasses = {\n 'bottom-right': 'bottom-6 right-6 md:right-8',\n 'bottom-left': 'bottom-6 left-6 md:left-8',\n 'top-right': 'top-6 right-6 md:right-8',\n 'top-left': 'top-6 left-6 md:left-8',\n };\n\n // CSS custom properties for theming\n const cssVars = {\n '--pilot-radius': `${borderRadius}px`,\n ...(accentColor && { '--pilot-accent': accentColor }),\n ...(accentColorDark && { '--pilot-accent-dark': accentColorDark }),\n ...(backgroundColor && { '--pilot-bg': backgroundColor, '--pilot-bg-95': `${backgroundColor}f2` }),\n ...(textColor && { '--pilot-text': textColor }),\n ...(textMutedColor && { '--pilot-text-muted': textMutedColor }),\n ...(borderColor && { '--pilot-border': borderColor }),\n ...(userMessageBg && { '--pilot-user-bg': userMessageBg }),\n ...(assistantMessageBg && { '--pilot-assistant-bg': assistantMessageBg }),\n } as React.CSSProperties;\n\n return (\n <div className={`pilot-container ${className}`} style={cssVars}>\n {/* Chat Panel */}\n <AnimatePresence>\n {isOpen && (\n <motion.div\n initial={{ opacity: 0, y: 20, scale: 0.95 }}\n animate={{ opacity: 1, y: 0, scale: 1 }}\n exit={{ opacity: 0, y: 20, scale: 0.95 }}\n transition={{ type: 'spring', stiffness: 400, damping: 30 }}\n layout\n className={`fixed pilot-panel flex flex-col shadow-2xl z-[200] transition-all duration-300 ${\n isFullscreen\n ? 'inset-4 md:inset-8'\n : `${positionClasses[position]} w-[calc(100%-48px)] md:w-[400px] h-[520px]`\n }`}\n style={{ borderRadius: `${borderRadius}px` }}\n >\n {/* Header */}\n <div className=\"px-5 py-4 pilot-border-bottom flex justify-between items-center\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 pilot-avatar rounded-xl flex items-center justify-center shadow-lg\">\n <Sparkles className=\"w-5 h-5 text-white\" />\n </div>\n <div>\n <div className=\"font-semibold pilot-text text-sm\">AI Assistant</div>\n <div className=\"flex items-center gap-1.5\">\n <span className=\"w-1.5 h-1.5 pilot-status-dot rounded-full animate-pulse\" />\n <span className=\"text-[10px] pilot-text-muted\">Ready to help</span>\n </div>\n </div>\n </div>\n <div className=\"flex items-center gap-1\">\n {tts && (\n <button\n onClick={() => setTtsEnabled(!ttsEnabled)}\n className={`p-2 rounded-lg transition-colors ${\n ttsEnabled ? 'pilot-button-active' : 'pilot-button-inactive'\n }`}\n title={ttsEnabled ? 'Disable voice' : 'Enable voice'}\n >\n {ttsEnabled ? (\n <Volume2 className=\"w-4 h-4\" />\n ) : (\n <VolumeX className=\"w-4 h-4\" />\n )}\n </button>\n )}\n {fullscreen && (\n <button\n onClick={() => setIsFullscreen(!isFullscreen)}\n className=\"p-2 rounded-lg transition-colors pilot-button-inactive\"\n title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}\n >\n {isFullscreen ? (\n <Minimize2 className=\"w-4 h-4\" />\n ) : (\n <Maximize2 className=\"w-4 h-4\" />\n )}\n </button>\n )}\n <button\n onClick={() => setIsOpen(false)}\n className=\"p-2 hover:bg-white/5 rounded-lg transition-colors\"\n >\n <X className=\"w-4 h-4 pilot-text-muted\" />\n </button>\n </div>\n </div>\n\n {/* Messages Area */}\n <div className=\"flex-1 overflow-y-auto p-4 space-y-4 scrollbar-thin scrollbar-thumb-white/10 scrollbar-track-transparent\">\n {messages.map((msg) => (\n <ChatMessage\n key={msg.id}\n message={msg}\n isStreaming={streamingMessageId === msg.id}\n isFullscreen={isFullscreen}\n />\n ))}\n\n {/* Loading indicator */}\n {isLoading && !streamingMessageId && (\n <div className=\"flex justify-start\">\n <div className=\"pilot-loading px-4 py-3 rounded-2xl rounded-bl-md\">\n <div className=\"flex gap-1.5\">\n {[0, 0.15, 0.3].map((delay, i) => (\n <motion.span\n key={i}\n className=\"w-2 h-2 pilot-loading-dot rounded-full\"\n animate={{ y: [0, -4, 0] }}\n transition={{ duration: 0.6, repeat: Infinity, delay }}\n />\n ))}\n </div>\n </div>\n </div>\n )}\n\n {/* Suggestions */}\n {showSuggestionsFeature && suggestions.length > 0 && (\n <Suggestions\n suggestions={suggestions}\n onSelect={handleSuggestionSelect}\n isVisible={showSuggestions && !isLoading}\n isFullscreen={isFullscreen}\n />\n )}\n\n <div ref={messagesEndRef} />\n </div>\n\n {/* Input Area */}\n <ChatInput\n value={input}\n onChange={setInput}\n onSubmit={handleSubmit}\n disabled={isLoading}\n placeholder={placeholder}\n isListening={isListening}\n onToggleListening={toggleListening}\n showMic={speech && speechSupported}\n />\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* Toggle Button */}\n {!isOpen && (\n <motion.button\n onClick={() => setIsOpen(true)}\n initial={{ opacity: 0, scale: 0.8 }}\n animate={{ opacity: 1, scale: 1 }}\n whileHover={{ scale: 1.05 }}\n whileTap={{ scale: 0.95 }}\n className={`fixed ${buttonPositionClasses[position]} flex items-center gap-2 pilot-toggle-button px-5 py-3.5 rounded-2xl font-medium shadow-xl transition-shadow z-[200]`}\n >\n <MessageCircle className=\"w-5 h-5\" />\n <span className=\"text-sm hidden sm:inline\">Ask AI</span>\n <span className=\"w-2 h-2 bg-white/80 rounded-full animate-pulse\" />\n </motion.button>\n )}\n </div>\n );\n}\n\nexport default SitePilot;\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -392,9 +392,16 @@ function SitePilot({
|
|
|
392
392
|
className = ""
|
|
393
393
|
}) {
|
|
394
394
|
const {
|
|
395
|
-
accent = "amber",
|
|
396
395
|
position = "bottom-right",
|
|
397
|
-
borderRadius = 24
|
|
396
|
+
borderRadius = 24,
|
|
397
|
+
accentColor,
|
|
398
|
+
accentColorDark,
|
|
399
|
+
backgroundColor,
|
|
400
|
+
textColor,
|
|
401
|
+
textMutedColor,
|
|
402
|
+
borderColor,
|
|
403
|
+
userMessageBg,
|
|
404
|
+
assistantMessageBg
|
|
398
405
|
} = theme;
|
|
399
406
|
const {
|
|
400
407
|
speech = true,
|
|
@@ -471,8 +478,15 @@ function SitePilot({
|
|
|
471
478
|
"top-left": "top-6 left-6 md:left-8"
|
|
472
479
|
};
|
|
473
480
|
const cssVars = {
|
|
474
|
-
"--pilot-
|
|
475
|
-
"--pilot-
|
|
481
|
+
"--pilot-radius": `${borderRadius}px`,
|
|
482
|
+
...accentColor && { "--pilot-accent": accentColor },
|
|
483
|
+
...accentColorDark && { "--pilot-accent-dark": accentColorDark },
|
|
484
|
+
...backgroundColor && { "--pilot-bg": backgroundColor, "--pilot-bg-95": `${backgroundColor}f2` },
|
|
485
|
+
...textColor && { "--pilot-text": textColor },
|
|
486
|
+
...textMutedColor && { "--pilot-text-muted": textMutedColor },
|
|
487
|
+
...borderColor && { "--pilot-border": borderColor },
|
|
488
|
+
...userMessageBg && { "--pilot-user-bg": userMessageBg },
|
|
489
|
+
...assistantMessageBg && { "--pilot-assistant-bg": assistantMessageBg }
|
|
476
490
|
};
|
|
477
491
|
return /* @__PURE__ */ jsxs("div", { className: `pilot-container ${className}`, style: cssVars, children: [
|
|
478
492
|
/* @__PURE__ */ jsx(AnimatePresence, { children: isOpen && /* @__PURE__ */ jsxs(
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks/useChat.ts","../src/hooks/useSpeech.ts","../src/components/ChatMessage.tsx","../src/components/ChatInput.tsx","../src/components/Suggestions.tsx","../src/components/SitePilot.tsx"],"names":["useState","useRef","useCallback","jsx","jsxs","useEffect","motion","AnimatePresence"],"mappings":"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","file":"index.mjs","sourcesContent":["'use client';\n\nimport { useState, useCallback, useRef } from 'react';\nimport type { ChatMessage, ToolExecution, StreamEvent } from '../types';\n\nexport interface UseChatOptions {\n /** API endpoint for chat */\n apiEndpoint: string;\n /** Initial messages */\n initialMessages?: ChatMessage[];\n /** Callback when a tool is called */\n onToolCall?: (toolName: string, args: Record<string, unknown>) => void | Promise<void>;\n /** Callback when streaming starts */\n onStreamStart?: () => void;\n /** Callback when streaming ends */\n onStreamEnd?: () => void;\n}\n\nexport interface UseChatReturn {\n /** All messages in the conversation */\n messages: ChatMessage[];\n /** Current input value */\n input: string;\n /** Set the input value */\n setInput: (value: string) => void;\n /** Whether the assistant is currently responding */\n isLoading: boolean;\n /** ID of the currently streaming message */\n streamingMessageId: string | null;\n /** Send a message */\n sendMessage: (content?: string) => Promise<void>;\n /** Clear all messages */\n clearMessages: () => void;\n /** Add a message manually */\n addMessage: (message: Omit<ChatMessage, 'id' | 'timestamp'>) => void;\n}\n\n/**\n * Hook for managing chat state and streaming\n */\nexport function useChat(options: UseChatOptions): UseChatReturn {\n const { apiEndpoint, initialMessages = [], onToolCall, onStreamStart, onStreamEnd } = options;\n\n const [messages, setMessages] = useState<ChatMessage[]>(initialMessages);\n const [input, setInput] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [streamingMessageId, setStreamingMessageId] = useState<string | null>(null);\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const addMessage = useCallback((message: Omit<ChatMessage, 'id' | 'timestamp'>) => {\n const newMessage: ChatMessage = {\n ...message,\n id: Date.now().toString(),\n timestamp: new Date(),\n };\n setMessages((prev) => [...prev, newMessage]);\n return newMessage;\n }, []);\n\n const clearMessages = useCallback(() => {\n setMessages(initialMessages);\n }, [initialMessages]);\n\n const sendMessage = useCallback(\n async (content?: string) => {\n const messageContent = content || input;\n if (!messageContent.trim() || isLoading) return;\n\n // Cancel any ongoing request\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n abortControllerRef.current = new AbortController();\n\n // Add user message\n const userMessage: ChatMessage = {\n id: Date.now().toString(),\n role: 'user',\n content: messageContent,\n timestamp: new Date(),\n };\n setMessages((prev) => [...prev, userMessage]);\n setInput('');\n setIsLoading(true);\n onStreamStart?.();\n\n // Add placeholder for assistant message\n const assistantMessageId = (Date.now() + 1).toString();\n const assistantMessage: ChatMessage = {\n id: assistantMessageId,\n role: 'assistant',\n content: '',\n timestamp: new Date(),\n toolCalls: [],\n };\n setMessages((prev) => [...prev, assistantMessage]);\n setStreamingMessageId(assistantMessageId);\n\n let fullText = '';\n const toolCalls: ToolExecution[] = [];\n\n try {\n // Prepare messages for API (convert to format expected by API)\n const apiMessages = messages.concat(userMessage).map((m) => ({\n role: m.role,\n content: m.content,\n }));\n\n const response = await fetch(apiEndpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ messages: apiMessages }),\n signal: abortControllerRef.current.signal,\n });\n\n if (!response.ok) {\n throw new Error('Failed to get response');\n }\n\n const reader = response.body?.getReader();\n if (!reader) throw new Error('No reader available');\n\n const decoder = new TextDecoder();\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n const text = decoder.decode(value);\n const lines = text.split('\\n');\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n try {\n const data = JSON.parse(line.slice(6)) as StreamEvent;\n\n if (data.type === 'text') {\n fullText += data.content;\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantMessageId ? { ...m, content: fullText } : m\n )\n );\n } else if (data.type === 'tool') {\n const toolCall = { name: data.name, args: data.args };\n toolCalls.push(toolCall);\n\n // Execute tool call callback\n if (onToolCall) {\n try {\n await onToolCall(data.name, data.args);\n } catch (e) {\n console.error('Tool execution error:', e);\n }\n }\n } else if (data.type === 'done') {\n // Update message with tool calls\n if (toolCalls.length > 0) {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantMessageId ? { ...m, toolCalls } : m\n )\n );\n }\n\n // If no text, show default message\n if (!fullText) {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantMessageId\n ? { ...m, content: \"I've made some changes. Take a look!\" }\n : m\n )\n );\n }\n } else if (data.type === 'error') {\n throw new Error(data.message);\n }\n } catch {\n // Skip invalid JSON lines\n }\n }\n }\n }\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n // Request was cancelled, ignore\n return;\n }\n\n console.error('Chat error:', error);\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantMessageId\n ? { ...m, content: 'Sorry, I encountered an error. Please try again.' }\n : m\n )\n );\n } finally {\n setIsLoading(false);\n setStreamingMessageId(null);\n onStreamEnd?.();\n }\n },\n [apiEndpoint, input, isLoading, messages, onToolCall, onStreamStart, onStreamEnd]\n );\n\n return {\n messages,\n input,\n setInput,\n isLoading,\n streamingMessageId,\n sendMessage,\n clearMessages,\n addMessage,\n };\n}\n","'use client';\n\nimport { useState, useRef, useEffect, useCallback } from 'react';\n\n// Web Speech API types\ninterface SpeechRecognitionEvent extends Event {\n results: SpeechRecognitionResultList;\n}\n\ninterface SpeechRecognitionInstance {\n continuous: boolean;\n interimResults: boolean;\n lang: string;\n start(): void;\n stop(): void;\n onresult: ((event: SpeechRecognitionEvent) => void) | null;\n onend: (() => void) | null;\n onerror: (() => void) | null;\n}\n\nexport interface UseSpeechOptions {\n /** Language for speech recognition */\n lang?: string;\n /** Callback when speech is recognized */\n onResult?: (transcript: string, isFinal: boolean) => void;\n}\n\nexport interface UseSpeechReturn {\n /** Whether speech recognition is supported */\n isSupported: boolean;\n /** Whether currently listening */\n isListening: boolean;\n /** Toggle listening on/off */\n toggleListening: () => void;\n /** Start listening */\n startListening: () => void;\n /** Stop listening */\n stopListening: () => void;\n /** Speak text using TTS */\n speak: (text: string) => void;\n /** Whether TTS is enabled */\n ttsEnabled: boolean;\n /** Toggle TTS on/off */\n setTtsEnabled: (enabled: boolean) => void;\n /** Cancel current speech */\n cancelSpeech: () => void;\n}\n\n/**\n * Hook for speech recognition and text-to-speech\n */\nexport function useSpeech(options: UseSpeechOptions = {}): UseSpeechReturn {\n const { lang = 'en-US', onResult } = options;\n\n const [isSupported, setIsSupported] = useState(false);\n const [isListening, setIsListening] = useState(false);\n const [ttsEnabled, setTtsEnabled] = useState(false);\n\n const recognitionRef = useRef<SpeechRecognitionInstance | null>(null);\n\n // Initialize speech recognition\n useEffect(() => {\n if (typeof window === 'undefined') return;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const windowWithSpeech = window as any;\n const SpeechRecognitionAPI =\n windowWithSpeech.SpeechRecognition || windowWithSpeech.webkitSpeechRecognition;\n\n if (SpeechRecognitionAPI) {\n setIsSupported(true);\n recognitionRef.current = new SpeechRecognitionAPI() as SpeechRecognitionInstance;\n recognitionRef.current.continuous = false;\n recognitionRef.current.interimResults = true;\n recognitionRef.current.lang = lang;\n\n recognitionRef.current.onresult = (event) => {\n const result = event.results[0];\n const transcript = result[0].transcript;\n onResult?.(transcript, result.isFinal);\n\n if (result.isFinal) {\n setIsListening(false);\n }\n };\n\n recognitionRef.current.onend = () => setIsListening(false);\n recognitionRef.current.onerror = () => setIsListening(false);\n }\n }, [lang, onResult]);\n\n const startListening = useCallback(() => {\n if (!recognitionRef.current) return;\n try {\n recognitionRef.current.start();\n setIsListening(true);\n } catch (e) {\n console.error('Speech recognition error:', e);\n }\n }, []);\n\n const stopListening = useCallback(() => {\n if (!recognitionRef.current) return;\n recognitionRef.current.stop();\n setIsListening(false);\n }, []);\n\n const toggleListening = useCallback(() => {\n if (isListening) {\n stopListening();\n } else {\n startListening();\n }\n }, [isListening, startListening, stopListening]);\n\n const speak = useCallback(\n (text: string) => {\n if (!ttsEnabled || typeof window === 'undefined' || !('speechSynthesis' in window)) {\n return;\n }\n\n speechSynthesis.cancel();\n const utterance = new SpeechSynthesisUtterance(text);\n utterance.rate = 1.0;\n utterance.pitch = 1.0;\n\n // Try to find a good voice\n const voices = speechSynthesis.getVoices();\n const preferredVoice = voices.find(\n (v) => v.name.includes('Google') || v.name.includes('Samantha') || v.name.includes('Alex')\n );\n if (preferredVoice) {\n utterance.voice = preferredVoice;\n }\n\n speechSynthesis.speak(utterance);\n },\n [ttsEnabled]\n );\n\n const cancelSpeech = useCallback(() => {\n if (typeof window !== 'undefined' && 'speechSynthesis' in window) {\n speechSynthesis.cancel();\n }\n }, []);\n\n return {\n isSupported,\n isListening,\n toggleListening,\n startListening,\n stopListening,\n speak,\n ttsEnabled,\n setTtsEnabled,\n cancelSpeech,\n };\n}\n","'use client';\n\nimport React from 'react';\nimport { motion } from 'framer-motion';\nimport ReactMarkdown from 'react-markdown';\nimport type { ChatMessage as ChatMessageType } from '../types';\n\nexport interface ChatMessageProps {\n message: ChatMessageType;\n isStreaming?: boolean;\n isFullscreen?: boolean;\n}\n\nexport function ChatMessage({ message, isStreaming, isFullscreen }: ChatMessageProps) {\n const isUser = message.role === 'user';\n\n return (\n <motion.div\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n className={`flex ${isUser ? 'justify-end' : 'justify-start'}`}\n >\n <div\n className={`px-4 py-3 rounded-2xl text-sm leading-relaxed ${\n isFullscreen ? 'max-w-[70%]' : 'max-w-[85%]'\n } ${\n isUser\n ? 'pilot-message-user rounded-br-md'\n : 'pilot-message-assistant rounded-bl-md'\n }`}\n >\n {isUser ? (\n message.content\n ) : (\n <div className=\"pilot-prose\">\n <ReactMarkdown>{message.content}</ReactMarkdown>\n {isStreaming && (\n <span className=\"inline-block w-2 h-4 pilot-cursor ml-0.5 animate-pulse\" />\n )}\n </div>\n )}\n </div>\n </motion.div>\n );\n}\n","'use client';\n\nimport React from 'react';\nimport { Send, Mic, MicOff } from 'lucide-react';\n\nexport interface ChatInputProps {\n value: string;\n onChange: (value: string) => void;\n onSubmit: () => void;\n disabled?: boolean;\n placeholder?: string;\n isListening?: boolean;\n onToggleListening?: () => void;\n showMic?: boolean;\n}\n\nexport function ChatInput({\n value,\n onChange,\n onSubmit,\n disabled = false,\n placeholder = 'Type a message...',\n isListening = false,\n onToggleListening,\n showMic = false,\n}: ChatInputProps) {\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (value.trim() && !disabled) {\n onSubmit();\n }\n };\n\n return (\n <form onSubmit={handleSubmit} className=\"p-4 pilot-border-top\">\n <div className=\"flex items-center gap-2 pilot-input-container px-4 py-3 transition-colors\">\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n className=\"bg-transparent flex-1 outline-none text-sm pilot-input\"\n placeholder={isListening ? 'Listening...' : placeholder}\n disabled={disabled}\n />\n {showMic && onToggleListening && (\n <button\n type=\"button\"\n onClick={onToggleListening}\n disabled={disabled}\n className={`p-2 rounded-xl transition-all ${\n isListening ? 'pilot-mic-active' : 'pilot-mic-inactive'\n }`}\n >\n {isListening ? <MicOff className=\"w-4 h-4\" /> : <Mic className=\"w-4 h-4\" />}\n </button>\n )}\n <button\n type=\"submit\"\n disabled={!value.trim() || disabled}\n className={`p-2 rounded-xl transition-all ${\n value.trim() && !disabled ? 'pilot-send-active' : 'pilot-send-inactive'\n }`}\n >\n <Send className=\"w-4 h-4\" />\n </button>\n </div>\n </form>\n );\n}\n","'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport { Zap } from 'lucide-react';\nimport type { Suggestion } from '../types';\n\nexport interface SuggestionsProps {\n suggestions: Suggestion[];\n onSelect: (text: string) => void;\n isVisible?: boolean;\n isFullscreen?: boolean;\n suggestionsToShow?: number;\n rotationInterval?: number;\n}\n\nexport function Suggestions({\n suggestions,\n onSelect,\n isVisible = true,\n isFullscreen = false,\n suggestionsToShow = 3,\n rotationInterval = 5000,\n}: SuggestionsProps) {\n const [currentIndex, setCurrentIndex] = useState(0);\n\n // Rotate suggestions\n useEffect(() => {\n if (!isVisible || suggestions.length <= suggestionsToShow) return;\n\n const interval = setInterval(() => {\n setCurrentIndex((prev) => (prev + 1) % Math.ceil(suggestions.length / suggestionsToShow));\n }, rotationInterval);\n\n return () => clearInterval(interval);\n }, [isVisible, suggestions.length, suggestionsToShow, rotationInterval]);\n\n // Get current suggestions to display\n const currentSuggestions = suggestions.slice(\n currentIndex * suggestionsToShow,\n currentIndex * suggestionsToShow + suggestionsToShow\n );\n\n const totalPages = Math.ceil(suggestions.length / suggestionsToShow);\n\n if (!isVisible || suggestions.length === 0) return null;\n\n return (\n <AnimatePresence>\n <motion.div\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -10 }}\n transition={{ duration: 0.3 }}\n className=\"pt-2\"\n >\n <div className=\"flex items-center justify-between mb-3\">\n <div className=\"flex items-center gap-1.5 pilot-text-muted\">\n <Zap className=\"w-3 h-3\" />\n <span className=\"text-[10px] uppercase tracking-wider font-medium\">Try asking</span>\n </div>\n {/* Pagination dots */}\n {totalPages > 1 && (\n <div className=\"flex gap-1\">\n {Array.from({ length: totalPages }).map((_, i) => (\n <button\n key={i}\n onClick={() => setCurrentIndex(i)}\n className={`h-1.5 rounded-full transition-all ${\n i === currentIndex\n ? 'pilot-dot-active w-3'\n : 'pilot-dot-inactive w-1.5 hover:opacity-75'\n }`}\n />\n ))}\n </div>\n )}\n </div>\n <AnimatePresence mode=\"wait\">\n <motion.div\n key={currentIndex}\n initial={{ opacity: 0, x: 20 }}\n animate={{ opacity: 1, x: 0 }}\n exit={{ opacity: 0, x: -20 }}\n transition={{ duration: 0.3 }}\n className={`flex gap-2 ${isFullscreen ? 'flex-row flex-wrap' : 'flex-col'}`}\n >\n {currentSuggestions.map((suggestion, index) => (\n <motion.button\n key={suggestion.text}\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ delay: index * 0.1 }}\n onClick={() => onSelect(suggestion.text)}\n className=\"pilot-suggestion group flex items-center gap-2 px-3 py-2 rounded-xl text-xs text-left transition-all duration-200\"\n >\n {suggestion.icon && <span className=\"text-base\">{suggestion.icon}</span>}\n <span>{suggestion.text}</span>\n </motion.button>\n ))}\n </motion.div>\n </AnimatePresence>\n </motion.div>\n </AnimatePresence>\n );\n}\n","'use client';\n\nimport React, { useState, useRef, useEffect, useCallback } from 'react';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport { X, MessageCircle, Sparkles, Volume2, VolumeX, Maximize2, Minimize2 } from 'lucide-react';\nimport { useChat } from '../hooks/useChat';\nimport { useSpeech } from '../hooks/useSpeech';\nimport { ChatMessage } from './ChatMessage';\nimport { ChatInput } from './ChatInput';\nimport { Suggestions } from './Suggestions';\nimport type { SitePilotProps, ChatMessage as ChatMessageType } from '../types';\n\n/**\n * SitePilot - AI chat widget that can control and navigate your website\n *\n * @example\n * ```tsx\n * import { SitePilot } from 'ai-site-pilot';\n *\n * <SitePilot\n * apiEndpoint=\"/api/chat\"\n * suggestions={[\n * { text: 'Show me products', icon: '🛍️' },\n * { text: 'Help me find...', icon: '🔍' },\n * ]}\n * onToolCall={(name, args) => {\n * // Handle tool execution\n * }}\n * />\n * ```\n */\nexport function SitePilot({\n apiEndpoint,\n theme = {},\n suggestions = [],\n features = {},\n onToolCall,\n defaultOpen = false,\n placeholder = 'Type a message...',\n welcomeMessage = \"Hi! I'm here to help you navigate and explore. What would you like to know?\",\n className = '',\n}: SitePilotProps) {\n const {\n accent = 'amber',\n position = 'bottom-right',\n borderRadius = 24,\n } = theme;\n\n const {\n speech = true,\n tts = true,\n fullscreen = true,\n suggestions: showSuggestionsFeature = true,\n } = features;\n\n const [isOpen, setIsOpen] = useState(defaultOpen);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const [showSuggestions, setShowSuggestions] = useState(true);\n\n const messagesEndRef = useRef<HTMLDivElement>(null);\n\n // Initial welcome message\n const initialMessages: ChatMessageType[] = welcomeMessage\n ? [\n {\n id: 'init',\n role: 'assistant',\n content: welcomeMessage,\n timestamp: new Date(),\n },\n ]\n : [];\n\n const {\n messages,\n input,\n setInput,\n isLoading,\n streamingMessageId,\n sendMessage,\n } = useChat({\n apiEndpoint,\n initialMessages,\n onToolCall,\n onStreamStart: () => setShowSuggestions(false),\n });\n\n const {\n isSupported: speechSupported,\n isListening,\n toggleListening,\n speak,\n ttsEnabled,\n setTtsEnabled,\n } = useSpeech({\n onResult: (transcript, isFinal) => {\n setInput(transcript);\n if (isFinal) {\n // Could auto-submit here if desired\n }\n },\n });\n\n // Scroll to bottom when messages change\n useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n }, [messages, isOpen]);\n\n // Speak assistant messages when TTS is enabled\n useEffect(() => {\n if (!ttsEnabled) return;\n\n const lastMessage = messages[messages.length - 1];\n if (\n lastMessage?.role === 'assistant' &&\n lastMessage.id !== streamingMessageId &&\n lastMessage.content\n ) {\n speak(lastMessage.content);\n }\n }, [messages, streamingMessageId, ttsEnabled, speak]);\n\n const handleSuggestionSelect = useCallback(\n (text: string) => {\n sendMessage(text);\n },\n [sendMessage]\n );\n\n const handleSubmit = useCallback(() => {\n sendMessage();\n }, [sendMessage]);\n\n // Position classes\n const positionClasses = {\n 'bottom-right': 'bottom-24 right-6 md:right-8',\n 'bottom-left': 'bottom-24 left-6 md:left-8',\n 'top-right': 'top-24 right-6 md:right-8',\n 'top-left': 'top-24 left-6 md:left-8',\n };\n\n const buttonPositionClasses = {\n 'bottom-right': 'bottom-6 right-6 md:right-8',\n 'bottom-left': 'bottom-6 left-6 md:left-8',\n 'top-right': 'top-6 right-6 md:right-8',\n 'top-left': 'top-6 left-6 md:left-8',\n };\n\n // CSS custom properties for theming\n const cssVars = {\n '--pilot-accent': accent,\n '--pilot-radius': `${borderRadius}px`,\n } as React.CSSProperties;\n\n return (\n <div className={`pilot-container ${className}`} style={cssVars}>\n {/* Chat Panel */}\n <AnimatePresence>\n {isOpen && (\n <motion.div\n initial={{ opacity: 0, y: 20, scale: 0.95 }}\n animate={{ opacity: 1, y: 0, scale: 1 }}\n exit={{ opacity: 0, y: 20, scale: 0.95 }}\n transition={{ type: 'spring', stiffness: 400, damping: 30 }}\n layout\n className={`fixed pilot-panel flex flex-col shadow-2xl z-[200] transition-all duration-300 ${\n isFullscreen\n ? 'inset-4 md:inset-8'\n : `${positionClasses[position]} w-[calc(100%-48px)] md:w-[400px] h-[520px]`\n }`}\n style={{ borderRadius: `${borderRadius}px` }}\n >\n {/* Header */}\n <div className=\"px-5 py-4 pilot-border-bottom flex justify-between items-center\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 pilot-avatar rounded-xl flex items-center justify-center shadow-lg\">\n <Sparkles className=\"w-5 h-5 text-white\" />\n </div>\n <div>\n <div className=\"font-semibold pilot-text text-sm\">AI Assistant</div>\n <div className=\"flex items-center gap-1.5\">\n <span className=\"w-1.5 h-1.5 pilot-status-dot rounded-full animate-pulse\" />\n <span className=\"text-[10px] pilot-text-muted\">Ready to help</span>\n </div>\n </div>\n </div>\n <div className=\"flex items-center gap-1\">\n {tts && (\n <button\n onClick={() => setTtsEnabled(!ttsEnabled)}\n className={`p-2 rounded-lg transition-colors ${\n ttsEnabled ? 'pilot-button-active' : 'pilot-button-inactive'\n }`}\n title={ttsEnabled ? 'Disable voice' : 'Enable voice'}\n >\n {ttsEnabled ? (\n <Volume2 className=\"w-4 h-4\" />\n ) : (\n <VolumeX className=\"w-4 h-4\" />\n )}\n </button>\n )}\n {fullscreen && (\n <button\n onClick={() => setIsFullscreen(!isFullscreen)}\n className=\"p-2 rounded-lg transition-colors pilot-button-inactive\"\n title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}\n >\n {isFullscreen ? (\n <Minimize2 className=\"w-4 h-4\" />\n ) : (\n <Maximize2 className=\"w-4 h-4\" />\n )}\n </button>\n )}\n <button\n onClick={() => setIsOpen(false)}\n className=\"p-2 hover:bg-white/5 rounded-lg transition-colors\"\n >\n <X className=\"w-4 h-4 pilot-text-muted\" />\n </button>\n </div>\n </div>\n\n {/* Messages Area */}\n <div className=\"flex-1 overflow-y-auto p-4 space-y-4 scrollbar-thin scrollbar-thumb-white/10 scrollbar-track-transparent\">\n {messages.map((msg) => (\n <ChatMessage\n key={msg.id}\n message={msg}\n isStreaming={streamingMessageId === msg.id}\n isFullscreen={isFullscreen}\n />\n ))}\n\n {/* Loading indicator */}\n {isLoading && !streamingMessageId && (\n <div className=\"flex justify-start\">\n <div className=\"pilot-loading px-4 py-3 rounded-2xl rounded-bl-md\">\n <div className=\"flex gap-1.5\">\n {[0, 0.15, 0.3].map((delay, i) => (\n <motion.span\n key={i}\n className=\"w-2 h-2 pilot-loading-dot rounded-full\"\n animate={{ y: [0, -4, 0] }}\n transition={{ duration: 0.6, repeat: Infinity, delay }}\n />\n ))}\n </div>\n </div>\n </div>\n )}\n\n {/* Suggestions */}\n {showSuggestionsFeature && suggestions.length > 0 && (\n <Suggestions\n suggestions={suggestions}\n onSelect={handleSuggestionSelect}\n isVisible={showSuggestions && !isLoading}\n isFullscreen={isFullscreen}\n />\n )}\n\n <div ref={messagesEndRef} />\n </div>\n\n {/* Input Area */}\n <ChatInput\n value={input}\n onChange={setInput}\n onSubmit={handleSubmit}\n disabled={isLoading}\n placeholder={placeholder}\n isListening={isListening}\n onToggleListening={toggleListening}\n showMic={speech && speechSupported}\n />\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* Toggle Button */}\n {!isOpen && (\n <motion.button\n onClick={() => setIsOpen(true)}\n initial={{ opacity: 0, scale: 0.8 }}\n animate={{ opacity: 1, scale: 1 }}\n whileHover={{ scale: 1.05 }}\n whileTap={{ scale: 0.95 }}\n className={`fixed ${buttonPositionClasses[position]} flex items-center gap-2 pilot-toggle-button px-5 py-3.5 rounded-2xl font-medium shadow-xl transition-shadow z-[200]`}\n >\n <MessageCircle className=\"w-5 h-5\" />\n <span className=\"text-sm hidden sm:inline\">Ask AI</span>\n <span className=\"w-2 h-2 bg-white/80 rounded-full animate-pulse\" />\n </motion.button>\n )}\n </div>\n );\n}\n\nexport default SitePilot;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/hooks/useChat.ts","../src/hooks/useSpeech.ts","../src/components/ChatMessage.tsx","../src/components/ChatInput.tsx","../src/components/Suggestions.tsx","../src/components/SitePilot.tsx"],"names":["useState","useRef","useCallback","jsx","jsxs","useEffect","motion","AnimatePresence"],"mappings":"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","file":"index.mjs","sourcesContent":["'use client';\n\nimport { useState, useCallback, useRef } from 'react';\nimport type { ChatMessage, ToolExecution, StreamEvent } from '../types';\n\nexport interface UseChatOptions {\n /** API endpoint for chat */\n apiEndpoint: string;\n /** Initial messages */\n initialMessages?: ChatMessage[];\n /** Callback when a tool is called */\n onToolCall?: (toolName: string, args: Record<string, unknown>) => void | Promise<void>;\n /** Callback when streaming starts */\n onStreamStart?: () => void;\n /** Callback when streaming ends */\n onStreamEnd?: () => void;\n}\n\nexport interface UseChatReturn {\n /** All messages in the conversation */\n messages: ChatMessage[];\n /** Current input value */\n input: string;\n /** Set the input value */\n setInput: (value: string) => void;\n /** Whether the assistant is currently responding */\n isLoading: boolean;\n /** ID of the currently streaming message */\n streamingMessageId: string | null;\n /** Send a message */\n sendMessage: (content?: string) => Promise<void>;\n /** Clear all messages */\n clearMessages: () => void;\n /** Add a message manually */\n addMessage: (message: Omit<ChatMessage, 'id' | 'timestamp'>) => void;\n}\n\n/**\n * Hook for managing chat state and streaming\n */\nexport function useChat(options: UseChatOptions): UseChatReturn {\n const { apiEndpoint, initialMessages = [], onToolCall, onStreamStart, onStreamEnd } = options;\n\n const [messages, setMessages] = useState<ChatMessage[]>(initialMessages);\n const [input, setInput] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [streamingMessageId, setStreamingMessageId] = useState<string | null>(null);\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const addMessage = useCallback((message: Omit<ChatMessage, 'id' | 'timestamp'>) => {\n const newMessage: ChatMessage = {\n ...message,\n id: Date.now().toString(),\n timestamp: new Date(),\n };\n setMessages((prev) => [...prev, newMessage]);\n return newMessage;\n }, []);\n\n const clearMessages = useCallback(() => {\n setMessages(initialMessages);\n }, [initialMessages]);\n\n const sendMessage = useCallback(\n async (content?: string) => {\n const messageContent = content || input;\n if (!messageContent.trim() || isLoading) return;\n\n // Cancel any ongoing request\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n abortControllerRef.current = new AbortController();\n\n // Add user message\n const userMessage: ChatMessage = {\n id: Date.now().toString(),\n role: 'user',\n content: messageContent,\n timestamp: new Date(),\n };\n setMessages((prev) => [...prev, userMessage]);\n setInput('');\n setIsLoading(true);\n onStreamStart?.();\n\n // Add placeholder for assistant message\n const assistantMessageId = (Date.now() + 1).toString();\n const assistantMessage: ChatMessage = {\n id: assistantMessageId,\n role: 'assistant',\n content: '',\n timestamp: new Date(),\n toolCalls: [],\n };\n setMessages((prev) => [...prev, assistantMessage]);\n setStreamingMessageId(assistantMessageId);\n\n let fullText = '';\n const toolCalls: ToolExecution[] = [];\n\n try {\n // Prepare messages for API (convert to format expected by API)\n const apiMessages = messages.concat(userMessage).map((m) => ({\n role: m.role,\n content: m.content,\n }));\n\n const response = await fetch(apiEndpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ messages: apiMessages }),\n signal: abortControllerRef.current.signal,\n });\n\n if (!response.ok) {\n throw new Error('Failed to get response');\n }\n\n const reader = response.body?.getReader();\n if (!reader) throw new Error('No reader available');\n\n const decoder = new TextDecoder();\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n const text = decoder.decode(value);\n const lines = text.split('\\n');\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n try {\n const data = JSON.parse(line.slice(6)) as StreamEvent;\n\n if (data.type === 'text') {\n fullText += data.content;\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantMessageId ? { ...m, content: fullText } : m\n )\n );\n } else if (data.type === 'tool') {\n const toolCall = { name: data.name, args: data.args };\n toolCalls.push(toolCall);\n\n // Execute tool call callback\n if (onToolCall) {\n try {\n await onToolCall(data.name, data.args);\n } catch (e) {\n console.error('Tool execution error:', e);\n }\n }\n } else if (data.type === 'done') {\n // Update message with tool calls\n if (toolCalls.length > 0) {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantMessageId ? { ...m, toolCalls } : m\n )\n );\n }\n\n // If no text, show default message\n if (!fullText) {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantMessageId\n ? { ...m, content: \"I've made some changes. Take a look!\" }\n : m\n )\n );\n }\n } else if (data.type === 'error') {\n throw new Error(data.message);\n }\n } catch {\n // Skip invalid JSON lines\n }\n }\n }\n }\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n // Request was cancelled, ignore\n return;\n }\n\n console.error('Chat error:', error);\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantMessageId\n ? { ...m, content: 'Sorry, I encountered an error. Please try again.' }\n : m\n )\n );\n } finally {\n setIsLoading(false);\n setStreamingMessageId(null);\n onStreamEnd?.();\n }\n },\n [apiEndpoint, input, isLoading, messages, onToolCall, onStreamStart, onStreamEnd]\n );\n\n return {\n messages,\n input,\n setInput,\n isLoading,\n streamingMessageId,\n sendMessage,\n clearMessages,\n addMessage,\n };\n}\n","'use client';\n\nimport { useState, useRef, useEffect, useCallback } from 'react';\n\n// Web Speech API types\ninterface SpeechRecognitionEvent extends Event {\n results: SpeechRecognitionResultList;\n}\n\ninterface SpeechRecognitionInstance {\n continuous: boolean;\n interimResults: boolean;\n lang: string;\n start(): void;\n stop(): void;\n onresult: ((event: SpeechRecognitionEvent) => void) | null;\n onend: (() => void) | null;\n onerror: (() => void) | null;\n}\n\nexport interface UseSpeechOptions {\n /** Language for speech recognition */\n lang?: string;\n /** Callback when speech is recognized */\n onResult?: (transcript: string, isFinal: boolean) => void;\n}\n\nexport interface UseSpeechReturn {\n /** Whether speech recognition is supported */\n isSupported: boolean;\n /** Whether currently listening */\n isListening: boolean;\n /** Toggle listening on/off */\n toggleListening: () => void;\n /** Start listening */\n startListening: () => void;\n /** Stop listening */\n stopListening: () => void;\n /** Speak text using TTS */\n speak: (text: string) => void;\n /** Whether TTS is enabled */\n ttsEnabled: boolean;\n /** Toggle TTS on/off */\n setTtsEnabled: (enabled: boolean) => void;\n /** Cancel current speech */\n cancelSpeech: () => void;\n}\n\n/**\n * Hook for speech recognition and text-to-speech\n */\nexport function useSpeech(options: UseSpeechOptions = {}): UseSpeechReturn {\n const { lang = 'en-US', onResult } = options;\n\n const [isSupported, setIsSupported] = useState(false);\n const [isListening, setIsListening] = useState(false);\n const [ttsEnabled, setTtsEnabled] = useState(false);\n\n const recognitionRef = useRef<SpeechRecognitionInstance | null>(null);\n\n // Initialize speech recognition\n useEffect(() => {\n if (typeof window === 'undefined') return;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const windowWithSpeech = window as any;\n const SpeechRecognitionAPI =\n windowWithSpeech.SpeechRecognition || windowWithSpeech.webkitSpeechRecognition;\n\n if (SpeechRecognitionAPI) {\n setIsSupported(true);\n recognitionRef.current = new SpeechRecognitionAPI() as SpeechRecognitionInstance;\n recognitionRef.current.continuous = false;\n recognitionRef.current.interimResults = true;\n recognitionRef.current.lang = lang;\n\n recognitionRef.current.onresult = (event) => {\n const result = event.results[0];\n const transcript = result[0].transcript;\n onResult?.(transcript, result.isFinal);\n\n if (result.isFinal) {\n setIsListening(false);\n }\n };\n\n recognitionRef.current.onend = () => setIsListening(false);\n recognitionRef.current.onerror = () => setIsListening(false);\n }\n }, [lang, onResult]);\n\n const startListening = useCallback(() => {\n if (!recognitionRef.current) return;\n try {\n recognitionRef.current.start();\n setIsListening(true);\n } catch (e) {\n console.error('Speech recognition error:', e);\n }\n }, []);\n\n const stopListening = useCallback(() => {\n if (!recognitionRef.current) return;\n recognitionRef.current.stop();\n setIsListening(false);\n }, []);\n\n const toggleListening = useCallback(() => {\n if (isListening) {\n stopListening();\n } else {\n startListening();\n }\n }, [isListening, startListening, stopListening]);\n\n const speak = useCallback(\n (text: string) => {\n if (!ttsEnabled || typeof window === 'undefined' || !('speechSynthesis' in window)) {\n return;\n }\n\n speechSynthesis.cancel();\n const utterance = new SpeechSynthesisUtterance(text);\n utterance.rate = 1.0;\n utterance.pitch = 1.0;\n\n // Try to find a good voice\n const voices = speechSynthesis.getVoices();\n const preferredVoice = voices.find(\n (v) => v.name.includes('Google') || v.name.includes('Samantha') || v.name.includes('Alex')\n );\n if (preferredVoice) {\n utterance.voice = preferredVoice;\n }\n\n speechSynthesis.speak(utterance);\n },\n [ttsEnabled]\n );\n\n const cancelSpeech = useCallback(() => {\n if (typeof window !== 'undefined' && 'speechSynthesis' in window) {\n speechSynthesis.cancel();\n }\n }, []);\n\n return {\n isSupported,\n isListening,\n toggleListening,\n startListening,\n stopListening,\n speak,\n ttsEnabled,\n setTtsEnabled,\n cancelSpeech,\n };\n}\n","'use client';\n\nimport React from 'react';\nimport { motion } from 'framer-motion';\nimport ReactMarkdown from 'react-markdown';\nimport type { ChatMessage as ChatMessageType } from '../types';\n\nexport interface ChatMessageProps {\n message: ChatMessageType;\n isStreaming?: boolean;\n isFullscreen?: boolean;\n}\n\nexport function ChatMessage({ message, isStreaming, isFullscreen }: ChatMessageProps) {\n const isUser = message.role === 'user';\n\n return (\n <motion.div\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n className={`flex ${isUser ? 'justify-end' : 'justify-start'}`}\n >\n <div\n className={`px-4 py-3 rounded-2xl text-sm leading-relaxed ${\n isFullscreen ? 'max-w-[70%]' : 'max-w-[85%]'\n } ${\n isUser\n ? 'pilot-message-user rounded-br-md'\n : 'pilot-message-assistant rounded-bl-md'\n }`}\n >\n {isUser ? (\n message.content\n ) : (\n <div className=\"pilot-prose\">\n <ReactMarkdown>{message.content}</ReactMarkdown>\n {isStreaming && (\n <span className=\"inline-block w-2 h-4 pilot-cursor ml-0.5 animate-pulse\" />\n )}\n </div>\n )}\n </div>\n </motion.div>\n );\n}\n","'use client';\n\nimport React from 'react';\nimport { Send, Mic, MicOff } from 'lucide-react';\n\nexport interface ChatInputProps {\n value: string;\n onChange: (value: string) => void;\n onSubmit: () => void;\n disabled?: boolean;\n placeholder?: string;\n isListening?: boolean;\n onToggleListening?: () => void;\n showMic?: boolean;\n}\n\nexport function ChatInput({\n value,\n onChange,\n onSubmit,\n disabled = false,\n placeholder = 'Type a message...',\n isListening = false,\n onToggleListening,\n showMic = false,\n}: ChatInputProps) {\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (value.trim() && !disabled) {\n onSubmit();\n }\n };\n\n return (\n <form onSubmit={handleSubmit} className=\"p-4 pilot-border-top\">\n <div className=\"flex items-center gap-2 pilot-input-container px-4 py-3 transition-colors\">\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n className=\"bg-transparent flex-1 outline-none text-sm pilot-input\"\n placeholder={isListening ? 'Listening...' : placeholder}\n disabled={disabled}\n />\n {showMic && onToggleListening && (\n <button\n type=\"button\"\n onClick={onToggleListening}\n disabled={disabled}\n className={`p-2 rounded-xl transition-all ${\n isListening ? 'pilot-mic-active' : 'pilot-mic-inactive'\n }`}\n >\n {isListening ? <MicOff className=\"w-4 h-4\" /> : <Mic className=\"w-4 h-4\" />}\n </button>\n )}\n <button\n type=\"submit\"\n disabled={!value.trim() || disabled}\n className={`p-2 rounded-xl transition-all ${\n value.trim() && !disabled ? 'pilot-send-active' : 'pilot-send-inactive'\n }`}\n >\n <Send className=\"w-4 h-4\" />\n </button>\n </div>\n </form>\n );\n}\n","'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport { Zap } from 'lucide-react';\nimport type { Suggestion } from '../types';\n\nexport interface SuggestionsProps {\n suggestions: Suggestion[];\n onSelect: (text: string) => void;\n isVisible?: boolean;\n isFullscreen?: boolean;\n suggestionsToShow?: number;\n rotationInterval?: number;\n}\n\nexport function Suggestions({\n suggestions,\n onSelect,\n isVisible = true,\n isFullscreen = false,\n suggestionsToShow = 3,\n rotationInterval = 5000,\n}: SuggestionsProps) {\n const [currentIndex, setCurrentIndex] = useState(0);\n\n // Rotate suggestions\n useEffect(() => {\n if (!isVisible || suggestions.length <= suggestionsToShow) return;\n\n const interval = setInterval(() => {\n setCurrentIndex((prev) => (prev + 1) % Math.ceil(suggestions.length / suggestionsToShow));\n }, rotationInterval);\n\n return () => clearInterval(interval);\n }, [isVisible, suggestions.length, suggestionsToShow, rotationInterval]);\n\n // Get current suggestions to display\n const currentSuggestions = suggestions.slice(\n currentIndex * suggestionsToShow,\n currentIndex * suggestionsToShow + suggestionsToShow\n );\n\n const totalPages = Math.ceil(suggestions.length / suggestionsToShow);\n\n if (!isVisible || suggestions.length === 0) return null;\n\n return (\n <AnimatePresence>\n <motion.div\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -10 }}\n transition={{ duration: 0.3 }}\n className=\"pt-2\"\n >\n <div className=\"flex items-center justify-between mb-3\">\n <div className=\"flex items-center gap-1.5 pilot-text-muted\">\n <Zap className=\"w-3 h-3\" />\n <span className=\"text-[10px] uppercase tracking-wider font-medium\">Try asking</span>\n </div>\n {/* Pagination dots */}\n {totalPages > 1 && (\n <div className=\"flex gap-1\">\n {Array.from({ length: totalPages }).map((_, i) => (\n <button\n key={i}\n onClick={() => setCurrentIndex(i)}\n className={`h-1.5 rounded-full transition-all ${\n i === currentIndex\n ? 'pilot-dot-active w-3'\n : 'pilot-dot-inactive w-1.5 hover:opacity-75'\n }`}\n />\n ))}\n </div>\n )}\n </div>\n <AnimatePresence mode=\"wait\">\n <motion.div\n key={currentIndex}\n initial={{ opacity: 0, x: 20 }}\n animate={{ opacity: 1, x: 0 }}\n exit={{ opacity: 0, x: -20 }}\n transition={{ duration: 0.3 }}\n className={`flex gap-2 ${isFullscreen ? 'flex-row flex-wrap' : 'flex-col'}`}\n >\n {currentSuggestions.map((suggestion, index) => (\n <motion.button\n key={suggestion.text}\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ delay: index * 0.1 }}\n onClick={() => onSelect(suggestion.text)}\n className=\"pilot-suggestion group flex items-center gap-2 px-3 py-2 rounded-xl text-xs text-left transition-all duration-200\"\n >\n {suggestion.icon && <span className=\"text-base\">{suggestion.icon}</span>}\n <span>{suggestion.text}</span>\n </motion.button>\n ))}\n </motion.div>\n </AnimatePresence>\n </motion.div>\n </AnimatePresence>\n );\n}\n","'use client';\n\nimport React, { useState, useRef, useEffect, useCallback } from 'react';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport { X, MessageCircle, Sparkles, Volume2, VolumeX, Maximize2, Minimize2 } from 'lucide-react';\nimport { useChat } from '../hooks/useChat';\nimport { useSpeech } from '../hooks/useSpeech';\nimport { ChatMessage } from './ChatMessage';\nimport { ChatInput } from './ChatInput';\nimport { Suggestions } from './Suggestions';\nimport type { SitePilotProps, ChatMessage as ChatMessageType } from '../types';\n\n/**\n * SitePilot - AI chat widget that can control and navigate your website\n *\n * @example\n * ```tsx\n * import { SitePilot } from 'ai-site-pilot';\n *\n * <SitePilot\n * apiEndpoint=\"/api/chat\"\n * suggestions={[\n * { text: 'Show me products', icon: '🛍️' },\n * { text: 'Help me find...', icon: '🔍' },\n * ]}\n * onToolCall={(name, args) => {\n * // Handle tool execution\n * }}\n * />\n * ```\n */\nexport function SitePilot({\n apiEndpoint,\n theme = {},\n suggestions = [],\n features = {},\n onToolCall,\n defaultOpen = false,\n placeholder = 'Type a message...',\n welcomeMessage = \"Hi! I'm here to help you navigate and explore. What would you like to know?\",\n className = '',\n}: SitePilotProps) {\n const {\n position = 'bottom-right',\n borderRadius = 24,\n accentColor,\n accentColorDark,\n backgroundColor,\n textColor,\n textMutedColor,\n borderColor,\n userMessageBg,\n assistantMessageBg,\n } = theme;\n\n const {\n speech = true,\n tts = true,\n fullscreen = true,\n suggestions: showSuggestionsFeature = true,\n } = features;\n\n const [isOpen, setIsOpen] = useState(defaultOpen);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const [showSuggestions, setShowSuggestions] = useState(true);\n\n const messagesEndRef = useRef<HTMLDivElement>(null);\n\n // Initial welcome message\n const initialMessages: ChatMessageType[] = welcomeMessage\n ? [\n {\n id: 'init',\n role: 'assistant',\n content: welcomeMessage,\n timestamp: new Date(),\n },\n ]\n : [];\n\n const {\n messages,\n input,\n setInput,\n isLoading,\n streamingMessageId,\n sendMessage,\n } = useChat({\n apiEndpoint,\n initialMessages,\n onToolCall,\n onStreamStart: () => setShowSuggestions(false),\n });\n\n const {\n isSupported: speechSupported,\n isListening,\n toggleListening,\n speak,\n ttsEnabled,\n setTtsEnabled,\n } = useSpeech({\n onResult: (transcript, isFinal) => {\n setInput(transcript);\n if (isFinal) {\n // Could auto-submit here if desired\n }\n },\n });\n\n // Scroll to bottom when messages change\n useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n }, [messages, isOpen]);\n\n // Speak assistant messages when TTS is enabled\n useEffect(() => {\n if (!ttsEnabled) return;\n\n const lastMessage = messages[messages.length - 1];\n if (\n lastMessage?.role === 'assistant' &&\n lastMessage.id !== streamingMessageId &&\n lastMessage.content\n ) {\n speak(lastMessage.content);\n }\n }, [messages, streamingMessageId, ttsEnabled, speak]);\n\n const handleSuggestionSelect = useCallback(\n (text: string) => {\n sendMessage(text);\n },\n [sendMessage]\n );\n\n const handleSubmit = useCallback(() => {\n sendMessage();\n }, [sendMessage]);\n\n // Position classes\n const positionClasses = {\n 'bottom-right': 'bottom-24 right-6 md:right-8',\n 'bottom-left': 'bottom-24 left-6 md:left-8',\n 'top-right': 'top-24 right-6 md:right-8',\n 'top-left': 'top-24 left-6 md:left-8',\n };\n\n const buttonPositionClasses = {\n 'bottom-right': 'bottom-6 right-6 md:right-8',\n 'bottom-left': 'bottom-6 left-6 md:left-8',\n 'top-right': 'top-6 right-6 md:right-8',\n 'top-left': 'top-6 left-6 md:left-8',\n };\n\n // CSS custom properties for theming\n const cssVars = {\n '--pilot-radius': `${borderRadius}px`,\n ...(accentColor && { '--pilot-accent': accentColor }),\n ...(accentColorDark && { '--pilot-accent-dark': accentColorDark }),\n ...(backgroundColor && { '--pilot-bg': backgroundColor, '--pilot-bg-95': `${backgroundColor}f2` }),\n ...(textColor && { '--pilot-text': textColor }),\n ...(textMutedColor && { '--pilot-text-muted': textMutedColor }),\n ...(borderColor && { '--pilot-border': borderColor }),\n ...(userMessageBg && { '--pilot-user-bg': userMessageBg }),\n ...(assistantMessageBg && { '--pilot-assistant-bg': assistantMessageBg }),\n } as React.CSSProperties;\n\n return (\n <div className={`pilot-container ${className}`} style={cssVars}>\n {/* Chat Panel */}\n <AnimatePresence>\n {isOpen && (\n <motion.div\n initial={{ opacity: 0, y: 20, scale: 0.95 }}\n animate={{ opacity: 1, y: 0, scale: 1 }}\n exit={{ opacity: 0, y: 20, scale: 0.95 }}\n transition={{ type: 'spring', stiffness: 400, damping: 30 }}\n layout\n className={`fixed pilot-panel flex flex-col shadow-2xl z-[200] transition-all duration-300 ${\n isFullscreen\n ? 'inset-4 md:inset-8'\n : `${positionClasses[position]} w-[calc(100%-48px)] md:w-[400px] h-[520px]`\n }`}\n style={{ borderRadius: `${borderRadius}px` }}\n >\n {/* Header */}\n <div className=\"px-5 py-4 pilot-border-bottom flex justify-between items-center\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 pilot-avatar rounded-xl flex items-center justify-center shadow-lg\">\n <Sparkles className=\"w-5 h-5 text-white\" />\n </div>\n <div>\n <div className=\"font-semibold pilot-text text-sm\">AI Assistant</div>\n <div className=\"flex items-center gap-1.5\">\n <span className=\"w-1.5 h-1.5 pilot-status-dot rounded-full animate-pulse\" />\n <span className=\"text-[10px] pilot-text-muted\">Ready to help</span>\n </div>\n </div>\n </div>\n <div className=\"flex items-center gap-1\">\n {tts && (\n <button\n onClick={() => setTtsEnabled(!ttsEnabled)}\n className={`p-2 rounded-lg transition-colors ${\n ttsEnabled ? 'pilot-button-active' : 'pilot-button-inactive'\n }`}\n title={ttsEnabled ? 'Disable voice' : 'Enable voice'}\n >\n {ttsEnabled ? (\n <Volume2 className=\"w-4 h-4\" />\n ) : (\n <VolumeX className=\"w-4 h-4\" />\n )}\n </button>\n )}\n {fullscreen && (\n <button\n onClick={() => setIsFullscreen(!isFullscreen)}\n className=\"p-2 rounded-lg transition-colors pilot-button-inactive\"\n title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}\n >\n {isFullscreen ? (\n <Minimize2 className=\"w-4 h-4\" />\n ) : (\n <Maximize2 className=\"w-4 h-4\" />\n )}\n </button>\n )}\n <button\n onClick={() => setIsOpen(false)}\n className=\"p-2 hover:bg-white/5 rounded-lg transition-colors\"\n >\n <X className=\"w-4 h-4 pilot-text-muted\" />\n </button>\n </div>\n </div>\n\n {/* Messages Area */}\n <div className=\"flex-1 overflow-y-auto p-4 space-y-4 scrollbar-thin scrollbar-thumb-white/10 scrollbar-track-transparent\">\n {messages.map((msg) => (\n <ChatMessage\n key={msg.id}\n message={msg}\n isStreaming={streamingMessageId === msg.id}\n isFullscreen={isFullscreen}\n />\n ))}\n\n {/* Loading indicator */}\n {isLoading && !streamingMessageId && (\n <div className=\"flex justify-start\">\n <div className=\"pilot-loading px-4 py-3 rounded-2xl rounded-bl-md\">\n <div className=\"flex gap-1.5\">\n {[0, 0.15, 0.3].map((delay, i) => (\n <motion.span\n key={i}\n className=\"w-2 h-2 pilot-loading-dot rounded-full\"\n animate={{ y: [0, -4, 0] }}\n transition={{ duration: 0.6, repeat: Infinity, delay }}\n />\n ))}\n </div>\n </div>\n </div>\n )}\n\n {/* Suggestions */}\n {showSuggestionsFeature && suggestions.length > 0 && (\n <Suggestions\n suggestions={suggestions}\n onSelect={handleSuggestionSelect}\n isVisible={showSuggestions && !isLoading}\n isFullscreen={isFullscreen}\n />\n )}\n\n <div ref={messagesEndRef} />\n </div>\n\n {/* Input Area */}\n <ChatInput\n value={input}\n onChange={setInput}\n onSubmit={handleSubmit}\n disabled={isLoading}\n placeholder={placeholder}\n isListening={isListening}\n onToggleListening={toggleListening}\n showMic={speech && speechSupported}\n />\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* Toggle Button */}\n {!isOpen && (\n <motion.button\n onClick={() => setIsOpen(true)}\n initial={{ opacity: 0, scale: 0.8 }}\n animate={{ opacity: 1, scale: 1 }}\n whileHover={{ scale: 1.05 }}\n whileTap={{ scale: 0.95 }}\n className={`fixed ${buttonPositionClasses[position]} flex items-center gap-2 pilot-toggle-button px-5 py-3.5 rounded-2xl font-medium shadow-xl transition-shadow z-[200]`}\n >\n <MessageCircle className=\"w-5 h-5\" />\n <span className=\"text-sm hidden sm:inline\">Ask AI</span>\n <span className=\"w-2 h-2 bg-white/80 rounded-full animate-pulse\" />\n </motion.button>\n )}\n </div>\n );\n}\n\nexport default SitePilot;\n"]}
|
package/dist/styles.css
CHANGED
|
@@ -71,12 +71,12 @@
|
|
|
71
71
|
|
|
72
72
|
/* Messages */
|
|
73
73
|
.pilot-message-user {
|
|
74
|
-
background: linear-gradient(135deg, var(--pilot-accent), var(--pilot-accent-dark));
|
|
74
|
+
background: var(--pilot-user-bg, linear-gradient(135deg, var(--pilot-accent), var(--pilot-accent-dark)));
|
|
75
75
|
color: var(--pilot-text);
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
.pilot-message-assistant {
|
|
79
|
-
background: rgba(255, 255, 255, 0.05);
|
|
79
|
+
background: var(--pilot-assistant-bg, rgba(255, 255, 255, 0.05));
|
|
80
80
|
color: #e4e4e7;
|
|
81
81
|
border: 1px solid var(--pilot-border-subtle);
|
|
82
82
|
}
|
|
@@ -30,12 +30,26 @@ interface Suggestion {
|
|
|
30
30
|
icon?: string;
|
|
31
31
|
}
|
|
32
32
|
interface SitePilotTheme {
|
|
33
|
-
/** Accent color name (e.g., 'amber', 'blue', 'green') or CSS color */
|
|
34
|
-
accent?: string;
|
|
35
33
|
/** Position of the chat panel */
|
|
36
34
|
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
37
35
|
/** Border radius in pixels */
|
|
38
36
|
borderRadius?: number;
|
|
37
|
+
/** Primary accent color (buttons, highlights) - e.g., '#f59e0b' or 'rgb(245, 158, 11)' */
|
|
38
|
+
accentColor?: string;
|
|
39
|
+
/** Secondary accent color for gradients - defaults to darker version of accentColor */
|
|
40
|
+
accentColorDark?: string;
|
|
41
|
+
/** Panel background color - e.g., '#0F0720' */
|
|
42
|
+
backgroundColor?: string;
|
|
43
|
+
/** Primary text color - e.g., '#ffffff' */
|
|
44
|
+
textColor?: string;
|
|
45
|
+
/** Muted/secondary text color - e.g., '#a1a1aa' */
|
|
46
|
+
textMutedColor?: string;
|
|
47
|
+
/** Border color - e.g., 'rgba(255,255,255,0.1)' */
|
|
48
|
+
borderColor?: string;
|
|
49
|
+
/** User message background (gradient start) */
|
|
50
|
+
userMessageBg?: string;
|
|
51
|
+
/** Assistant message background */
|
|
52
|
+
assistantMessageBg?: string;
|
|
39
53
|
}
|
|
40
54
|
interface SitePilotFeatures {
|
|
41
55
|
/** Enable speech recognition input */
|
|
@@ -30,12 +30,26 @@ interface Suggestion {
|
|
|
30
30
|
icon?: string;
|
|
31
31
|
}
|
|
32
32
|
interface SitePilotTheme {
|
|
33
|
-
/** Accent color name (e.g., 'amber', 'blue', 'green') or CSS color */
|
|
34
|
-
accent?: string;
|
|
35
33
|
/** Position of the chat panel */
|
|
36
34
|
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
37
35
|
/** Border radius in pixels */
|
|
38
36
|
borderRadius?: number;
|
|
37
|
+
/** Primary accent color (buttons, highlights) - e.g., '#f59e0b' or 'rgb(245, 158, 11)' */
|
|
38
|
+
accentColor?: string;
|
|
39
|
+
/** Secondary accent color for gradients - defaults to darker version of accentColor */
|
|
40
|
+
accentColorDark?: string;
|
|
41
|
+
/** Panel background color - e.g., '#0F0720' */
|
|
42
|
+
backgroundColor?: string;
|
|
43
|
+
/** Primary text color - e.g., '#ffffff' */
|
|
44
|
+
textColor?: string;
|
|
45
|
+
/** Muted/secondary text color - e.g., '#a1a1aa' */
|
|
46
|
+
textMutedColor?: string;
|
|
47
|
+
/** Border color - e.g., 'rgba(255,255,255,0.1)' */
|
|
48
|
+
borderColor?: string;
|
|
49
|
+
/** User message background (gradient start) */
|
|
50
|
+
userMessageBg?: string;
|
|
51
|
+
/** Assistant message background */
|
|
52
|
+
assistantMessageBg?: string;
|
|
39
53
|
}
|
|
40
54
|
interface SitePilotFeatures {
|
|
41
55
|
/** Enable speech recognition input */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-site-pilot",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "AI chat widget that can control and navigate your website. Full-stack solution with streaming, tool system, and polished UI.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
},
|
|
31
31
|
"files": [
|
|
32
32
|
"dist",
|
|
33
|
-
"README.md"
|
|
33
|
+
"README.md",
|
|
34
|
+
"CLAUDE.md"
|
|
34
35
|
],
|
|
35
36
|
"scripts": {
|
|
36
37
|
"build": "tsup && cp src/styles.css dist/styles.css",
|