litellmts-core 1.0.1 → 2.0.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.
Files changed (46) hide show
  1. package/README.md +46 -21
  2. package/dist/auth/copilot.js +3 -3
  3. package/dist/auth/store.d.ts +1 -0
  4. package/dist/auth/store.js +45 -5
  5. package/dist/handlers/ai21.js +7 -5
  6. package/dist/handlers/anthropic.d.ts +1 -1
  7. package/dist/handlers/anthropic.js +36 -71
  8. package/dist/handlers/cohere.js +104 -43
  9. package/dist/handlers/copilot.js +4 -2
  10. package/dist/handlers/deepinfra.js +18 -3
  11. package/dist/handlers/gemini.d.ts +1 -1
  12. package/dist/handlers/gemini.js +47 -90
  13. package/dist/handlers/geminiEmbedding.d.ts +1 -1
  14. package/dist/handlers/geminiEmbedding.js +6 -9
  15. package/dist/handlers/mistral.js +18 -3
  16. package/dist/handlers/mistralEmbedding.js +3 -1
  17. package/dist/handlers/ollama.js +14 -4
  18. package/dist/handlers/ollamaEmbedding.js +4 -2
  19. package/dist/handlers/openai.js +38 -11
  20. package/dist/handlers/openaiEmbedding.js +10 -2
  21. package/dist/handlers/openaiLike.d.ts +1 -1
  22. package/dist/handlers/openaiLike.js +26 -3
  23. package/dist/handlers/openaiLikeEmbedding.d.ts +1 -1
  24. package/dist/handlers/openaiLikeEmbedding.js +6 -2
  25. package/dist/handlers/replicate.js +41 -16
  26. package/dist/handlers/vertexAnthropic.d.ts +2 -0
  27. package/dist/handlers/vertexAnthropic.js +43 -0
  28. package/dist/handlers/vertexai.d.ts +2 -0
  29. package/dist/handlers/vertexai.js +51 -0
  30. package/dist/handlers/vertexaiEmbedding.d.ts +2 -0
  31. package/dist/handlers/vertexaiEmbedding.js +31 -0
  32. package/dist/index.d.ts +1 -0
  33. package/dist/index.js +5 -1
  34. package/dist/mappings/openaiLike.js +0 -5
  35. package/dist/models/index.d.ts +2 -0
  36. package/dist/models/index.js +7 -0
  37. package/dist/models/registry.d.ts +13 -0
  38. package/dist/models/registry.js +32 -0
  39. package/dist/models/types.d.ts +9 -0
  40. package/dist/models/types.js +2 -0
  41. package/dist/utils/anthropic.d.ts +10 -0
  42. package/dist/utils/anthropic.js +99 -0
  43. package/dist/utils/gemini.d.ts +12 -0
  44. package/dist/utils/gemini.js +73 -0
  45. package/dist/utils/sse.js +0 -1
  46. package/package.json +12 -18
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VertexAIHandler = VertexAIHandler;
4
+ const genai_1 = require("@google/genai");
5
+ const gemini_1 = require("../utils/gemini");
6
+ async function VertexAIHandler(params) {
7
+ const project = params.project ?? process.env.GCP_PROJECT;
8
+ if (!project)
9
+ throw new Error('Vertex AI requires GCP_PROJECT environment variable or project in params.');
10
+ const location = params.location ?? process.env.GCP_LOCATION ?? 'us-central1';
11
+ const modelName = params.model.startsWith('vertex/')
12
+ ? params.model.slice(7)
13
+ : params.model;
14
+ const client = new genai_1.GoogleGenAI({
15
+ vertexai: true,
16
+ project,
17
+ location,
18
+ });
19
+ const contents = (0, gemini_1.toGeminiContent)(params.messages);
20
+ try {
21
+ if (params.stream) {
22
+ const stream = await client.models.generateContentStream({
23
+ model: modelName,
24
+ contents,
25
+ config: {
26
+ temperature: params.temperature ?? undefined,
27
+ topP: params.top_p ?? undefined,
28
+ maxOutputTokens: params.max_tokens ?? undefined,
29
+ stopSequences: params.stop ? (Array.isArray(params.stop) ? params.stop : [params.stop]) : undefined,
30
+ },
31
+ });
32
+ return (0, gemini_1.toStreamingResponse)(stream, modelName);
33
+ }
34
+ const response = await client.models.generateContent({
35
+ model: modelName,
36
+ contents,
37
+ config: {
38
+ temperature: params.temperature ?? undefined,
39
+ topP: params.top_p ?? undefined,
40
+ maxOutputTokens: params.max_tokens ?? undefined,
41
+ stopSequences: params.stop ? (Array.isArray(params.stop) ? params.stop : [params.stop]) : undefined,
42
+ },
43
+ });
44
+ return (0, gemini_1.toResponse)(response, modelName);
45
+ }
46
+ catch (err) {
47
+ throw new Error(`Vertex AI error: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
48
+ }
49
+ }
50
+ const registry_1 = require("../registry");
51
+ (0, registry_1.registerCompletionHandler)('vertex/', VertexAIHandler);
@@ -0,0 +1,2 @@
1
+ import type { EmbeddingParams, EmbeddingResponse } from '../types';
2
+ export declare function VertexAIEmbeddingHandler(params: EmbeddingParams): Promise<EmbeddingResponse>;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VertexAIEmbeddingHandler = VertexAIEmbeddingHandler;
4
+ const genai_1 = require("@google/genai");
5
+ async function VertexAIEmbeddingHandler(params) {
6
+ const project = params.project ?? process.env.GCP_PROJECT;
7
+ if (!project)
8
+ throw new Error('Vertex AI requires GCP_PROJECT environment variable or project in params.');
9
+ const location = params.location ?? process.env.GCP_LOCATION ?? 'us-central1';
10
+ const modelName = params.model.startsWith('vertex/')
11
+ ? params.model.slice(7)
12
+ : params.model;
13
+ const client = new genai_1.GoogleGenAI({
14
+ vertexai: true,
15
+ project,
16
+ location,
17
+ });
18
+ const input = typeof params.input === 'string'
19
+ ? params.input
20
+ : params.input.join(' ');
21
+ const result = await client.models.embedContent({
22
+ model: modelName,
23
+ contents: [{ role: 'user', parts: [{ text: input }] }],
24
+ });
25
+ return {
26
+ model: modelName,
27
+ data: [{ embedding: result.embeddings?.[0]?.values ?? [], index: 0 }],
28
+ };
29
+ }
30
+ const registry_1 = require("../registry");
31
+ (0, registry_1.registerEmbeddingHandler)('vertex/', VertexAIEmbeddingHandler);
package/dist/index.d.ts CHANGED
@@ -7,4 +7,5 @@
7
7
  */
8
8
  export { completion } from './completion';
9
9
  export { embedding } from './embedding';
10
+ export { listModels, listProviders, clearModelCache } from './models';
10
11
  export { login, loginAnthropic, getValidToken, getAnthropicKey } from './auth';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getAnthropicKey = exports.getValidToken = exports.loginAnthropic = exports.login = exports.embedding = exports.completion = void 0;
3
+ exports.getAnthropicKey = exports.getValidToken = exports.loginAnthropic = exports.login = exports.clearModelCache = exports.listProviders = exports.listModels = exports.embedding = exports.completion = void 0;
4
4
  /**
5
5
  * @litellmts/core — Unified API client for 45+ LLM providers.
6
6
  *
@@ -12,6 +12,10 @@ var completion_1 = require("./completion");
12
12
  Object.defineProperty(exports, "completion", { enumerable: true, get: function () { return completion_1.completion; } });
13
13
  var embedding_1 = require("./embedding");
14
14
  Object.defineProperty(exports, "embedding", { enumerable: true, get: function () { return embedding_1.embedding; } });
15
+ var models_1 = require("./models");
16
+ Object.defineProperty(exports, "listModels", { enumerable: true, get: function () { return models_1.listModels; } });
17
+ Object.defineProperty(exports, "listProviders", { enumerable: true, get: function () { return models_1.listProviders; } });
18
+ Object.defineProperty(exports, "clearModelCache", { enumerable: true, get: function () { return models_1.clearModelCache; } });
15
19
  var auth_1 = require("./auth");
16
20
  Object.defineProperty(exports, "login", { enumerable: true, get: function () { return auth_1.login; } });
17
21
  Object.defineProperty(exports, "loginAnthropic", { enumerable: true, get: function () { return auth_1.loginAnthropic; } });
@@ -77,11 +77,6 @@ exports.OPENAI_LIKE_MAPPINGS = {
77
77
  baseUrl: 'https://integrate.api.nvidia.com/v1',
78
78
  apiKeyEnv: 'NVIDIA_API_KEY',
79
79
  },
80
- 'ai21/': {
81
- name: 'AI21 Labs',
82
- baseUrl: 'https://api.ai21.com/studio/v1',
83
- apiKeyEnv: 'AI21_API_KEY',
84
- },
85
80
  'codestral/': {
86
81
  name: 'Codestral',
87
82
  baseUrl: 'https://codestral.mistral.ai/v1',
@@ -0,0 +1,2 @@
1
+ export { listModels, listProviders, clearModelCache } from './registry';
2
+ export type { ModelInfo, ProviderInfo } from './types';
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.clearModelCache = exports.listProviders = exports.listModels = void 0;
4
+ var registry_1 = require("./registry");
5
+ Object.defineProperty(exports, "listModels", { enumerable: true, get: function () { return registry_1.listModels; } });
6
+ Object.defineProperty(exports, "listProviders", { enumerable: true, get: function () { return registry_1.listProviders; } });
7
+ Object.defineProperty(exports, "clearModelCache", { enumerable: true, get: function () { return registry_1.clearModelCache; } });
@@ -0,0 +1,13 @@
1
+ import type { ModelInfo, ProviderInfo } from './types';
2
+ type ModelFetcher = (params?: {
3
+ apiKey?: string;
4
+ baseUrl?: string;
5
+ }) => Promise<ModelInfo[]>;
6
+ export declare function registerModelProvider(provider: string, fetcher: ModelFetcher): void;
7
+ export declare function listModels(provider: string, opts?: {
8
+ apiKey?: string;
9
+ baseUrl?: string;
10
+ }): Promise<ModelInfo[]>;
11
+ export declare function listProviders(): ProviderInfo[];
12
+ export declare function clearModelCache(): void;
13
+ export {};
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerModelProvider = registerModelProvider;
4
+ exports.listModels = listModels;
5
+ exports.listProviders = listProviders;
6
+ exports.clearModelCache = clearModelCache;
7
+ const fetchers = new Map();
8
+ const cache = new Map();
9
+ const CACHE_TTL = 5 * 60 * 1000;
10
+ function registerModelProvider(provider, fetcher) {
11
+ fetchers.set(provider, fetcher);
12
+ }
13
+ async function listModels(provider, opts) {
14
+ const cached = cache.get(provider);
15
+ if (cached && cached.expires > Date.now())
16
+ return cached.data;
17
+ const fetcher = fetchers.get(provider);
18
+ if (!fetcher)
19
+ throw new Error(`Provider '${provider}' not found.`);
20
+ const data = await fetcher(opts);
21
+ cache.set(provider, { data, expires: Date.now() + CACHE_TTL });
22
+ return data;
23
+ }
24
+ function listProviders() {
25
+ return Array.from(fetchers.keys()).map((key) => ({
26
+ name: key,
27
+ hasModelList: true,
28
+ }));
29
+ }
30
+ function clearModelCache() {
31
+ cache.clear();
32
+ }
@@ -0,0 +1,9 @@
1
+ export interface ModelInfo {
2
+ id: string;
3
+ provider: string;
4
+ created?: number;
5
+ }
6
+ export interface ProviderInfo {
7
+ name: string;
8
+ hasModelList: boolean;
9
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,10 @@
1
+ import type Anthropic from '@anthropic-ai/sdk';
2
+ import type { Message, FinishReason, ResultNotStreaming, ResultStreaming } from '../types';
3
+ export declare function toAnthropicMessages(input: Message[]): {
4
+ system: string | undefined;
5
+ messages: Anthropic.MessageParam[];
6
+ };
7
+ export declare function toAnthropicFinishReason(reason: Anthropic.StopReason | null | undefined): FinishReason;
8
+ export declare function getTextContent(content: Anthropic.ContentBlock[]): string;
9
+ export declare function toAnthropicResponse(message: Anthropic.Message): ResultNotStreaming;
10
+ export declare function toAnthropicStreamingResponse(stream: AsyncIterable<Anthropic.RawMessageStreamEvent>): ResultStreaming;
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toAnthropicMessages = toAnthropicMessages;
4
+ exports.toAnthropicFinishReason = toAnthropicFinishReason;
5
+ exports.getTextContent = getTextContent;
6
+ exports.toAnthropicResponse = toAnthropicResponse;
7
+ exports.toAnthropicStreamingResponse = toAnthropicStreamingResponse;
8
+ const getUnixTimestamp_1 = require("./getUnixTimestamp");
9
+ function toAnthropicMessages(input) {
10
+ let system;
11
+ const messages = [];
12
+ for (const msg of input) {
13
+ if (msg.role === 'system') {
14
+ system = (system ? system + '\n' : '') + (msg.content ?? '');
15
+ continue;
16
+ }
17
+ if (msg.role === 'user' || msg.role === 'assistant') {
18
+ messages.push({
19
+ role: msg.role,
20
+ content: msg.content ?? '',
21
+ });
22
+ }
23
+ }
24
+ return { system, messages };
25
+ }
26
+ function toAnthropicFinishReason(reason) {
27
+ return reason === 'max_tokens' ? 'length' : 'stop';
28
+ }
29
+ function getTextContent(content) {
30
+ return content
31
+ .filter((block) => block.type === 'text')
32
+ .map((block) => block.text)
33
+ .join('');
34
+ }
35
+ function toAnthropicResponse(message) {
36
+ return {
37
+ model: message.model,
38
+ created: (0, getUnixTimestamp_1.getUnixTimestamp)(),
39
+ usage: {
40
+ prompt_tokens: message.usage.input_tokens,
41
+ completion_tokens: message.usage.output_tokens,
42
+ total_tokens: message.usage.input_tokens + message.usage.output_tokens,
43
+ },
44
+ choices: [
45
+ {
46
+ message: {
47
+ content: getTextContent(message.content),
48
+ role: 'assistant',
49
+ },
50
+ finish_reason: toAnthropicFinishReason(message.stop_reason),
51
+ index: 0,
52
+ },
53
+ ],
54
+ };
55
+ }
56
+ async function* toAnthropicStreamingResponse(stream) {
57
+ let model = '';
58
+ let stopReason;
59
+ for await (const event of stream) {
60
+ switch (event.type) {
61
+ case 'message_start':
62
+ model = event.message.model;
63
+ stopReason = event.message.stop_reason;
64
+ break;
65
+ case 'content_block_delta':
66
+ if (event.delta.type === 'text_delta') {
67
+ const chunk = {
68
+ model,
69
+ created: (0, getUnixTimestamp_1.getUnixTimestamp)(),
70
+ choices: [
71
+ {
72
+ delta: { content: event.delta.text, role: 'assistant' },
73
+ finish_reason: null,
74
+ index: 0,
75
+ },
76
+ ],
77
+ };
78
+ yield chunk;
79
+ }
80
+ break;
81
+ case 'message_delta':
82
+ stopReason = event.delta.stop_reason;
83
+ break;
84
+ case 'message_stop':
85
+ yield {
86
+ model,
87
+ created: (0, getUnixTimestamp_1.getUnixTimestamp)(),
88
+ choices: [
89
+ {
90
+ delta: { content: '', role: 'assistant' },
91
+ finish_reason: toAnthropicFinishReason(stopReason),
92
+ index: 0,
93
+ },
94
+ ],
95
+ };
96
+ break;
97
+ }
98
+ }
99
+ }
@@ -0,0 +1,12 @@
1
+ import type { GenerateContentResponse } from '@google/genai';
2
+ import type { Message, FinishReason, ConsistentResponseUsage, ResultNotStreaming, ResultStreaming } from '../types';
3
+ export declare function toGeminiContent(messages: Message[]): {
4
+ role: string;
5
+ parts: {
6
+ text: string;
7
+ }[];
8
+ }[];
9
+ export declare function toFinishReason(reason: string | null | undefined): FinishReason;
10
+ export declare function toUsage(meta: GenerateContentResponse['usageMetadata']): ConsistentResponseUsage | undefined;
11
+ export declare function toResponse(response: GenerateContentResponse, model: string): ResultNotStreaming;
12
+ export declare function toStreamingResponse(stream: AsyncGenerator<GenerateContentResponse>, model: string): ResultStreaming;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toGeminiContent = toGeminiContent;
4
+ exports.toFinishReason = toFinishReason;
5
+ exports.toUsage = toUsage;
6
+ exports.toResponse = toResponse;
7
+ exports.toStreamingResponse = toStreamingResponse;
8
+ const getUnixTimestamp_1 = require("./getUnixTimestamp");
9
+ function toGeminiContent(messages) {
10
+ return messages.map((msg) => ({
11
+ role: msg.role === 'assistant' ? 'model' : msg.role,
12
+ parts: msg.content ? [{ text: msg.content }] : [],
13
+ }));
14
+ }
15
+ function toFinishReason(reason) {
16
+ switch (reason) {
17
+ case 'STOP':
18
+ return 'stop';
19
+ case 'MAX_TOKENS':
20
+ return 'length';
21
+ default:
22
+ return 'stop';
23
+ }
24
+ }
25
+ function toUsage(meta) {
26
+ if (!meta)
27
+ return undefined;
28
+ return {
29
+ prompt_tokens: meta.promptTokenCount ?? 0,
30
+ completion_tokens: meta.candidatesTokenCount ?? 0,
31
+ total_tokens: meta.totalTokenCount ?? 0,
32
+ };
33
+ }
34
+ function toResponse(response, model) {
35
+ const candidate = response.candidates?.[0];
36
+ return {
37
+ model,
38
+ created: (0, getUnixTimestamp_1.getUnixTimestamp)(),
39
+ usage: toUsage(response.usageMetadata),
40
+ choices: [
41
+ {
42
+ index: candidate?.index ?? 0,
43
+ finish_reason: toFinishReason(candidate?.finishReason),
44
+ message: {
45
+ role: 'assistant',
46
+ content: candidate?.content?.parts?.map((p) => p.text ?? '').join('') ?? null,
47
+ },
48
+ },
49
+ ],
50
+ };
51
+ }
52
+ async function* toStreamingResponse(stream, model) {
53
+ for await (const chunk of stream) {
54
+ const candidate = chunk.candidates?.[0];
55
+ const deltaContent = candidate?.content?.parts?.map((p) => p.text ?? '').join('') ?? '';
56
+ const chunkOutput = {
57
+ model,
58
+ created: (0, getUnixTimestamp_1.getUnixTimestamp)(),
59
+ usage: toUsage(chunk.usageMetadata),
60
+ choices: [
61
+ {
62
+ index: candidate?.index ?? 0,
63
+ finish_reason: toFinishReason(candidate?.finishReason),
64
+ delta: {
65
+ content: deltaContent,
66
+ role: 'assistant',
67
+ },
68
+ },
69
+ ],
70
+ };
71
+ yield chunkOutput;
72
+ }
73
+ }
package/dist/utils/sse.js CHANGED
@@ -30,7 +30,6 @@ async function* iterateSSEStream(response, parseChunk, doneToken = '[DONE]') {
30
30
  continue;
31
31
  const payload = trimmed.slice(6);
32
32
  if (payload === doneToken) {
33
- done = true;
34
33
  return;
35
34
  }
36
35
  yield parseChunk(payload);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "litellmts-core",
3
- "version": "1.0.1",
3
+ "version": "2.0.0",
4
4
  "description": "TypeScript implementation of LiteLLM — unified interface for 45+ LLM providers",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -25,34 +25,28 @@
25
25
  "author": "madkoding",
26
26
  "license": "GPL-3.0-only",
27
27
  "devDependencies": {
28
- "@eslint/js": "^9.19.0",
29
- "@types/eventsource": "^1.1.15",
28
+ "@eslint/js": "^10.0.1",
30
29
  "@types/jest": "^29.5.14",
31
30
  "@types/node": "^25.9.3",
32
- "dotenv": "^16.4.7",
33
- "eslint": "^9.19.0",
31
+ "dotenv": "^17.4.2",
32
+ "eslint": "^10.4.1",
34
33
  "eslint-config-prettier": "^10.0.1",
35
- "jest": "^29.7.0",
34
+ "jest": "^30.4.2",
36
35
  "jest-runner-groups": "^2.2.0",
37
36
  "prettier": "^3.4.2",
38
- "ts-jest": "^29.2.5",
37
+ "ts-jest": "^29.4.11",
39
38
  "typescript": "~5.9.3",
40
- "typescript-eslint": "^8.24.0"
39
+ "typescript-eslint": "^8.61.0"
41
40
  },
42
41
  "dependencies": {
43
- "@anthropic-ai/sdk": "^0.39.0",
44
- "@google/generative-ai": "^0.24.1",
45
- "cohere-ai": "^7.21.0",
46
- "eventsource": "^2.0.2",
42
+ "@anthropic-ai/sdk": "^0.104.1",
43
+ "@google/genai": "^2.8.0",
44
+ "cohere-ai": "^8.0.0",
45
+ "eventsource": "^4.1.0",
47
46
  "js-tiktoken": "^1.0.21",
48
- "openai": "^4.104.0",
47
+ "openai": "^6.42.0",
49
48
  "replicate": "^1.4.0"
50
49
  },
51
- "overrides": {
52
- "jest-runner-groups": {
53
- "jest-runner": "29.7.0"
54
- }
55
- },
56
50
  "engines": {
57
51
  "node": ">=22"
58
52
  },