ai-site-pilot 0.3.0 → 0.4.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/README.md CHANGED
@@ -5,91 +5,36 @@
5
5
 
6
6
  AI chat widget that can **control and navigate your website**. Unlike typical chatbots that just answer questions, Site Pilot can take actions—scroll to sections, open modals, filter content, and more.
7
7
 
8
+ Works with any AI model (Gemini, GPT-4, Claude, Llama) via [OpenRouter](https://openrouter.ai).
9
+
8
10
  ## Features
9
11
 
10
12
  - 🎯 **Tool System** - Define custom actions the AI can take on your site
11
- - 🌊 **Streaming** - Real-time streaming responses with SSE
13
+ - 🌊 **Streaming** - Real-time streaming responses
14
+ - 🤖 **Any Model** - GPT-4, Claude, Gemini, Llama - just change one string
12
15
  - 🎤 **Speech** - Voice input and text-to-speech output
13
16
  - 🎨 **Themeable** - CSS variables for easy customization
14
17
  - 📱 **Responsive** - Works on all screen sizes
15
- - **Vercel AI SDK** - Works with any LLM provider
16
-
17
- ## How It Works
18
-
19
- The package provides the chat UI and streaming infrastructure. **You teach the AI about your specific site** through:
20
-
21
- 1. **System Prompt** - Tell the AI what sections, data, and features exist on your site
22
- 2. **Tool Definitions** - Define what actions the AI can take (filter, navigate, open modals)
23
- 3. **Client Handlers** - Write the code that actually executes those actions
24
-
25
- ```
26
- User: "Show me your mobile apps"
27
-
28
- AI understands request
29
-
30
- AI calls filter_by_category("Mobile") tool
31
-
32
- Your handler receives the call
33
-
34
- Your code filters the UI
35
- ```
36
-
37
- The AI doesn't automatically know your site structure—you teach it via the system prompt. See the [complete example](#teaching-the-ai-your-site) below.
18
+ - 🆓 **Free Tier** - Gemini 2.0 Flash is free on OpenRouter
38
19
 
39
20
  ## Installation
40
21
 
41
22
  ```bash
42
23
  npm install ai-site-pilot
43
-
44
- # Choose your backend (pick ONE):
45
- npm install @google/genai # Gemini (recommended, no AI SDK needed)
46
- npm install ai @ai-sdk/google # Vercel AI SDK with Gemini
47
- npm install ai @ai-sdk/openai # Vercel AI SDK with OpenAI
48
24
  ```
49
25
 
50
26
  ## Quick Start
51
27
 
52
- ### 1. Create the API Route
53
-
54
- **Option A: Gemini Direct (Recommended)** - No Vercel AI SDK needed!
55
-
56
- ```typescript
57
- // app/api/chat/route.ts
58
- import { createGeminiHandler } from 'ai-site-pilot/api';
59
- import { defineTool } from 'ai-site-pilot/tools';
60
-
61
- const navigateTool = defineTool({
62
- name: 'navigate',
63
- description: 'Navigate to a section of the page',
64
- parameters: {
65
- type: 'object',
66
- properties: {
67
- section: {
68
- type: 'string',
69
- description: 'Section to navigate to',
70
- enum: ['home', 'products', 'about', 'contact'],
71
- },
72
- },
73
- required: ['section'],
74
- },
75
- });
28
+ ### 1. Get an OpenRouter API Key
76
29
 
77
- export const POST = createGeminiHandler({
78
- apiKey: process.env.GOOGLE_GENERATIVE_AI_API_KEY,
79
- model: 'gemini-2.0-flash',
80
- systemPrompt: `You are a helpful assistant for our website.
81
- You can navigate users to different sections using the navigate tool.`,
82
- tools: [navigateTool],
83
- });
84
- ```
30
+ Sign up at [openrouter.ai](https://openrouter.ai) and get your API key.
85
31
 
86
- **Option B: Vercel AI SDK** - Works with any AI SDK provider
32
+ ### 2. Create the API Route
87
33
 
88
34
  ```typescript
89
35
  // app/api/chat/route.ts
90
- import { createChatHandler } from 'ai-site-pilot/api';
36
+ import { createHandler } from 'ai-site-pilot/api';
91
37
  import { defineTool } from 'ai-site-pilot/tools';
92
- import { google } from '@ai-sdk/google';
93
38
 
94
39
  const navigateTool = defineTool({
95
40
  name: 'navigate',
@@ -107,15 +52,15 @@ const navigateTool = defineTool({
107
52
  },
108
53
  });
109
54
 
110
- export const POST = createChatHandler({
111
- model: google('gemini-2.0-flash'),
55
+ export const POST = createHandler({
56
+ model: 'google/gemini-2.0-flash-exp:free', // Free! Or use any model
112
57
  systemPrompt: `You are a helpful assistant for our website.
113
58
  You can navigate users to different sections using the navigate tool.`,
114
59
  tools: [navigateTool],
115
60
  });
116
61
  ```
117
62
 
118
- ### 2. Add the Component
63
+ ### 3. Add the Component
119
64
 
120
65
  ```tsx
121
66
  // app/layout.tsx or components/ChatWidget.tsx
@@ -144,88 +89,88 @@ export function ChatWidget() {
144
89
  }
145
90
  ```
146
91
 
147
- ## API Reference
92
+ ### 4. Add Environment Variable
148
93
 
149
- ### `<SitePilot />`
94
+ ```bash
95
+ # .env.local
96
+ OPENROUTER_API_KEY=sk-or-...
97
+ ```
150
98
 
151
- Main chat widget component.
99
+ That's it!
152
100
 
153
- | Prop | Type | Default | Description |
154
- |------|------|---------|-------------|
155
- | `apiEndpoint` | `string` | required | API endpoint for chat |
156
- | `theme` | `SitePilotTheme` | `{}` | Theme configuration |
157
- | `suggestions` | `Suggestion[]` | `[]` | Suggestion prompts |
158
- | `features` | `SitePilotFeatures` | `{}` | Feature toggles |
159
- | `onToolCall` | `(name, args) => void` | - | Tool call handler |
160
- | `defaultOpen` | `boolean` | `false` | Initial open state |
161
- | `placeholder` | `string` | `'Type a message...'` | Input placeholder |
162
- | `welcomeMessage` | `string` | `'Hi! I'm here to help...'` | Welcome message |
101
+ ## Available Models
163
102
 
164
- #### Theme Options
103
+ Change the `model` string to use any model:
165
104
 
166
- ```typescript
167
- interface SitePilotTheme {
168
- position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
169
- borderRadius?: number;
170
-
171
- // Colors - all accept CSS color values (hex, rgb, hsl)
172
- accentColor?: string; // Primary accent '#f59e0b'
173
- accentColorDark?: string; // Gradient end '#d97706'
174
- backgroundColor?: string; // Panel background '#0F0720'
175
- textColor?: string; // Primary text '#ffffff'
176
- textMutedColor?: string; // Secondary text '#a1a1aa'
177
- borderColor?: string; // Border 'rgba(255,255,255,0.1)'
178
- userMessageBg?: string; // User message bubble
179
- assistantMessageBg?: string; // Assistant message bubble
180
- }
181
- ```
105
+ | Model | ID | Notes |
106
+ |-------|-----|-------|
107
+ | Gemini 2.0 Flash | `google/gemini-2.0-flash-exp:free` | **Free!** |
108
+ | GPT-4o | `openai/gpt-4o` | Best overall |
109
+ | Claude 3.5 Sonnet | `anthropic/claude-3.5-sonnet` | Best for coding |
110
+ | Llama 3.1 70B | `meta-llama/llama-3.1-70b-instruct` | Open source |
182
111
 
183
- #### Feature Toggles
112
+ See all models at [openrouter.ai/models](https://openrouter.ai/models)
184
113
 
185
- ```typescript
186
- interface SitePilotFeatures {
187
- speech?: boolean; // Voice input (default: true)
188
- tts?: boolean; // Text-to-speech (default: true)
189
- fullscreen?: boolean; // Fullscreen mode (default: true)
190
- suggestions?: boolean; // Show suggestions (default: true)
191
- }
192
- ```
114
+ ## API Reference
193
115
 
194
- ### `createGeminiHandler()`
116
+ ### `createHandler()`
195
117
 
196
- Factory for creating Next.js API route handlers using Gemini directly (no AI SDK needed).
118
+ Creates a Next.js API route handler.
197
119
 
198
120
  ```typescript
199
- import { createGeminiHandler } from 'ai-site-pilot/api';
121
+ import { createHandler } from 'ai-site-pilot/api';
200
122
 
201
- export const POST = createGeminiHandler({
202
- apiKey: process.env.GOOGLE_GENERATIVE_AI_API_KEY, // Optional, uses env var by default
203
- model: 'gemini-2.0-flash', // Default: gemini-2.0-flash
123
+ export const POST = createHandler({
124
+ // Required
204
125
  systemPrompt: 'You are a helpful assistant...',
126
+
127
+ // Optional
128
+ apiKey: process.env.OPENROUTER_API_KEY, // Uses env var by default
129
+ model: 'google/gemini-2.0-flash-exp:free', // Default
205
130
  tools: [myTool1, myTool2],
206
131
  temperature: 0.7,
132
+ siteUrl: 'https://mysite.com', // Shown in OpenRouter dashboard
133
+ siteName: 'My Site',
207
134
  });
208
135
  ```
209
136
 
210
- ### `createChatHandler()`
211
-
212
- Factory for creating Next.js API route handlers using Vercel AI SDK.
137
+ ### `<SitePilot />`
213
138
 
214
- ```typescript
215
- import { createChatHandler } from 'ai-site-pilot/api';
139
+ Main chat widget component.
216
140
 
217
- export const POST = createChatHandler({
218
- model: google('gemini-2.0-flash'), // Any Vercel AI SDK model
219
- systemPrompt: 'You are a helpful assistant...',
220
- tools: [myTool1, myTool2],
221
- temperature: 0.7,
222
- maxTokens: 1000,
223
- });
141
+ ```tsx
142
+ <SitePilot
143
+ apiEndpoint="/api/chat"
144
+ suggestions={[{ text: 'Help me', icon: '❓' }]}
145
+ onToolCall={(name, args) => { /* handle tool calls */ }}
146
+ theme={{ accent: 'pink' }} // or accentColor: '#ec4899'
147
+ features={{ speech: true, tts: true }}
148
+ welcomeMessage="Hi! How can I help?"
149
+ placeholder="Type a message..."
150
+ defaultOpen={false}
151
+ />
224
152
  ```
225
153
 
154
+ ### Theme Presets
155
+
156
+ Use the `accent` prop for easy theming:
157
+
158
+ | Preset | Color |
159
+ |--------|-------|
160
+ | `amber` | Default orange/amber |
161
+ | `pink` | Hot pink |
162
+ | `blue` | Primary blue |
163
+ | `green` | Emerald green |
164
+ | `purple` | Violet purple |
165
+ | `red` | Coral red |
166
+ | `cyan` | Teal cyan |
167
+ | `orange` | Bright orange |
168
+
169
+ Or use `accentColor` with any hex color: `accentColor: '#8b5cf6'`
170
+
226
171
  ### `defineTool()`
227
172
 
228
- Helper for defining tools with type safety.
173
+ Helper for defining tools.
229
174
 
230
175
  ```typescript
231
176
  import { defineTool } from 'ai-site-pilot/tools';
@@ -241,166 +186,21 @@ const searchTool = defineTool({
241
186
  },
242
187
  required: ['query'],
243
188
  },
244
- handler: async ({ query, category }) => {
245
- // Client-side handler (optional)
246
- const results = await searchProducts(query, category);
247
- displayResults(results);
248
- },
249
189
  });
250
190
  ```
251
191
 
252
- ### `useChat()`
253
-
254
- Hook for custom chat implementations.
255
-
256
- ```typescript
257
- import { useChat } from 'ai-site-pilot/hooks';
258
-
259
- function MyCustomChat() {
260
- const {
261
- messages,
262
- input,
263
- setInput,
264
- isLoading,
265
- sendMessage,
266
- clearMessages,
267
- } = useChat({
268
- apiEndpoint: '/api/chat',
269
- onToolCall: (name, args) => {
270
- // Handle tool calls
271
- },
272
- });
273
-
274
- return (
275
- // Your custom UI
276
- );
277
- }
278
- ```
279
-
280
- ## Styling
281
-
282
- ### CSS Variables
283
-
284
- Override these variables to customize the appearance:
285
-
286
- ```css
287
- .pilot-container {
288
- --pilot-accent-h: 38; /* Hue */
289
- --pilot-accent-s: 92%; /* Saturation */
290
- --pilot-accent-l: 50%; /* Lightness */
291
- --pilot-bg: #0F0720; /* Background */
292
- --pilot-text: #ffffff; /* Text color */
293
- --pilot-text-muted: #a1a1aa; /* Muted text */
294
- --pilot-border: rgba(255, 255, 255, 0.1);
295
- --pilot-radius: 24px;
296
- }
297
- ```
298
-
299
- ### Tailwind Integration
300
-
301
- If using Tailwind, you can extend your config:
302
-
303
- ```javascript
304
- // tailwind.config.js
305
- module.exports = {
306
- theme: {
307
- extend: {
308
- colors: {
309
- pilot: {
310
- accent: 'hsl(var(--pilot-accent-h), var(--pilot-accent-s), var(--pilot-accent-l))',
311
- },
312
- },
313
- },
314
- },
315
- };
316
- ```
317
-
318
- ## Use Cases
319
-
320
- ### E-commerce
321
-
322
- ```typescript
323
- const tools = [
324
- defineTool({
325
- name: 'search_products',
326
- description: 'Search product catalog',
327
- parameters: { /* ... */ },
328
- }),
329
- defineTool({
330
- name: 'add_to_cart',
331
- description: 'Add item to shopping cart',
332
- parameters: { /* ... */ },
333
- }),
334
- defineTool({
335
- name: 'show_category',
336
- description: 'Filter products by category',
337
- parameters: { /* ... */ },
338
- }),
339
- ];
340
- ```
341
-
342
- ### Documentation Sites
343
-
344
- ```typescript
345
- const tools = [
346
- defineTool({
347
- name: 'search_docs',
348
- description: 'Search documentation',
349
- parameters: { /* ... */ },
350
- }),
351
- defineTool({
352
- name: 'navigate_to_page',
353
- description: 'Go to a documentation page',
354
- parameters: { /* ... */ },
355
- }),
356
- ];
357
- ```
358
-
359
- ### Portfolio Sites
360
-
361
- ```typescript
362
- const tools = [
363
- defineTool({
364
- name: 'open_project',
365
- description: 'Open project details modal',
366
- parameters: { /* ... */ },
367
- }),
368
- defineTool({
369
- name: 'filter_by_category',
370
- description: 'Filter projects by category',
371
- parameters: { /* ... */ },
372
- }),
373
- ];
374
- ```
375
-
376
192
  ## Custom API Implementation
377
193
 
378
- If you need to implement your own API route (e.g., using a different AI provider), the widget expects Server-Sent Events (SSE) in this format:
379
-
380
- ### SSE Streaming Format
194
+ If you need to use a different AI provider, implement this SSE format:
381
195
 
382
196
  ```
383
197
  data: {"type":"text","content":"Hello, "}
384
-
385
198
  data: {"type":"text","content":"how can I help?"}
386
-
387
199
  data: {"type":"tool","name":"navigate","args":{"section":"products"}}
388
-
389
200
  data: {"type":"done"}
390
201
  ```
391
202
 
392
- #### Event Types
393
-
394
- | Type | Description | Example |
395
- |------|-------------|---------|
396
- | `text` | Streaming text chunk | `{"type":"text","content":"Hello"}` |
397
- | `tool` | Tool/function call | `{"type":"tool","name":"navigate","args":{"section":"home"}}` |
398
- | `done` | Stream complete | `{"type":"done"}` |
399
- | `error` | Error occurred | `{"type":"error","message":"Something went wrong"}` |
400
-
401
- ### SSE Utilities
402
-
403
- Use the built-in SSE helpers for custom implementations:
203
+ Use the built-in SSE helpers:
404
204
 
405
205
  ```typescript
406
206
  import { createSSEEncoder, getSSEHeaders } from 'ai-site-pilot/api';
@@ -410,13 +210,8 @@ export async function POST(req: Request) {
410
210
 
411
211
  const stream = new ReadableStream({
412
212
  async start(controller) {
413
- // Stream text
414
213
  controller.enqueue(sse.encodeText('Hello!'));
415
-
416
- // Send tool call
417
214
  controller.enqueue(sse.encodeTool('navigate', { section: 'products' }));
418
-
419
- // Done
420
215
  controller.enqueue(sse.encodeDone());
421
216
  controller.close();
422
217
  },
@@ -428,15 +223,14 @@ export async function POST(req: Request) {
428
223
 
429
224
  ## Handling Tool-Only Responses
430
225
 
431
- When the AI calls tools without providing text, you can customize the fallback message:
226
+ When the AI calls tools without text, customize the fallback:
432
227
 
433
228
  ```typescript
434
229
  import { SitePilot, createFallbackMessageGenerator } from 'ai-site-pilot';
435
230
 
436
231
  const generateFallback = createFallbackMessageGenerator({
437
- navigate: (args) => `Scrolled to **${args.section}** section.`,
438
- filter_products: (args) => `Showing **${args.category}** products.`,
439
- search: (args) => `Found results for "${args.query}".`,
232
+ navigate: (args) => `Scrolled to **${args.section}**.`,
233
+ filter: (args) => `Showing **${args.category}** items.`,
440
234
  });
441
235
 
442
236
  <SitePilot
@@ -449,9 +243,7 @@ const generateFallback = createFallbackMessageGenerator({
449
243
 
450
244
  - React 18+ or React 19
451
245
  - Next.js 13+ (for API routes)
452
- - One of:
453
- - `@google/genai` (Gemini direct - recommended)
454
- - `ai` + provider package (Vercel AI SDK)
246
+ - OpenRouter API key (free at [openrouter.ai](https://openrouter.ai))
455
247
 
456
248
  ## License
457
249
 
@@ -1,66 +1,16 @@
1
- import { LanguageModel } from 'ai';
2
1
  import { T as ToolDefinition } from '../types--7jDyUM6.mjs';
3
- import { S as StreamEvent } from '../types-K00dDlBC.mjs';
2
+ import { S as StreamEvent } from '../types-UmyDfs25.mjs';
4
3
 
5
4
  /**
6
- * Factory for creating Next.js API route handlers
5
+ * Universal chat handler using OpenRouter
6
+ * Works with any model: Gemini, GPT-4, Claude, Llama, etc.
7
+ * No SDK required - just standard fetch.
7
8
  */
8
9
 
9
- interface ChatHandlerConfig {
10
- /** The AI model to use (from Vercel AI SDK) */
11
- model: LanguageModel;
12
- /** System prompt for the AI */
13
- systemPrompt: string;
14
- /** Tool definitions for the AI */
15
- tools?: ToolDefinition[];
16
- /** Temperature for response generation (0-1) */
17
- temperature?: number;
18
- /** Maximum tokens in response */
19
- maxTokens?: number;
20
- }
21
- /**
22
- * Create a Next.js API route handler for chat
23
- *
24
- * Works with any Vercel AI SDK compatible model including:
25
- * - Google Gemini (@ai-sdk/google)
26
- * - OpenAI (@ai-sdk/openai)
27
- * - Anthropic (@ai-sdk/anthropic)
28
- * - And more...
29
- *
30
- * @example
31
- * ```ts
32
- * // app/api/chat/route.ts
33
- * import { createChatHandler } from 'ai-site-pilot/api';
34
- * import { google } from '@ai-sdk/google';
35
- *
36
- * export const POST = createChatHandler({
37
- * model: google('gemini-2.0-flash'),
38
- * systemPrompt: 'You are a helpful assistant...',
39
- * tools: myTools,
40
- * });
41
- * ```
42
- *
43
- * @example Using OpenAI
44
- * ```ts
45
- * import { openai } from '@ai-sdk/openai';
46
- *
47
- * export const POST = createChatHandler({
48
- * model: openai('gpt-4o'),
49
- * systemPrompt: 'You are a helpful assistant...',
50
- * });
51
- * ```
52
- */
53
- declare function createChatHandler(config: ChatHandlerConfig): (req: Request) => Promise<Response>;
54
-
55
- /**
56
- * Gemini-specific handler using @google/genai directly
57
- * No Vercel AI SDK required!
58
- */
59
-
60
- interface GeminiHandlerConfig {
61
- /** Google AI API key (or set GOOGLE_GENERATIVE_AI_API_KEY env var) */
10
+ interface HandlerConfig {
11
+ /** OpenRouter API key (or set OPENROUTER_API_KEY env var) */
62
12
  apiKey?: string;
63
- /** Gemini model to use (default: gemini-2.0-flash) */
13
+ /** Model to use (e.g., 'google/gemini-2.0-flash-exp:free', 'openai/gpt-4o', 'anthropic/claude-3.5-sonnet') */
64
14
  model?: string;
65
15
  /** System prompt for the AI */
66
16
  systemPrompt: string;
@@ -68,27 +18,33 @@ interface GeminiHandlerConfig {
68
18
  tools?: ToolDefinition[];
69
19
  /** Temperature for response generation (0-1) */
70
20
  temperature?: number;
21
+ /** Your site URL (shown in OpenRouter dashboard) */
22
+ siteUrl?: string;
23
+ /** Your app name (shown in OpenRouter dashboard) */
24
+ siteName?: string;
71
25
  }
72
26
  /**
73
- * Create a Next.js API route handler for Gemini
27
+ * Create a Next.js API route handler using OpenRouter
74
28
  *
75
- * Uses @google/genai directly - no Vercel AI SDK required!
76
- * Works with Gemini 2.0+ models.
29
+ * Works with any model - just change the model string:
30
+ * - 'google/gemini-2.0-flash-exp:free' (free!)
31
+ * - 'openai/gpt-4o'
32
+ * - 'anthropic/claude-3.5-sonnet'
33
+ * - 'meta-llama/llama-3.1-70b-instruct'
77
34
  *
78
35
  * @example
79
36
  * ```ts
80
37
  * // app/api/chat/route.ts
81
- * import { createGeminiHandler } from 'ai-site-pilot/api';
38
+ * import { createHandler } from 'ai-site-pilot/api';
82
39
  *
83
- * export const POST = createGeminiHandler({
84
- * apiKey: process.env.GOOGLE_GENERATIVE_AI_API_KEY,
85
- * model: 'gemini-2.0-flash',
40
+ * export const POST = createHandler({
41
+ * model: 'google/gemini-2.0-flash-exp:free',
86
42
  * systemPrompt: 'You are a helpful assistant...',
87
43
  * tools: myTools,
88
44
  * });
89
45
  * ```
90
46
  */
91
- declare function createGeminiHandler(config: GeminiHandlerConfig): (req: Request) => Promise<Response>;
47
+ declare function createHandler(config: HandlerConfig): (req: Request) => Promise<Response>;
92
48
 
93
49
  /**
94
50
  * SSE streaming utilities
@@ -113,4 +69,4 @@ declare function getSSEHeaders(): HeadersInit;
113
69
  */
114
70
  declare function parseSSEStream(reader: ReadableStreamDefaultReader<Uint8Array>): AsyncGenerator<StreamEvent>;
115
71
 
116
- export { type ChatHandlerConfig, type GeminiHandlerConfig, createChatHandler, createGeminiHandler, createSSEEncoder, getSSEHeaders, parseSSEStream };
72
+ export { type HandlerConfig, createHandler, createSSEEncoder, getSSEHeaders, parseSSEStream };