@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
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenRouter Provider Integration Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests that make REAL API calls to OpenRouter.
|
|
5
|
+
* Requires OPENROUTER_API_KEY environment variable.
|
|
6
|
+
*/
|
|
7
|
+
import { OpenRouterProvider } from '../openrouter';
|
|
8
|
+
import { getAPIKey, skipIfNoAPIKey } from './setup';
|
|
9
|
+
const describeIntegration = skipIfNoAPIKey();
|
|
10
|
+
describeIntegration('OpenRouter Integration', () => {
|
|
11
|
+
let provider;
|
|
12
|
+
beforeAll(() => {
|
|
13
|
+
provider = new OpenRouterProvider({
|
|
14
|
+
apiKey: getAPIKey()
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
describe('Model Listing', () => {
|
|
18
|
+
it('should list real models from OpenRouter', async () => {
|
|
19
|
+
const models = await provider.listModels({
|
|
20
|
+
apiKey: getAPIKey()
|
|
21
|
+
});
|
|
22
|
+
expect(models.length).toBeGreaterThan(0);
|
|
23
|
+
console.log(` Found ${models.length} models`);
|
|
24
|
+
console.log(` Sample: ${models.slice(0, 5).map(m => m.id).join(', ')}`);
|
|
25
|
+
}, 30000);
|
|
26
|
+
it('should include models from multiple providers', async () => {
|
|
27
|
+
const models = await provider.listModels({
|
|
28
|
+
apiKey: getAPIKey()
|
|
29
|
+
});
|
|
30
|
+
// OpenRouter aggregates models from multiple providers
|
|
31
|
+
const providers = new Set(models.map(m => m.id.split('/')[0]));
|
|
32
|
+
expect(providers.size).toBeGreaterThan(1);
|
|
33
|
+
console.log(` Model providers: ${Array.from(providers).slice(0, 5).join(', ')}`);
|
|
34
|
+
}, 30000);
|
|
35
|
+
it('should include model pricing', async () => {
|
|
36
|
+
const models = await provider.listModels({
|
|
37
|
+
apiKey: getAPIKey()
|
|
38
|
+
});
|
|
39
|
+
const modelsWithPricing = models.filter(m => (m.pricing.text?.input || 0) > 0 || (m.pricing.text?.output || 0) > 0);
|
|
40
|
+
expect(modelsWithPricing.length).toBeGreaterThan(0);
|
|
41
|
+
console.log(` Models with pricing: ${modelsWithPricing.length}/${models.length}`);
|
|
42
|
+
}, 30000);
|
|
43
|
+
});
|
|
44
|
+
describe('Health Check', () => {
|
|
45
|
+
it('should pass health check', async () => {
|
|
46
|
+
const isHealthy = await provider.checkHealth();
|
|
47
|
+
expect(isHealthy).toBe(true);
|
|
48
|
+
}, 30000);
|
|
49
|
+
});
|
|
50
|
+
describe('Chat Completion', () => {
|
|
51
|
+
it('should complete a simple chat with a free model', async () => {
|
|
52
|
+
const executor = provider.createExecutor();
|
|
53
|
+
const request = {
|
|
54
|
+
messages: [
|
|
55
|
+
{
|
|
56
|
+
role: 'user',
|
|
57
|
+
content: 'Reply with exactly: "Test successful"'
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
};
|
|
61
|
+
// Use a free model to avoid charges
|
|
62
|
+
const response = await executor(request, {}, { model: 'google/gemini-flash-1.5' });
|
|
63
|
+
expect(response.content).toBeTruthy();
|
|
64
|
+
expect(typeof response.content).toBe('string');
|
|
65
|
+
expect(response.finishReason).toBeTruthy();
|
|
66
|
+
expect(response.usage).toBeDefined();
|
|
67
|
+
console.log(` Response: ${response.content}`);
|
|
68
|
+
const totalTokens = (response.usage?.text?.input || 0) + (response.usage?.text?.output || 0);
|
|
69
|
+
console.log(` Tokens: ${totalTokens}`);
|
|
70
|
+
}, 30000);
|
|
71
|
+
it('should stream chat completion', async () => {
|
|
72
|
+
const streamer = provider.createStreamer();
|
|
73
|
+
const request = {
|
|
74
|
+
messages: [
|
|
75
|
+
{
|
|
76
|
+
role: 'user',
|
|
77
|
+
content: 'Count from 1 to 3'
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
};
|
|
81
|
+
const chunks = [];
|
|
82
|
+
let finalUsage = null;
|
|
83
|
+
for await (const chunk of streamer(request, {}, { model: 'google/gemini-flash-1.5' })) {
|
|
84
|
+
if (chunk.content) {
|
|
85
|
+
chunks.push(chunk.content);
|
|
86
|
+
}
|
|
87
|
+
if (chunk.usage) {
|
|
88
|
+
finalUsage = chunk.usage;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
expect(chunks.length).toBeGreaterThan(0);
|
|
92
|
+
const fullText = chunks.join('');
|
|
93
|
+
console.log(` Received ${chunks.length} chunks`);
|
|
94
|
+
console.log(` Full response: ${fullText}`);
|
|
95
|
+
}, 30000);
|
|
96
|
+
it('should use model from context metadata', async () => {
|
|
97
|
+
const executor = provider.createExecutor();
|
|
98
|
+
const request = {
|
|
99
|
+
messages: [
|
|
100
|
+
{
|
|
101
|
+
role: 'user',
|
|
102
|
+
content: 'Say "hi"'
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
};
|
|
106
|
+
const ctx = {
|
|
107
|
+
metadata: {
|
|
108
|
+
model: 'google/gemini-flash-1.5'
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
const response = await executor(request, ctx, {});
|
|
112
|
+
expect(response.content).toBeTruthy();
|
|
113
|
+
console.log(` Used model from context`);
|
|
114
|
+
console.log(` Response: ${response.content}`);
|
|
115
|
+
}, 30000);
|
|
116
|
+
it('should work with different model providers on OpenRouter', async () => {
|
|
117
|
+
const executor = provider.createExecutor();
|
|
118
|
+
// Test models from different providers available on OpenRouter
|
|
119
|
+
const testModels = [
|
|
120
|
+
'google/gemini-flash-1.5',
|
|
121
|
+
'meta-llama/llama-3.2-3b-instruct:free'
|
|
122
|
+
];
|
|
123
|
+
for (const model of testModels) {
|
|
124
|
+
try {
|
|
125
|
+
const response = await executor({ messages: [{ role: 'user', content: 'Hi' }] }, {}, { model });
|
|
126
|
+
expect(response.content).toBeTruthy();
|
|
127
|
+
console.log(` ${model}: ✓`);
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
console.log(` ${model}: ✗ (${error.message})`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}, 60000);
|
|
134
|
+
});
|
|
135
|
+
describe('Model Selection', () => {
|
|
136
|
+
it('should find free models', async () => {
|
|
137
|
+
const models = await provider.listModels({
|
|
138
|
+
apiKey: getAPIKey()
|
|
139
|
+
});
|
|
140
|
+
const freeModels = models.filter(m => m.pricing.text?.input && !m.pricing.text?.output);
|
|
141
|
+
expect(freeModels.length).toBeGreaterThan(0);
|
|
142
|
+
console.log(` Free models: ${freeModels.length}`);
|
|
143
|
+
console.log(` Examples: ${freeModels.slice(0, 3).map(m => m.id).join(', ')}`);
|
|
144
|
+
}, 30000);
|
|
145
|
+
it('should find models with vision capability', async () => {
|
|
146
|
+
const models = await provider.listModels({
|
|
147
|
+
apiKey: getAPIKey()
|
|
148
|
+
});
|
|
149
|
+
const visionModels = models.filter(m => m.capabilities.has('vision'));
|
|
150
|
+
if (visionModels.length > 0) {
|
|
151
|
+
console.log(` Vision models: ${visionModels.length}`);
|
|
152
|
+
console.log(` Examples: ${visionModels.slice(0, 3).map(m => m.id).join(', ')}`);
|
|
153
|
+
expect(visionModels.length).toBeGreaterThan(0);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
console.log(` No vision models detected (may need API update)`);
|
|
157
|
+
}
|
|
158
|
+
}, 30000);
|
|
159
|
+
});
|
|
160
|
+
describe('Error Handling', () => {
|
|
161
|
+
it('should handle invalid model', async () => {
|
|
162
|
+
const executor = provider.createExecutor();
|
|
163
|
+
const request = {
|
|
164
|
+
messages: [{ role: 'user', content: 'Test' }]
|
|
165
|
+
};
|
|
166
|
+
await expect(executor(request, {}, { model: 'invalid/model/name' })).rejects.toThrow();
|
|
167
|
+
}, 30000);
|
|
168
|
+
it('should handle rate limiting gracefully', async () => {
|
|
169
|
+
const executor = provider.createExecutor();
|
|
170
|
+
const request = {
|
|
171
|
+
messages: [{ role: 'user', content: 'Hi' }]
|
|
172
|
+
};
|
|
173
|
+
// Make multiple rapid requests using free model
|
|
174
|
+
const promises = Array(3).fill(null).map(() => executor(request, {}, { model: 'google/gemini-flash-1.5' }));
|
|
175
|
+
// At least some should succeed
|
|
176
|
+
const results = await Promise.allSettled(promises);
|
|
177
|
+
const succeeded = results.filter(r => r.status === 'fulfilled').length;
|
|
178
|
+
expect(succeeded).toBeGreaterThan(0);
|
|
179
|
+
console.log(` ${succeeded}/3 requests succeeded`);
|
|
180
|
+
}, 60000);
|
|
181
|
+
});
|
|
182
|
+
describe('Cost Comparison', () => {
|
|
183
|
+
it('should show cost range across available models', async () => {
|
|
184
|
+
const models = await provider.listModels({
|
|
185
|
+
apiKey: getAPIKey()
|
|
186
|
+
});
|
|
187
|
+
const paidModels = models.filter(m => (m.pricing.text?.input || 0) > 0 || (m.pricing.text?.output || 0) > 0);
|
|
188
|
+
if (paidModels.length > 0) {
|
|
189
|
+
// Find cheapest and most expensive
|
|
190
|
+
paidModels.sort((a, b) => ((a.pricing.text?.input || 0) + (a.pricing.text?.output || 0)) -
|
|
191
|
+
((b.pricing.text?.input || 0) + (b.pricing.text?.output || 0)));
|
|
192
|
+
const cheapest = paidModels[0];
|
|
193
|
+
const mostExpensive = paidModels[paidModels.length - 1];
|
|
194
|
+
console.log(` Cheapest: ${cheapest.id}`);
|
|
195
|
+
console.log(` $${cheapest.pricing.text?.input}/M input, $${cheapest.pricing.text?.output}/M output`);
|
|
196
|
+
console.log(` Most expensive: ${mostExpensive.id}`);
|
|
197
|
+
console.log(` $${mostExpensive.pricing.text?.input}/M input, $${mostExpensive.pricing.text?.output}/M output`);
|
|
198
|
+
expect(paidModels.length).toBeGreaterThan(0);
|
|
199
|
+
}
|
|
200
|
+
}, 30000);
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
//# sourceMappingURL=openrouter.integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openrouter.integration.test.js","sourceRoot":"","sources":["../../src/__integration__/openrouter.integration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/__integration__/setup.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,eAAO,MAAM,SAAS,QAAO,MAW5B,CAAC;AAEF,eAAO,MAAM,SAAS,QAAO,OAE5B,CAAC;AAEF,eAAO,MAAM,cAAc,qBAM1B,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenRouter Integration Test Setup
|
|
3
|
+
*/
|
|
4
|
+
import dotenv from 'dotenv';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
// Load .env.test from root
|
|
7
|
+
dotenv.config({ path: path.resolve(__dirname, '../../../../.env.test') });
|
|
8
|
+
export const getAPIKey = () => {
|
|
9
|
+
const key = process.env.OPENROUTER_API_KEY;
|
|
10
|
+
if (!key) {
|
|
11
|
+
throw new Error('Missing OPENROUTER_API_KEY in environment. ' +
|
|
12
|
+
'Add it to .env.test or set it as an environment variable.');
|
|
13
|
+
}
|
|
14
|
+
return key;
|
|
15
|
+
};
|
|
16
|
+
export const hasAPIKey = () => {
|
|
17
|
+
return !!process.env.OPENROUTER_API_KEY;
|
|
18
|
+
};
|
|
19
|
+
export const skipIfNoAPIKey = () => {
|
|
20
|
+
if (!hasAPIKey()) {
|
|
21
|
+
console.warn('Skipping OpenRouter integration tests - no API key found');
|
|
22
|
+
return describe.skip;
|
|
23
|
+
}
|
|
24
|
+
return describe;
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/__integration__/setup.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,2BAA2B;AAC3B,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,uBAAuB,CAAC,EAAE,CAAC,CAAC;AAE1E,MAAM,CAAC,MAAM,SAAS,GAAG,GAAW,EAAE;IACpC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAE3C,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CACb,6CAA6C;YAC7C,2DAA2D,CAC5D,CAAC;IACJ,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,GAAY,EAAE;IACrC,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;AAC1C,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,EAAE;IACjC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;QACzE,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenRouter Provider
|
|
3
|
+
*
|
|
4
|
+
* Provider for OpenRouter API with provider-specific routing and fallback options.
|
|
5
|
+
*/
|
|
6
|
+
import type { ModelInfo, Provider } from '@aeye/ai';
|
|
7
|
+
import type { Chunk, Request, Response } from '@aeye/core';
|
|
8
|
+
import { OpenAIConfig, OpenAIProvider } from '@aeye/openai';
|
|
9
|
+
import OpenAI from 'openai';
|
|
10
|
+
import { OpenRouterChatChunk, OpenRouterChatRequest, OpenRouterChatResponse, OpenRouterModel } from './types';
|
|
11
|
+
/**
|
|
12
|
+
* OpenRouter provider configuration
|
|
13
|
+
*/
|
|
14
|
+
export interface OpenRouterConfig extends OpenAIConfig {
|
|
15
|
+
defaultParams?: {
|
|
16
|
+
siteUrl?: string;
|
|
17
|
+
appName?: string;
|
|
18
|
+
providers?: {
|
|
19
|
+
order?: string[];
|
|
20
|
+
allowFallbacks?: boolean;
|
|
21
|
+
requireParameters?: boolean;
|
|
22
|
+
dataCollection?: 'deny' | 'allow';
|
|
23
|
+
zdr?: boolean;
|
|
24
|
+
only?: string[];
|
|
25
|
+
ignore?: string[];
|
|
26
|
+
quantizations?: ('int4' | 'int8' | 'fp4' | 'fp6' | 'fp8' | 'fp16' | 'bf16' | 'fp32' | 'unknown')[];
|
|
27
|
+
sort?: 'price' | 'throughput' | 'latency';
|
|
28
|
+
maxPrice?: {
|
|
29
|
+
prompt?: number;
|
|
30
|
+
completion?: number;
|
|
31
|
+
image?: number;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
transforms?: string[];
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Convert OpenRouter model to ModelInfo with full details
|
|
39
|
+
*/
|
|
40
|
+
export declare function convertOpenRouterModel(model: OpenRouterModel, zdrModelIds: Set<string>, metrics?: {
|
|
41
|
+
latency?: number;
|
|
42
|
+
throughput?: number;
|
|
43
|
+
uptime?: number;
|
|
44
|
+
} | null): ModelInfo;
|
|
45
|
+
/**
|
|
46
|
+
* OpenRouter provider implementation extending base OpenAI-compatible provider
|
|
47
|
+
*/
|
|
48
|
+
export declare class OpenRouterProvider extends OpenAIProvider<OpenRouterConfig> implements Provider<OpenRouterConfig> {
|
|
49
|
+
readonly name = "openrouter";
|
|
50
|
+
protected createClient(config: OpenRouterConfig): OpenAI;
|
|
51
|
+
protected convertModel(model: OpenAI.Model): ModelInfo;
|
|
52
|
+
/**
|
|
53
|
+
* Augment chat request with OpenRouter-specific parameters
|
|
54
|
+
*/
|
|
55
|
+
protected augmentChatRequest(params: OpenRouterChatRequest, request: Request, config: OpenRouterConfig): void;
|
|
56
|
+
/**
|
|
57
|
+
*
|
|
58
|
+
* @param expected
|
|
59
|
+
* @param response
|
|
60
|
+
*/
|
|
61
|
+
protected augmentChatResponse(expected: OpenRouterChatResponse, response: Response, config: OpenRouterConfig): void;
|
|
62
|
+
protected augmentChatChunk(expected: OpenRouterChatChunk, chunk: Chunk, config: OpenRouterConfig): void;
|
|
63
|
+
/**
|
|
64
|
+
* OpenRouter does not support image generation
|
|
65
|
+
*/
|
|
66
|
+
generateImage: undefined;
|
|
67
|
+
/**
|
|
68
|
+
* OpenRouter does not support image generation streaming
|
|
69
|
+
*/
|
|
70
|
+
generateImageStream: undefined;
|
|
71
|
+
/**
|
|
72
|
+
* OpenRouter does not support image editing
|
|
73
|
+
*/
|
|
74
|
+
editImage: undefined;
|
|
75
|
+
/**
|
|
76
|
+
* OpenRouter does not support image editing
|
|
77
|
+
*/
|
|
78
|
+
editImageStream: undefined;
|
|
79
|
+
/**
|
|
80
|
+
* OpenRouter does not support audio transcription
|
|
81
|
+
*/
|
|
82
|
+
transcribe: undefined;
|
|
83
|
+
/**
|
|
84
|
+
* OpenRouter does not support audio transcription streaming
|
|
85
|
+
*/
|
|
86
|
+
transcribeStream: undefined;
|
|
87
|
+
/**
|
|
88
|
+
* OpenRouter does not support speech synthesis
|
|
89
|
+
*/
|
|
90
|
+
speech: undefined;
|
|
91
|
+
/**
|
|
92
|
+
* OpenRouter does not support embeddings
|
|
93
|
+
*/
|
|
94
|
+
embed: undefined;
|
|
95
|
+
/**
|
|
96
|
+
* Override listModels to use OpenRouter's model API with ZDR support
|
|
97
|
+
*/
|
|
98
|
+
listModels(config: OpenRouterConfig): Promise<ModelInfo[]>;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=openrouter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openrouter.d.ts","sourceRoot":"","sources":["../src/openrouter.ts"],"names":[],"mappings":"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"}
|