mcp-agent-foundry 1.0.1 → 1.2.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 (78) hide show
  1. package/README.md +22 -2
  2. package/dist/cli/setup-wizard.d.ts +4 -2
  3. package/dist/cli/setup-wizard.d.ts.map +1 -1
  4. package/dist/cli/setup-wizard.js +1024 -37
  5. package/dist/cli/setup-wizard.js.map +1 -1
  6. package/dist/cli/test-connection.d.ts +34 -2
  7. package/dist/cli/test-connection.d.ts.map +1 -1
  8. package/dist/cli/test-connection.js +384 -2
  9. package/dist/cli/test-connection.js.map +1 -1
  10. package/dist/cli.d.ts +15 -3
  11. package/dist/cli.d.ts.map +1 -1
  12. package/dist/cli.js +198 -30
  13. package/dist/cli.js.map +1 -1
  14. package/dist/config/defaults.d.ts +2 -2
  15. package/dist/config/defaults.js +16 -16
  16. package/dist/config/defaults.js.map +1 -1
  17. package/dist/config/validator.d.ts +113 -0
  18. package/dist/config/validator.d.ts.map +1 -1
  19. package/dist/config/validator.js +113 -0
  20. package/dist/config/validator.js.map +1 -1
  21. package/dist/failover/health-tracker.d.ts +175 -0
  22. package/dist/failover/health-tracker.d.ts.map +1 -0
  23. package/dist/failover/health-tracker.js +350 -0
  24. package/dist/failover/health-tracker.js.map +1 -0
  25. package/dist/failover/index.d.ts +9 -0
  26. package/dist/failover/index.d.ts.map +1 -0
  27. package/dist/failover/index.js +9 -0
  28. package/dist/failover/index.js.map +1 -0
  29. package/dist/failover/orchestrator.d.ts +189 -0
  30. package/dist/failover/orchestrator.d.ts.map +1 -0
  31. package/dist/failover/orchestrator.js +488 -0
  32. package/dist/failover/orchestrator.js.map +1 -0
  33. package/dist/failover/pricing.d.ts +115 -0
  34. package/dist/failover/pricing.d.ts.map +1 -0
  35. package/dist/failover/pricing.js +283 -0
  36. package/dist/failover/pricing.js.map +1 -0
  37. package/dist/persistence/state-schema.d.ts +50 -0
  38. package/dist/persistence/state-schema.d.ts.map +1 -1
  39. package/dist/persistence/state-schema.js +2 -0
  40. package/dist/persistence/state-schema.js.map +1 -1
  41. package/dist/providers/fireworks.d.ts +23 -0
  42. package/dist/providers/fireworks.d.ts.map +1 -0
  43. package/dist/providers/fireworks.js +31 -0
  44. package/dist/providers/fireworks.js.map +1 -0
  45. package/dist/providers/groq.d.ts +23 -0
  46. package/dist/providers/groq.d.ts.map +1 -0
  47. package/dist/providers/groq.js +31 -0
  48. package/dist/providers/groq.js.map +1 -0
  49. package/dist/providers/kimi-code.d.ts +32 -0
  50. package/dist/providers/kimi-code.d.ts.map +1 -0
  51. package/dist/providers/kimi-code.js +46 -0
  52. package/dist/providers/kimi-code.js.map +1 -0
  53. package/dist/providers/kimi.d.ts +1 -1
  54. package/dist/providers/kimi.js +1 -1
  55. package/dist/providers/openrouter.d.ts +23 -0
  56. package/dist/providers/openrouter.d.ts.map +1 -0
  57. package/dist/providers/openrouter.js +31 -0
  58. package/dist/providers/openrouter.js.map +1 -0
  59. package/dist/providers/perplexity.d.ts +29 -0
  60. package/dist/providers/perplexity.d.ts.map +1 -0
  61. package/dist/providers/perplexity.js +51 -0
  62. package/dist/providers/perplexity.js.map +1 -0
  63. package/dist/providers/together.d.ts +23 -0
  64. package/dist/providers/together.d.ts.map +1 -0
  65. package/dist/providers/together.js +31 -0
  66. package/dist/providers/together.js.map +1 -0
  67. package/dist/router/engine.d.ts +21 -0
  68. package/dist/router/engine.d.ts.map +1 -1
  69. package/dist/router/engine.js +81 -21
  70. package/dist/router/engine.js.map +1 -1
  71. package/dist/server.d.ts.map +1 -1
  72. package/dist/server.js +49 -0
  73. package/dist/server.js.map +1 -1
  74. package/dist/types.d.ts +52 -1
  75. package/dist/types.d.ts.map +1 -1
  76. package/dist/types.js +14 -0
  77. package/dist/types.js.map +1 -1
  78. package/package.json +1 -1
