@ai-orchestration/core 0.2.0 → 0.3.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 +16 -0
- package/dist/cjs/core/errors.d.ts +21 -0
- package/dist/cjs/core/errors.d.ts.map +1 -0
- package/dist/cjs/core/errors.js +40 -0
- package/dist/cjs/core/errors.js.map +1 -0
- package/dist/cjs/core/interfaces.d.ts +166 -0
- package/dist/cjs/core/interfaces.d.ts.map +1 -0
- package/dist/cjs/core/interfaces.js +6 -0
- package/dist/cjs/core/interfaces.js.map +1 -0
- package/dist/cjs/core/metrics.d.ts +161 -0
- package/dist/cjs/core/metrics.d.ts.map +1 -0
- package/dist/cjs/core/metrics.js +282 -0
- package/dist/cjs/core/metrics.js.map +1 -0
- package/dist/cjs/core/orchestrator.d.ts +97 -0
- package/dist/cjs/core/orchestrator.d.ts.map +1 -0
- package/dist/cjs/core/orchestrator.js +402 -0
- package/dist/cjs/core/orchestrator.js.map +1 -0
- package/dist/cjs/core/types.d.ts +111 -0
- package/dist/cjs/core/types.d.ts.map +1 -0
- package/dist/cjs/core/types.js +6 -0
- package/dist/cjs/core/types.js.map +1 -0
- package/dist/cjs/factory/index.d.ts +14 -0
- package/dist/cjs/factory/index.d.ts.map +1 -0
- package/dist/cjs/factory/index.js +208 -0
- package/dist/cjs/factory/index.js.map +1 -0
- package/dist/cjs/index.d.ts +16 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +37 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/providers/base.d.ts +30 -0
- package/dist/cjs/providers/base.d.ts.map +1 -0
- package/dist/cjs/providers/base.js +35 -0
- package/dist/cjs/providers/base.js.map +1 -0
- package/dist/cjs/providers/cerebras.d.ts +26 -0
- package/dist/cjs/providers/cerebras.d.ts.map +1 -0
- package/dist/cjs/providers/cerebras.js +207 -0
- package/dist/cjs/providers/cerebras.js.map +1 -0
- package/dist/cjs/providers/gemini.d.ts +26 -0
- package/dist/cjs/providers/gemini.d.ts.map +1 -0
- package/dist/cjs/providers/gemini.js +180 -0
- package/dist/cjs/providers/gemini.js.map +1 -0
- package/dist/cjs/providers/groq.d.ts +26 -0
- package/dist/cjs/providers/groq.d.ts.map +1 -0
- package/dist/cjs/providers/groq.js +242 -0
- package/dist/cjs/providers/groq.js.map +1 -0
- package/dist/cjs/providers/index.d.ts +15 -0
- package/dist/cjs/providers/index.d.ts.map +1 -0
- package/dist/cjs/providers/index.js +19 -0
- package/dist/cjs/providers/index.js.map +1 -0
- package/dist/cjs/providers/local.d.ts +27 -0
- package/dist/cjs/providers/local.d.ts.map +1 -0
- package/dist/cjs/providers/local.js +205 -0
- package/dist/cjs/providers/local.js.map +1 -0
- package/dist/cjs/providers/openrouter.d.ts +26 -0
- package/dist/cjs/providers/openrouter.d.ts.map +1 -0
- package/dist/cjs/providers/openrouter.js +187 -0
- package/dist/cjs/providers/openrouter.js.map +1 -0
- package/dist/cjs/strategies/base.d.ts +16 -0
- package/dist/cjs/strategies/base.d.ts.map +1 -0
- package/dist/cjs/strategies/base.js +25 -0
- package/dist/cjs/strategies/base.js.map +1 -0
- package/dist/cjs/strategies/fallback.d.ts +14 -0
- package/dist/cjs/strategies/fallback.d.ts.map +1 -0
- package/dist/cjs/strategies/fallback.js +32 -0
- package/dist/cjs/strategies/fallback.js.map +1 -0
- package/dist/cjs/strategies/health-aware.d.ts +20 -0
- package/dist/cjs/strategies/health-aware.d.ts.map +1 -0
- package/dist/cjs/strategies/health-aware.js +108 -0
- package/dist/cjs/strategies/health-aware.js.map +1 -0
- package/dist/cjs/strategies/index.d.ts +14 -0
- package/dist/cjs/strategies/index.d.ts.map +1 -0
- package/dist/cjs/strategies/index.js +19 -0
- package/dist/cjs/strategies/index.js.map +1 -0
- package/dist/cjs/strategies/priority.d.ts +18 -0
- package/dist/cjs/strategies/priority.d.ts.map +1 -0
- package/dist/cjs/strategies/priority.js +39 -0
- package/dist/cjs/strategies/priority.js.map +1 -0
- package/dist/cjs/strategies/round-robin.d.ts +10 -0
- package/dist/cjs/strategies/round-robin.d.ts.map +1 -0
- package/dist/cjs/strategies/round-robin.js +28 -0
- package/dist/cjs/strategies/round-robin.js.map +1 -0
- package/dist/cjs/strategies/weighted.d.ts +20 -0
- package/dist/cjs/strategies/weighted.d.ts.map +1 -0
- package/dist/cjs/strategies/weighted.js +61 -0
- package/dist/cjs/strategies/weighted.js.map +1 -0
- package/dist/esm/core/errors.d.ts +21 -0
- package/dist/esm/core/errors.d.ts.map +1 -0
- package/dist/esm/core/errors.js +33 -0
- package/dist/esm/core/errors.js.map +1 -0
- package/dist/esm/core/interfaces.d.ts +166 -0
- package/dist/esm/core/interfaces.d.ts.map +1 -0
- package/dist/esm/core/interfaces.js +5 -0
- package/dist/esm/core/interfaces.js.map +1 -0
- package/dist/esm/core/metrics.d.ts +161 -0
- package/dist/esm/core/metrics.d.ts.map +1 -0
- package/dist/esm/core/metrics.js +278 -0
- package/dist/esm/core/metrics.js.map +1 -0
- package/dist/esm/core/orchestrator.d.ts +97 -0
- package/dist/esm/core/orchestrator.d.ts.map +1 -0
- package/dist/esm/core/orchestrator.js +398 -0
- package/dist/esm/core/orchestrator.js.map +1 -0
- package/dist/esm/core/types.d.ts +111 -0
- package/dist/esm/core/types.d.ts.map +1 -0
- package/dist/esm/core/types.js +5 -0
- package/dist/esm/core/types.js.map +1 -0
- package/dist/esm/factory/index.d.ts +14 -0
- package/dist/esm/factory/index.d.ts.map +1 -0
- package/dist/esm/factory/index.js +204 -0
- package/dist/esm/factory/index.js.map +1 -0
- package/dist/esm/index.d.ts +16 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +16 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/providers/base.d.ts +30 -0
- package/dist/esm/providers/base.d.ts.map +1 -0
- package/dist/esm/providers/base.js +31 -0
- package/dist/esm/providers/base.js.map +1 -0
- package/dist/esm/providers/cerebras.d.ts +26 -0
- package/dist/esm/providers/cerebras.d.ts.map +1 -0
- package/dist/esm/providers/cerebras.js +203 -0
- package/dist/esm/providers/cerebras.js.map +1 -0
- package/dist/esm/providers/gemini.d.ts +26 -0
- package/dist/esm/providers/gemini.d.ts.map +1 -0
- package/dist/esm/providers/gemini.js +176 -0
- package/dist/esm/providers/gemini.js.map +1 -0
- package/dist/esm/providers/groq.d.ts +26 -0
- package/dist/esm/providers/groq.d.ts.map +1 -0
- package/dist/esm/providers/groq.js +238 -0
- package/dist/esm/providers/groq.js.map +1 -0
- package/dist/esm/providers/index.d.ts +15 -0
- package/dist/esm/providers/index.d.ts.map +1 -0
- package/dist/esm/providers/index.js +10 -0
- package/dist/esm/providers/index.js.map +1 -0
- package/dist/esm/providers/local.d.ts +27 -0
- package/dist/esm/providers/local.d.ts.map +1 -0
- package/dist/esm/providers/local.js +201 -0
- package/dist/esm/providers/local.js.map +1 -0
- package/dist/esm/providers/openrouter.d.ts +26 -0
- package/dist/esm/providers/openrouter.d.ts.map +1 -0
- package/dist/esm/providers/openrouter.js +183 -0
- package/dist/esm/providers/openrouter.js.map +1 -0
- package/dist/esm/strategies/base.d.ts +16 -0
- package/dist/esm/strategies/base.d.ts.map +1 -0
- package/dist/esm/strategies/base.js +21 -0
- package/dist/esm/strategies/base.js.map +1 -0
- package/dist/esm/strategies/fallback.d.ts +14 -0
- package/dist/esm/strategies/fallback.d.ts.map +1 -0
- package/dist/esm/strategies/fallback.js +28 -0
- package/dist/esm/strategies/fallback.js.map +1 -0
- package/dist/esm/strategies/health-aware.d.ts +20 -0
- package/dist/esm/strategies/health-aware.d.ts.map +1 -0
- package/dist/esm/strategies/health-aware.js +104 -0
- package/dist/esm/strategies/health-aware.js.map +1 -0
- package/dist/esm/strategies/index.d.ts +14 -0
- package/dist/esm/strategies/index.d.ts.map +1 -0
- package/dist/esm/strategies/index.js +10 -0
- package/dist/esm/strategies/index.js.map +1 -0
- package/dist/esm/strategies/priority.d.ts +18 -0
- package/dist/esm/strategies/priority.d.ts.map +1 -0
- package/dist/esm/strategies/priority.js +35 -0
- package/dist/esm/strategies/priority.js.map +1 -0
- package/dist/esm/strategies/round-robin.d.ts +10 -0
- package/dist/esm/strategies/round-robin.d.ts.map +1 -0
- package/dist/esm/strategies/round-robin.js +24 -0
- package/dist/esm/strategies/round-robin.js.map +1 -0
- package/dist/esm/strategies/weighted.d.ts +20 -0
- package/dist/esm/strategies/weighted.d.ts.map +1 -0
- package/dist/esm/strategies/weighted.js +57 -0
- package/dist/esm/strategies/weighted.js.map +1 -0
- package/examples/metrics.ts +1 -0
- package/package.json +15 -6
- package/tsconfig.cjs.json +9 -0
- package/tsconfig.esm.json +9 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Health-aware strategy: selects providers based on health metrics (latency, success rate)
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.HealthAwareStrategy = void 0;
|
|
7
|
+
const base_js_1 = require("./base.js");
|
|
8
|
+
class HealthAwareStrategy extends base_js_1.BaseStrategy {
|
|
9
|
+
constructor(config) {
|
|
10
|
+
super();
|
|
11
|
+
this.stats = new Map();
|
|
12
|
+
this.preferLowLatency = config?.preferLowLatency ?? true;
|
|
13
|
+
this.minHealthScore = config?.minHealthScore ?? 0;
|
|
14
|
+
}
|
|
15
|
+
async select(providers, context) {
|
|
16
|
+
const available = this.filterAttempted(providers, context);
|
|
17
|
+
if (available.length === 0) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
// Fetch health for all providers
|
|
21
|
+
const healthChecks = await Promise.allSettled(available.map(async (p) => {
|
|
22
|
+
const health = await p.checkHealth();
|
|
23
|
+
return { provider: p, health };
|
|
24
|
+
}));
|
|
25
|
+
// Build stats with health information
|
|
26
|
+
const candidates = [];
|
|
27
|
+
for (const result of healthChecks) {
|
|
28
|
+
if (result.status === 'fulfilled') {
|
|
29
|
+
const { provider, health } = result.value;
|
|
30
|
+
if (!health.healthy)
|
|
31
|
+
continue;
|
|
32
|
+
const stats = this.getOrCreateStats(provider);
|
|
33
|
+
stats.health = health;
|
|
34
|
+
const healthScore = this.calculateHealthScore(stats);
|
|
35
|
+
if (healthScore >= this.minHealthScore) {
|
|
36
|
+
candidates.push(stats);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (candidates.length === 0) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
// Sort by health score (and latency if preferred)
|
|
44
|
+
candidates.sort((a, b) => {
|
|
45
|
+
const scoreA = this.calculateHealthScore(a);
|
|
46
|
+
const scoreB = this.calculateHealthScore(b);
|
|
47
|
+
if (scoreA !== scoreB) {
|
|
48
|
+
return scoreB - scoreA; // Higher score first
|
|
49
|
+
}
|
|
50
|
+
// If scores are equal and prefer low latency, sort by latency
|
|
51
|
+
if (this.preferLowLatency) {
|
|
52
|
+
const latencyA = a.health.latency ?? Infinity;
|
|
53
|
+
const latencyB = b.health.latency ?? Infinity;
|
|
54
|
+
return latencyA - latencyB;
|
|
55
|
+
}
|
|
56
|
+
return 0;
|
|
57
|
+
});
|
|
58
|
+
return candidates[0].provider;
|
|
59
|
+
}
|
|
60
|
+
update(provider, success, metadata) {
|
|
61
|
+
const stats = this.getOrCreateStats(provider);
|
|
62
|
+
if (success) {
|
|
63
|
+
stats.successCount++;
|
|
64
|
+
// Update latency if available
|
|
65
|
+
if (metadata && typeof metadata === 'object' && 'latency' in metadata) {
|
|
66
|
+
const latency = Number(metadata.latency);
|
|
67
|
+
if (!isNaN(latency)) {
|
|
68
|
+
stats.avgLatency =
|
|
69
|
+
stats.avgLatency === undefined
|
|
70
|
+
? latency
|
|
71
|
+
: (stats.avgLatency + latency) / 2;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
stats.failureCount++;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
getOrCreateStats(provider) {
|
|
80
|
+
let stats = this.stats.get(provider.id);
|
|
81
|
+
if (!stats) {
|
|
82
|
+
stats = {
|
|
83
|
+
provider,
|
|
84
|
+
health: { healthy: true },
|
|
85
|
+
successCount: 0,
|
|
86
|
+
failureCount: 0,
|
|
87
|
+
};
|
|
88
|
+
this.stats.set(provider.id, stats);
|
|
89
|
+
}
|
|
90
|
+
return stats;
|
|
91
|
+
}
|
|
92
|
+
calculateHealthScore(stats) {
|
|
93
|
+
const total = stats.successCount + stats.failureCount;
|
|
94
|
+
if (total === 0) {
|
|
95
|
+
return 1.0; // No data, assume healthy
|
|
96
|
+
}
|
|
97
|
+
const successRate = stats.successCount / total;
|
|
98
|
+
// Factor in latency if available
|
|
99
|
+
let latencyFactor = 1.0;
|
|
100
|
+
if (stats.avgLatency !== undefined) {
|
|
101
|
+
// Normalize latency (assume < 1000ms is good, > 5000ms is bad)
|
|
102
|
+
latencyFactor = Math.max(0, 1 - (stats.avgLatency - 1000) / 4000);
|
|
103
|
+
}
|
|
104
|
+
return successRate * latencyFactor;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exports.HealthAwareStrategy = HealthAwareStrategy;
|
|
108
|
+
//# sourceMappingURL=health-aware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health-aware.js","sourceRoot":"","sources":["../../../src/strategies/health-aware.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Export all strategies
|
|
3
|
+
*/
|
|
4
|
+
export { BaseStrategy } from './base.js';
|
|
5
|
+
export { RoundRobinStrategy } from './round-robin.js';
|
|
6
|
+
export { PriorityStrategy } from './priority.js';
|
|
7
|
+
export type { PriorityStrategyConfig } from './priority.js';
|
|
8
|
+
export { FallbackStrategy } from './fallback.js';
|
|
9
|
+
export type { FallbackStrategyConfig } from './fallback.js';
|
|
10
|
+
export { WeightedStrategy } from './weighted.js';
|
|
11
|
+
export type { WeightedStrategyConfig } from './weighted.js';
|
|
12
|
+
export { HealthAwareStrategy } from './health-aware.js';
|
|
13
|
+
export type { HealthAwareStrategyConfig } from './health-aware.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/strategies/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,YAAY,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Export all strategies
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.HealthAwareStrategy = exports.WeightedStrategy = exports.FallbackStrategy = exports.PriorityStrategy = exports.RoundRobinStrategy = exports.BaseStrategy = void 0;
|
|
7
|
+
var base_js_1 = require("./base.js");
|
|
8
|
+
Object.defineProperty(exports, "BaseStrategy", { enumerable: true, get: function () { return base_js_1.BaseStrategy; } });
|
|
9
|
+
var round_robin_js_1 = require("./round-robin.js");
|
|
10
|
+
Object.defineProperty(exports, "RoundRobinStrategy", { enumerable: true, get: function () { return round_robin_js_1.RoundRobinStrategy; } });
|
|
11
|
+
var priority_js_1 = require("./priority.js");
|
|
12
|
+
Object.defineProperty(exports, "PriorityStrategy", { enumerable: true, get: function () { return priority_js_1.PriorityStrategy; } });
|
|
13
|
+
var fallback_js_1 = require("./fallback.js");
|
|
14
|
+
Object.defineProperty(exports, "FallbackStrategy", { enumerable: true, get: function () { return fallback_js_1.FallbackStrategy; } });
|
|
15
|
+
var weighted_js_1 = require("./weighted.js");
|
|
16
|
+
Object.defineProperty(exports, "WeightedStrategy", { enumerable: true, get: function () { return weighted_js_1.WeightedStrategy; } });
|
|
17
|
+
var health_aware_js_1 = require("./health-aware.js");
|
|
18
|
+
Object.defineProperty(exports, "HealthAwareStrategy", { enumerable: true, get: function () { return health_aware_js_1.HealthAwareStrategy; } });
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/strategies/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,qCAAyC;AAAhC,uGAAA,YAAY,OAAA;AACrB,mDAAsD;AAA7C,oHAAA,kBAAkB,OAAA;AAC3B,6CAAiD;AAAxC,+GAAA,gBAAgB,OAAA;AAEzB,6CAAiD;AAAxC,+GAAA,gBAAgB,OAAA;AAEzB,6CAAiD;AAAxC,+GAAA,gBAAgB,OAAA;AAEzB,qDAAwD;AAA/C,sHAAA,mBAAmB,OAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Priority strategy: selects providers based on priority order
|
|
3
|
+
*/
|
|
4
|
+
import { BaseStrategy } from './base.js';
|
|
5
|
+
import type { AIService, SelectionContext } from '../core/interfaces.js';
|
|
6
|
+
export interface PriorityStrategyConfig {
|
|
7
|
+
priorities?: Record<string, number>;
|
|
8
|
+
}
|
|
9
|
+
export declare class PriorityStrategy extends BaseStrategy {
|
|
10
|
+
private priorities;
|
|
11
|
+
constructor(config?: PriorityStrategyConfig);
|
|
12
|
+
select(providers: AIService[], context?: SelectionContext): Promise<AIService | null>;
|
|
13
|
+
/**
|
|
14
|
+
* Set priority for a provider
|
|
15
|
+
*/
|
|
16
|
+
setPriority(providerId: string, priority: number): void;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=priority.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"priority.d.ts","sourceRoot":"","sources":["../../../src/strategies/priority.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzE,MAAM,WAAW,sBAAsB;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,UAAU,CAAkC;gBAExC,MAAM,CAAC,EAAE,sBAAsB;IASrC,MAAM,CACV,SAAS,EAAE,SAAS,EAAE,EACtB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAgB5B;;OAEG;IACH,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;CAGxD"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Priority strategy: selects providers based on priority order
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PriorityStrategy = void 0;
|
|
7
|
+
const base_js_1 = require("./base.js");
|
|
8
|
+
class PriorityStrategy extends base_js_1.BaseStrategy {
|
|
9
|
+
constructor(config) {
|
|
10
|
+
super();
|
|
11
|
+
this.priorities = new Map();
|
|
12
|
+
if (config?.priorities) {
|
|
13
|
+
Object.entries(config.priorities).forEach(([id, priority]) => {
|
|
14
|
+
this.priorities.set(id, priority);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
async select(providers, context) {
|
|
19
|
+
const available = this.filterAttempted(providers, context);
|
|
20
|
+
if (available.length === 0) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
// Sort by priority (lower number = higher priority)
|
|
24
|
+
const sorted = [...available].sort((a, b) => {
|
|
25
|
+
const priorityA = this.priorities.get(a.id) ?? 999;
|
|
26
|
+
const priorityB = this.priorities.get(b.id) ?? 999;
|
|
27
|
+
return priorityA - priorityB;
|
|
28
|
+
});
|
|
29
|
+
return sorted[0];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Set priority for a provider
|
|
33
|
+
*/
|
|
34
|
+
setPriority(providerId, priority) {
|
|
35
|
+
this.priorities.set(providerId, priority);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.PriorityStrategy = PriorityStrategy;
|
|
39
|
+
//# sourceMappingURL=priority.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"priority.js","sourceRoot":"","sources":["../../../src/strategies/priority.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,uCAAyC;AAOzC,MAAa,gBAAiB,SAAQ,sBAAY;IAGhD,YAAY,MAA+B;QACzC,KAAK,EAAE,CAAC;QAHF,eAAU,GAAwB,IAAI,GAAG,EAAE,CAAC;QAIlD,IAAI,MAAM,EAAE,UAAU,EAAE,CAAC;YACvB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE;gBAC3D,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;YACpC,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CACV,SAAsB,EACtB,OAA0B;QAE1B,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC3D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,oDAAoD;QACpD,MAAM,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC;YACnD,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC;YACnD,OAAO,SAAS,GAAG,SAAS,CAAC;QAC/B,CAAC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,UAAkB,EAAE,QAAgB;QAC9C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC5C,CAAC;CACF;AArCD,4CAqCC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Round-robin strategy: cycles through providers in order
|
|
3
|
+
*/
|
|
4
|
+
import { BaseStrategy } from './base.js';
|
|
5
|
+
import type { AIService, SelectionContext } from '../core/interfaces.js';
|
|
6
|
+
export declare class RoundRobinStrategy extends BaseStrategy {
|
|
7
|
+
private currentIndex;
|
|
8
|
+
select(providers: AIService[], context?: SelectionContext): Promise<AIService | null>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=round-robin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"round-robin.d.ts","sourceRoot":"","sources":["../../../src/strategies/round-robin.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzE,qBAAa,kBAAmB,SAAQ,YAAY;IAClD,OAAO,CAAC,YAAY,CAAK;IAEnB,MAAM,CACV,SAAS,EAAE,SAAS,EAAE,EACtB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;CAgB7B"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Round-robin strategy: cycles through providers in order
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.RoundRobinStrategy = void 0;
|
|
7
|
+
const base_js_1 = require("./base.js");
|
|
8
|
+
class RoundRobinStrategy extends base_js_1.BaseStrategy {
|
|
9
|
+
constructor() {
|
|
10
|
+
super(...arguments);
|
|
11
|
+
this.currentIndex = 0;
|
|
12
|
+
}
|
|
13
|
+
async select(providers, context) {
|
|
14
|
+
const available = this.filterAttempted(providers, context);
|
|
15
|
+
if (available.length === 0) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
// Reset index if it's out of bounds
|
|
19
|
+
if (this.currentIndex >= available.length) {
|
|
20
|
+
this.currentIndex = 0;
|
|
21
|
+
}
|
|
22
|
+
const selected = available[this.currentIndex];
|
|
23
|
+
this.currentIndex = (this.currentIndex + 1) % available.length;
|
|
24
|
+
return selected;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.RoundRobinStrategy = RoundRobinStrategy;
|
|
28
|
+
//# sourceMappingURL=round-robin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"round-robin.js","sourceRoot":"","sources":["../../../src/strategies/round-robin.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,uCAAyC;AAGzC,MAAa,kBAAmB,SAAQ,sBAAY;IAApD;;QACU,iBAAY,GAAG,CAAC,CAAC;IAqB3B,CAAC;IAnBC,KAAK,CAAC,MAAM,CACV,SAAsB,EACtB,OAA0B;QAE1B,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC3D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,oCAAoC;QACpC,IAAI,IAAI,CAAC,YAAY,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;YAC1C,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QACxB,CAAC;QAED,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC9C,IAAI,CAAC,YAAY,GAAG,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC;QAE/D,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF;AAtBD,gDAsBC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Weighted strategy: selects providers based on weights (for load balancing or cost-aware selection)
|
|
3
|
+
*/
|
|
4
|
+
import { BaseStrategy } from './base.js';
|
|
5
|
+
import type { AIService, SelectionContext } from '../core/interfaces.js';
|
|
6
|
+
export interface WeightedStrategyConfig {
|
|
7
|
+
weights?: Record<string, number>;
|
|
8
|
+
costAware?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare class WeightedStrategy extends BaseStrategy {
|
|
11
|
+
private weights;
|
|
12
|
+
private costAware;
|
|
13
|
+
constructor(config?: WeightedStrategyConfig);
|
|
14
|
+
select(providers: AIService[], context?: SelectionContext): Promise<AIService | null>;
|
|
15
|
+
/**
|
|
16
|
+
* Set weight for a provider
|
|
17
|
+
*/
|
|
18
|
+
setWeight(providerId: string, weight: number): void;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=weighted.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weighted.d.ts","sourceRoot":"","sources":["../../../src/strategies/weighted.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzE,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,SAAS,CAAU;gBAEf,MAAM,CAAC,EAAE,sBAAsB;IAWrC,MAAM,CACV,SAAS,EAAE,SAAS,EAAE,EACtB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IA8C5B;;OAEG;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;CAGpD"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Weighted strategy: selects providers based on weights (for load balancing or cost-aware selection)
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.WeightedStrategy = void 0;
|
|
7
|
+
const base_js_1 = require("./base.js");
|
|
8
|
+
class WeightedStrategy extends base_js_1.BaseStrategy {
|
|
9
|
+
constructor(config) {
|
|
10
|
+
super();
|
|
11
|
+
this.weights = new Map();
|
|
12
|
+
this.costAware = config?.costAware ?? false;
|
|
13
|
+
if (config?.weights) {
|
|
14
|
+
Object.entries(config.weights).forEach(([id, weight]) => {
|
|
15
|
+
this.weights.set(id, weight);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async select(providers, context) {
|
|
20
|
+
const available = this.filterAttempted(providers, context);
|
|
21
|
+
if (available.length === 0) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
// Calculate effective weights
|
|
25
|
+
const weightedProviders = available.map((provider) => {
|
|
26
|
+
let weight = this.weights.get(provider.id) ?? 1.0;
|
|
27
|
+
// Adjust weight based on cost if cost-aware
|
|
28
|
+
if (this.costAware && provider.metadata.costPerToken) {
|
|
29
|
+
const avgCost = (provider.metadata.costPerToken.prompt +
|
|
30
|
+
provider.metadata.costPerToken.completion) /
|
|
31
|
+
2;
|
|
32
|
+
// Lower cost = higher weight (inverse relationship)
|
|
33
|
+
weight = weight / (avgCost + 0.0001); // Add small epsilon to avoid division by zero
|
|
34
|
+
}
|
|
35
|
+
return { provider, weight };
|
|
36
|
+
});
|
|
37
|
+
// Calculate total weight
|
|
38
|
+
const totalWeight = weightedProviders.reduce((sum, wp) => sum + wp.weight, 0);
|
|
39
|
+
if (totalWeight === 0) {
|
|
40
|
+
return available[0]; // Fallback to first available
|
|
41
|
+
}
|
|
42
|
+
// Select using weighted random
|
|
43
|
+
let random = Math.random() * totalWeight;
|
|
44
|
+
for (const { provider, weight } of weightedProviders) {
|
|
45
|
+
random -= weight;
|
|
46
|
+
if (random <= 0) {
|
|
47
|
+
return provider;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Fallback (shouldn't reach here)
|
|
51
|
+
return available[0];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Set weight for a provider
|
|
55
|
+
*/
|
|
56
|
+
setWeight(providerId, weight) {
|
|
57
|
+
this.weights.set(providerId, weight);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.WeightedStrategy = WeightedStrategy;
|
|
61
|
+
//# sourceMappingURL=weighted.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weighted.js","sourceRoot":"","sources":["../../../src/strategies/weighted.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,uCAAyC;AAQzC,MAAa,gBAAiB,SAAQ,sBAAY;IAIhD,YAAY,MAA+B;QACzC,KAAK,EAAE,CAAC;QAJF,YAAO,GAAwB,IAAI,GAAG,EAAE,CAAC;QAK/C,IAAI,CAAC,SAAS,GAAG,MAAM,EAAE,SAAS,IAAI,KAAK,CAAC;QAE5C,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE;gBACtD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YAC/B,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CACV,SAAsB,EACtB,OAA0B;QAE1B,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC3D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,8BAA8B;QAC9B,MAAM,iBAAiB,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;YACnD,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC;YAElD,4CAA4C;YAC5C,IAAI,IAAI,CAAC,SAAS,IAAI,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;gBACrD,MAAM,OAAO,GACX,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,MAAM;oBACpC,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,UAAU,CAAC;oBAC5C,CAAC,CAAC;gBACJ,oDAAoD;gBACpD,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,8CAA8C;YACtF,CAAC;YAED,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QAC9B,CAAC,CAAC,CAAC;QAEH,yBAAyB;QACzB,MAAM,WAAW,GAAG,iBAAiB,CAAC,MAAM,CAC1C,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,MAAM,EAC5B,CAAC,CACF,CAAC;QAEF,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,8BAA8B;QACrD,CAAC;QAED,+BAA+B;QAC/B,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,WAAW,CAAC;QACzC,KAAK,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,iBAAiB,EAAE,CAAC;YACrD,MAAM,IAAI,MAAM,CAAC;YACjB,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;gBAChB,OAAO,QAAQ,CAAC;YAClB,CAAC;QACH,CAAC;QAED,kCAAkC;QAClC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,UAAkB,EAAE,MAAc;QAC1C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;CACF;AAtED,4CAsEC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error classes for the framework
|
|
3
|
+
*/
|
|
4
|
+
export declare class ProviderError extends Error {
|
|
5
|
+
readonly providerId: string;
|
|
6
|
+
readonly cause?: Error | undefined;
|
|
7
|
+
constructor(message: string, providerId: string, cause?: Error | undefined);
|
|
8
|
+
}
|
|
9
|
+
export declare class StrategyError extends Error {
|
|
10
|
+
readonly cause?: Error | undefined;
|
|
11
|
+
constructor(message: string, cause?: Error | undefined);
|
|
12
|
+
}
|
|
13
|
+
export declare class OrchestratorError extends Error {
|
|
14
|
+
readonly cause?: Error | undefined;
|
|
15
|
+
constructor(message: string, cause?: Error | undefined);
|
|
16
|
+
}
|
|
17
|
+
export declare class ConfigurationError extends Error {
|
|
18
|
+
readonly cause?: Error | undefined;
|
|
19
|
+
constructor(message: string, cause?: Error | undefined);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,qBAAa,aAAc,SAAQ,KAAK;aAGpB,UAAU,EAAE,MAAM;aAClB,KAAK,CAAC,EAAE,KAAK;gBAF7B,OAAO,EAAE,MAAM,EACC,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,KAAK,YAAA;CAKhC;AAED,qBAAa,aAAc,SAAQ,KAAK;aACO,KAAK,CAAC,EAAE,KAAK;gBAA9C,OAAO,EAAE,MAAM,EAAkB,KAAK,CAAC,EAAE,KAAK,YAAA;CAI3D;AAED,qBAAa,iBAAkB,SAAQ,KAAK;aACG,KAAK,CAAC,EAAE,KAAK;gBAA9C,OAAO,EAAE,MAAM,EAAkB,KAAK,CAAC,EAAE,KAAK,YAAA;CAI3D;AAED,qBAAa,kBAAmB,SAAQ,KAAK;aACE,KAAK,CAAC,EAAE,KAAK;gBAA9C,OAAO,EAAE,MAAM,EAAkB,KAAK,CAAC,EAAE,KAAK,YAAA;CAI3D"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error classes for the framework
|
|
3
|
+
*/
|
|
4
|
+
export class ProviderError extends Error {
|
|
5
|
+
constructor(message, providerId, cause) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.providerId = providerId;
|
|
8
|
+
this.cause = cause;
|
|
9
|
+
this.name = 'ProviderError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class StrategyError extends Error {
|
|
13
|
+
constructor(message, cause) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.cause = cause;
|
|
16
|
+
this.name = 'StrategyError';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class OrchestratorError extends Error {
|
|
20
|
+
constructor(message, cause) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.cause = cause;
|
|
23
|
+
this.name = 'OrchestratorError';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export class ConfigurationError extends Error {
|
|
27
|
+
constructor(message, cause) {
|
|
28
|
+
super(message);
|
|
29
|
+
this.cause = cause;
|
|
30
|
+
this.name = 'ConfigurationError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YACE,OAAe,EACC,UAAkB,EAClB,KAAa;QAE7B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,eAAU,GAAV,UAAU,CAAQ;QAClB,UAAK,GAAL,KAAK,CAAQ;QAG7B,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAe,EAAkB,KAAa;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;QAD4B,UAAK,GAAL,KAAK,CAAQ;QAExD,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAC1C,YAAY,OAAe,EAAkB,KAAa;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;QAD4B,UAAK,GAAL,KAAK,CAAQ;QAExD,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAe,EAAkB,KAAa;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;QAD4B,UAAK,GAAL,KAAK,CAAQ;QAExD,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core interfaces for AI providers and strategies
|
|
3
|
+
*/
|
|
4
|
+
import type { ChatMessage, ChatOptions, ChatResponse, ChatChunk, ProviderHealth, ProviderMetadata } from './types.js';
|
|
5
|
+
export type { ChatMessage, ChatOptions, ChatResponse, ChatChunk, ProviderHealth, ProviderMetadata, };
|
|
6
|
+
/**
|
|
7
|
+
* Main interface that all AI providers must implement
|
|
8
|
+
*/
|
|
9
|
+
export interface AIService {
|
|
10
|
+
/**
|
|
11
|
+
* Unique identifier for this provider instance
|
|
12
|
+
*/
|
|
13
|
+
readonly id: string;
|
|
14
|
+
/**
|
|
15
|
+
* Provider metadata
|
|
16
|
+
*/
|
|
17
|
+
readonly metadata: ProviderMetadata;
|
|
18
|
+
/**
|
|
19
|
+
* Check the health status of this provider
|
|
20
|
+
*/
|
|
21
|
+
checkHealth(): Promise<ProviderHealth>;
|
|
22
|
+
/**
|
|
23
|
+
* Perform a chat completion (non-streaming)
|
|
24
|
+
*/
|
|
25
|
+
chat(messages: ChatMessage[], options?: ChatOptions): Promise<ChatResponse>;
|
|
26
|
+
/**
|
|
27
|
+
* Perform a chat completion with streaming
|
|
28
|
+
*/
|
|
29
|
+
chatStream(messages: ChatMessage[], options?: ChatOptions): Promise<ReadableStream<ChatChunk>>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Strategy interface for selecting providers
|
|
33
|
+
*/
|
|
34
|
+
export interface SelectionStrategy {
|
|
35
|
+
/**
|
|
36
|
+
* Select a provider from the available list
|
|
37
|
+
* @param providers List of available providers
|
|
38
|
+
* @param context Optional context for selection (e.g., request metadata)
|
|
39
|
+
*/
|
|
40
|
+
select(providers: AIService[], context?: SelectionContext): Promise<AIService | null>;
|
|
41
|
+
/**
|
|
42
|
+
* Update strategy state (e.g., after a successful/failed request)
|
|
43
|
+
*/
|
|
44
|
+
update?(provider: AIService, success: boolean, metadata?: unknown): void;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Context passed to selection strategies
|
|
48
|
+
*/
|
|
49
|
+
export interface SelectionContext {
|
|
50
|
+
messages?: ChatMessage[];
|
|
51
|
+
options?: ChatOptions;
|
|
52
|
+
previousAttempts?: string[];
|
|
53
|
+
[key: string]: unknown;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Configuration for a provider instance
|
|
57
|
+
*/
|
|
58
|
+
export interface ProviderConfig {
|
|
59
|
+
id: string;
|
|
60
|
+
type: string;
|
|
61
|
+
apiKey?: string;
|
|
62
|
+
baseURL?: string;
|
|
63
|
+
model?: string;
|
|
64
|
+
enabled?: boolean;
|
|
65
|
+
priority?: number;
|
|
66
|
+
weight?: number;
|
|
67
|
+
metadata?: Record<string, unknown>;
|
|
68
|
+
[key: string]: unknown;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Configuration for a selection strategy
|
|
72
|
+
*/
|
|
73
|
+
export interface StrategyConfig {
|
|
74
|
+
type: string;
|
|
75
|
+
[key: string]: unknown;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Circuit breaker configuration
|
|
79
|
+
*/
|
|
80
|
+
export interface CircuitBreakerConfig {
|
|
81
|
+
/**
|
|
82
|
+
* Enable circuit breaker functionality
|
|
83
|
+
*/
|
|
84
|
+
enabled?: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Number of consecutive failures before opening the circuit
|
|
87
|
+
*/
|
|
88
|
+
failureThreshold?: number;
|
|
89
|
+
/**
|
|
90
|
+
* Time in milliseconds before attempting to reset the circuit
|
|
91
|
+
*/
|
|
92
|
+
resetTimeout?: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Health check configuration
|
|
96
|
+
*/
|
|
97
|
+
export interface HealthCheckConfig {
|
|
98
|
+
/**
|
|
99
|
+
* Interval between health checks in milliseconds
|
|
100
|
+
*/
|
|
101
|
+
interval?: number;
|
|
102
|
+
/**
|
|
103
|
+
* Timeout for individual health checks in milliseconds
|
|
104
|
+
*/
|
|
105
|
+
timeout?: number;
|
|
106
|
+
/**
|
|
107
|
+
* Maximum consecutive failures before marking provider as unhealthy
|
|
108
|
+
*/
|
|
109
|
+
maxConsecutiveFailures?: number;
|
|
110
|
+
/**
|
|
111
|
+
* Maximum latency threshold in milliseconds. Providers exceeding this will be marked unhealthy.
|
|
112
|
+
*/
|
|
113
|
+
latencyThreshold?: number;
|
|
114
|
+
/**
|
|
115
|
+
* Enable periodic health checks
|
|
116
|
+
*/
|
|
117
|
+
enabled?: boolean;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Main orchestrator configuration
|
|
121
|
+
*/
|
|
122
|
+
export interface OrchestratorConfig {
|
|
123
|
+
providers: ProviderConfig[];
|
|
124
|
+
strategy: StrategyConfig;
|
|
125
|
+
defaultOptions?: ChatOptions;
|
|
126
|
+
/**
|
|
127
|
+
* Maximum number of retry attempts before giving up.
|
|
128
|
+
* Defaults to the number of providers if not specified.
|
|
129
|
+
*/
|
|
130
|
+
maxRetries?: number;
|
|
131
|
+
/**
|
|
132
|
+
* Global timeout for all requests in milliseconds.
|
|
133
|
+
* Defaults to 30000 (30 seconds) if not specified.
|
|
134
|
+
*/
|
|
135
|
+
requestTimeout?: number;
|
|
136
|
+
/**
|
|
137
|
+
* Delay between retries in milliseconds, or 'exponential' for exponential backoff.
|
|
138
|
+
* Defaults to 1000 (1 second) if not specified.
|
|
139
|
+
*/
|
|
140
|
+
retryDelay?: number | 'exponential';
|
|
141
|
+
/**
|
|
142
|
+
* Circuit breaker configuration
|
|
143
|
+
*/
|
|
144
|
+
circuitBreaker?: CircuitBreakerConfig;
|
|
145
|
+
/**
|
|
146
|
+
* Health check configuration
|
|
147
|
+
*/
|
|
148
|
+
healthCheck?: HealthCheckConfig;
|
|
149
|
+
/**
|
|
150
|
+
* Enable metrics collection (default: true)
|
|
151
|
+
*/
|
|
152
|
+
enableMetrics?: boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Callback for metrics events
|
|
155
|
+
*/
|
|
156
|
+
onMetricsEvent?: import('./metrics.js').MetricsCallback;
|
|
157
|
+
/**
|
|
158
|
+
* @deprecated Use healthCheck.enabled instead
|
|
159
|
+
*/
|
|
160
|
+
enableHealthChecks?: boolean;
|
|
161
|
+
/**
|
|
162
|
+
* @deprecated Use healthCheck.interval instead
|
|
163
|
+
*/
|
|
164
|
+
healthCheckInterval?: number;
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=interfaces.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../../src/core/interfaces.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../../src/core/interfaces.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|