@aeye/openrouter 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +556 -0
- package/dist/__integration__/openrouter.integration.test.d.ts +8 -0
- package/dist/__integration__/openrouter.integration.test.d.ts.map +1 -0
- package/dist/__integration__/openrouter.integration.test.js +203 -0
- package/dist/__integration__/openrouter.integration.test.js.map +1 -0
- package/dist/__integration__/setup.d.ts +7 -0
- package/dist/__integration__/setup.d.ts.map +1 -0
- package/dist/__integration__/setup.js +26 -0
- package/dist/__integration__/setup.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/openrouter.d.ts +100 -0
- package/dist/openrouter.d.ts.map +1 -0
- package/dist/openrouter.js +315 -0
- package/dist/openrouter.js.map +1 -0
- package/dist/source.d.ts +34 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +77 -0
- package/dist/source.js.map +1 -0
- package/dist/types.d.ts +178 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
# @aeye/openrouter
|
|
2
|
+
|
|
3
|
+
OpenRouter provider for the @aeye (AI TypeScript) framework. OpenRouter provides unified access to multiple AI providers through a single API, with automatic fallbacks, routing optimization, and competitive pricing.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Multi-Provider Access**: Access models from OpenAI, Anthropic, Google, Meta, and more through one API
|
|
8
|
+
- **Automatic Fallbacks**: Seamless failover to alternative providers if primary fails
|
|
9
|
+
- **Intelligent Routing**: Automatic selection of best provider for each request
|
|
10
|
+
- **Cost Tracking**: Built-in cost information in responses
|
|
11
|
+
- **ZDR Support**: Zero Data Retention mode for privacy-sensitive applications
|
|
12
|
+
- **Provider Preferences**: Control which providers to use, prefer, or avoid
|
|
13
|
+
- **Reasoning Models**: Support for advanced reasoning with o1, Claude, and others
|
|
14
|
+
- **Streaming**: Full streaming support across compatible models
|
|
15
|
+
- **Extends OpenAI**: Built on the OpenAI provider for compatibility
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @aeye/openrouter @aeye/openai @aeye/ai @aeye/core openai zod
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { OpenRouterProvider } from '@aeye/openrouter';
|
|
27
|
+
import { AI } from '@aeye/ai';
|
|
28
|
+
|
|
29
|
+
// Create provider instance
|
|
30
|
+
const openrouter = new OpenRouterProvider({
|
|
31
|
+
apiKey: process.env.OPENROUTER_API_KEY!,
|
|
32
|
+
defaultParams: {
|
|
33
|
+
siteUrl: 'https://yourapp.com',
|
|
34
|
+
appName: 'Your App Name',
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Use with AI instance
|
|
39
|
+
const ai = AI.with()
|
|
40
|
+
.providers({ openrouter })
|
|
41
|
+
.create();
|
|
42
|
+
|
|
43
|
+
// Make a request (OpenRouter picks the best provider)
|
|
44
|
+
const response = await ai.chat.get([
|
|
45
|
+
{ role: 'user', content: 'Explain TypeScript generics' }
|
|
46
|
+
], {
|
|
47
|
+
metadata: { model: 'openai/gpt-4-turbo' }
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
console.log(response.content);
|
|
51
|
+
console.log('Cost:', response.usage.cost); // Actual cost from OpenRouter
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Configuration
|
|
55
|
+
|
|
56
|
+
### Basic Configuration
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import { OpenRouterProvider, OpenRouterConfig } from '@aeye/openrouter';
|
|
60
|
+
|
|
61
|
+
const config: OpenRouterConfig = {
|
|
62
|
+
apiKey: process.env.OPENROUTER_API_KEY!,
|
|
63
|
+
defaultParams: {
|
|
64
|
+
siteUrl: 'https://yourapp.com', // Your app URL (helps with rankings)
|
|
65
|
+
appName: 'My AI App', // Your app name (shown in OpenRouter dashboard)
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const provider = new OpenRouterProvider(config);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Advanced Configuration
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
const provider = new OpenRouterProvider({
|
|
76
|
+
apiKey: process.env.OPENROUTER_API_KEY!,
|
|
77
|
+
defaultParams: {
|
|
78
|
+
siteUrl: 'https://yourapp.com',
|
|
79
|
+
appName: 'My AI App',
|
|
80
|
+
|
|
81
|
+
// Automatic fallbacks
|
|
82
|
+
allowFallbacks: true, // Enable fallback to alternative providers
|
|
83
|
+
|
|
84
|
+
// Provider preferences
|
|
85
|
+
providers: {
|
|
86
|
+
prefer: ['openai', 'anthropic'], // Prefer these providers
|
|
87
|
+
allow: ['openai', 'anthropic', 'google'], // Only use these providers
|
|
88
|
+
deny: ['provider-x'], // Never use these providers
|
|
89
|
+
ignore: ['low-quality-provider'], // Exclude from consideration
|
|
90
|
+
order: ['openai', 'anthropic'], // Preferred order
|
|
91
|
+
quantizations: ['int8', 'fp16'], // Preferred quantization levels
|
|
92
|
+
dataCollection: 'deny', // or 'allow' - control data collection
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
// Privacy & security
|
|
96
|
+
requireParameters: true, // Require all providers to support parameters
|
|
97
|
+
dataCollection: 'deny', // Global data collection setting
|
|
98
|
+
|
|
99
|
+
// Model transformations
|
|
100
|
+
transforms: ['middle-out'], // Apply transformations to requests
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Usage Examples
|
|
106
|
+
|
|
107
|
+
### Basic Chat with Cost Tracking
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
const response = await ai.chat.get([
|
|
111
|
+
{ role: 'user', content: 'What is the capital of France?' }
|
|
112
|
+
], {
|
|
113
|
+
metadata: { model: 'openai/gpt-3.5-turbo' }
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
console.log(response.content);
|
|
117
|
+
console.log('Tokens:', response.usage.totalTokens);
|
|
118
|
+
console.log('Cost: $', response.usage.cost); // Actual cost from OpenRouter
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Using Multiple Models
|
|
122
|
+
|
|
123
|
+
OpenRouter allows you to access models from different providers using the format `provider/model`:
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
// OpenAI GPT-4
|
|
127
|
+
const gpt4 = await ai.chat.get(messages, {
|
|
128
|
+
metadata: { model: 'openai/gpt-4-turbo' }
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Anthropic Claude
|
|
132
|
+
const claude = await ai.chat.get(messages, {
|
|
133
|
+
metadata: { model: 'anthropic/claude-3-opus' }
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// Google Gemini
|
|
137
|
+
const gemini = await ai.chat.get(messages, {
|
|
138
|
+
metadata: { model: 'google/gemini-pro' }
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// Meta Llama
|
|
142
|
+
const llama = await ai.chat.get(messages, {
|
|
143
|
+
metadata: { model: 'meta-llama/llama-3-70b' }
|
|
144
|
+
});
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Automatic Model Selection
|
|
148
|
+
|
|
149
|
+
Let OpenRouter choose the best model based on your criteria:
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
const ai = AI.with()
|
|
153
|
+
.providers({ openrouter })
|
|
154
|
+
.create({
|
|
155
|
+
defaultMetadata: {
|
|
156
|
+
required: ['chat', 'streaming'],
|
|
157
|
+
weights: {
|
|
158
|
+
speed: 0.3,
|
|
159
|
+
cost: 0.4,
|
|
160
|
+
quality: 0.3,
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// OpenRouter will select the best model matching criteria
|
|
166
|
+
const response = await ai.chat.get([
|
|
167
|
+
{ role: 'user', content: 'Explain quantum computing' }
|
|
168
|
+
]);
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Provider Fallbacks
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
// Primary provider fails? OpenRouter automatically falls back
|
|
175
|
+
const provider = new OpenRouterProvider({
|
|
176
|
+
apiKey: process.env.OPENROUTER_API_KEY!,
|
|
177
|
+
defaultParams: {
|
|
178
|
+
allowFallbacks: true,
|
|
179
|
+
providers: {
|
|
180
|
+
order: ['openai', 'anthropic', 'google'], // Try in this order
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// If OpenAI is down, automatically tries Anthropic, then Google
|
|
186
|
+
const response = await ai.chat.get(messages, {
|
|
187
|
+
metadata: { model: 'openai/gpt-4-turbo' }
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Zero Data Retention (ZDR)
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
// Only use ZDR-compliant models
|
|
195
|
+
const ai = AI.with()
|
|
196
|
+
.providers({ openrouter })
|
|
197
|
+
.create({
|
|
198
|
+
defaultMetadata: {
|
|
199
|
+
required: ['chat', 'zdr'], // Require ZDR support
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// Also configure at provider level
|
|
204
|
+
const provider = new OpenRouterProvider({
|
|
205
|
+
apiKey: process.env.OPENROUTER_API_KEY!,
|
|
206
|
+
defaultParams: {
|
|
207
|
+
dataCollection: 'deny', // Ensure no data collection
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Streaming with Cost Tracking
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
let totalCost = 0;
|
|
216
|
+
|
|
217
|
+
for await (const chunk of ai.chat.stream([
|
|
218
|
+
{ role: 'user', content: 'Write a story about a robot' }
|
|
219
|
+
], {
|
|
220
|
+
metadata: { model: 'anthropic/claude-3-sonnet' }
|
|
221
|
+
})) {
|
|
222
|
+
if (chunk.content) {
|
|
223
|
+
process.stdout.write(chunk.content);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Cost is sent in final chunk
|
|
227
|
+
if (chunk.usage?.cost) {
|
|
228
|
+
totalCost = chunk.usage.cost;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
console.log(`\n\nTotal cost: $${totalCost}`);
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Reasoning Models
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
// Use OpenAI o1 through OpenRouter
|
|
239
|
+
const response = await ai.chat.get([
|
|
240
|
+
{
|
|
241
|
+
role: 'user',
|
|
242
|
+
content: 'Solve: If a train leaves NYC at 3pm going 60mph, and another leaves Boston at 4pm going 80mph, when do they meet?'
|
|
243
|
+
}
|
|
244
|
+
], {
|
|
245
|
+
metadata: { model: 'openai/o1-preview' }
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
console.log('Reasoning:', response.reasoning);
|
|
249
|
+
console.log('Answer:', response.content);
|
|
250
|
+
console.log('Cost:', response.usage.cost);
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Function Calling
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
import z from 'zod';
|
|
257
|
+
|
|
258
|
+
const response = await ai.chat.get([
|
|
259
|
+
{ role: 'user', content: 'What is the weather in Paris?' }
|
|
260
|
+
], {
|
|
261
|
+
metadata: { model: 'openai/gpt-4-turbo' },
|
|
262
|
+
tools: [
|
|
263
|
+
{
|
|
264
|
+
name: 'get_weather',
|
|
265
|
+
description: 'Get current weather for a location',
|
|
266
|
+
parameters: z.object({
|
|
267
|
+
location: z.string(),
|
|
268
|
+
unit: z.enum(['celsius', 'fahrenheit']).optional(),
|
|
269
|
+
}),
|
|
270
|
+
}
|
|
271
|
+
],
|
|
272
|
+
toolChoice: 'auto',
|
|
273
|
+
});
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Fetching Available Models
|
|
277
|
+
|
|
278
|
+
OpenRouter provides a model source that can fetch all available models:
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
import { OpenRouterModelSource } from '@aeye/openrouter';
|
|
282
|
+
|
|
283
|
+
const source = new OpenRouterModelSource({
|
|
284
|
+
apiKey: process.env.OPENROUTER_API_KEY,
|
|
285
|
+
includeZDR: true, // Include ZDR information
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
const models = await source.fetchModels();
|
|
289
|
+
|
|
290
|
+
models.forEach(model => {
|
|
291
|
+
console.log(`${model.id}`);
|
|
292
|
+
console.log(` Pricing: $${model.pricing.inputTokensPer1M}/1M input tokens`);
|
|
293
|
+
console.log(` Context: ${model.contextWindow} tokens`);
|
|
294
|
+
console.log(` ZDR: ${model.capabilities.has('zdr')}`);
|
|
295
|
+
});
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Automatic Model Registration
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
// Automatically fetch and register OpenRouter models
|
|
302
|
+
const ai = AI.with()
|
|
303
|
+
.providers({ openrouter })
|
|
304
|
+
.create({
|
|
305
|
+
fetchOpenRouterModels: true, // Auto-fetch all available models
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// Now all OpenRouter models are available for automatic selection
|
|
309
|
+
const response = await ai.chat.get(messages);
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## Configuration Options
|
|
313
|
+
|
|
314
|
+
### OpenRouterConfig
|
|
315
|
+
|
|
316
|
+
Extends `OpenAIConfig` from `@aeye/openai`.
|
|
317
|
+
|
|
318
|
+
| Property | Type | Required | Description |
|
|
319
|
+
|----------|------|----------|-------------|
|
|
320
|
+
| `apiKey` | `string` | Yes | OpenRouter API key |
|
|
321
|
+
| `baseURL` | `string` | No | Custom base URL (defaults to https://openrouter.ai/api/v1) |
|
|
322
|
+
| `defaultParams` | `object` | No | Default parameters for all requests |
|
|
323
|
+
|
|
324
|
+
### defaultParams
|
|
325
|
+
|
|
326
|
+
| Property | Type | Description |
|
|
327
|
+
|----------|------|-------------|
|
|
328
|
+
| `siteUrl` | `string` | Your app URL (helps with rankings on OpenRouter) |
|
|
329
|
+
| `appName` | `string` | Your app name (shown in OpenRouter dashboard) |
|
|
330
|
+
| `allowFallbacks` | `boolean` | Enable automatic provider fallbacks |
|
|
331
|
+
| `requireParameters` | `boolean` | Require all providers support parameters |
|
|
332
|
+
| `dataCollection` | `'deny' \| 'allow'` | Control data collection |
|
|
333
|
+
| `order` | `string[]` | Preferred provider order |
|
|
334
|
+
| `providers` | `object` | Provider preferences (see below) |
|
|
335
|
+
| `transforms` | `string[]` | Request transformations to apply |
|
|
336
|
+
|
|
337
|
+
### providers Options
|
|
338
|
+
|
|
339
|
+
| Property | Type | Description |
|
|
340
|
+
|----------|------|-------------|
|
|
341
|
+
| `allow` | `string[]` | Whitelist of allowed providers |
|
|
342
|
+
| `deny` | `string[]` | Blacklist of denied providers |
|
|
343
|
+
| `prefer` | `string[]` | Preferred providers (given priority) |
|
|
344
|
+
| `ignore` | `string[]` | Providers to ignore |
|
|
345
|
+
| `order` | `string[]` | Explicit provider order |
|
|
346
|
+
| `quantizations` | `string[]` | Preferred quantization levels |
|
|
347
|
+
| `dataCollection` | `'deny' \| 'allow'` | Provider-level data collection |
|
|
348
|
+
|
|
349
|
+
## Cost Information
|
|
350
|
+
|
|
351
|
+
OpenRouter includes actual cost information in every response:
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
const response = await ai.chat.get(messages, {
|
|
355
|
+
metadata: { model: 'openai/gpt-4-turbo' }
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// Cost is automatically included
|
|
359
|
+
console.log('Input tokens:', response.usage.inputTokens);
|
|
360
|
+
console.log('Output tokens:', response.usage.outputTokens);
|
|
361
|
+
console.log('Cost: $', response.usage.cost); // Actual USD cost
|
|
362
|
+
|
|
363
|
+
// Cost calculation is skipped when provider returns cost
|
|
364
|
+
// No need to manually calculate costs!
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
The cost is provided by OpenRouter's API in the `total_cost` field and automatically extracted into the `usage.cost` field.
|
|
368
|
+
|
|
369
|
+
## Model Format
|
|
370
|
+
|
|
371
|
+
OpenRouter uses the format `provider/model-name`:
|
|
372
|
+
|
|
373
|
+
- `openai/gpt-4-turbo`
|
|
374
|
+
- `anthropic/claude-3-opus`
|
|
375
|
+
- `google/gemini-pro`
|
|
376
|
+
- `meta-llama/llama-3-70b-instruct`
|
|
377
|
+
- `mistralai/mistral-large`
|
|
378
|
+
- `cohere/command-r-plus`
|
|
379
|
+
|
|
380
|
+
See the [OpenRouter Models](https://openrouter.ai/models) page for the full list.
|
|
381
|
+
|
|
382
|
+
## Privacy & Data Retention
|
|
383
|
+
|
|
384
|
+
### Zero Data Retention (ZDR)
|
|
385
|
+
|
|
386
|
+
OpenRouter supports ZDR mode where your data is not stored:
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
// Require ZDR-compliant models
|
|
390
|
+
const ai = AI.with()
|
|
391
|
+
.providers({ openrouter })
|
|
392
|
+
.create({
|
|
393
|
+
defaultMetadata: {
|
|
394
|
+
required: ['chat', 'zdr'],
|
|
395
|
+
},
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
// Or configure at provider level
|
|
399
|
+
const provider = new OpenRouterProvider({
|
|
400
|
+
apiKey: process.env.OPENROUTER_API_KEY!,
|
|
401
|
+
defaultParams: {
|
|
402
|
+
dataCollection: 'deny',
|
|
403
|
+
providers: {
|
|
404
|
+
dataCollection: 'deny',
|
|
405
|
+
},
|
|
406
|
+
},
|
|
407
|
+
});
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
Models with ZDR support have the `zdr` capability tag.
|
|
411
|
+
|
|
412
|
+
## Error Handling
|
|
413
|
+
|
|
414
|
+
OpenRouter uses the same error types as the OpenAI provider:
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
import { ProviderError, RateLimitError } from '@aeye/openrouter';
|
|
418
|
+
|
|
419
|
+
try {
|
|
420
|
+
const response = await ai.chat.get(messages, {
|
|
421
|
+
metadata: { model: 'openai/gpt-4-turbo' }
|
|
422
|
+
});
|
|
423
|
+
} catch (error) {
|
|
424
|
+
if (error instanceof RateLimitError) {
|
|
425
|
+
console.error('Rate limit exceeded');
|
|
426
|
+
console.log(`Retry after ${error.retryAfter} seconds`);
|
|
427
|
+
} else if (error instanceof ProviderError) {
|
|
428
|
+
console.error(`Provider error: ${error.message}`);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
## Best Practices
|
|
434
|
+
|
|
435
|
+
1. **Set Site URL and App Name**: This helps with OpenRouter rankings and analytics
|
|
436
|
+
```typescript
|
|
437
|
+
defaultParams: {
|
|
438
|
+
siteUrl: 'https://yourapp.com',
|
|
439
|
+
appName: 'Your App',
|
|
440
|
+
}
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
2. **Use Cost Tracking**: Monitor costs with the built-in `usage.cost` field
|
|
444
|
+
```typescript
|
|
445
|
+
console.log('Cost: $', response.usage.cost);
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
3. **Enable Fallbacks**: Use automatic fallbacks for reliability
|
|
449
|
+
```typescript
|
|
450
|
+
defaultParams: {
|
|
451
|
+
allowFallbacks: true,
|
|
452
|
+
providers: {
|
|
453
|
+
order: ['openai', 'anthropic', 'google'],
|
|
454
|
+
},
|
|
455
|
+
}
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
4. **Specify Provider Preferences**: Control which providers are used
|
|
459
|
+
```typescript
|
|
460
|
+
providers: {
|
|
461
|
+
prefer: ['openai', 'anthropic'],
|
|
462
|
+
deny: ['low-quality-provider'],
|
|
463
|
+
}
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
5. **Use ZDR for Sensitive Data**: Enable Zero Data Retention for privacy
|
|
467
|
+
```typescript
|
|
468
|
+
defaultParams: {
|
|
469
|
+
dataCollection: 'deny',
|
|
470
|
+
}
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
6. **Monitor Model Availability**: OpenRouter's model list changes frequently
|
|
474
|
+
```typescript
|
|
475
|
+
fetchOpenRouterModels: true // Auto-fetch latest models
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
## API Reference
|
|
479
|
+
|
|
480
|
+
### OpenRouterProvider
|
|
481
|
+
|
|
482
|
+
Extends `OpenAIProvider` from `@aeye/openai`.
|
|
483
|
+
|
|
484
|
+
**Constructor**: `new OpenRouterProvider(config: OpenRouterConfig)`
|
|
485
|
+
|
|
486
|
+
**Methods**:
|
|
487
|
+
- Inherits all methods from `OpenAIProvider`
|
|
488
|
+
- `createExecutor<TContext, TMetadata>(config?)` - Returns executor with cost tracking
|
|
489
|
+
- `createStreamer<TContext, TMetadata>(config?)` - Returns streamer with cost tracking
|
|
490
|
+
- `listModels(config?)` - Fetches models from OpenRouter API with ZDR info
|
|
491
|
+
|
|
492
|
+
**Overridden Methods**:
|
|
493
|
+
- `createClient(config)` - Creates OpenAI client with OpenRouter endpoint
|
|
494
|
+
- `customizeChatParams(params, config, request)` - Adds OpenRouter-specific params
|
|
495
|
+
|
|
496
|
+
### OpenRouterModelSource
|
|
497
|
+
|
|
498
|
+
Model source for fetching OpenRouter models.
|
|
499
|
+
|
|
500
|
+
**Constructor**: `new OpenRouterModelSource(config?: OpenRouterSourceConfig)`
|
|
501
|
+
|
|
502
|
+
**Methods**:
|
|
503
|
+
- `fetchModels(config?): Promise<ModelInfo[]>` - Fetch all available models
|
|
504
|
+
|
|
505
|
+
**Config Options**:
|
|
506
|
+
- `apiKey?: string` - OpenRouter API key (optional for public models)
|
|
507
|
+
- `includeZDR?: boolean` - Include ZDR information (default: true)
|
|
508
|
+
|
|
509
|
+
## Supported Features
|
|
510
|
+
|
|
511
|
+
- ✅ Chat completions
|
|
512
|
+
- ✅ Streaming
|
|
513
|
+
- ✅ Function calling
|
|
514
|
+
- ✅ Vision (for supported models)
|
|
515
|
+
- ✅ Reasoning models
|
|
516
|
+
- ✅ Cost tracking
|
|
517
|
+
- ✅ Automatic fallbacks
|
|
518
|
+
- ✅ Provider routing
|
|
519
|
+
- ✅ ZDR mode
|
|
520
|
+
- ✅ Multi-modal (for supported models)
|
|
521
|
+
- ❌ Image generation (not supported by OpenRouter)
|
|
522
|
+
- ❌ Speech synthesis (not supported by OpenRouter)
|
|
523
|
+
- ❌ Transcription (not supported by OpenRouter)
|
|
524
|
+
- ❌ Embeddings (not supported by OpenRouter)
|
|
525
|
+
|
|
526
|
+
For image generation, speech, transcription, and embeddings, use provider-specific packages like `@aeye/openai`, `@aeye/anthropic`, etc.
|
|
527
|
+
|
|
528
|
+
## Related Packages
|
|
529
|
+
|
|
530
|
+
- **[@aeye/core](../core)**: Core @aeye framework types and interfaces
|
|
531
|
+
- **[@aeye/ai](../ai)**: AI abstractions and utilities
|
|
532
|
+
- **[@aeye/openai](../openai)**: OpenAI provider (base class)
|
|
533
|
+
- **[@aeye/anthropic](../anthropic)**: Anthropic Claude provider
|
|
534
|
+
- **[@aeye/google](../google)**: Google AI provider
|
|
535
|
+
|
|
536
|
+
## Links
|
|
537
|
+
|
|
538
|
+
- [OpenRouter Website](https://openrouter.ai)
|
|
539
|
+
- [OpenRouter Models](https://openrouter.ai/models)
|
|
540
|
+
- [OpenRouter Documentation](https://openrouter.ai/docs)
|
|
541
|
+
- [OpenRouter API Keys](https://openrouter.ai/keys)
|
|
542
|
+
|
|
543
|
+
## License
|
|
544
|
+
|
|
545
|
+
MIT
|
|
546
|
+
|
|
547
|
+
## Contributing
|
|
548
|
+
|
|
549
|
+
Contributions are welcome! Please see the main [@aeye repository](https://github.com/ClickerMonkey/aeye) for contribution guidelines.
|
|
550
|
+
|
|
551
|
+
## Support
|
|
552
|
+
|
|
553
|
+
For issues and questions:
|
|
554
|
+
- GitHub Issues: https://github.com/ClickerMonkey/aeye/issues
|
|
555
|
+
- Documentation: https://github.com/ClickerMonkey/aeye
|
|
556
|
+
- OpenRouter Discord: https://discord.gg/openrouter
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openrouter.integration.test.d.ts","sourceRoot":"","sources":["../../src/__integration__/openrouter.integration.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|