@@ -0,0 +1,488 @@
1
+ /**
2
+ * Failover Orchestrator
3
+ *
4
+ * Wraps provider operations with intelligent retry and failover logic.
5
+ * Integrates health tracking, circuit breakers, and cost-aware routing.
6
+ */
7
+ import { ProviderError, RateLimitError, TimeoutError, FailoverExhaustedError } from '../types.js';
8
+ import { retry, isRetryableError } from '../utils/retry.js';
9
+ import { CircuitBreaker, CircuitOpenError } from '../utils/circuit-breaker.js';
10
+ import { ProviderHealthTracker } from './health-tracker.js';
11
+ import { PricingService } from './pricing.js';
12
+ // ============================================================================
13
+ // Constants
14
+ // ============================================================================
15
+ const DEFAULT_CONFIG = {
16
+ enabled: true,
17
+ maxTotalRetries: 6,
18
+ healthCheckIntervalMs: 60000,
19
+ cooldownMs: 300000,
20
+ preferCostEfficient: false,
21
+ circuitBreaker: {
22
+ failureThreshold: 5,
23
+ successThreshold: 2,
24
+ timeout: 30000,
25
+ },
26
+ };
27
+ /**
28
+ * Default error codes that trigger failover.
29
+ */
30
+ const DEFAULT_FAILOVER_ERRORS = [429, 500, 502, 503, 504];
31
+ // ============================================================================
32
+ // FailoverOrchestrator Class
33
+ // ============================================================================
34
+ /**
35
+ * Orchestrates provider requests with intelligent failover.
36
+ *
37
+ * Features:
38
+ * - Automatic retry with exponential backoff
39
+ * - Multi-provider failover chain
40
+ * - Health tracking and cooldown management
41
+ * - Circuit breaker per provider
42
+ * - Cost-aware provider selection
43
+ * - Failover event logging for diagnostics
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * const orchestrator = new FailoverOrchestrator(
48
+ * providers,
49
+ * config,
50
+ * logger
51
+ * );
52
+ *
53
+ * // Execute with automatic failover
54
+ * const result = await orchestrator.executeWithFailover(
55
+ * 'coder',
56
+ * messages,
57
+ * { temperature: 0.7 }
58
+ * );
59
+ * ```
60
+ */
61
+ export class FailoverOrchestrator {
62
+ providers;
63
+ appConfig;
64
+ logger;
65
+ config;
66
+ healthTracker;
67
+ pricingService;
68
+ circuitBreakers = new Map();
69
+ failoverEvents = [];
70
+ maxEventHistory = 100;
71
+ constructor(providers, appConfig, logger, config) {
72
+ this.providers = providers;
73
+ this.appConfig = appConfig;
74
+ this.logger = logger;
75
+ this.config = { ...DEFAULT_CONFIG, ...config };
76
+ // Initialize health tracker
77
+ this.healthTracker = new ProviderHealthTracker(logger, {
78
+ cooldownMs: this.config.cooldownMs,
79
+ healthCheckIntervalMs: this.config.healthCheckIntervalMs,
80
+ });
81
+ // Initialize pricing service
82
+ this.pricingService = new PricingService(logger);
83
+ }
84
+ /**
85
+ * Execute a completion request with automatic failover.
86
+ */
87
+ async executeWithFailover(role, messages, options) {
88
+ if (!this.config.enabled) {
89
+ // Failover disabled, use primary provider only
90
+ return this.executeSingleProvider(role, messages, options);
91
+ }
92
+ const startTime = Date.now();
93
+ const roleConfig = this.appConfig.roles[role];
94
+ if (!roleConfig) {
95
+ throw new Error(`Unknown role: ${role}`);
96
+ }
97
+ // Build the chain of providers to try
98
+ const providerChain = this.buildProviderChain(role, roleConfig);
99
+ const errors = new Map();
100
+ const attemptedProviders = [];
101
+ let totalRetries = 0;
102
+ let failoverCount = 0;
103
+ // Get failover error codes from config or use defaults
104
+ const failoverErrors = roleConfig.fallback_chain?.on_errors ?? DEFAULT_FAILOVER_ERRORS;
105
+ // Get retry config from role or use defaults
106
+ const retryConfig = roleConfig.fallback_chain?.retry ?? {};
107
+ for (const { provider, model } of providerChain) {
108
+ if (totalRetries >= this.config.maxTotalRetries) {
109
+ this.logger.warn('Max total retries reached', {
110
+ role,
111
+ totalRetries,
112
+ attemptedProviders,
113
+ });
114
+ break;
115
+ }
116
+ // Check if provider is available
117
+ if (!this.healthTracker.isAvailable(provider)) {
118
+ const cooldown = this.healthTracker.getCooldownRemaining(provider);
119
+ this.logger.debug('Skipping provider in cooldown', {
120
+ provider,
121
+ cooldownRemainingMs: cooldown,
122
+ });
123
+ continue;
124
+ }
125
+ // Check circuit breaker
126
+ const breaker = this.getOrCreateCircuitBreaker(provider);
127
+ if (breaker.getState() === 'OPEN') {
128
+ this.logger.debug('Skipping provider with open circuit', { provider });
129
+ continue;
130
+ }
131
+ attemptedProviders.push(provider);
132
+ try {
133
+ const result = await this.executeWithRetry(provider, model, messages, options, retryConfig, failoverErrors);
134
+ const latencyMs = Date.now() - startTime;
135
+ return {
136
+ response: result.response,
137
+ provider,
138
+ model,
139
+ retryCount: result.retryCount,
140
+ failoverCount,
141
+ latencyMs,
142
+ usedFailover: failoverCount > 0,
143
+ };
144
+ }
145
+ catch (error) {
146
+ const err = error instanceof Error ? error : new Error(String(error));
147
+ errors.set(provider, err);
148
+ totalRetries++;
149
+ // Check if this error should trigger failover
150
+ const shouldFailover = this.shouldTriggerFailover(err, failoverErrors);
151
+ if (shouldFailover && providerChain.length > attemptedProviders.length) {
152
+ const nextProvider = this.getNextProvider(providerChain, attemptedProviders);
153
+ if (nextProvider) {
154
+ this.recordFailoverEvent(role, provider, nextProvider.provider, err);
155
+ failoverCount++;
156
+ this.logger.info('Failing over to next provider', {
157
+ role,
158
+ fromProvider: provider,
159
+ toProvider: nextProvider.provider,
160
+ errorMessage: err.message,
161
+ });
162
+ continue;
163
+ }
164
+ }
165
+ // No more providers or not a failover-triggering error
166
+ throw err;
167
+ }
168
+ }
169
+ // All providers exhausted
170
+ throw new FailoverExhaustedError(role, attemptedProviders, errors);
171
+ }
172
+ /**
173
+ * Get available providers for a role, sorted by health and optionally cost.
174
+ */
175
+ getAvailableProviders(role) {
176
+ const roleConfig = this.appConfig.roles[role];
177
+ if (!roleConfig) {
178
+ return [];
179
+ }
180
+ const chain = this.buildProviderChain(role, roleConfig);
181
+ // Filter to only configured and available providers
182
+ const available = chain.filter(({ provider }) => {
183
+ const isConfigured = this.providers.isConfigured(provider);
184
+ const isAvailable = this.healthTracker.isAvailable(provider);
185
+ return isConfigured && isAvailable;
186
+ });
187
+ // Optionally sort by cost
188
+ if (this.config.preferCostEfficient) {
189
+ return this.pricingService.sortByCost(available);
190
+ }
191
+ return available;
192
+ }
193
+ /**
194
+ * Get health status for all tracked providers.
195
+ */
196
+ getProviderHealth() {
197
+ return this.healthTracker.getAllHealth();
198
+ }
199
+ /**
200
+ * Get recent failover events.
201
+ */
202
+ getFailoverEvents() {
203
+ return [...this.failoverEvents];
204
+ }
205
+ /**
206
+ * Initialize the orchestrator (fetch pricing, start health checks).
207
+ */
208
+ async initialize() {
209
+ // Fetch pricing data
210
+ await this.pricingService.refresh();
211
+ // Start health check loop
212
+ this.healthTracker.startHealthCheckLoop(async (provider) => {
213
+ const providerInstance = this.providers.get(provider);
214
+ await providerInstance.healthCheck();
215
+ });
216
+ this.logger.info('Failover orchestrator initialized');
217
+ }
218
+ /**
219
+ * Shutdown the orchestrator (stop health checks, persist state).
220
+ */
221
+ shutdown() {
222
+ this.healthTracker.stopHealthCheckLoop();
223
+ this.logger.info('Failover orchestrator shut down');
224
+ }
225
+ /**
226
+ * Serialize state for persistence.
227
+ */
228
+ serializeState() {
229
+ return {
230
+ providerHealth: this.healthTracker.serialize(),
231
+ failoverEvents: this.failoverEvents.map((e) => ({
232
+ timestamp: e.timestamp.getTime(),
233
+ role: e.role,
234
+ fromProvider: e.fromProvider,
235
+ toProvider: e.toProvider,
236
+ reason: e.reason,
237
+ errorCode: e.errorCode,
238
+ errorMessage: e.errorMessage,
239
+ })),
240
+ };
241
+ }
242
+ /**
243
+ * Restore state from persistence.
244
+ */
245
+ restoreState(state) {
246
+ if (state.providerHealth) {
247
+ this.healthTracker.restore(state.providerHealth);
248
+ }
249
+ if (state.failoverEvents) {
250
+ this.failoverEvents.length = 0;
251
+ for (const e of state.failoverEvents) {
252
+ this.failoverEvents.push({
253
+ timestamp: new Date(e.timestamp),
254
+ role: e.role,
255
+ fromProvider: e.fromProvider,
256
+ toProvider: e.toProvider,
257
+ reason: e.reason,
258
+ errorCode: e.errorCode,
259
+ errorMessage: e.errorMessage,
260
+ });
261
+ }
262
+ }
263
+ this.logger.info('Failover orchestrator state restored');
264
+ }
265
+ /**
266
+ * Get the pricing service for external use.
267
+ */
268
+ getPricingService() {
269
+ return this.pricingService;
270
+ }
271
+ /**
272
+ * Get the health tracker for external use.
273
+ */
274
+ getHealthTracker() {
275
+ return this.healthTracker;
276
+ }
277
+ // ==========================================================================
278
+ // Private Methods
279
+ // ==========================================================================
280
+ /**
281
+ * Build the ordered chain of providers to try for a role.
282
+ */
283
+ buildProviderChain(role, roleConfig) {
284
+ const chain = [];
285
+ // Primary provider
286
+ chain.push({
287
+ provider: roleConfig.provider,
288
+ model: roleConfig.model,
289
+ });
290
+ // Fallback chain (extended)
291
+ if (roleConfig.fallback_chain?.providers) {
292
+ for (const fb of roleConfig.fallback_chain.providers) {
293
+ chain.push({
294
+ provider: fb.provider,
295
+ model: fb.model,
296
+ });
297
+ }
298
+ }
299
+ // Legacy single fallback
300
+ if (roleConfig.fallback) {
301
+ // Only add if not already in chain
302
+ const exists = chain.some((p) => p.provider === roleConfig.fallback.provider && p.model === roleConfig.fallback.model);
303
+ if (!exists) {
304
+ chain.push({
305
+ provider: roleConfig.fallback.provider,
306
+ model: roleConfig.fallback.model,
307
+ });
308
+ }
309
+ }
310
+ return chain;
311
+ }
312
+ /**
313
+ * Execute a single provider request with retry logic.
314
+ */
315
+ async executeWithRetry(provider, model, messages, options, retryConfig, _failoverErrors) {
316
+ const breaker = this.getOrCreateCircuitBreaker(provider);
317
+ let retryCount = 0;
318
+ const retryOptions = {
319
+ maxAttempts: retryConfig.max_attempts ?? 2,
320
+ initialDelayMs: retryConfig.initial_delay_ms ?? 1000,
321
+ maxDelayMs: retryConfig.max_delay_ms ?? 30000,
322
+ shouldRetry: (error) => isRetryableError(error),
323
+ onRetry: (error, attempt, delayMs) => {
324
+ retryCount++;
325
+ this.logger.debug('Retrying provider request', {
326
+ provider,
327
+ attempt,
328
+ delayMs,
329
+ error: error.message,
330
+ });
331
+ },
332
+ };
333
+ try {
334
+ const response = await retry(async () => {
335
+ const startTime = Date.now();
336
+ try {
337
+ // Execute through circuit breaker
338
+ const result = await breaker.execute(async () => {
339
+ const providerInstance = this.providers.get(provider);
340
+ const request = {
341
+ model,
342
+ messages,
343
+ temperature: options.temperature,
344
+ max_tokens: options.max_tokens,
345
+ timeout_ms: options.timeout_ms,
346
+ };
347
+ return providerInstance.complete(request);
348
+ });
349
+ // Record success
350
+ const latencyMs = Date.now() - startTime;
351
+ this.healthTracker.markSuccess(provider, latencyMs);
352
+ return result;
353
+ }
354
+ catch (error) {
355
+ const latencyMs = Date.now() - startTime;
356
+ const err = error instanceof Error ? error : new Error(String(error));
357
+ // Extract status code if available
358
+ let statusCode;
359
+ if (error instanceof ProviderError) {
360
+ statusCode = error.statusCode;
361
+ }
362
+ else if (error instanceof RateLimitError) {
363
+ statusCode = 429;
364
+ }
365
+ else if (error instanceof CircuitOpenError) {
366
+ // Circuit is open, don't record as failure
367
+ throw error;
368
+ }
369
+ // Record failure
370
+ this.healthTracker.markFailure(provider, err, statusCode);
371
+ throw error;
372
+ }
373
+ }, retryOptions);
374
+ return { response, retryCount };
375
+ }
376
+ catch (error) {
377
+ // Final failure after retries
378
+ throw error;
379
+ }
380
+ }
381
+ /**
382
+ * Execute without failover (single provider only).
383
+ */
384
+ async executeSingleProvider(role, messages, options) {
385
+ const startTime = Date.now();
386
+ const roleConfig = this.appConfig.roles[role];
387
+ if (!roleConfig) {
388
+ throw new Error(`Unknown role: ${role}`);
389
+ }
390
+ const providerInstance = this.providers.get(roleConfig.provider);
391
+ const request = {
392
+ model: roleConfig.model,
393
+ messages,
394
+ temperature: options.temperature,
395
+ max_tokens: options.max_tokens,
396
+ timeout_ms: options.timeout_ms,
397
+ };
398
+ const response = await providerInstance.complete(request);
399
+ const latencyMs = Date.now() - startTime;
400
+ return {
401
+ response,
402
+ provider: roleConfig.provider,
403
+ model: roleConfig.model,
404
+ retryCount: 0,
405
+ failoverCount: 0,
406
+ latencyMs,
407
+ usedFailover: false,
408
+ };
409
+ }
410
+ /**
411
+ * Check if an error should trigger failover.
412
+ */
413
+ shouldTriggerFailover(error, failoverErrors) {
414
+ // Rate limit always triggers failover
415
+ if (error instanceof RateLimitError) {
416
+ return true;
417
+ }
418
+ // Timeout triggers failover
419
+ if (error instanceof TimeoutError) {
420
+ return true;
421
+ }
422
+ // Circuit open triggers failover
423
+ if (error instanceof CircuitOpenError) {
424
+ return true;
425
+ }
426
+ // Check status code
427
+ if (error instanceof ProviderError && error.statusCode !== undefined) {
428
+ return failoverErrors.includes(error.statusCode);
429
+ }
430
+ return false;
431
+ }
432
+ /**
433
+ * Get the next provider in the chain that hasn't been tried.
434
+ */
435
+ getNextProvider(chain, attempted) {
436
+ for (const p of chain) {
437
+ if (!attempted.includes(p.provider)) {
438
+ return p;
439
+ }
440
+ }
441
+ return undefined;
442
+ }
443
+ /**
444
+ * Get or create a circuit breaker for a provider.
445
+ */
446
+ getOrCreateCircuitBreaker(provider) {
447
+ let breaker = this.circuitBreakers.get(provider);
448
+ if (!breaker) {
449
+ breaker = new CircuitBreaker(this.config.circuitBreaker);
450
+ // Log state changes
451
+ breaker.onStateChange((prev, next, meta) => {
452
+ this.logger.info('Circuit breaker state change', {
453
+ provider,
454
+ previousState: prev,
455
+ newState: next,
456
+ failureCount: meta.failureCount,
457
+ });
458
+ });
459
+ this.circuitBreakers.set(provider, breaker);
460
+ }
461
+ return breaker;
462
+ }
463
+ /**
464
+ * Record a failover event for diagnostics.
465
+ */
466
+ recordFailoverEvent(role, fromProvider, toProvider, error) {
467
+ const event = {
468
+ timestamp: new Date(),
469
+ role,
470
+ fromProvider,
471
+ toProvider,
472
+ reason: error.message,
473
+ };
474
+ if (error instanceof ProviderError) {
475
+ event.errorCode = error.statusCode;
476
+ }
477
+ else if (error instanceof RateLimitError) {
478
+ event.errorCode = 429;
479
+ }
480
+ event.errorMessage = error.message;
481
+ this.failoverEvents.push(event);
482
+ // Trim history
483
+ while (this.failoverEvents.length > this.maxEventHistory) {
484
+ this.failoverEvents.shift();
485
+ }
486
+ }
487
+ }
488
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/failover/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Provider Pricing Service
3
+ *
4
+ * Fetches and caches pricing data for LLM providers to enable cost-aware routing.
5
+ * Uses OpenRouter API as the primary data source for comprehensive pricing info.
6
+ */
7
+ import type { Logger } from '../observability/logger.js';
8
+ /**
9
+ * Pricing information for a provider model.
10
+ */
11
+ export interface ProviderPricing {
12
+ /** Provider name (e.g., 'openai', 'anthropic') */
13
+ provider: string;
14
+ /** Model identifier */
15
+ model: string;
16
+ /** Cost per million input tokens in USD */
17
+ inputPerMillion: number;
18
+ /** Cost per million output tokens in USD */
19
+ outputPerMillion: number;
20
+ /** Data source (e.g., 'openrouter', 'manual') */
21
+ source: string;
22
+ /** When the pricing was last updated */
23
+ updatedAt: Date;
24
+ }
25
+ /**
26
+ * Configuration for the pricing service.
27
+ */
28
+ export interface PricingServiceConfig {
29
+ /** Cache TTL in ms (default: 86400000 = 24 hours) */
30
+ cacheTtlMs?: number;
31
+ /** OpenRouter API key for fetching pricing (optional, uses free endpoint) */
32
+ openRouterApiKey?: string;
33
+ /** Timeout for API requests in ms (default: 10000) */
34
+ timeoutMs?: number;
35
+ }
36
+ /**
37
+ * Service for fetching and managing provider pricing data.
38
+ *
39
+ * Features:
40
+ * - Fetches pricing from OpenRouter API
41
+ * - Caches pricing data with configurable TTL
42
+ * - Falls back to manual pricing for providers not on OpenRouter
43
+ * - Provides cost comparison utilities
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * const pricing = new PricingService(logger);
48
+ * await pricing.refresh();
49
+ *
50
+ * // Get pricing for a specific model
51
+ * const cost = pricing.getPricing('openai', 'gpt-4o');
52
+ *
53
+ * // Sort providers by cost
54
+ * const sorted = pricing.sortByCost(['openai', 'anthropic', 'deepseek']);
55
+ * ```
56
+ */
57
+ export declare class PricingService {
58
+ private readonly config;
59
+ private readonly logger;
60
+ private cache;
61
+ private lastFetch;
62
+ constructor(logger: Logger, config?: PricingServiceConfig);
63
+ /**
64
+ * Fetch/refresh pricing data from OpenRouter API.
65
+ */
66
+ refresh(): Promise<void>;
67
+ /**
68
+ * Get pricing for a specific provider/model.
69
+ */
70
+ getPricing(provider: string, model: string): ProviderPricing | undefined;
71
+ /**
72
+ * Get all cached pricing data.
73
+ */
74
+ getAllPricing(): ProviderPricing[];
75
+ /**
76
+ * Sort providers by cost (cheapest first).
77
+ * Uses average of input/output costs for comparison.
78
+ */
79
+ sortByCost(providers: Array<{
80
+ provider: string;
81
+ model: string;
82
+ }>): Array<{
83
+ provider: string;
84
+ model: string;
85
+ cost: number;
86
+ }>;
87
+ /**
88
+ * Get cheapest provider from a list.
89
+ */
90
+ getCheapest(providers: Array<{
91
+ provider: string;
92
+ model: string;
93
+ }>): {
94
+ provider: string;
95
+ model: string;
96
+ } | undefined;
97
+ /**
98
+ * Check if cache is stale.
99
+ */
100
+ isCacheStale(): boolean;
101
+ /**
102
+ * Format a cost summary string for logging.
103
+ */
104
+ formatCostSummary(providers: Array<{
105
+ provider: string;
106
+ model: string;
107
+ }>): string;
108
+ /**
109
+ * Calculate estimated cost for a request.
110
+ */
111
+ estimateCost(provider: string, model: string, inputTokens: number, outputTokens: number): number | null;
112
+ private getCacheKey;
113
+ private parseOpenRouterResponse;
114
+ }
115
+ //# sourceMappingURL=pricing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../../src/failover/pricing.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAMzD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,eAAe,EAAE,MAAM,CAAC;IACxB,4CAA4C;IAC5C,gBAAgB,EAAE,MAAM,CAAC;IACzB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAgFD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiC;IACxD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,KAAK,CAA2C;IACxD,OAAO,CAAC,SAAS,CAAqB;gBAE1B,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,oBAAoB;IAWzD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAwD9B;;OAEG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAkBxE;;OAEG;IACH,aAAa,IAAI,eAAe,EAAE;IAIlC;;;OAGG;IACH,UAAU,CACR,SAAS,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,GACpD,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAY3D;;OAEG;IACH,WAAW,CACT,SAAS,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,GACpD;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS;IAKlD;;OAEG;IACH,YAAY,IAAI,OAAO;IASvB;;OAEG;IACH,iBAAiB,CACf,SAAS,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,GACpD,MAAM;IAkBT;;OAEG;IACH,YAAY,CACV,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,MAAM,GAAG,IAAI;IAgBhB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,uBAAuB;CAwChC"}