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 +76 -284
- package/dist/api/index.d.mts +22 -66
- package/dist/api/index.d.ts +22 -66
- package/dist/api/index.js +93 -126
- package/dist/api/index.js.map +1 -1
- package/dist/api/index.mjs +93 -125
- package/dist/api/index.mjs.map +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 +55 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +55 -1
- package/dist/index.mjs.map +1 -1
- package/dist/{types-K00dDlBC.d.mts → types-UmyDfs25.d.mts} +5 -1
- package/dist/{types-K00dDlBC.d.ts → types-UmyDfs25.d.ts} +5 -1
- package/package.json +4 -16
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
|
|
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
|
-
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
32
|
+
### 2. Create the API Route
|
|
87
33
|
|
|
88
34
|
```typescript
|
|
89
35
|
// app/api/chat/route.ts
|
|
90
|
-
import {
|
|
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 =
|
|
111
|
-
model: google
|
|
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
|
-
###
|
|
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
|
-
|
|
92
|
+
### 4. Add Environment Variable
|
|
148
93
|
|
|
149
|
-
|
|
94
|
+
```bash
|
|
95
|
+
# .env.local
|
|
96
|
+
OPENROUTER_API_KEY=sk-or-...
|
|
97
|
+
```
|
|
150
98
|
|
|
151
|
-
|
|
99
|
+
That's it!
|
|
152
100
|
|
|
153
|
-
|
|
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
|
-
|
|
103
|
+
Change the `model` string to use any model:
|
|
165
104
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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
|
-
|
|
112
|
+
See all models at [openrouter.ai/models](https://openrouter.ai/models)
|
|
184
113
|
|
|
185
|
-
|
|
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
|
-
### `
|
|
116
|
+
### `createHandler()`
|
|
195
117
|
|
|
196
|
-
|
|
118
|
+
Creates a Next.js API route handler.
|
|
197
119
|
|
|
198
120
|
```typescript
|
|
199
|
-
import {
|
|
121
|
+
import { createHandler } from 'ai-site-pilot/api';
|
|
200
122
|
|
|
201
|
-
export const POST =
|
|
202
|
-
|
|
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
|
-
###
|
|
211
|
-
|
|
212
|
-
Factory for creating Next.js API route handlers using Vercel AI SDK.
|
|
137
|
+
### `<SitePilot />`
|
|
213
138
|
|
|
214
|
-
|
|
215
|
-
import { createChatHandler } from 'ai-site-pilot/api';
|
|
139
|
+
Main chat widget component.
|
|
216
140
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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}
|
|
438
|
-
|
|
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
|
-
-
|
|
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
|
|
package/dist/api/index.d.mts
CHANGED
|
@@ -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-
|
|
2
|
+
import { S as StreamEvent } from '../types-UmyDfs25.mjs';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
|
-
*
|
|
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
|
|
10
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
27
|
+
* Create a Next.js API route handler using OpenRouter
|
|
74
28
|
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
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 {
|
|
38
|
+
* import { createHandler } from 'ai-site-pilot/api';
|
|
82
39
|
*
|
|
83
|
-
* export const POST =
|
|
84
|
-
*
|
|
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
|
|
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
|
|
72
|
+
export { type HandlerConfig, createHandler, createSSEEncoder, getSSEHeaders, parseSSEStream };
|