@stackbilt/llm-providers 1.2.0 → 1.5.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/LICENSE +0 -0
- package/README.md +58 -11
- package/dist/errors.d.ts +14 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +19 -0
- package/dist/errors.js.map +1 -1
- package/dist/factory.d.ts +8 -4
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +129 -47
- package/dist/factory.js.map +1 -1
- package/dist/image/index.d.ts +0 -0
- package/dist/image/index.d.ts.map +0 -0
- package/dist/image/index.js +0 -0
- package/dist/image/index.js.map +0 -0
- package/dist/image/provider.d.ts +0 -0
- package/dist/image/provider.d.ts.map +0 -0
- package/dist/image/provider.js +0 -0
- package/dist/image/provider.js.map +0 -0
- package/dist/image/types.d.ts +0 -0
- package/dist/image/types.d.ts.map +0 -0
- package/dist/image/types.js +0 -0
- package/dist/image/types.js.map +0 -0
- package/dist/index.d.ts +10 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -85
- package/dist/index.js.map +1 -1
- package/dist/model-catalog.d.ts +42 -0
- package/dist/model-catalog.d.ts.map +1 -0
- package/dist/model-catalog.js +532 -0
- package/dist/model-catalog.js.map +1 -0
- package/dist/providers/anthropic.d.ts +1 -0
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +47 -14
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/base.d.ts +0 -0
- package/dist/providers/base.d.ts.map +0 -0
- package/dist/providers/base.js +0 -0
- package/dist/providers/base.js.map +0 -0
- package/dist/providers/cerebras.d.ts +1 -0
- package/dist/providers/cerebras.d.ts.map +1 -1
- package/dist/providers/cerebras.js +54 -7
- package/dist/providers/cerebras.js.map +1 -1
- package/dist/providers/cloudflare.d.ts +3 -0
- package/dist/providers/cloudflare.d.ts.map +1 -1
- package/dist/providers/cloudflare.js +81 -18
- package/dist/providers/cloudflare.js.map +1 -1
- package/dist/providers/groq.d.ts +1 -0
- package/dist/providers/groq.d.ts.map +1 -1
- package/dist/providers/groq.js +58 -7
- package/dist/providers/groq.js.map +1 -1
- package/dist/providers/openai.d.ts +1 -0
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +50 -17
- package/dist/providers/openai.js.map +1 -1
- package/dist/types.d.ts +0 -0
- package/dist/types.d.ts.map +0 -0
- package/dist/types.js +0 -0
- package/dist/types.js.map +0 -0
- package/dist/utils/circuit-breaker.d.ts +0 -0
- package/dist/utils/circuit-breaker.d.ts.map +0 -0
- package/dist/utils/circuit-breaker.js +0 -0
- package/dist/utils/circuit-breaker.js.map +0 -0
- package/dist/utils/cost-tracker.d.ts +0 -0
- package/dist/utils/cost-tracker.d.ts.map +0 -0
- package/dist/utils/cost-tracker.js +0 -0
- package/dist/utils/cost-tracker.js.map +0 -0
- package/dist/utils/credit-ledger.d.ts +0 -0
- package/dist/utils/credit-ledger.d.ts.map +0 -0
- package/dist/utils/credit-ledger.js +0 -0
- package/dist/utils/credit-ledger.js.map +0 -0
- package/dist/utils/exhaustion.d.ts +0 -0
- package/dist/utils/exhaustion.d.ts.map +0 -0
- package/dist/utils/exhaustion.js +0 -0
- package/dist/utils/exhaustion.js.map +0 -0
- package/dist/utils/hooks.d.ts +10 -0
- package/dist/utils/hooks.d.ts.map +1 -1
- package/dist/utils/hooks.js +1 -1
- package/dist/utils/hooks.js.map +1 -1
- package/dist/utils/latency-histogram.d.ts +0 -0
- package/dist/utils/latency-histogram.d.ts.map +0 -0
- package/dist/utils/latency-histogram.js +0 -0
- package/dist/utils/latency-histogram.js.map +0 -0
- package/dist/utils/logger.d.ts +0 -0
- package/dist/utils/logger.d.ts.map +0 -0
- package/dist/utils/logger.js +0 -0
- package/dist/utils/logger.js.map +0 -0
- package/dist/utils/retry.d.ts +0 -0
- package/dist/utils/retry.d.ts.map +0 -0
- package/dist/utils/retry.js +0 -0
- package/dist/utils/retry.js.map +0 -0
- package/dist/utils/schema-validator.d.ts +67 -0
- package/dist/utils/schema-validator.d.ts.map +1 -0
- package/dist/utils/schema-validator.js +140 -0
- package/dist/utils/schema-validator.js.map +1 -0
- package/package.json +1 -1
package/LICENSE
CHANGED
|
File without changes
|
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@ A multi-provider LLM abstraction layer with automatic failover, graduated circui
|
|
|
8
8
|
- **Graduated circuit breaker** -- 4-state machine (closed / degraded / recovering / open) with probabilistic traffic routing prevents cascading failures
|
|
9
9
|
- **Exponential backoff retry** -- configurable delays, jitter, and per-error-class behavior
|
|
10
10
|
- **Cost tracking and optimization** -- per-provider cost attribution, budget alerts with CreditLedger, automatic routing to cheaper providers
|
|
11
|
+
- **Declarative model catalog** -- semantic model metadata drives recommendations, provider defaults, and fallback routing
|
|
11
12
|
- **Rate limit enforcement** -- CreditLedger tracks RPM/RPD/TPM/TPD per provider; factory skips providers that exceed limits
|
|
12
13
|
- **Streaming** -- SSE streaming support for all providers
|
|
13
14
|
- **Tool/function calling** -- OpenAI, Anthropic, Cerebras, and Cloudflare tool use with unified response format
|
|
@@ -66,11 +67,11 @@ const llm = LLMProviders.fromEnv(env, {
|
|
|
66
67
|
|
|
67
68
|
| Provider | Models | Streaming | Tools | Notes |
|
|
68
69
|
|----------|--------|-----------|-------|-------|
|
|
69
|
-
| **OpenAI** | GPT-4o
|
|
70
|
-
| **Anthropic** | Claude Opus 4.6, Sonnet 4.6, Sonnet 4, Haiku 4.5, 3.7 Sonnet, 3.5 Sonnet/Haiku, 3 Opus/Sonnet
|
|
71
|
-
| **Cloudflare** |
|
|
70
|
+
| **OpenAI** | GPT-4o Mini, GPT-4 Turbo, GPT-4, GPT-3.5 Turbo | Yes | Yes | Default: `gpt-4o-mini` |
|
|
71
|
+
| **Anthropic** | Claude Opus 4.6, Sonnet 4.6, Sonnet 4, Haiku 4.5, 3.7 Sonnet, 3.5 Sonnet/Haiku, 3 Opus/Sonnet | Yes | Yes | Default: `claude-haiku-4-5-20251001` |
|
|
72
|
+
| **Cloudflare** | Gemma 4 26B, Llama 4 Scout, GPT-OSS 120B, LLaMA 3.x, Mistral 7B, Qwen 1.5, TinyLlama, and more | Yes | GPT-OSS, Gemma 4, Llama 4 Scout | Default is request-aware and catalog-driven |
|
|
72
73
|
| **Cerebras** | LLaMA 3.1 8B, LLaMA 3.3 70B, ZAI-GLM 4.7, Qwen 3 235B | Yes | GLM/Qwen only | ~2,200 tok/s |
|
|
73
|
-
| **Groq** | LLaMA 3.3 70B Versatile, LLaMA 3.1 8B Instant | Yes |
|
|
74
|
+
| **Groq** | LLaMA 3.3 70B Versatile, LLaMA 3.1 8B Instant, GPT-OSS 120B | Yes | LLaMA 3.3 70B, GPT-OSS 120B | Ultra-fast inference |
|
|
74
75
|
|
|
75
76
|
### Provider Configuration
|
|
76
77
|
|
|
@@ -160,6 +161,49 @@ const llm = new LLMProviders({
|
|
|
160
161
|
});
|
|
161
162
|
```
|
|
162
163
|
|
|
164
|
+
## Model Catalog & Runtime Selection
|
|
165
|
+
|
|
166
|
+
Model selection is driven by a declarative catalog rather than a hardcoded fallback array. The selector intersects:
|
|
167
|
+
|
|
168
|
+
- requested use case and capabilities
|
|
169
|
+
- configured providers
|
|
170
|
+
- circuit breaker state (`CLOSED`, `DEGRADED`, `RECOVERING`, `OPEN`)
|
|
171
|
+
- CreditLedger utilization and projected burn/depletion pressure
|
|
172
|
+
|
|
173
|
+
The catalog also distinguishes active, compatibility, and retired models. Retired IDs can remain exported for compatibility, but they are not recommendation targets.
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
import {
|
|
177
|
+
MODEL_CATALOG,
|
|
178
|
+
MODEL_RECOMMENDATIONS,
|
|
179
|
+
getRecommendedModel,
|
|
180
|
+
inferUseCaseFromRequest
|
|
181
|
+
} from '@stackbilt/llm-providers';
|
|
182
|
+
|
|
183
|
+
const useCase = inferUseCaseFromRequest({
|
|
184
|
+
messages: [{ role: 'user', content: 'Call the weather tool' }],
|
|
185
|
+
tools: [{
|
|
186
|
+
type: 'function',
|
|
187
|
+
function: {
|
|
188
|
+
name: 'get_weather',
|
|
189
|
+
description: 'Get weather',
|
|
190
|
+
parameters: { type: 'object' }
|
|
191
|
+
}
|
|
192
|
+
}]
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const model = getRecommendedModel('TOOL_CALLING', ['cloudflare', 'openai']);
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
For runtime-aware recommendations from a configured instance:
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
const recommended = llm.getRecommendedModel({
|
|
202
|
+
messages: [{ role: 'user', content: 'Summarize this incident' }],
|
|
203
|
+
maxTokens: 800
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
163
207
|
## Fallback Rules
|
|
164
208
|
|
|
165
209
|
Customize when and how the factory falls back between providers:
|
|
@@ -178,7 +222,7 @@ const llm = new LLMProviders({
|
|
|
178
222
|
});
|
|
179
223
|
```
|
|
180
224
|
|
|
181
|
-
Default
|
|
225
|
+
Default provider precedence remains Cloudflare → Cerebras → Groq → Anthropic → OpenAI, but actual dispatch is catalog-driven and can be reordered at runtime by request fit, circuit-breaker state, and ledger burn-rate pressure.
|
|
182
226
|
|
|
183
227
|
## Error Handling
|
|
184
228
|
|
|
@@ -215,11 +259,11 @@ import { MODELS, getRecommendedModel } from '@stackbilt/llm-providers';
|
|
|
215
259
|
MODELS.CLAUDE_OPUS_4_6; // 'claude-opus-4-6-20250618'
|
|
216
260
|
MODELS.CLAUDE_SONNET_4_6; // 'claude-sonnet-4-6-20250618'
|
|
217
261
|
MODELS.CLAUDE_HAIKU_4_5; // 'claude-haiku-4-5-20251001'
|
|
218
|
-
MODELS.GPT_4O; // 'gpt-4o'
|
|
262
|
+
MODELS.GPT_4O; // 'gpt-4o' (deprecated / compatibility only)
|
|
219
263
|
MODELS.GPT_4O_MINI; // 'gpt-4o-mini'
|
|
220
264
|
MODELS.CEREBRAS_ZAI_GLM_4_7; // 'zai-glm-4.7'
|
|
221
265
|
|
|
222
|
-
// Get best model for a use case given available providers
|
|
266
|
+
// Get best active model for a use case given available providers
|
|
223
267
|
const model = getRecommendedModel('COST_EFFECTIVE', ['openai', 'cloudflare']);
|
|
224
268
|
```
|
|
225
269
|
|
|
@@ -230,12 +274,12 @@ const model = getRecommendedModel('COST_EFFECTIVE', ['openai', 'cloudflare']);
|
|
|
230
274
|
| Class | Description |
|
|
231
275
|
|-------|-------------|
|
|
232
276
|
| `LLMProviders` | High-level facade -- initialize providers, generate responses, check health |
|
|
233
|
-
| `LLMProviderFactory` | Lower-level factory with provider chain building and fallback logic |
|
|
277
|
+
| `LLMProviderFactory` | Lower-level factory with provider chain building, catalog-based routing, and fallback logic |
|
|
234
278
|
| `OpenAIProvider` | OpenAI GPT models (streaming, tools) |
|
|
235
279
|
| `AnthropicProvider` | Anthropic Claude models (streaming, tools) |
|
|
236
|
-
| `CloudflareProvider` | Cloudflare Workers AI (streaming, tools on GPT-OSS, batch) |
|
|
280
|
+
| `CloudflareProvider` | Cloudflare Workers AI (streaming, tools on GPT-OSS/Gemma 4/Llama 4, batch) |
|
|
237
281
|
| `CerebrasProvider` | Cerebras fast inference (streaming, tools on GLM/Qwen) |
|
|
238
|
-
| `GroqProvider` | Groq fast inference (streaming) |
|
|
282
|
+
| `GroqProvider` | Groq fast inference (streaming, tools on GPT-OSS/LLaMA 3.3 70B) |
|
|
239
283
|
| `BaseProvider` | Abstract base with shared resiliency, metrics, and cost calculation |
|
|
240
284
|
|
|
241
285
|
### Utilities
|
|
@@ -248,6 +292,7 @@ const model = getRecommendedModel('COST_EFFECTIVE', ['openai', 'cloudflare']);
|
|
|
248
292
|
| `CostTracker` | Per-provider cost accumulation and budget alerts |
|
|
249
293
|
| `CreditLedger` | Monthly budgets, rate limits, burn rate projection, threshold events |
|
|
250
294
|
| `CostOptimizer` | Static methods for optimal provider selection |
|
|
295
|
+
| `MODEL_CATALOG` | Declarative model metadata for routing and recommendation |
|
|
251
296
|
| `ImageProvider` | Multi-provider image generation (Cloudflare SDXL/FLUX, Google Gemini) |
|
|
252
297
|
|
|
253
298
|
### Logger
|
|
@@ -268,6 +313,7 @@ const model = getRecommendedModel('COST_EFFECTIVE', ['openai', 'cloudflare']);
|
|
|
268
313
|
| `ProviderFactoryConfig` | Factory config: provider configs, fallback rules, ledger, logger |
|
|
269
314
|
| `CostAnalytics` | Cost breakdown, total, and recommendations |
|
|
270
315
|
| `ProviderHealthEntry` | Health status, metrics, circuit breaker state, capabilities |
|
|
316
|
+
| `ModelCatalogEntry` | Declarative model metadata: provider, lifecycle, capabilities, use cases |
|
|
271
317
|
|
|
272
318
|
### Factory Functions
|
|
273
319
|
|
|
@@ -276,7 +322,8 @@ const model = getRecommendedModel('COST_EFFECTIVE', ['openai', 'cloudflare']);
|
|
|
276
322
|
| `createLLMProviders(config)` | Create an `LLMProviders` instance |
|
|
277
323
|
| `createCostOptimizedLLMProviders(config)` | Create with cost optimization, circuit breakers, and retries enabled |
|
|
278
324
|
| `LLMProviders.fromEnv(env)` | Auto-discover providers from environment variables |
|
|
279
|
-
| `getRecommendedModel(
|
|
325
|
+
| `llm.getRecommendedModel(request, useCase?)` | Runtime recommendation using configured providers, health, and ledger state |
|
|
326
|
+
| `getRecommendedModel(useCase, providers, context?)` | Pick the best active model for a use case |
|
|
280
327
|
| `retry(fn, config)` | One-shot retry wrapper for any async function |
|
|
281
328
|
|
|
282
329
|
## License
|
package/dist/errors.d.ts
CHANGED
|
@@ -56,6 +56,20 @@ export declare class ToolLoopLimitError extends LLMProviderError {
|
|
|
56
56
|
export declare class ToolLoopAbortedError extends LLMProviderError {
|
|
57
57
|
constructor(provider: string, message?: string);
|
|
58
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Thrown when a provider's response envelope fails runtime schema validation.
|
|
61
|
+
*
|
|
62
|
+
* Indicates the upstream API silently changed shape - a field was renamed,
|
|
63
|
+
* removed, or had its type changed. Non-retryable: retrying hits the same
|
|
64
|
+
* broken shape. The factory treats this as fallback-eligible so traffic
|
|
65
|
+
* routes to a healthy provider while the drift is investigated.
|
|
66
|
+
*/
|
|
67
|
+
export declare class SchemaDriftError extends LLMProviderError {
|
|
68
|
+
path: string;
|
|
69
|
+
expected: string;
|
|
70
|
+
actual: string;
|
|
71
|
+
constructor(provider: string, path: string, expected: string, actual: string);
|
|
72
|
+
}
|
|
59
73
|
/**
|
|
60
74
|
* Error factory for creating provider-specific errors from HTTP responses
|
|
61
75
|
*/
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.js
CHANGED
|
@@ -95,6 +95,25 @@ export class ToolLoopAbortedError extends LLMProviderError {
|
|
|
95
95
|
super(message, 'TOOL_LOOP_ABORTED', provider, false, 400);
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Thrown when a provider's response envelope fails runtime schema validation.
|
|
100
|
+
*
|
|
101
|
+
* Indicates the upstream API silently changed shape - a field was renamed,
|
|
102
|
+
* removed, or had its type changed. Non-retryable: retrying hits the same
|
|
103
|
+
* broken shape. The factory treats this as fallback-eligible so traffic
|
|
104
|
+
* routes to a healthy provider while the drift is investigated.
|
|
105
|
+
*/
|
|
106
|
+
export class SchemaDriftError extends LLMProviderError {
|
|
107
|
+
path;
|
|
108
|
+
expected;
|
|
109
|
+
actual;
|
|
110
|
+
constructor(provider, path, expected, actual) {
|
|
111
|
+
super(`Response schema drift at ${path}: expected ${expected}, got ${actual}`, 'SCHEMA_DRIFT', provider, false, 422);
|
|
112
|
+
this.path = path;
|
|
113
|
+
this.expected = expected;
|
|
114
|
+
this.actual = actual;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
98
117
|
export class LLMErrorFactory {
|
|
99
118
|
static fromHttpResponse(provider, statusCode, responseBody, message) {
|
|
100
119
|
const defaultMessage = message || responseBody?.message || responseBody?.error?.message || 'Unknown error';
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/factory.d.ts
CHANGED
|
@@ -7,12 +7,14 @@ import type { Logger } from './utils/logger';
|
|
|
7
7
|
import type { ObservabilityHooks } from './utils/hooks';
|
|
8
8
|
import type { ProviderCostBreakdownEntry } from './utils/cost-tracker';
|
|
9
9
|
import type { CreditLedger } from './utils/credit-ledger';
|
|
10
|
+
import { type ModelRecommendationUseCase } from './model-catalog';
|
|
10
11
|
export interface ProviderFactoryConfig {
|
|
11
12
|
openai?: OpenAIConfig;
|
|
12
13
|
anthropic?: AnthropicConfig;
|
|
13
14
|
cloudflare?: CloudflareConfig;
|
|
14
15
|
cerebras?: CerebrasConfig;
|
|
15
16
|
groq?: GroqConfig;
|
|
17
|
+
preferredProvider?: 'openai' | 'anthropic' | 'cloudflare' | 'cerebras' | 'groq' | 'auto';
|
|
16
18
|
defaultProvider?: 'openai' | 'anthropic' | 'cloudflare' | 'cerebras' | 'groq' | 'auto';
|
|
17
19
|
fallbackRules?: FallbackRule[];
|
|
18
20
|
costOptimization?: boolean;
|
|
@@ -65,13 +67,13 @@ export declare class LLMProviderFactory {
|
|
|
65
67
|
analyzeImage(input: AnalyzeImageInput): Promise<LLMResponse>;
|
|
66
68
|
getProviderBalance(provider?: string): Promise<ProviderBalance | Record<string, ProviderBalance>>;
|
|
67
69
|
/**
|
|
68
|
-
*
|
|
70
|
+
* Recommend a model dynamically from the declarative catalog.
|
|
69
71
|
*/
|
|
70
|
-
|
|
72
|
+
getRecommendedModel(request: LLMRequest, useCase?: ModelRecommendationUseCase): string;
|
|
71
73
|
/**
|
|
72
|
-
*
|
|
74
|
+
* Build provider chain and provider-specific default models from the catalog.
|
|
73
75
|
*/
|
|
74
|
-
private
|
|
76
|
+
private buildProviderPlan;
|
|
75
77
|
/**
|
|
76
78
|
* Get appropriate provider for a specific model
|
|
77
79
|
*/
|
|
@@ -136,6 +138,8 @@ export declare class LLMProviderFactory {
|
|
|
136
138
|
private parseJsonResponse;
|
|
137
139
|
private getDefaultVisionModel;
|
|
138
140
|
private providerSupportsVision;
|
|
141
|
+
private getSelectionHealth;
|
|
142
|
+
private resolveUseCase;
|
|
139
143
|
private getSingleProviderBalance;
|
|
140
144
|
private getLedgerBalance;
|
|
141
145
|
private isLedgerLimited;
|
package/dist/factory.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,WAAW,EAEX,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,cAAc,EAEd,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,UAAU,EACV,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,SAAS,EAGT,YAAY,EACZ,eAAe,EAEhB,MAAM,SAAS,CAAC;AAEjB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAQxD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"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"}
|
package/dist/factory.js
CHANGED
|
@@ -13,7 +13,8 @@ import { CostTracker, defaultCostTracker } from './utils/cost-tracker';
|
|
|
13
13
|
import { defaultCircuitBreakerManager } from './utils/circuit-breaker';
|
|
14
14
|
import { defaultExhaustionRegistry } from './utils/exhaustion';
|
|
15
15
|
import { defaultLatencyHistogram } from './utils/latency-histogram';
|
|
16
|
-
import {
|
|
16
|
+
import { PROVIDER_FALLBACK_ORDER, getProviderDefaultModel, getProviderForCatalogModel, inferUseCaseFromRequest, rankModels, } from './model-catalog';
|
|
17
|
+
import { LLMProviderError, ConfigurationError, CircuitBreakerOpenError, AuthenticationError, RateLimitError, QuotaExceededError, SchemaDriftError, ToolLoopAbortedError, ToolLoopLimitError, } from './errors';
|
|
17
18
|
export class LLMProviderFactory {
|
|
18
19
|
providers = new Map();
|
|
19
20
|
config;
|
|
@@ -73,8 +74,9 @@ export class LLMProviderFactory {
|
|
|
73
74
|
* Generate response with intelligent provider selection and fallback
|
|
74
75
|
*/
|
|
75
76
|
async generateResponse(request) {
|
|
76
|
-
const
|
|
77
|
-
const
|
|
77
|
+
const selectionPlan = this.buildProviderPlan(request);
|
|
78
|
+
const providerChain = selectionPlan.chain;
|
|
79
|
+
const providerModels = selectionPlan.providerModels;
|
|
78
80
|
let lastError = null;
|
|
79
81
|
let previousProvider = null;
|
|
80
82
|
for (let index = 0; index < providerChain.length; index++) {
|
|
@@ -167,6 +169,19 @@ export class LLMProviderFactory {
|
|
|
167
169
|
timestamp: Date.now(),
|
|
168
170
|
});
|
|
169
171
|
}
|
|
172
|
+
// Schema drift — the upstream API silently changed shape. Surface
|
|
173
|
+
// structured telemetry so oncall sees the drift before it cascades.
|
|
174
|
+
if (err instanceof SchemaDriftError) {
|
|
175
|
+
this.hooks.onSchemaDrift?.({
|
|
176
|
+
provider: providerName,
|
|
177
|
+
model: request.model,
|
|
178
|
+
requestId: request.requestId,
|
|
179
|
+
path: err.path,
|
|
180
|
+
expected: err.expected,
|
|
181
|
+
actual: err.actual,
|
|
182
|
+
timestamp: Date.now(),
|
|
183
|
+
});
|
|
184
|
+
}
|
|
170
185
|
const fallbackDecision = this.getFallbackDecision(error);
|
|
171
186
|
if (!fallbackDecision.shouldFallback) {
|
|
172
187
|
throw error;
|
|
@@ -178,8 +193,9 @@ export class LLMProviderFactory {
|
|
|
178
193
|
throw lastError || new LLMProviderError('All providers failed', 'ALL_PROVIDERS_FAILED', 'factory', false);
|
|
179
194
|
}
|
|
180
195
|
async generateResponseStream(request) {
|
|
181
|
-
const
|
|
182
|
-
const
|
|
196
|
+
const selectionPlan = this.buildProviderPlan({ ...request, stream: true });
|
|
197
|
+
const providerChain = selectionPlan.chain;
|
|
198
|
+
const providerModels = selectionPlan.providerModels;
|
|
183
199
|
let lastError = null;
|
|
184
200
|
let previousProvider = null;
|
|
185
201
|
for (let index = 0; index < providerChain.length; index++) {
|
|
@@ -401,66 +417,82 @@ export class LLMProviderFactory {
|
|
|
401
417
|
return result;
|
|
402
418
|
}
|
|
403
419
|
/**
|
|
404
|
-
*
|
|
420
|
+
* Recommend a model dynamically from the declarative catalog.
|
|
421
|
+
*/
|
|
422
|
+
getRecommendedModel(request, useCase = this.resolveUseCase(request)) {
|
|
423
|
+
const ranked = rankModels(useCase, Array.from(this.providers.keys()), {
|
|
424
|
+
request,
|
|
425
|
+
providerHealth: this.getSelectionHealth(),
|
|
426
|
+
ledger: this.config.ledger,
|
|
427
|
+
});
|
|
428
|
+
if (ranked.length > 0) {
|
|
429
|
+
return ranked[0].model;
|
|
430
|
+
}
|
|
431
|
+
const fallbackProvider = PROVIDER_FALLBACK_ORDER.find(provider => this.providers.has(provider));
|
|
432
|
+
if (!fallbackProvider) {
|
|
433
|
+
throw new ConfigurationError('factory', 'No available providers configured');
|
|
434
|
+
}
|
|
435
|
+
return getProviderDefaultModel(fallbackProvider, request);
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Build provider chain and provider-specific default models from the catalog.
|
|
405
439
|
*/
|
|
406
|
-
|
|
440
|
+
buildProviderPlan(request) {
|
|
407
441
|
const chain = [];
|
|
442
|
+
const providerModels = new Map();
|
|
443
|
+
const selectionHealth = this.getSelectionHealth();
|
|
444
|
+
const useCase = this.resolveUseCase(request);
|
|
408
445
|
// If specific provider requested, try it first
|
|
409
446
|
if (request.model) {
|
|
410
447
|
const providerForModel = this.getProviderForModel(request.model);
|
|
411
448
|
if (providerForModel && this.providers.has(providerForModel)) {
|
|
412
449
|
chain.push(providerForModel);
|
|
450
|
+
providerModels.set(providerForModel, request.model);
|
|
413
451
|
}
|
|
414
452
|
}
|
|
415
453
|
// Add default provider if different from model provider
|
|
416
|
-
const defaultProvider = this.config.defaultProvider
|
|
454
|
+
const defaultProvider = this.config.preferredProvider ?? this.config.defaultProvider ?? 'auto';
|
|
417
455
|
if (defaultProvider !== 'auto' && !chain.includes(defaultProvider)) {
|
|
418
456
|
if (this.providers.has(defaultProvider)) {
|
|
419
457
|
chain.push(defaultProvider);
|
|
458
|
+
if (!request.model) {
|
|
459
|
+
providerModels.set(defaultProvider, getProviderDefaultModel(defaultProvider, request));
|
|
460
|
+
}
|
|
420
461
|
}
|
|
421
462
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
463
|
+
const rankedModels = rankModels(useCase, Array.from(this.providers.keys()), {
|
|
464
|
+
request,
|
|
465
|
+
providerHealth: selectionHealth,
|
|
466
|
+
ledger: this.config.ledger,
|
|
467
|
+
});
|
|
468
|
+
for (const candidate of rankedModels) {
|
|
469
|
+
if (!providerModels.has(candidate.provider)) {
|
|
470
|
+
providerModels.set(candidate.provider, candidate.model);
|
|
471
|
+
}
|
|
472
|
+
if (!chain.includes(candidate.provider) && this.providers.has(candidate.provider)) {
|
|
473
|
+
chain.push(candidate.provider);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
for (const provider of PROVIDER_FALLBACK_ORDER) {
|
|
477
|
+
if (!this.providers.has(provider))
|
|
478
|
+
continue;
|
|
479
|
+
if (!chain.includes(provider)) {
|
|
426
480
|
chain.push(provider);
|
|
427
481
|
}
|
|
482
|
+
if (!providerModels.has(provider)) {
|
|
483
|
+
providerModels.set(provider, getProviderDefaultModel(provider, request));
|
|
484
|
+
}
|
|
428
485
|
}
|
|
429
|
-
return chain;
|
|
430
|
-
}
|
|
431
|
-
/**
|
|
432
|
-
* Get prioritized list of providers based on cost optimization and capabilities
|
|
433
|
-
*/
|
|
434
|
-
getPrioritizedProviders(request) {
|
|
435
|
-
const visionOnly = (request.images?.length ?? 0) > 0;
|
|
436
|
-
if (!this.config.costOptimization) {
|
|
437
|
-
// Default priority: all configured providers, cheapest first
|
|
438
|
-
return ['cloudflare', 'cerebras', 'groq', 'anthropic', 'openai']
|
|
439
|
-
.filter(p => this.providers.has(p))
|
|
440
|
-
.filter(p => !visionOnly || this.providerSupportsVision(p));
|
|
441
|
-
}
|
|
442
|
-
// Cost-optimized routing
|
|
443
|
-
const providers = Array.from(this.providers.keys())
|
|
444
|
-
.filter(p => !visionOnly || this.providerSupportsVision(p));
|
|
445
|
-
const sortedProviders = [...providers].sort((a, b) => {
|
|
446
|
-
const providerA = this.providers.get(a);
|
|
447
|
-
const providerB = this.providers.get(b);
|
|
448
|
-
const estimatedCostA = providerA.estimateCost(request);
|
|
449
|
-
const estimatedCostB = providerB.estimateCost(request);
|
|
450
|
-
if (estimatedCostA !== estimatedCostB) {
|
|
451
|
-
return estimatedCostA - estimatedCostB;
|
|
452
|
-
}
|
|
453
|
-
// If estimates tie, prefer the provider with less accumulated spend.
|
|
454
|
-
const trackedCostA = this.costTracker.getProviderCost(a);
|
|
455
|
-
const trackedCostB = this.costTracker.getProviderCost(b);
|
|
456
|
-
return trackedCostA - trackedCostB;
|
|
457
|
-
});
|
|
458
|
-
return sortedProviders;
|
|
486
|
+
return { chain, providerModels, useCase };
|
|
459
487
|
}
|
|
460
488
|
/**
|
|
461
489
|
* Get appropriate provider for a specific model
|
|
462
490
|
*/
|
|
463
491
|
getProviderForModel(model) {
|
|
492
|
+
const catalogProvider = getProviderForCatalogModel(model);
|
|
493
|
+
if (catalogProvider) {
|
|
494
|
+
return catalogProvider;
|
|
495
|
+
}
|
|
464
496
|
// OpenAI models
|
|
465
497
|
if (model.startsWith('gpt-')) {
|
|
466
498
|
return 'openai';
|
|
@@ -517,10 +549,16 @@ export class LLMProviderFactory {
|
|
|
517
549
|
error instanceof RateLimitError) {
|
|
518
550
|
return { shouldFallback: true };
|
|
519
551
|
}
|
|
552
|
+
// Schema drift: provider's response shape changed. Retry won't help;
|
|
553
|
+
// only another provider can. Defense against silent API deprecations.
|
|
554
|
+
if (error instanceof SchemaDriftError) {
|
|
555
|
+
return { shouldFallback: true };
|
|
556
|
+
}
|
|
520
557
|
if (error instanceof LLMProviderError) {
|
|
521
558
|
if (error.code === 'SERVER_ERROR' ||
|
|
522
559
|
error.code === 'NETWORK_ERROR' ||
|
|
523
|
-
error.code === 'TIMEOUT'
|
|
560
|
+
error.code === 'TIMEOUT' ||
|
|
561
|
+
error.code === 'SCHEMA_DRIFT') {
|
|
524
562
|
return { shouldFallback: true };
|
|
525
563
|
}
|
|
526
564
|
}
|
|
@@ -834,15 +872,59 @@ export class LLMProviderFactory {
|
|
|
834
872
|
getDefaultVisionModel() {
|
|
835
873
|
if (this.config.defaultVisionModel)
|
|
836
874
|
return this.config.defaultVisionModel;
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
875
|
+
const visionRequest = {
|
|
876
|
+
messages: [{ role: 'user', content: 'Describe this image.' }],
|
|
877
|
+
images: [{}],
|
|
878
|
+
maxTokens: 1
|
|
879
|
+
};
|
|
880
|
+
if (this.providers.has('anthropic')) {
|
|
881
|
+
return getProviderDefaultModel('anthropic', visionRequest);
|
|
882
|
+
}
|
|
883
|
+
if (this.providers.has('openai')) {
|
|
884
|
+
return getProviderDefaultModel('openai', visionRequest);
|
|
885
|
+
}
|
|
886
|
+
if (this.providers.has('cloudflare')) {
|
|
887
|
+
return getProviderDefaultModel('cloudflare', visionRequest);
|
|
888
|
+
}
|
|
841
889
|
return undefined;
|
|
842
890
|
}
|
|
843
891
|
providerSupportsVision(providerName) {
|
|
844
892
|
return this.providers.get(providerName)?.supportsVision === true;
|
|
845
893
|
}
|
|
894
|
+
getSelectionHealth() {
|
|
895
|
+
const health = {};
|
|
896
|
+
for (const providerName of this.providers.keys()) {
|
|
897
|
+
const metrics = this.providers.get(providerName)?.getMetrics();
|
|
898
|
+
const circuitBreaker = this.config.enableCircuitBreaker
|
|
899
|
+
? defaultCircuitBreakerManager.getBreaker(providerName).getState()
|
|
900
|
+
: null;
|
|
901
|
+
health[providerName] = {
|
|
902
|
+
healthy: circuitBreaker?.state !== 'OPEN',
|
|
903
|
+
metrics,
|
|
904
|
+
circuitBreaker,
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
return health;
|
|
908
|
+
}
|
|
909
|
+
resolveUseCase(request) {
|
|
910
|
+
const metadataUseCase = request.metadata?.useCase;
|
|
911
|
+
if (typeof metadataUseCase === 'string') {
|
|
912
|
+
const normalized = metadataUseCase.toUpperCase();
|
|
913
|
+
if (normalized === 'COST_EFFECTIVE' ||
|
|
914
|
+
normalized === 'HIGH_PERFORMANCE' ||
|
|
915
|
+
normalized === 'BALANCED' ||
|
|
916
|
+
normalized === 'TOOL_CALLING' ||
|
|
917
|
+
normalized === 'LONG_CONTEXT' ||
|
|
918
|
+
normalized === 'VISION') {
|
|
919
|
+
return normalized;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
const inferredUseCase = inferUseCaseFromRequest(request);
|
|
923
|
+
if (this.config.costOptimization && inferredUseCase === 'BALANCED') {
|
|
924
|
+
return 'COST_EFFECTIVE';
|
|
925
|
+
}
|
|
926
|
+
return inferredUseCase;
|
|
927
|
+
}
|
|
846
928
|
async getSingleProviderBalance(providerName) {
|
|
847
929
|
const ledgerBalance = this.getLedgerBalance(providerName);
|
|
848
930
|
if (ledgerBalance) {
|