litellmts-core 1.1.0 → 2.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 +44 -19
- package/dist/handlers/ai21.js +7 -5
- package/dist/handlers/anthropic.d.ts +1 -1
- package/dist/handlers/anthropic.js +22 -103
- package/dist/handlers/cohere.js +21 -5
- package/dist/handlers/copilot.js +4 -2
- package/dist/handlers/deepinfra.js +15 -2
- package/dist/handlers/gemini.d.ts +1 -1
- package/dist/handlers/gemini.js +41 -89
- package/dist/handlers/geminiEmbedding.d.ts +1 -1
- package/dist/handlers/geminiEmbedding.js +6 -9
- package/dist/handlers/mistral.js +15 -2
- package/dist/handlers/ollama.js +18 -8
- package/dist/handlers/openai.js +18 -3
- package/dist/handlers/openaiEmbedding.js +5 -2
- package/dist/handlers/openaiLike.d.ts +1 -1
- package/dist/handlers/openaiLike.js +26 -3
- package/dist/handlers/openaiLikeEmbedding.d.ts +1 -1
- package/dist/handlers/openaiLikeEmbedding.js +6 -2
- package/dist/handlers/replicate.js +15 -2
- package/dist/handlers/vertexAnthropic.d.ts +2 -0
- package/dist/handlers/vertexAnthropic.js +43 -0
- package/dist/handlers/vertexai.d.ts +2 -0
- package/dist/handlers/vertexai.js +51 -0
- package/dist/handlers/vertexaiEmbedding.d.ts +2 -0
- package/dist/handlers/vertexaiEmbedding.js +31 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -1
- package/dist/mappings/openaiLike.js +0 -5
- package/dist/models/index.d.ts +2 -0
- package/dist/models/index.js +7 -0
- package/dist/models/registry.d.ts +13 -0
- package/dist/models/registry.js +73 -0
- package/dist/models/types.d.ts +9 -0
- package/dist/models/types.js +2 -0
- package/dist/utils/anthropic.d.ts +10 -0
- package/dist/utils/anthropic.js +99 -0
- package/dist/utils/gemini.d.ts +12 -0
- package/dist/utils/gemini.js +73 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ npm install litellmts-core
|
|
|
42
42
|
import { completion } from 'litellmts-core';
|
|
43
43
|
|
|
44
44
|
const response = await completion({
|
|
45
|
-
model: 'gpt-4o-mini',
|
|
45
|
+
model: 'openai/gpt-4o-mini',
|
|
46
46
|
messages: [{ role: 'user', content: 'Hello!' }],
|
|
47
47
|
});
|
|
48
48
|
|
|
@@ -53,7 +53,7 @@ Swap providers by changing just the model string:
|
|
|
53
53
|
|
|
54
54
|
```ts
|
|
55
55
|
// Same code, different provider:
|
|
56
|
-
await completion({ model: 'claude-sonnet-4-20250514', ... });
|
|
56
|
+
await completion({ model: 'anthropic/claude-sonnet-4-20250514', ... });
|
|
57
57
|
await completion({ model: 'gemini/gemini-2.5-pro', ... });
|
|
58
58
|
await completion({ model: 'groq/llama-3.3-70b', ... });
|
|
59
59
|
await completion({ model: 'deepseek/deepseek-chat', ... });
|
|
@@ -63,6 +63,8 @@ await completion({ model: 'deepseek/deepseek-chat', ... });
|
|
|
63
63
|
|
|
64
64
|
- **Unified API** — same `completion()` / `embedding()` for every provider
|
|
65
65
|
- **Streaming** — all providers support `stream: true`
|
|
66
|
+
- **Model listing** — `listModels('openai')` fetches available models from each provider's API
|
|
67
|
+
- **Provider discovery** — `listProviders()` returns all configured providers
|
|
66
68
|
- **TypeScript first** — full type safety with auto-completion
|
|
67
69
|
- **45+ providers** — from OpenAI to niche OpenAI-compatible APIs
|
|
68
70
|
- **No SDK sprawl** — one dependency replaces 10+ vendor SDKs
|
|
@@ -77,7 +79,7 @@ await completion({ model: 'deepseek/deepseek-chat', ... });
|
|
|
77
79
|
import { completion } from 'litellmts-core';
|
|
78
80
|
|
|
79
81
|
const response = await completion({
|
|
80
|
-
model: 'gpt-4o-mini',
|
|
82
|
+
model: 'openai/gpt-4o-mini',
|
|
81
83
|
messages: [
|
|
82
84
|
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
83
85
|
{ role: 'user', content: 'What is TypeScript?' },
|
|
@@ -96,7 +98,7 @@ console.log(response.usage);
|
|
|
96
98
|
|
|
97
99
|
```ts
|
|
98
100
|
const stream = await completion({
|
|
99
|
-
model: 'claude-sonnet-4-20250514',
|
|
101
|
+
model: 'anthropic/claude-sonnet-4-20250514',
|
|
100
102
|
messages: [{ role: 'user', content: 'Write a poem' }],
|
|
101
103
|
stream: true,
|
|
102
104
|
});
|
|
@@ -112,13 +114,33 @@ for await (const chunk of stream) {
|
|
|
112
114
|
import { embedding } from 'litellmts-core';
|
|
113
115
|
|
|
114
116
|
const result = await embedding({
|
|
115
|
-
model: 'text-embedding-3-small',
|
|
117
|
+
model: 'openai/text-embedding-3-small',
|
|
116
118
|
input: 'Hello world',
|
|
117
119
|
});
|
|
118
120
|
|
|
119
121
|
console.log(result.data[0].embedding); // number[]
|
|
120
122
|
```
|
|
121
123
|
|
|
124
|
+
### Model Discovery
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
import { listModels, listProviders, clearModelCache } from 'litellmts-core';
|
|
128
|
+
|
|
129
|
+
// List all available models for a provider (fetched live from their API)
|
|
130
|
+
const models = await listModels('openai');
|
|
131
|
+
// => [{ id: 'gpt-4o', provider: 'openai', created: 1700000000 }, ...]
|
|
132
|
+
|
|
133
|
+
// List all configured providers
|
|
134
|
+
const providers = listProviders();
|
|
135
|
+
// => [{ name: 'openai', hasModelList: true }, { name: 'groq', hasModelList: true }, ...]
|
|
136
|
+
|
|
137
|
+
// Get models for a specific provider with apiKey override
|
|
138
|
+
const groqModels = await listModels('groq', { apiKey: 'gsk_...' });
|
|
139
|
+
|
|
140
|
+
// Clear cached model lists (re-fetches on next call)
|
|
141
|
+
clearModelCache();
|
|
142
|
+
```
|
|
143
|
+
|
|
122
144
|
### API Keys
|
|
123
145
|
|
|
124
146
|
Keys are read from environment variables by default:
|
|
@@ -153,17 +175,17 @@ npx litellm login anthropic
|
|
|
153
175
|
|
|
154
176
|
### Dedicated Handlers
|
|
155
177
|
|
|
156
|
-
| Provider |
|
|
157
|
-
|
|
158
|
-
| OpenAI | `
|
|
159
|
-
| Anthropic | `
|
|
178
|
+
| Provider | Model prefix | Completion | Streaming | Embedding | API Key Env |
|
|
179
|
+
|---|---|---|---|---|---|---|
|
|
180
|
+
| OpenAI | `openai/` | ✅ | ✅ | ✅ | `OPENAI_API_KEY` |
|
|
181
|
+
| Anthropic | `anthropic/` | ✅ | ✅ | ❌ | `ANTHROPIC_API_KEY` |
|
|
160
182
|
| Google Gemini | `gemini/` | ✅ | ✅ | ✅ | `GEMINI_API_KEY` |
|
|
161
183
|
| GitHub Copilot | `copilot/` | ✅ | ✅ | ❌ | (OAuth) |
|
|
162
184
|
| Mistral | `mistral/` | ✅ | ✅ | ✅ | `MISTRAL_API_KEY` |
|
|
163
|
-
| Cohere | `
|
|
185
|
+
| Cohere | `cohere/` | ✅ | ✅ | ❌ | `COHERE_API_KEY` |
|
|
164
186
|
| DeepInfra | `deepinfra/` | ✅ | ✅ | ❌ | `DEEPINFRA_API_KEY` |
|
|
165
187
|
| Replicate | `replicate/` | ✅ | ✅ | ❌ | `REPLICATE_API_KEY` |
|
|
166
|
-
| AI21 Labs | `
|
|
188
|
+
| AI21 Labs | `ai21/` | ✅ | ✅ | ❌ | `AI21_API_KEY` |
|
|
167
189
|
| Ollama (local) | `ollama/` | ✅ | ✅ | ✅ | — |
|
|
168
190
|
|
|
169
191
|
### OpenAI-Compatible (38 providers)
|
|
@@ -213,16 +235,19 @@ npx litellm login anthropic
|
|
|
213
235
|
┌──────────────┐ ┌──────────────┐ ┌─────────────────┐
|
|
214
236
|
│ completion() │────▶│ getHandler() │────▶│ OpenAIHandler │
|
|
215
237
|
│ embedding() │ │ (prefix │ │ AnthropicHandler│
|
|
216
|
-
│
|
|
217
|
-
│
|
|
238
|
+
│ listModels() │ │ matching) │ │ GeminiHandler │
|
|
239
|
+
│ listProviders│ │ │ │ OpenAILikeHandler│
|
|
218
240
|
└──────────────┘ └──────────────┘ └─────────────────┘
|
|
219
241
|
│
|
|
220
|
-
┌──────┴──────┐
|
|
221
|
-
│ Registry │
|
|
222
|
-
│
|
|
223
|
-
│
|
|
224
|
-
│
|
|
225
|
-
└─────────────┘
|
|
242
|
+
┌──────┴──────┐ ┌──────────────────┐
|
|
243
|
+
│ Registry │ │ Model Registry │
|
|
244
|
+
│ openai/ → │ │ (in-memory │
|
|
245
|
+
│ anthropic/ │ │ cache + TTL) │
|
|
246
|
+
│ groq/ → .. │ │ │
|
|
247
|
+
└─────────────┘ │ listModels() │
|
|
248
|
+
│ listProviders() │
|
|
249
|
+
│ clearModelCache()│
|
|
250
|
+
└──────────────────┘
|
|
226
251
|
```
|
|
227
252
|
|
|
228
253
|
## Development
|
package/dist/handlers/ai21.js
CHANGED
|
@@ -56,9 +56,11 @@ async function AI21Handler(params) {
|
|
|
56
56
|
const apiKey = params.apiKey ?? process.env.AI21_API_KEY;
|
|
57
57
|
if (!apiKey)
|
|
58
58
|
throw new Error('AI21 requires an API key. Set AI21_API_KEY environment variable or pass apiKey in params.');
|
|
59
|
-
const
|
|
59
|
+
const modelName = params.model.startsWith('ai21/')
|
|
60
|
+
? params.model.slice(5)
|
|
61
|
+
: params.model;
|
|
60
62
|
const prompt = (0, combinePrompts_1.combinePrompts)(params.messages);
|
|
61
|
-
const res = await getAI21Response(
|
|
63
|
+
const res = await getAI21Response(modelName, prompt, baseUrl, apiKey, params.stream ?? false);
|
|
62
64
|
if (!res.ok) {
|
|
63
65
|
throw new Error(`Received an error with code ${res.status} from AI21 API.`);
|
|
64
66
|
}
|
|
@@ -66,7 +68,7 @@ async function AI21Handler(params) {
|
|
|
66
68
|
return (0, sse_1.iterateSSEStream)(res, (payload) => {
|
|
67
69
|
const parsed = JSON.parse(payload);
|
|
68
70
|
return {
|
|
69
|
-
model,
|
|
71
|
+
model: modelName,
|
|
70
72
|
created: (0, getUnixTimestamp_1.getUnixTimestamp)(),
|
|
71
73
|
choices: [
|
|
72
74
|
{
|
|
@@ -81,7 +83,7 @@ async function AI21Handler(params) {
|
|
|
81
83
|
});
|
|
82
84
|
}
|
|
83
85
|
const body = (await res.json());
|
|
84
|
-
return toResponse(body,
|
|
86
|
+
return toResponse(body, modelName);
|
|
85
87
|
}
|
|
86
88
|
const registry_1 = require("../registry");
|
|
87
|
-
(0, registry_1.registerCompletionHandler)('
|
|
89
|
+
(0, registry_1.registerCompletionHandler)('ai21/', AI21Handler);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { HandlerParams,
|
|
1
|
+
import type { HandlerParams, ResultNotStreaming, ResultStreaming } from '../types';
|
|
2
2
|
export declare function AnthropicHandler(params: HandlerParams): Promise<ResultNotStreaming | ResultStreaming>;
|
|
@@ -5,109 +5,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.AnthropicHandler = AnthropicHandler;
|
|
7
7
|
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
8
|
-
const
|
|
8
|
+
const anthropic_1 = require("../utils/anthropic");
|
|
9
9
|
const auth_1 = require("../auth");
|
|
10
|
-
|
|
11
|
-
let system;
|
|
12
|
-
const messages = [];
|
|
13
|
-
for (const msg of input) {
|
|
14
|
-
if (msg.role === 'system') {
|
|
15
|
-
system = (system ? system + '\n' : '') + (msg.content ?? '');
|
|
16
|
-
continue;
|
|
17
|
-
}
|
|
18
|
-
if (msg.role === 'user' || msg.role === 'assistant') {
|
|
19
|
-
messages.push({
|
|
20
|
-
role: msg.role,
|
|
21
|
-
content: msg.content ?? '',
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return { system, messages };
|
|
26
|
-
}
|
|
27
|
-
function toFinishReason(reason) {
|
|
28
|
-
if (reason === 'max_tokens') {
|
|
29
|
-
return 'length';
|
|
30
|
-
}
|
|
31
|
-
return 'stop';
|
|
32
|
-
}
|
|
33
|
-
function getTextContent(content) {
|
|
34
|
-
return content
|
|
35
|
-
.filter((block) => block.type === 'text')
|
|
36
|
-
.map((block) => block.text)
|
|
37
|
-
.join('');
|
|
38
|
-
}
|
|
39
|
-
function toResponse(message) {
|
|
40
|
-
return {
|
|
41
|
-
model: message.model,
|
|
42
|
-
created: (0, getUnixTimestamp_1.getUnixTimestamp)(),
|
|
43
|
-
usage: {
|
|
44
|
-
prompt_tokens: message.usage.input_tokens,
|
|
45
|
-
completion_tokens: message.usage.output_tokens,
|
|
46
|
-
total_tokens: message.usage.input_tokens + message.usage.output_tokens,
|
|
47
|
-
},
|
|
48
|
-
choices: [
|
|
49
|
-
{
|
|
50
|
-
message: {
|
|
51
|
-
content: getTextContent(message.content),
|
|
52
|
-
role: 'assistant',
|
|
53
|
-
},
|
|
54
|
-
finish_reason: toFinishReason(message.stop_reason),
|
|
55
|
-
index: 0,
|
|
56
|
-
},
|
|
57
|
-
],
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
async function* toStreamingResponse(stream) {
|
|
61
|
-
let model = '';
|
|
62
|
-
let stopReason;
|
|
63
|
-
for await (const event of stream) {
|
|
64
|
-
switch (event.type) {
|
|
65
|
-
case 'message_start':
|
|
66
|
-
model = event.message.model;
|
|
67
|
-
stopReason = event.message.stop_reason;
|
|
68
|
-
break;
|
|
69
|
-
case 'content_block_delta':
|
|
70
|
-
if (event.delta.type === 'text_delta') {
|
|
71
|
-
yield {
|
|
72
|
-
model,
|
|
73
|
-
created: (0, getUnixTimestamp_1.getUnixTimestamp)(),
|
|
74
|
-
choices: [
|
|
75
|
-
{
|
|
76
|
-
delta: { content: event.delta.text, role: 'assistant' },
|
|
77
|
-
finish_reason: null,
|
|
78
|
-
index: 0,
|
|
79
|
-
},
|
|
80
|
-
],
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
break;
|
|
84
|
-
case 'message_delta':
|
|
85
|
-
stopReason = event.delta.stop_reason;
|
|
86
|
-
break;
|
|
87
|
-
case 'message_stop':
|
|
88
|
-
yield {
|
|
89
|
-
model,
|
|
90
|
-
created: (0, getUnixTimestamp_1.getUnixTimestamp)(),
|
|
91
|
-
choices: [
|
|
92
|
-
{
|
|
93
|
-
delta: { content: '', role: 'assistant' },
|
|
94
|
-
finish_reason: toFinishReason(stopReason),
|
|
95
|
-
index: 0,
|
|
96
|
-
},
|
|
97
|
-
],
|
|
98
|
-
};
|
|
99
|
-
break;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
10
|
+
const registry_1 = require("../models/registry");
|
|
103
11
|
async function AnthropicHandler(params) {
|
|
104
12
|
const apiKey = params.apiKey ?? process.env.ANTHROPIC_API_KEY ?? (await (0, auth_1.getAnthropicKey)());
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const
|
|
13
|
+
const modelName = params.model.startsWith('anthropic/')
|
|
14
|
+
? params.model.slice(10)
|
|
15
|
+
: params.model;
|
|
16
|
+
const anthropic = new sdk_1.default({ apiKey });
|
|
17
|
+
const { system, messages } = (0, anthropic_1.toAnthropicMessages)(params.messages);
|
|
109
18
|
const anthropicParams = {
|
|
110
|
-
model:
|
|
19
|
+
model: modelName,
|
|
111
20
|
max_tokens: params.max_tokens ?? 300,
|
|
112
21
|
messages,
|
|
113
22
|
...(system ? { system } : {}),
|
|
@@ -118,14 +27,24 @@ async function AnthropicHandler(params) {
|
|
|
118
27
|
...anthropicParams,
|
|
119
28
|
stream: true,
|
|
120
29
|
});
|
|
121
|
-
return
|
|
30
|
+
return (0, anthropic_1.toAnthropicStreamingResponse)(stream);
|
|
122
31
|
}
|
|
123
32
|
const message = await anthropic.messages.create(anthropicParams);
|
|
124
|
-
return
|
|
33
|
+
return (0, anthropic_1.toAnthropicResponse)(message);
|
|
125
34
|
}
|
|
126
35
|
catch (err) {
|
|
127
36
|
throw new Error(`Anthropic API error: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
128
37
|
}
|
|
129
38
|
}
|
|
130
|
-
|
|
131
|
-
|
|
39
|
+
(0, registry_1.registerModelProvider)('anthropic', async ({ apiKey } = {}) => {
|
|
40
|
+
const key = apiKey ?? process.env.ANTHROPIC_API_KEY;
|
|
41
|
+
if (!key)
|
|
42
|
+
return [];
|
|
43
|
+
const res = await fetch('https://api.anthropic.com/v1/models', {
|
|
44
|
+
headers: { 'x-api-key': key, 'anthropic-version': '2023-06-01' },
|
|
45
|
+
});
|
|
46
|
+
const { data } = await res.json();
|
|
47
|
+
return data.map((m) => ({ id: m.id, provider: 'anthropic' }));
|
|
48
|
+
});
|
|
49
|
+
const registry_2 = require("../registry");
|
|
50
|
+
(0, registry_2.registerCompletionHandler)('anthropic/', AnthropicHandler);
|
package/dist/handlers/cohere.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.CohereHandler = CohereHandler;
|
|
4
4
|
const cohere_ai_1 = require("cohere-ai");
|
|
5
5
|
const getUnixTimestamp_1 = require("../utils/getUnixTimestamp");
|
|
6
|
+
const registry_1 = require("../models/registry");
|
|
6
7
|
function toChatHistory(messages) {
|
|
7
8
|
let system;
|
|
8
9
|
const chatMessages = [];
|
|
@@ -43,10 +44,13 @@ async function CohereHandler(params) {
|
|
|
43
44
|
const apiKey = params.apiKey ?? process.env.COHERE_API_KEY;
|
|
44
45
|
if (!apiKey)
|
|
45
46
|
throw new Error('Cohere requires an API key. Set COHERE_API_KEY environment variable or pass apiKey in params.');
|
|
47
|
+
const modelName = params.model.startsWith('cohere/')
|
|
48
|
+
? params.model.slice(7)
|
|
49
|
+
: params.model;
|
|
46
50
|
const cohere = new cohere_ai_1.CohereClient({ token: apiKey });
|
|
47
51
|
const { message, chatHistory, preamble } = toChatHistory(params.messages);
|
|
48
52
|
const chatParams = {
|
|
49
|
-
model:
|
|
53
|
+
model: modelName,
|
|
50
54
|
message,
|
|
51
55
|
...(chatHistory ? { chatHistory } : {}),
|
|
52
56
|
...(preamble ? { preamble } : {}),
|
|
@@ -58,11 +62,11 @@ async function CohereHandler(params) {
|
|
|
58
62
|
const stream = await cohere.chatStream({
|
|
59
63
|
...chatParams,
|
|
60
64
|
});
|
|
61
|
-
return toStreamingResponse(stream,
|
|
65
|
+
return toStreamingResponse(stream, modelName);
|
|
62
66
|
}
|
|
63
67
|
const { text, finishReason, meta } = await cohere.chat(chatParams);
|
|
64
68
|
return {
|
|
65
|
-
model:
|
|
69
|
+
model: modelName,
|
|
66
70
|
created: (0, getUnixTimestamp_1.getUnixTimestamp)(),
|
|
67
71
|
usage: meta?.tokens
|
|
68
72
|
? {
|
|
@@ -126,5 +130,17 @@ async function* toStreamingResponse(stream, model) {
|
|
|
126
130
|
}
|
|
127
131
|
}
|
|
128
132
|
}
|
|
129
|
-
|
|
130
|
-
|
|
133
|
+
(0, registry_1.registerModelProvider)('cohere', async ({ apiKey } = {}) => {
|
|
134
|
+
const key = apiKey ?? process.env.COHERE_API_KEY;
|
|
135
|
+
if (!key)
|
|
136
|
+
return [];
|
|
137
|
+
const res = await fetch('https://api.cohere.com/v1/models', {
|
|
138
|
+
headers: { Authorization: `Bearer ${key}` },
|
|
139
|
+
});
|
|
140
|
+
if (!res.ok)
|
|
141
|
+
return [];
|
|
142
|
+
const json = await res.json();
|
|
143
|
+
return (json.models ?? []).map((m) => ({ id: m.id, provider: 'cohere' }));
|
|
144
|
+
});
|
|
145
|
+
const registry_2 = require("../registry");
|
|
146
|
+
(0, registry_2.registerCompletionHandler)('cohere/', CohereHandler);
|
package/dist/handlers/copilot.js
CHANGED
|
@@ -132,5 +132,7 @@ async function CopilotHandler(params) {
|
|
|
132
132
|
};
|
|
133
133
|
return result;
|
|
134
134
|
}
|
|
135
|
-
const registry_1 = require("../registry");
|
|
136
|
-
(0, registry_1.
|
|
135
|
+
const registry_1 = require("../models/registry");
|
|
136
|
+
(0, registry_1.registerModelProvider)('copilot', async () => []);
|
|
137
|
+
const registry_2 = require("../registry");
|
|
138
|
+
(0, registry_2.registerCompletionHandler)('copilot/', CopilotHandler);
|
|
@@ -54,5 +54,18 @@ async function DeepInfraHandler(params) {
|
|
|
54
54
|
};
|
|
55
55
|
return result;
|
|
56
56
|
}
|
|
57
|
-
const registry_1 = require("../registry");
|
|
58
|
-
(0, registry_1.
|
|
57
|
+
const registry_1 = require("../models/registry");
|
|
58
|
+
(0, registry_1.registerModelProvider)('deepinfra', async ({ apiKey } = {}) => {
|
|
59
|
+
const key = apiKey ?? process.env.DEEPINFRA_API_KEY;
|
|
60
|
+
if (!key)
|
|
61
|
+
return [];
|
|
62
|
+
const res = await fetch('https://api.deepinfra.com/v1/openai/models', {
|
|
63
|
+
headers: { Authorization: `Bearer ${key}` },
|
|
64
|
+
});
|
|
65
|
+
if (!res.ok)
|
|
66
|
+
return [];
|
|
67
|
+
const { data } = await res.json();
|
|
68
|
+
return (data ?? []).map((m) => ({ id: m.id, provider: 'deepinfra' }));
|
|
69
|
+
});
|
|
70
|
+
const registry_2 = require("../registry");
|
|
71
|
+
(0, registry_2.registerCompletionHandler)('deepinfra/', DeepInfraHandler);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { HandlerParams, ResultNotStreaming, ResultStreaming } from '../types';
|
|
1
|
+
import type { HandlerParams, ResultNotStreaming, ResultStreaming } from '../types';
|
|
2
2
|
export declare function GeminiHandler(params: HandlerParams): Promise<ResultNotStreaming | ResultStreaming>;
|
package/dist/handlers/gemini.js
CHANGED
|
@@ -1,78 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GeminiHandler = GeminiHandler;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
function toGeminiContent(messages) {
|
|
7
|
-
return messages.map((msg) => {
|
|
8
|
-
const parts = [];
|
|
9
|
-
if (msg.content) {
|
|
10
|
-
parts.push({ text: msg.content });
|
|
11
|
-
}
|
|
12
|
-
return {
|
|
13
|
-
role: msg.role === 'assistant' ? 'model' : msg.role,
|
|
14
|
-
parts,
|
|
15
|
-
};
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
function toFinishReason(reason) {
|
|
19
|
-
switch (reason) {
|
|
20
|
-
case 'STOP':
|
|
21
|
-
return 'stop';
|
|
22
|
-
case 'MAX_TOKENS':
|
|
23
|
-
return 'length';
|
|
24
|
-
default:
|
|
25
|
-
return 'stop';
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
function toUsage(meta) {
|
|
29
|
-
if (!meta)
|
|
30
|
-
return undefined;
|
|
31
|
-
return {
|
|
32
|
-
prompt_tokens: meta.promptTokenCount,
|
|
33
|
-
completion_tokens: meta.candidatesTokenCount,
|
|
34
|
-
total_tokens: meta.totalTokenCount,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
function toResponse(response, model) {
|
|
38
|
-
const candidate = response.candidates?.[0];
|
|
39
|
-
return {
|
|
40
|
-
model: model,
|
|
41
|
-
created: (0, getUnixTimestamp_1.getUnixTimestamp)(),
|
|
42
|
-
usage: toUsage(response.usageMetadata),
|
|
43
|
-
choices: [
|
|
44
|
-
{
|
|
45
|
-
index: candidate?.index ?? 0,
|
|
46
|
-
finish_reason: toFinishReason(candidate?.finishReason),
|
|
47
|
-
message: {
|
|
48
|
-
role: 'assistant',
|
|
49
|
-
content: candidate ? candidate.content.parts.map((p) => 'text' in p ? p.text : '').join('') : null,
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
],
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
async function* toStreamingResponse(stream, model) {
|
|
56
|
-
for await (const chunk of stream) {
|
|
57
|
-
const candidate = chunk.candidates?.[0];
|
|
58
|
-
const deltaContent = candidate?.content.parts.map((p) => 'text' in p ? p.text : '').join('') ?? '';
|
|
59
|
-
yield {
|
|
60
|
-
model,
|
|
61
|
-
created: (0, getUnixTimestamp_1.getUnixTimestamp)(),
|
|
62
|
-
usage: toUsage(chunk.usageMetadata),
|
|
63
|
-
choices: [
|
|
64
|
-
{
|
|
65
|
-
index: candidate?.index ?? 0,
|
|
66
|
-
finish_reason: toFinishReason(candidate?.finishReason),
|
|
67
|
-
delta: {
|
|
68
|
-
content: deltaContent,
|
|
69
|
-
role: 'assistant',
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
],
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
}
|
|
4
|
+
const genai_1 = require("@google/genai");
|
|
5
|
+
const gemini_1 = require("../utils/gemini");
|
|
76
6
|
async function GeminiHandler(params) {
|
|
77
7
|
const apiKey = params.apiKey ?? process.env.GEMINI_API_KEY;
|
|
78
8
|
if (!apiKey)
|
|
@@ -80,28 +10,50 @@ async function GeminiHandler(params) {
|
|
|
80
10
|
const modelName = params.model.startsWith('gemini/')
|
|
81
11
|
? params.model.slice(7)
|
|
82
12
|
: params.model;
|
|
83
|
-
const
|
|
84
|
-
const
|
|
85
|
-
model: modelName,
|
|
86
|
-
generationConfig: {
|
|
87
|
-
temperature: params.temperature ?? undefined,
|
|
88
|
-
topP: params.top_p ?? undefined,
|
|
89
|
-
maxOutputTokens: params.max_tokens ?? undefined,
|
|
90
|
-
stopSequences: params.stop ? (Array.isArray(params.stop) ? params.stop : [params.stop]) : undefined,
|
|
91
|
-
},
|
|
92
|
-
});
|
|
93
|
-
const contents = toGeminiContent(params.messages);
|
|
13
|
+
const client = new genai_1.GoogleGenAI({ apiKey });
|
|
14
|
+
const contents = (0, gemini_1.toGeminiContent)(params.messages);
|
|
94
15
|
try {
|
|
95
16
|
if (params.stream) {
|
|
96
|
-
const
|
|
97
|
-
|
|
17
|
+
const stream = await client.models.generateContentStream({
|
|
18
|
+
model: modelName,
|
|
19
|
+
contents,
|
|
20
|
+
config: {
|
|
21
|
+
temperature: params.temperature ?? undefined,
|
|
22
|
+
topP: params.top_p ?? undefined,
|
|
23
|
+
maxOutputTokens: params.max_tokens ?? undefined,
|
|
24
|
+
stopSequences: params.stop ? (Array.isArray(params.stop) ? params.stop : [params.stop]) : undefined,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
return (0, gemini_1.toStreamingResponse)(stream, modelName);
|
|
98
28
|
}
|
|
99
|
-
const
|
|
100
|
-
|
|
29
|
+
const response = await client.models.generateContent({
|
|
30
|
+
model: modelName,
|
|
31
|
+
contents,
|
|
32
|
+
config: {
|
|
33
|
+
temperature: params.temperature ?? undefined,
|
|
34
|
+
topP: params.top_p ?? undefined,
|
|
35
|
+
maxOutputTokens: params.max_tokens ?? undefined,
|
|
36
|
+
stopSequences: params.stop ? (Array.isArray(params.stop) ? params.stop : [params.stop]) : undefined,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
return (0, gemini_1.toResponse)(response, modelName);
|
|
101
40
|
}
|
|
102
41
|
catch (err) {
|
|
103
42
|
throw new Error(`Gemini API error: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
104
43
|
}
|
|
105
44
|
}
|
|
106
|
-
const registry_1 = require("../registry");
|
|
107
|
-
(0, registry_1.
|
|
45
|
+
const registry_1 = require("../models/registry");
|
|
46
|
+
(0, registry_1.registerModelProvider)('gemini', async ({ apiKey } = {}) => {
|
|
47
|
+
const key = apiKey ?? process.env.GEMINI_API_KEY;
|
|
48
|
+
if (!key)
|
|
49
|
+
return [];
|
|
50
|
+
const client = new genai_1.GoogleGenAI({ apiKey: key });
|
|
51
|
+
const pager = await client.models.list();
|
|
52
|
+
const models = [];
|
|
53
|
+
for await (const m of pager) {
|
|
54
|
+
models.push({ id: m.name ?? m.displayName, provider: 'gemini' });
|
|
55
|
+
}
|
|
56
|
+
return models;
|
|
57
|
+
});
|
|
58
|
+
const registry_2 = require("../registry");
|
|
59
|
+
(0, registry_2.registerCompletionHandler)('gemini/', GeminiHandler);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { EmbeddingParams, EmbeddingResponse } from '../types';
|
|
1
|
+
import type { EmbeddingParams, EmbeddingResponse } from '../types';
|
|
2
2
|
export declare function GeminiEmbeddingHandler(params: EmbeddingParams): Promise<EmbeddingResponse>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GeminiEmbeddingHandler = GeminiEmbeddingHandler;
|
|
4
|
-
const
|
|
4
|
+
const genai_1 = require("@google/genai");
|
|
5
5
|
async function GeminiEmbeddingHandler(params) {
|
|
6
6
|
const apiKey = params.apiKey ?? process.env.GEMINI_API_KEY;
|
|
7
7
|
if (!apiKey)
|
|
@@ -9,20 +9,17 @@ async function GeminiEmbeddingHandler(params) {
|
|
|
9
9
|
const modelName = params.model.startsWith('gemini/')
|
|
10
10
|
? params.model.slice(7)
|
|
11
11
|
: params.model;
|
|
12
|
-
const
|
|
13
|
-
const model = genAI.getGenerativeModel({ model: modelName });
|
|
12
|
+
const client = new genai_1.GoogleGenAI({ apiKey });
|
|
14
13
|
const input = typeof params.input === 'string'
|
|
15
14
|
? params.input
|
|
16
15
|
: params.input.join(' ');
|
|
17
|
-
const result = await
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
parts: [{ text: input }],
|
|
21
|
-
},
|
|
16
|
+
const result = await client.models.embedContent({
|
|
17
|
+
model: modelName,
|
|
18
|
+
contents: [{ role: 'user', parts: [{ text: input }] }],
|
|
22
19
|
});
|
|
23
20
|
return {
|
|
24
21
|
model: modelName,
|
|
25
|
-
data: [{ embedding: result.
|
|
22
|
+
data: [{ embedding: result.embeddings?.[0]?.values ?? [], index: 0 }],
|
|
26
23
|
};
|
|
27
24
|
}
|
|
28
25
|
const registry_1 = require("../registry");
|
package/dist/handlers/mistral.js
CHANGED
|
@@ -54,5 +54,18 @@ async function MistralHandler(params) {
|
|
|
54
54
|
};
|
|
55
55
|
return result;
|
|
56
56
|
}
|
|
57
|
-
const registry_1 = require("../registry");
|
|
58
|
-
(0, registry_1.
|
|
57
|
+
const registry_1 = require("../models/registry");
|
|
58
|
+
(0, registry_1.registerModelProvider)('mistral', async ({ apiKey } = {}) => {
|
|
59
|
+
const key = apiKey ?? process.env.MISTRAL_API_KEY;
|
|
60
|
+
if (!key)
|
|
61
|
+
return [];
|
|
62
|
+
const res = await fetch('https://api.mistral.ai/v1/models', {
|
|
63
|
+
headers: { Authorization: `Bearer ${key}` },
|
|
64
|
+
});
|
|
65
|
+
if (!res.ok)
|
|
66
|
+
return [];
|
|
67
|
+
const { data } = await res.json();
|
|
68
|
+
return (data ?? []).map((m) => ({ id: m.id, provider: 'mistral' }));
|
|
69
|
+
});
|
|
70
|
+
const registry_2 = require("../registry");
|
|
71
|
+
(0, registry_2.registerCompletionHandler)('mistral/', MistralHandler);
|