@node-llm/core 1.5.2 → 1.6.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 +84 -110
- package/dist/aliases.js +239 -239
- package/dist/chat/Chat.d.ts +18 -17
- package/dist/chat/Chat.d.ts.map +1 -1
- package/dist/chat/Chat.js +63 -42
- package/dist/chat/ChatOptions.d.ts +8 -9
- package/dist/chat/ChatOptions.d.ts.map +1 -1
- package/dist/chat/ChatResponse.d.ts +1 -1
- package/dist/chat/ChatResponse.d.ts.map +1 -1
- package/dist/chat/ChatResponse.js +22 -8
- package/dist/chat/ChatStream.d.ts.map +1 -1
- package/dist/chat/ChatStream.js +16 -22
- package/dist/chat/Content.d.ts +3 -3
- package/dist/chat/Content.d.ts.map +1 -1
- package/dist/chat/Content.js +3 -6
- package/dist/chat/Message.d.ts +3 -1
- package/dist/chat/Message.d.ts.map +1 -1
- package/dist/chat/Role.d.ts.map +1 -1
- package/dist/chat/Tool.d.ts +15 -15
- package/dist/chat/Tool.d.ts.map +1 -1
- package/dist/chat/Tool.js +9 -7
- package/dist/chat/ToolHandler.d.ts +4 -3
- package/dist/chat/ToolHandler.d.ts.map +1 -1
- package/dist/chat/ToolHandler.js +10 -14
- package/dist/chat/Validation.d.ts.map +1 -1
- package/dist/chat/Validation.js +13 -6
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +80 -25
- package/dist/constants.js +1 -1
- package/dist/errors/index.d.ts +21 -7
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +14 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/llm.d.ts +44 -46
- package/dist/llm.d.ts.map +1 -1
- package/dist/llm.js +206 -134
- package/dist/model_aliases.d.ts.map +1 -1
- package/dist/models/ModelRegistry.d.ts.map +1 -1
- package/dist/models/ModelRegistry.js +12 -10
- package/dist/models/PricingRegistry.d.ts +31 -0
- package/dist/models/PricingRegistry.d.ts.map +1 -0
- package/dist/models/PricingRegistry.js +101 -0
- package/dist/models/models.d.ts.map +1 -1
- package/dist/models/models.js +5954 -7352
- package/dist/models/types.d.ts +37 -34
- package/dist/models/types.d.ts.map +1 -1
- package/dist/moderation/Moderation.d.ts.map +1 -1
- package/dist/moderation/Moderation.js +15 -5
- package/dist/providers/BaseProvider.d.ts +12 -8
- package/dist/providers/BaseProvider.d.ts.map +1 -1
- package/dist/providers/BaseProvider.js +17 -7
- package/dist/providers/Provider.d.ts +20 -5
- package/dist/providers/Provider.d.ts.map +1 -1
- package/dist/providers/anthropic/AnthropicProvider.d.ts +1 -1
- package/dist/providers/anthropic/AnthropicProvider.d.ts.map +1 -1
- package/dist/providers/anthropic/AnthropicProvider.js +3 -3
- package/dist/providers/anthropic/Capabilities.d.ts +2 -1
- package/dist/providers/anthropic/Capabilities.d.ts.map +1 -1
- package/dist/providers/anthropic/Capabilities.js +3 -20
- package/dist/providers/anthropic/Chat.d.ts.map +1 -1
- package/dist/providers/anthropic/Chat.js +27 -17
- package/dist/providers/anthropic/Errors.d.ts.map +1 -1
- package/dist/providers/anthropic/Errors.js +5 -2
- package/dist/providers/anthropic/Models.d.ts.map +1 -1
- package/dist/providers/anthropic/Models.js +6 -6
- package/dist/providers/anthropic/Streaming.d.ts.map +1 -1
- package/dist/providers/anthropic/Streaming.js +17 -12
- package/dist/providers/anthropic/Utils.js +8 -5
- package/dist/providers/anthropic/index.d.ts.map +1 -1
- package/dist/providers/anthropic/index.js +4 -3
- package/dist/providers/anthropic/types.d.ts +11 -4
- package/dist/providers/anthropic/types.d.ts.map +1 -1
- package/dist/providers/deepseek/Capabilities.d.ts +7 -5
- package/dist/providers/deepseek/Capabilities.d.ts.map +1 -1
- package/dist/providers/deepseek/Capabilities.js +9 -5
- package/dist/providers/deepseek/Chat.d.ts.map +1 -1
- package/dist/providers/deepseek/Chat.js +10 -9
- package/dist/providers/deepseek/DeepSeekProvider.d.ts +1 -1
- package/dist/providers/deepseek/DeepSeekProvider.d.ts.map +1 -1
- package/dist/providers/deepseek/DeepSeekProvider.js +4 -4
- package/dist/providers/deepseek/Models.d.ts.map +1 -1
- package/dist/providers/deepseek/Models.js +7 -7
- package/dist/providers/deepseek/Streaming.d.ts.map +1 -1
- package/dist/providers/deepseek/Streaming.js +11 -8
- package/dist/providers/deepseek/index.d.ts.map +1 -1
- package/dist/providers/deepseek/index.js +5 -4
- package/dist/providers/gemini/Capabilities.d.ts +5 -33
- package/dist/providers/gemini/Capabilities.d.ts.map +1 -1
- package/dist/providers/gemini/Capabilities.js +7 -30
- package/dist/providers/gemini/Chat.d.ts.map +1 -1
- package/dist/providers/gemini/Chat.js +24 -19
- package/dist/providers/gemini/ChatUtils.d.ts.map +1 -1
- package/dist/providers/gemini/ChatUtils.js +10 -10
- package/dist/providers/gemini/Embeddings.d.ts.map +1 -1
- package/dist/providers/gemini/Embeddings.js +2 -2
- package/dist/providers/gemini/Errors.d.ts.map +1 -1
- package/dist/providers/gemini/Errors.js +5 -2
- package/dist/providers/gemini/GeminiProvider.d.ts +1 -1
- package/dist/providers/gemini/GeminiProvider.d.ts.map +1 -1
- package/dist/providers/gemini/GeminiProvider.js +3 -3
- package/dist/providers/gemini/Image.d.ts.map +1 -1
- package/dist/providers/gemini/Image.js +8 -8
- package/dist/providers/gemini/Models.d.ts.map +1 -1
- package/dist/providers/gemini/Models.js +6 -6
- package/dist/providers/gemini/Streaming.d.ts.map +1 -1
- package/dist/providers/gemini/Streaming.js +18 -14
- package/dist/providers/gemini/Transcription.d.ts.map +1 -1
- package/dist/providers/gemini/Transcription.js +11 -11
- package/dist/providers/gemini/index.d.ts +1 -1
- package/dist/providers/gemini/index.d.ts.map +1 -1
- package/dist/providers/gemini/index.js +5 -4
- package/dist/providers/gemini/types.d.ts +4 -4
- package/dist/providers/gemini/types.d.ts.map +1 -1
- package/dist/providers/ollama/Capabilities.d.ts.map +1 -1
- package/dist/providers/ollama/Capabilities.js +6 -2
- package/dist/providers/ollama/Models.js +1 -1
- package/dist/providers/ollama/OllamaProvider.d.ts +1 -1
- package/dist/providers/ollama/OllamaProvider.d.ts.map +1 -1
- package/dist/providers/ollama/OllamaProvider.js +2 -2
- package/dist/providers/ollama/index.d.ts +1 -1
- package/dist/providers/ollama/index.d.ts.map +1 -1
- package/dist/providers/ollama/index.js +7 -3
- package/dist/providers/openai/Capabilities.d.ts +2 -1
- package/dist/providers/openai/Capabilities.d.ts.map +1 -1
- package/dist/providers/openai/Capabilities.js +9 -21
- package/dist/providers/openai/Chat.d.ts.map +1 -1
- package/dist/providers/openai/Chat.js +18 -14
- package/dist/providers/openai/Embedding.d.ts.map +1 -1
- package/dist/providers/openai/Embedding.js +11 -7
- package/dist/providers/openai/Errors.d.ts.map +1 -1
- package/dist/providers/openai/Errors.js +5 -2
- package/dist/providers/openai/Image.d.ts.map +1 -1
- package/dist/providers/openai/Image.js +6 -6
- package/dist/providers/openai/Models.d.ts +1 -1
- package/dist/providers/openai/Models.d.ts.map +1 -1
- package/dist/providers/openai/Models.js +12 -8
- package/dist/providers/openai/Moderation.d.ts.map +1 -1
- package/dist/providers/openai/Moderation.js +6 -6
- package/dist/providers/openai/OpenAIProvider.d.ts +2 -3
- package/dist/providers/openai/OpenAIProvider.d.ts.map +1 -1
- package/dist/providers/openai/OpenAIProvider.js +4 -4
- package/dist/providers/openai/Streaming.d.ts.map +1 -1
- package/dist/providers/openai/Streaming.js +18 -13
- package/dist/providers/openai/Transcription.d.ts.map +1 -1
- package/dist/providers/openai/Transcription.js +15 -12
- package/dist/providers/openai/index.d.ts +1 -1
- package/dist/providers/openai/index.d.ts.map +1 -1
- package/dist/providers/openai/index.js +6 -5
- package/dist/providers/openai/types.d.ts +1 -1
- package/dist/providers/openai/utils.js +2 -2
- package/dist/providers/openrouter/Capabilities.d.ts +3 -3
- package/dist/providers/openrouter/Capabilities.d.ts.map +1 -1
- package/dist/providers/openrouter/Capabilities.js +21 -24
- package/dist/providers/openrouter/Models.d.ts.map +1 -1
- package/dist/providers/openrouter/Models.js +20 -16
- package/dist/providers/openrouter/OpenRouterProvider.d.ts.map +1 -1
- package/dist/providers/openrouter/OpenRouterProvider.js +1 -1
- package/dist/providers/openrouter/index.d.ts +1 -1
- package/dist/providers/openrouter/index.d.ts.map +1 -1
- package/dist/providers/openrouter/index.js +6 -5
- package/dist/providers/registry.d.ts +18 -2
- package/dist/providers/registry.d.ts.map +1 -1
- package/dist/providers/registry.js +17 -2
- package/dist/providers/utils.js +1 -1
- package/dist/schema/Schema.d.ts +3 -3
- package/dist/schema/Schema.d.ts.map +1 -1
- package/dist/schema/Schema.js +2 -2
- package/dist/schema/to-json-schema.d.ts +1 -1
- package/dist/schema/to-json-schema.d.ts.map +1 -1
- package/dist/streaming/Stream.d.ts.map +1 -1
- package/dist/streaming/Stream.js +3 -3
- package/dist/utils/Binary.d.ts.map +1 -1
- package/dist/utils/Binary.js +32 -23
- package/dist/utils/FileLoader.d.ts.map +1 -1
- package/dist/utils/FileLoader.js +25 -4
- package/dist/utils/audio.js +2 -2
- package/dist/utils/fetch.d.ts.map +1 -1
- package/dist/utils/fetch.js +14 -4
- package/dist/utils/logger.d.ts +3 -3
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +2 -2
- package/package.json +1 -1
package/dist/llm.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../src/llm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,
|
|
1
|
+
{"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../src/llm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAU9D,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAUrD,OAAO,EAAU,aAAa,EAAiB,MAAM,aAAa,CAAC;AAEnE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,SAAS,GAAG;IACf,QAAQ,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC7B,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,UAAU,CAAC,CAAC;AAY7C,qBAAa,WAAW;aAKJ,MAAM,EAAE,aAAa;aACrB,QAAQ,CAAC,EAAE,QAAQ;aACnB,KAAK,EAAE,QAAQ,CAAC,YAAY,CAAC;IAC7C,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAP3B,SAAgB,MAAM,uBAAiB;IACvC,SAAgB,OAAO,yBAAmB;gBAGxB,MAAM,EAAE,aAAa,EACrB,QAAQ,CAAC,EAAE,QAAQ,YAAA,EACnB,KAAK,GAAE,QAAQ,CAAC,YAAY,CAA+B,EAC1D,QAAQ,GAAE;QACzB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;KACf;IAOR,IAAI,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAEzC;IACD,IAAI,yBAAyB,IAAI,MAAM,GAAG,SAAS,CAElD;IACD,IAAI,sBAAsB,IAAI,MAAM,GAAG,SAAS,CAE/C;IACD,IAAI,qBAAqB,IAAI,MAAM,GAAG,SAAS,CAE9C;IAED;;;OAGG;IACH,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,WAAW;IAgBtF;;;OAGG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,QAAQ,GAAG,IAAI;IAI7D,cAAc;IAId,OAAO,CAAC,qBAAqB;IAY7B,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI;IAU3C,UAAU,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAUlC,KAAK,CACT,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;QACR,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,GACA,OAAO,CAAC,cAAc,CAAC;IA0BpB,UAAU,CACd,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QACR,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;QAC7B,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,GACA,OAAO,CAAC,aAAa,CAAC;IAyBnB,QAAQ,CACZ,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EACxB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,GACjF,OAAO,CAAC,UAAU,CAAC;IAqBhB,KAAK,CACT,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EACxB,OAAO,CAAC,EAAE;QACR,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,GACA,OAAO,CAAC,SAAS,CAAC;CA0BtB;AAED,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,eAAe,EAAE,CAAC;AAEhF;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,SAAc,GAAG,WAAW,CAkD9D;AAuCD;;;;;;;;;GASG;AACH,eAAO,MAAM,OAAO,EAAE,WA6BpB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,aAAa;wBACJ,SAAS,GAAG,CAAC,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;CAOlE,CAAC"}
|
package/dist/llm.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { Chat } from "./chat/Chat.js";
|
|
2
|
-
import { providerRegistry, ensureOpenAIRegistered, registerAnthropicProvider, registerGeminiProvider, registerDeepSeekProvider, registerOllamaProvider, registerOpenRouterProvider
|
|
2
|
+
import { providerRegistry, ensureOpenAIRegistered, registerAnthropicProvider, registerGeminiProvider, registerDeepSeekProvider, registerOllamaProvider, registerOpenRouterProvider } from "./providers/registry.js";
|
|
3
3
|
import { GeneratedImage } from "./image/GeneratedImage.js";
|
|
4
4
|
import { ModelRegistry } from "./models/ModelRegistry.js";
|
|
5
|
+
import { PricingRegistry } from "./models/PricingRegistry.js";
|
|
5
6
|
import { Transcription } from "./transcription/Transcription.js";
|
|
6
7
|
import { Moderation } from "./moderation/Moderation.js";
|
|
7
8
|
import { Embedding } from "./embedding/Embedding.js";
|
|
8
9
|
import { ProviderNotConfiguredError, UnsupportedFeatureError, ModelCapabilityError } from "./errors/index.js";
|
|
9
10
|
import { resolveModelAlias } from "./model_aliases.js";
|
|
11
|
+
import { logger } from "./utils/logger.js";
|
|
10
12
|
import { config, Configuration } from "./config.js";
|
|
11
13
|
// Provider registration map
|
|
12
14
|
const PROVIDER_REGISTRARS = {
|
|
@@ -15,125 +17,63 @@ const PROVIDER_REGISTRARS = {
|
|
|
15
17
|
anthropic: registerAnthropicProvider,
|
|
16
18
|
deepseek: registerDeepSeekProvider,
|
|
17
19
|
ollama: registerOllamaProvider,
|
|
18
|
-
openrouter: registerOpenRouterProvider
|
|
20
|
+
openrouter: registerOpenRouterProvider
|
|
19
21
|
};
|
|
20
22
|
export class NodeLLMCore {
|
|
21
|
-
models = ModelRegistry;
|
|
22
23
|
config;
|
|
23
24
|
provider;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
retry = {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
25
|
+
retry;
|
|
26
|
+
defaults;
|
|
27
|
+
models = ModelRegistry;
|
|
28
|
+
pricing = PricingRegistry;
|
|
29
|
+
constructor(config, provider, retry = { attempts: 1, delayMs: 0 }, defaults = {}) {
|
|
30
|
+
this.config = config;
|
|
31
|
+
this.provider = provider;
|
|
32
|
+
this.retry = retry;
|
|
33
|
+
this.defaults = defaults;
|
|
34
|
+
Object.freeze(this.config);
|
|
35
|
+
Object.freeze(this.retry);
|
|
36
|
+
Object.freeze(this.defaults);
|
|
37
|
+
}
|
|
38
|
+
get defaultChatModel() {
|
|
39
|
+
return this.defaults.chat;
|
|
40
|
+
}
|
|
41
|
+
get defaultTranscriptionModel() {
|
|
42
|
+
return this.defaults.transcription;
|
|
43
|
+
}
|
|
44
|
+
get defaultModerationModel() {
|
|
45
|
+
return this.defaults.moderation;
|
|
46
|
+
}
|
|
47
|
+
get defaultEmbeddingModel() {
|
|
48
|
+
return this.defaults.embedding;
|
|
49
49
|
}
|
|
50
50
|
/**
|
|
51
51
|
* Returns a scoped LLM instance configured for a specific provider.
|
|
52
|
-
* This
|
|
53
|
-
* on the main NodeLLM singleton.
|
|
54
|
-
*
|
|
55
|
-
* @param providerName - The provider to use (e.g., "openai", "anthropic")
|
|
56
|
-
* @param scopedConfig - Optional configuration overrides for this scoped instance
|
|
57
|
-
*
|
|
58
|
-
* @example
|
|
59
|
-
* ```ts
|
|
60
|
-
* const openai = NodeLLM.withProvider("openai");
|
|
61
|
-
* const anthropic = NodeLLM.withProvider("anthropic");
|
|
62
|
-
*
|
|
63
|
-
* // These can now run in parallel without race conditions
|
|
64
|
-
* await Promise.all([
|
|
65
|
-
* openai.chat("gpt-4o").ask(prompt),
|
|
66
|
-
* anthropic.chat("claude-3-5-sonnet").ask(prompt),
|
|
67
|
-
* ]);
|
|
68
|
-
* ```
|
|
69
|
-
*
|
|
70
|
-
* @example With scoped credentials
|
|
71
|
-
* ```ts
|
|
72
|
-
* const customAnthropic = NodeLLM.withProvider("anthropic", {
|
|
73
|
-
* anthropicApiKey: "sk-ant-custom-key"
|
|
74
|
-
* });
|
|
75
|
-
* ```
|
|
52
|
+
* This returns a NEW immutable instance.
|
|
76
53
|
*/
|
|
77
54
|
withProvider(providerName, scopedConfig) {
|
|
78
|
-
const baseConfig =
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
55
|
+
const baseConfig = this.config instanceof Configuration ? this.config.toPlainObject() : this.config;
|
|
56
|
+
// We leverage createLLM to handle the resolution of the new provider string
|
|
57
|
+
return createLLM({
|
|
58
|
+
...baseConfig,
|
|
59
|
+
...scopedConfig,
|
|
60
|
+
provider: providerName,
|
|
61
|
+
// Preserve defaults unless overridden (conceptually, though createLLM takes specific keys)
|
|
62
|
+
defaultChatModel: this.defaults.chat,
|
|
63
|
+
defaultTranscriptionModel: this.defaults.transcription,
|
|
64
|
+
defaultModerationModel: this.defaults.moderation,
|
|
65
|
+
defaultEmbeddingModel: this.defaults.embedding
|
|
66
|
+
});
|
|
82
67
|
}
|
|
83
68
|
/**
|
|
84
69
|
* Register a custom LLM provider.
|
|
85
|
-
* This
|
|
86
|
-
*
|
|
87
|
-
* @param name - Unique identifier for the provider
|
|
88
|
-
* @param factory - A function that returns a Provider instance
|
|
70
|
+
* Note: This modifies the global provider registry.
|
|
89
71
|
*/
|
|
90
72
|
registerProvider(name, factory) {
|
|
91
73
|
providerRegistry.register(name, factory);
|
|
92
74
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (typeof configOrCallback === "function") {
|
|
96
|
-
configOrCallback(this.config);
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
// Object style: for setting provider and other options
|
|
100
|
-
const options = configOrCallback;
|
|
101
|
-
// Extract known control keys
|
|
102
|
-
const { provider, retry, defaultChatModel, defaultTranscriptionModel, defaultModerationModel, defaultEmbeddingModel, ...apiConfig } = options;
|
|
103
|
-
// Merge API keys into global config
|
|
104
|
-
Object.assign(this.config, apiConfig);
|
|
105
|
-
if (apiConfig.maxRetries !== undefined) {
|
|
106
|
-
this.retry.attempts = apiConfig.maxRetries + 1;
|
|
107
|
-
}
|
|
108
|
-
if (defaultChatModel) {
|
|
109
|
-
this.defaultChatModelId = defaultChatModel;
|
|
110
|
-
}
|
|
111
|
-
if (defaultTranscriptionModel) {
|
|
112
|
-
this.defaultTranscriptionModelId = defaultTranscriptionModel;
|
|
113
|
-
}
|
|
114
|
-
if (defaultModerationModel) {
|
|
115
|
-
this.defaultModerationModelId = defaultModerationModel;
|
|
116
|
-
}
|
|
117
|
-
if (defaultEmbeddingModel) {
|
|
118
|
-
this.defaultEmbeddingModelId = defaultEmbeddingModel;
|
|
119
|
-
}
|
|
120
|
-
if (retry) {
|
|
121
|
-
this.retry = {
|
|
122
|
-
attempts: retry.attempts ?? 1,
|
|
123
|
-
delayMs: retry.delayMs ?? 0,
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
if (typeof provider === "string") {
|
|
127
|
-
// Use the provider registrars map
|
|
128
|
-
const registrar = PROVIDER_REGISTRARS[provider];
|
|
129
|
-
if (registrar) {
|
|
130
|
-
registrar();
|
|
131
|
-
}
|
|
132
|
-
this.provider = providerRegistry.resolve(provider);
|
|
133
|
-
}
|
|
134
|
-
else if (provider) {
|
|
135
|
-
this.provider = provider;
|
|
136
|
-
}
|
|
75
|
+
getRetryConfig() {
|
|
76
|
+
return this.retry;
|
|
137
77
|
}
|
|
138
78
|
ensureProviderSupport(method) {
|
|
139
79
|
if (!this.provider) {
|
|
@@ -148,7 +88,7 @@ export class NodeLLMCore {
|
|
|
148
88
|
if (!this.provider) {
|
|
149
89
|
throw new ProviderNotConfiguredError();
|
|
150
90
|
}
|
|
151
|
-
const rawModel = model || this.
|
|
91
|
+
const rawModel = model || this.defaults.chat || this.provider.defaultModel("chat");
|
|
152
92
|
const resolvedModel = resolveModelAlias(rawModel, this.provider.id);
|
|
153
93
|
return new Chat(this.provider, resolvedModel, options, this.retry);
|
|
154
94
|
}
|
|
@@ -161,59 +101,50 @@ export class NodeLLMCore {
|
|
|
161
101
|
}
|
|
162
102
|
async paint(prompt, options) {
|
|
163
103
|
const provider = this.ensureProviderSupport("paint");
|
|
164
|
-
// Default to resolving aliases
|
|
165
104
|
const rawModel = options?.model;
|
|
166
105
|
const model = resolveModelAlias(rawModel || "", provider.id);
|
|
167
106
|
if (options?.assumeModelExists) {
|
|
168
|
-
|
|
107
|
+
logger.warn(`Skipping validation for model ${model}`);
|
|
169
108
|
}
|
|
170
|
-
else if (model &&
|
|
109
|
+
else if (model &&
|
|
110
|
+
provider.capabilities &&
|
|
111
|
+
!provider.capabilities.supportsImageGeneration(model)) {
|
|
171
112
|
throw new ModelCapabilityError(model, "image generation");
|
|
172
113
|
}
|
|
173
114
|
const response = await provider.paint({
|
|
174
115
|
prompt,
|
|
175
116
|
...options,
|
|
176
117
|
model,
|
|
177
|
-
requestTimeout: options?.requestTimeout ?? this.config.requestTimeout
|
|
118
|
+
requestTimeout: options?.requestTimeout ?? this.config.requestTimeout
|
|
178
119
|
});
|
|
179
120
|
return new GeneratedImage(response);
|
|
180
121
|
}
|
|
181
122
|
async transcribe(file, options) {
|
|
182
123
|
const provider = this.ensureProviderSupport("transcribe");
|
|
183
|
-
const rawModel = options?.model || this.
|
|
124
|
+
const rawModel = options?.model || this.defaults.transcription || "";
|
|
184
125
|
const model = resolveModelAlias(rawModel, provider.id);
|
|
185
126
|
if (options?.assumeModelExists) {
|
|
186
|
-
|
|
127
|
+
logger.warn(`Skipping validation for model ${model}`);
|
|
187
128
|
}
|
|
188
|
-
else if (model &&
|
|
129
|
+
else if (model &&
|
|
130
|
+
provider.capabilities &&
|
|
131
|
+
!provider.capabilities.supportsTranscription(model)) {
|
|
189
132
|
throw new ModelCapabilityError(model, "transcription");
|
|
190
133
|
}
|
|
191
134
|
const response = await provider.transcribe({
|
|
192
135
|
file,
|
|
193
136
|
...options,
|
|
194
137
|
model,
|
|
195
|
-
requestTimeout: options?.requestTimeout ?? this.config.requestTimeout
|
|
138
|
+
requestTimeout: options?.requestTimeout ?? this.config.requestTimeout
|
|
196
139
|
});
|
|
197
140
|
return new Transcription(response);
|
|
198
141
|
}
|
|
199
|
-
get defaultTranscriptionModel() {
|
|
200
|
-
return this.defaultTranscriptionModelId;
|
|
201
|
-
}
|
|
202
|
-
get defaultModerationModel() {
|
|
203
|
-
return this.defaultModerationModelId;
|
|
204
|
-
}
|
|
205
|
-
get defaultEmbeddingModel() {
|
|
206
|
-
return this.defaultEmbeddingModelId;
|
|
207
|
-
}
|
|
208
|
-
getRetryConfig() {
|
|
209
|
-
return this.retry;
|
|
210
|
-
}
|
|
211
142
|
async moderate(input, options) {
|
|
212
143
|
const provider = this.ensureProviderSupport("moderate");
|
|
213
|
-
const rawModel = options?.model || this.
|
|
144
|
+
const rawModel = options?.model || this.defaults.moderation || "";
|
|
214
145
|
const model = resolveModelAlias(rawModel, provider.id);
|
|
215
146
|
if (options?.assumeModelExists) {
|
|
216
|
-
|
|
147
|
+
logger.warn(`Skipping validation for model ${model}`);
|
|
217
148
|
}
|
|
218
149
|
else if (model && provider.capabilities && !provider.capabilities.supportsModeration(model)) {
|
|
219
150
|
throw new ModelCapabilityError(model, "moderation");
|
|
@@ -222,29 +153,170 @@ export class NodeLLMCore {
|
|
|
222
153
|
input,
|
|
223
154
|
...options,
|
|
224
155
|
model,
|
|
225
|
-
requestTimeout: options?.requestTimeout ?? this.config.requestTimeout
|
|
156
|
+
requestTimeout: options?.requestTimeout ?? this.config.requestTimeout
|
|
226
157
|
});
|
|
227
158
|
return new Moderation(response);
|
|
228
159
|
}
|
|
229
160
|
async embed(input, options) {
|
|
230
161
|
const provider = this.ensureProviderSupport("embed");
|
|
231
|
-
const rawModel = options?.model || this.
|
|
162
|
+
const rawModel = options?.model || this.defaults.embedding || "";
|
|
232
163
|
const model = resolveModelAlias(rawModel, provider.id);
|
|
233
164
|
const request = {
|
|
234
165
|
input,
|
|
235
166
|
model,
|
|
236
167
|
dimensions: options?.dimensions,
|
|
237
|
-
requestTimeout: options?.requestTimeout ?? this.config.requestTimeout
|
|
168
|
+
requestTimeout: options?.requestTimeout ?? this.config.requestTimeout
|
|
238
169
|
};
|
|
239
170
|
if (options?.assumeModelExists) {
|
|
240
|
-
|
|
171
|
+
logger.warn(`Skipping validation for model ${request.model}`);
|
|
241
172
|
}
|
|
242
|
-
else if (request.model &&
|
|
173
|
+
else if (request.model &&
|
|
174
|
+
provider.capabilities &&
|
|
175
|
+
!provider.capabilities.supportsEmbeddings(request.model)) {
|
|
243
176
|
throw new ModelCapabilityError(request.model, "embeddings");
|
|
244
177
|
}
|
|
245
178
|
const response = await provider.embed(request);
|
|
246
179
|
return new Embedding(response);
|
|
247
180
|
}
|
|
248
181
|
}
|
|
249
|
-
export { Transcription, Moderation, Embedding };
|
|
250
|
-
|
|
182
|
+
export { Transcription, Moderation, Embedding, ModelRegistry, PricingRegistry };
|
|
183
|
+
/**
|
|
184
|
+
* Creates a new immutable LLM instance.
|
|
185
|
+
*/
|
|
186
|
+
export function createLLM(options = {}) {
|
|
187
|
+
// 1. Resolve Configuration
|
|
188
|
+
// We must ensure we are working with a SNAPSHOT of the configuration,
|
|
189
|
+
// not a live reference to the global mutable Configuration instance.
|
|
190
|
+
let configSnapshot;
|
|
191
|
+
if (options instanceof Configuration) {
|
|
192
|
+
configSnapshot = options.toPlainObject();
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
// If it's a plain object, we merge it into a fresh Configuration to handle
|
|
196
|
+
// defaults and environment variable fallbacks correctly, then snapshot it.
|
|
197
|
+
const tempConfig = new Configuration();
|
|
198
|
+
Object.assign(tempConfig, options);
|
|
199
|
+
configSnapshot = tempConfig.toPlainObject();
|
|
200
|
+
}
|
|
201
|
+
// Use the snapshot for the rest of the logic
|
|
202
|
+
const baseConfig = configSnapshot;
|
|
203
|
+
// 2. Resolve Retry
|
|
204
|
+
let retry = { attempts: 1, delayMs: 0 };
|
|
205
|
+
if (baseConfig.maxRetries !== undefined) {
|
|
206
|
+
retry.attempts = baseConfig.maxRetries + 1;
|
|
207
|
+
}
|
|
208
|
+
if (options.retry) {
|
|
209
|
+
retry = {
|
|
210
|
+
attempts: options.retry.attempts ?? retry.attempts,
|
|
211
|
+
delayMs: options.retry.delayMs ?? retry.delayMs
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
// 3. Resolve Provider
|
|
215
|
+
let providerInstance;
|
|
216
|
+
if (typeof options.provider === "string") {
|
|
217
|
+
const registrar = PROVIDER_REGISTRARS[options.provider];
|
|
218
|
+
if (registrar)
|
|
219
|
+
registrar();
|
|
220
|
+
providerInstance = providerRegistry.resolve(options.provider, baseConfig);
|
|
221
|
+
}
|
|
222
|
+
else if (options.provider) {
|
|
223
|
+
providerInstance = options.provider;
|
|
224
|
+
}
|
|
225
|
+
// 4. Resolve Defaults
|
|
226
|
+
const defaults = {
|
|
227
|
+
chat: options.defaultChatModel,
|
|
228
|
+
transcription: options.defaultTranscriptionModel,
|
|
229
|
+
moderation: options.defaultModerationModel,
|
|
230
|
+
embedding: options.defaultEmbeddingModel
|
|
231
|
+
};
|
|
232
|
+
return new NodeLLMCore(baseConfig, providerInstance, retry, defaults);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* DEFAULT IMMUTABLE INSTANCE
|
|
236
|
+
*
|
|
237
|
+
* NodeLLM is a default immutable instance created at startup.
|
|
238
|
+
*
|
|
239
|
+
* **Architectural Contract**:
|
|
240
|
+
* - Configuration is captured from environment variables at module load time
|
|
241
|
+
* - The instance is frozen and cannot be mutated
|
|
242
|
+
* - Runtime provider switching is achieved via `withProvider()`, not mutation
|
|
243
|
+
* - Model names do NOT imply provider selection (provider must be explicit)
|
|
244
|
+
*
|
|
245
|
+
* **Usage Patterns**:
|
|
246
|
+
*
|
|
247
|
+
* 1. Using the default instance (if env vars are set):
|
|
248
|
+
* ```typescript
|
|
249
|
+
* import { NodeLLM } from '@node-llm/core';
|
|
250
|
+
* const chat = NodeLLM.chat("gpt-4");
|
|
251
|
+
* ```
|
|
252
|
+
*
|
|
253
|
+
* 2. Runtime provider switching (recommended):
|
|
254
|
+
* ```typescript
|
|
255
|
+
* const llm = NodeLLM.withProvider("openai", {
|
|
256
|
+
* openaiApiKey: process.env.OPENAI_API_KEY
|
|
257
|
+
* });
|
|
258
|
+
* const chat = llm.chat("gpt-4");
|
|
259
|
+
* ```
|
|
260
|
+
*
|
|
261
|
+
* 3. Creating custom instances:
|
|
262
|
+
* ```typescript
|
|
263
|
+
* import { createLLM } from '@node-llm/core';
|
|
264
|
+
* const llm = createLLM({ provider: "anthropic", anthropicApiKey: "..." });
|
|
265
|
+
* ```
|
|
266
|
+
*
|
|
267
|
+
* @see ARCHITECTURE.md for full contract details
|
|
268
|
+
*/
|
|
269
|
+
let _defaultInstance;
|
|
270
|
+
/**
|
|
271
|
+
* The global, immutable NodeLLM instance.
|
|
272
|
+
*
|
|
273
|
+
* DESIGN: Lazy Initialization
|
|
274
|
+
* To support 'import "dotenv/config"' patterns in ESM, this instance
|
|
275
|
+
* does NOT snapshot the environment until its first property access.
|
|
276
|
+
* Once accessed, it is frozen and becomes a stable, immutable contract.
|
|
277
|
+
*
|
|
278
|
+
* @see ARCHITECTURE.md for full contract details
|
|
279
|
+
*/
|
|
280
|
+
export const NodeLLM = new Proxy({}, {
|
|
281
|
+
get: (target, prop) => {
|
|
282
|
+
if (!_defaultInstance) {
|
|
283
|
+
_defaultInstance = createLLM(config);
|
|
284
|
+
Object.freeze(_defaultInstance);
|
|
285
|
+
}
|
|
286
|
+
const val = Reflect.get(_defaultInstance, prop);
|
|
287
|
+
// Only bind if it's a function AND it exists on the prototype (is a method)
|
|
288
|
+
// This avoids binding properties like 'models' which is a Class.
|
|
289
|
+
if (typeof val === "function" && prop in NodeLLMCore.prototype) {
|
|
290
|
+
return val.bind(_defaultInstance);
|
|
291
|
+
}
|
|
292
|
+
return val;
|
|
293
|
+
},
|
|
294
|
+
getPrototypeOf: () => NodeLLMCore.prototype,
|
|
295
|
+
getOwnPropertyDescriptor: (target, prop) => {
|
|
296
|
+
if (!_defaultInstance) {
|
|
297
|
+
_defaultInstance = createLLM(config);
|
|
298
|
+
Object.freeze(_defaultInstance);
|
|
299
|
+
}
|
|
300
|
+
return Object.getOwnPropertyDescriptor(_defaultInstance, prop);
|
|
301
|
+
},
|
|
302
|
+
ownKeys: () => {
|
|
303
|
+
if (!_defaultInstance) {
|
|
304
|
+
_defaultInstance = createLLM(config);
|
|
305
|
+
Object.freeze(_defaultInstance);
|
|
306
|
+
}
|
|
307
|
+
return Reflect.ownKeys(_defaultInstance);
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
/**
|
|
311
|
+
* LEGACY BOOTSTRAPPER (DEPRECATED)
|
|
312
|
+
*
|
|
313
|
+
* Provided to ease migration from the mutable singleton pattern.
|
|
314
|
+
* configure() will warn and no-op, as the global instance is now immutable.
|
|
315
|
+
*/
|
|
316
|
+
export const LegacyNodeLLM = {
|
|
317
|
+
configure(_options) {
|
|
318
|
+
console.warn("NodeLLM.configure() is deprecated and currently a NO-OP. " +
|
|
319
|
+
"The global NodeLLM instance is now immutable. " +
|
|
320
|
+
"Use createLLM() for instance-based LLMs or NodeLLM.withProvider() for runtime switching.");
|
|
321
|
+
}
|
|
322
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model_aliases.d.ts","sourceRoot":"","sources":["../src/model_aliases.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"model_aliases.d.ts","sourceRoot":"","sources":["../src/model_aliases.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,YAAY,GACpB,QAAQ,GACR,WAAW,GACX,QAAQ,GACR,UAAU,GACV,YAAY,GACZ,SAAS,GACT,UAAU,GACV,SAAS,GACT,MAAM,CAAC;AAEX,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,YAAY,GAAG,MAAM,CAiBhF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ModelRegistry.d.ts","sourceRoot":"","sources":["../../src/models/ModelRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"ModelRegistry.d.ts","sourceRoot":"","sources":["../../src/models/ModelRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAInC,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,MAAM,CAA6C;IAElE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAIlE;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,GAAG,KAAK,EAAE,GAAG,IAAI;IAe1C;;OAEG;IACH,MAAM,CAAC,GAAG,IAAI,KAAK,EAAE;IAIrB;;OAEG;IACH,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAKhF;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO;IAK/E;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAK9E;;OAEG;IACH,MAAM,CAAC,aAAa,CAClB,KAAK,EAAE;QACL,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,EACD,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM;sBAPA,MAAM;uBACL,MAAM;sBACP,MAAM;wBACJ,MAAM;2BACH,MAAM;;;;;sBAJX,MAAM;uBACL,MAAM;sBACP,MAAM;wBACJ,MAAM;2BACH,MAAM;;CAyC9B"}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { modelsData } from "./models.js";
|
|
2
|
+
import { PricingRegistry } from "./PricingRegistry.js";
|
|
2
3
|
export class ModelRegistry {
|
|
3
4
|
static models = modelsData;
|
|
4
5
|
static find(modelId, provider) {
|
|
5
|
-
return this.models.find(m =>
|
|
6
|
+
return this.models.find((m) => m.id.toLowerCase() === modelId.toLowerCase() && (!provider || m.provider === provider));
|
|
6
7
|
}
|
|
7
8
|
/**
|
|
8
9
|
* Add or update models in the registry.
|
|
9
10
|
*/
|
|
10
11
|
static save(models) {
|
|
11
12
|
const toAdd = Array.isArray(models) ? models : [models];
|
|
12
|
-
toAdd.forEach(newModel => {
|
|
13
|
-
const index = this.models.findIndex(m => m.id === newModel.id && m.provider === newModel.provider);
|
|
13
|
+
toAdd.forEach((newModel) => {
|
|
14
|
+
const index = this.models.findIndex((m) => m.id === newModel.id && m.provider === newModel.provider);
|
|
14
15
|
if (index >= 0) {
|
|
15
16
|
this.models[index] = newModel;
|
|
16
17
|
}
|
|
@@ -50,21 +51,22 @@ export class ModelRegistry {
|
|
|
50
51
|
* Calculate cost for usage.
|
|
51
52
|
*/
|
|
52
53
|
static calculateCost(usage, modelId, provider) {
|
|
53
|
-
const
|
|
54
|
-
if (!
|
|
54
|
+
const pricing = PricingRegistry.getPricing(modelId, provider);
|
|
55
|
+
if (!pricing || !pricing.text_tokens?.standard) {
|
|
55
56
|
return usage;
|
|
56
57
|
}
|
|
57
|
-
const prices =
|
|
58
|
+
const prices = pricing.text_tokens.standard;
|
|
58
59
|
const inputPrice = prices.input_per_million || 0;
|
|
59
60
|
const outputPrice = prices.output_per_million || 0;
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
// Fallback for reasoning: if not specified, default to 2.5x standard output price for specific reasoning models
|
|
62
|
+
// or just standard output price for others.
|
|
63
|
+
const reasoningPrice = prices.reasoning_output_per_million ?? (modelId.includes("reasoner") || modelId.includes("3-7") ? outputPrice * 2.5 : outputPrice);
|
|
64
|
+
const cachedPrice = prices.cached_input_per_million ?? inputPrice / 2;
|
|
62
65
|
const inputCost = ((usage.input_tokens - (usage.cached_tokens || 0)) / 1_000_000) * inputPrice +
|
|
63
66
|
((usage.cached_tokens || 0) / 1_000_000) * cachedPrice;
|
|
64
67
|
const outputTokens = usage.output_tokens - (usage.reasoning_tokens || 0);
|
|
65
68
|
const reasoningTokens = usage.reasoning_tokens || 0;
|
|
66
|
-
const outputCost = (outputTokens / 1_000_000) * outputPrice +
|
|
67
|
-
(reasoningTokens / 1_000_000) * reasoningPrice;
|
|
69
|
+
const outputCost = (outputTokens / 1_000_000) * outputPrice + (reasoningTokens / 1_000_000) * reasoningPrice;
|
|
68
70
|
const totalCost = inputCost + outputCost;
|
|
69
71
|
return {
|
|
70
72
|
...usage,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ModelPricing } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Registry for LLM pricing information.
|
|
4
|
+
* Priority: Runtime Overrides > Library Default Patterns > ModelRegistry (models.ts)
|
|
5
|
+
*/
|
|
6
|
+
export declare class PricingRegistry {
|
|
7
|
+
private static pricingOverrides;
|
|
8
|
+
private static lastUpdated;
|
|
9
|
+
private static DEFAULT_PATTERNS;
|
|
10
|
+
/**
|
|
11
|
+
* Get pricing for a model.
|
|
12
|
+
*/
|
|
13
|
+
static getPricing(modelId: string, provider: string): ModelPricing | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Register or override pricing at runtime.
|
|
16
|
+
*/
|
|
17
|
+
static register(provider: string, modelId: string, pricing: ModelPricing): void;
|
|
18
|
+
/**
|
|
19
|
+
* Fetch updates from a remote URL.
|
|
20
|
+
*/
|
|
21
|
+
static fetchUpdates(url: string): Promise<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* Get the timestamp of the last update.
|
|
24
|
+
*/
|
|
25
|
+
static getLastUpdated(): Date | null;
|
|
26
|
+
/**
|
|
27
|
+
* Reset overrides.
|
|
28
|
+
*/
|
|
29
|
+
static reset(): void;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=PricingRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PricingRegistry.d.ts","sourceRoot":"","sources":["../../src/models/PricingRegistry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAmC;IAClE,OAAO,CAAC,MAAM,CAAC,WAAW,CAA2B;IAGrD,OAAO,CAAC,MAAM,CAAC,gBAAgB,CA4B7B;IAEF;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAmB9E;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY;IAIxE;;OAEG;WACU,YAAY,CAAC,GAAG,EAAE,MAAM;IAmBrC;;OAEG;IACH,MAAM,CAAC,cAAc,IAAI,IAAI,GAAG,IAAI;IAIpC;;OAEG;IACH,MAAM,CAAC,KAAK;CAIb"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { ModelRegistry } from "./ModelRegistry.js";
|
|
2
|
+
/**
|
|
3
|
+
* Registry for LLM pricing information.
|
|
4
|
+
* Priority: Runtime Overrides > Library Default Patterns > ModelRegistry (models.ts)
|
|
5
|
+
*/
|
|
6
|
+
export class PricingRegistry {
|
|
7
|
+
static pricingOverrides = new Map();
|
|
8
|
+
static lastUpdated = new Date();
|
|
9
|
+
// Library-level fallbacks for common model families
|
|
10
|
+
static DEFAULT_PATTERNS = [
|
|
11
|
+
{
|
|
12
|
+
provider: "anthropic",
|
|
13
|
+
pattern: /claude-3-7/,
|
|
14
|
+
pricing: {
|
|
15
|
+
text_tokens: {
|
|
16
|
+
standard: { input_per_million: 3.0, output_per_million: 15.0, reasoning_output_per_million: 37.5 },
|
|
17
|
+
batch: { input_per_million: 1.5, output_per_million: 7.5, reasoning_output_per_million: 18.75 }
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
provider: "anthropic",
|
|
23
|
+
pattern: /claude-3/,
|
|
24
|
+
pricing: {
|
|
25
|
+
text_tokens: {
|
|
26
|
+
standard: { input_per_million: 3.0, output_per_million: 15.0 },
|
|
27
|
+
batch: { input_per_million: 1.5, output_per_million: 7.5 }
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
provider: "openai",
|
|
33
|
+
pattern: /gpt-3/,
|
|
34
|
+
pricing: {
|
|
35
|
+
text_tokens: { standard: { input_per_million: 0.5, output_per_million: 1.5 } }
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
];
|
|
39
|
+
/**
|
|
40
|
+
* Get pricing for a model.
|
|
41
|
+
*/
|
|
42
|
+
static getPricing(modelId, provider) {
|
|
43
|
+
// 1. Check custom overrides (Runtime/Remote)
|
|
44
|
+
const key = `${provider}/${modelId}`;
|
|
45
|
+
if (this.pricingOverrides.has(key)) {
|
|
46
|
+
return this.pricingOverrides.get(key);
|
|
47
|
+
}
|
|
48
|
+
// 2. Check library default patterns (Core Overrides)
|
|
49
|
+
for (const entry of this.DEFAULT_PATTERNS) {
|
|
50
|
+
if (entry.provider === provider && entry.pattern.test(modelId)) {
|
|
51
|
+
return entry.pricing;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// 3. Fallback to registry lookup (models.ts)
|
|
55
|
+
const model = ModelRegistry.find(modelId, provider);
|
|
56
|
+
return model?.pricing;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Register or override pricing at runtime.
|
|
60
|
+
*/
|
|
61
|
+
static register(provider, modelId, pricing) {
|
|
62
|
+
this.pricingOverrides.set(`${provider}/${modelId}`, pricing);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Fetch updates from a remote URL.
|
|
66
|
+
*/
|
|
67
|
+
static async fetchUpdates(url) {
|
|
68
|
+
try {
|
|
69
|
+
const response = await fetch(url);
|
|
70
|
+
if (!response.ok)
|
|
71
|
+
throw new Error(response.statusText);
|
|
72
|
+
const data = await response.json();
|
|
73
|
+
if (data.models) {
|
|
74
|
+
for (const [key, pricing] of Object.entries(data.models)) {
|
|
75
|
+
const [provider, modelId] = key.split("/");
|
|
76
|
+
if (provider && modelId)
|
|
77
|
+
this.register(provider, modelId, pricing);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
this.lastUpdated = new Date();
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
console.error("[NodeLLM] Error fetching pricing updates:", error);
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get the timestamp of the last update.
|
|
90
|
+
*/
|
|
91
|
+
static getLastUpdated() {
|
|
92
|
+
return this.lastUpdated;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Reset overrides.
|
|
96
|
+
*/
|
|
97
|
+
static reset() {
|
|
98
|
+
this.pricingOverrides.clear();
|
|
99
|
+
this.lastUpdated = new Date();
|
|
100
|
+
}
|
|
101
|
+
}
|