@sparkleideas/providers 3.0.0-alpha.6-patch.26 → 3.0.0-alpha.6-patch.27
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/dist/anthropic-provider.d.ts +26 -0
- package/dist/anthropic-provider.d.ts.map +1 -0
- package/dist/anthropic-provider.js +513 -0
- package/dist/base-provider.d.ts +174 -0
- package/dist/base-provider.d.ts.map +1 -0
- package/dist/base-provider.js +636 -0
- package/dist/cohere-provider.d.ts +26 -0
- package/dist/cohere-provider.d.ts.map +1 -0
- package/dist/cohere-provider.js +501 -0
- package/dist/google-provider.d.ts +25 -0
- package/dist/google-provider.d.ts.map +1 -0
- package/dist/google-provider.js +498 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +62 -0
- package/dist/ollama-provider.d.ts +26 -0
- package/dist/ollama-provider.d.ts.map +1 -0
- package/dist/ollama-provider.js +489 -0
- package/dist/openai-provider.d.ts +26 -0
- package/dist/openai-provider.d.ts.map +1 -0
- package/dist/openai-provider.js +543 -0
- package/dist/provider-manager.d.ts +117 -0
- package/dist/provider-manager.d.ts.map +1 -0
- package/dist/provider-manager.js +712 -0
- package/dist/ruvector-provider.d.ts +65 -0
- package/dist/ruvector-provider.d.ts.map +1 -0
- package/dist/ruvector-provider.js +813 -0
- package/dist/types.d.ts +280 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +108 -0
- package/package.json +1 -1
|
@@ -0,0 +1,712 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* V3 Provider Manager
|
|
4
|
+
*
|
|
5
|
+
* Orchestrates multiple LLM providers with:
|
|
6
|
+
* - Load balancing (round-robin, latency-based, cost-based)
|
|
7
|
+
* - Automatic failover
|
|
8
|
+
* - Request caching
|
|
9
|
+
* - Cost optimization
|
|
10
|
+
*
|
|
11
|
+
* @module @sparkleideas/providers/provider-manager
|
|
12
|
+
*/
|
|
13
|
+
var __extends = (this && this.__extends) || (function () {
|
|
14
|
+
var extendStatics = function (d, b) {
|
|
15
|
+
extendStatics = Object.setPrototypeOf ||
|
|
16
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
17
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
18
|
+
return extendStatics(d, b);
|
|
19
|
+
};
|
|
20
|
+
return function (d, b) {
|
|
21
|
+
if (typeof b !== "function" && b !== null)
|
|
22
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
23
|
+
extendStatics(d, b);
|
|
24
|
+
function __() { this.constructor = d; }
|
|
25
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
26
|
+
};
|
|
27
|
+
})();
|
|
28
|
+
var __assign = (this && this.__assign) || function () {
|
|
29
|
+
__assign = Object.assign || function(t) {
|
|
30
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
31
|
+
s = arguments[i];
|
|
32
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
33
|
+
t[p] = s[p];
|
|
34
|
+
}
|
|
35
|
+
return t;
|
|
36
|
+
};
|
|
37
|
+
return __assign.apply(this, arguments);
|
|
38
|
+
};
|
|
39
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
40
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
41
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
42
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
43
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
44
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
45
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
49
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
50
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
51
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
52
|
+
function step(op) {
|
|
53
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
54
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
55
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
56
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
57
|
+
switch (op[0]) {
|
|
58
|
+
case 0: case 1: t = op; break;
|
|
59
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
60
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
61
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
62
|
+
default:
|
|
63
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
64
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
65
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
66
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
67
|
+
if (t[2]) _.ops.pop();
|
|
68
|
+
_.trys.pop(); continue;
|
|
69
|
+
}
|
|
70
|
+
op = body.call(thisArg, _);
|
|
71
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
72
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
76
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
77
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
78
|
+
var m = o[Symbol.asyncIterator], i;
|
|
79
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
80
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
81
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
82
|
+
};
|
|
83
|
+
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
84
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
85
|
+
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
86
|
+
return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
|
|
87
|
+
function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
|
|
88
|
+
function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
|
|
89
|
+
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
|
90
|
+
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
|
91
|
+
function fulfill(value) { resume("next", value); }
|
|
92
|
+
function reject(value) { resume("throw", value); }
|
|
93
|
+
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
94
|
+
};
|
|
95
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
96
|
+
exports.ProviderManager = void 0;
|
|
97
|
+
exports.createProviderManager = createProviderManager;
|
|
98
|
+
var events_1 = require("events");
|
|
99
|
+
var types_js_1 = require("./types.js");
|
|
100
|
+
var base_provider_js_1 = require("./base-provider.js");
|
|
101
|
+
var anthropic_provider_js_1 = require("./anthropic-provider.js");
|
|
102
|
+
var openai_provider_js_1 = require("./openai-provider.js");
|
|
103
|
+
var google_provider_js_1 = require("./google-provider.js");
|
|
104
|
+
var cohere_provider_js_1 = require("./cohere-provider.js");
|
|
105
|
+
var ollama_provider_js_1 = require("./ollama-provider.js");
|
|
106
|
+
var ruvector_provider_js_1 = require("./ruvector-provider.js");
|
|
107
|
+
/**
|
|
108
|
+
* Provider Manager - Orchestrates multiple LLM providers
|
|
109
|
+
*/
|
|
110
|
+
var ProviderManager = /** @class */ (function (_super) {
|
|
111
|
+
__extends(ProviderManager, _super);
|
|
112
|
+
function ProviderManager(config, logger) {
|
|
113
|
+
var _this = _super.call(this) || this;
|
|
114
|
+
_this.config = config;
|
|
115
|
+
_this.providers = new Map();
|
|
116
|
+
_this.cache = new Map();
|
|
117
|
+
_this.metrics = new Map();
|
|
118
|
+
_this.roundRobinIndex = 0;
|
|
119
|
+
_this.logger = logger || base_provider_js_1.consoleLogger;
|
|
120
|
+
return _this;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Initialize all configured providers
|
|
124
|
+
*/
|
|
125
|
+
ProviderManager.prototype.initialize = function () {
|
|
126
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
127
|
+
var initPromises;
|
|
128
|
+
var _this = this;
|
|
129
|
+
return __generator(this, function (_a) {
|
|
130
|
+
switch (_a.label) {
|
|
131
|
+
case 0:
|
|
132
|
+
this.logger.info('Initializing provider manager', {
|
|
133
|
+
providerCount: this.config.providers.length,
|
|
134
|
+
});
|
|
135
|
+
initPromises = this.config.providers.map(function (providerConfig) { return __awaiter(_this, void 0, void 0, function () {
|
|
136
|
+
var provider, error_1;
|
|
137
|
+
return __generator(this, function (_a) {
|
|
138
|
+
switch (_a.label) {
|
|
139
|
+
case 0:
|
|
140
|
+
_a.trys.push([0, 2, , 3]);
|
|
141
|
+
provider = this.createProvider(providerConfig);
|
|
142
|
+
return [4 /*yield*/, provider.initialize()];
|
|
143
|
+
case 1:
|
|
144
|
+
_a.sent();
|
|
145
|
+
this.providers.set(providerConfig.provider, provider);
|
|
146
|
+
this.metrics.set(providerConfig.provider, {
|
|
147
|
+
latency: 0,
|
|
148
|
+
errorRate: 0,
|
|
149
|
+
cost: 0,
|
|
150
|
+
lastUsed: 0,
|
|
151
|
+
});
|
|
152
|
+
this.logger.info("Provider ".concat(providerConfig.provider, " initialized"));
|
|
153
|
+
return [3 /*break*/, 3];
|
|
154
|
+
case 2:
|
|
155
|
+
error_1 = _a.sent();
|
|
156
|
+
this.logger.error("Failed to initialize ".concat(providerConfig.provider), error_1);
|
|
157
|
+
return [3 /*break*/, 3];
|
|
158
|
+
case 3: return [2 /*return*/];
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}); });
|
|
162
|
+
return [4 /*yield*/, Promise.all(initPromises)];
|
|
163
|
+
case 1:
|
|
164
|
+
_a.sent();
|
|
165
|
+
this.logger.info('Provider manager initialized', {
|
|
166
|
+
activeProviders: Array.from(this.providers.keys()),
|
|
167
|
+
});
|
|
168
|
+
return [2 /*return*/];
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* Create a provider instance
|
|
175
|
+
*/
|
|
176
|
+
ProviderManager.prototype.createProvider = function (config) {
|
|
177
|
+
var options = {
|
|
178
|
+
config: config,
|
|
179
|
+
logger: this.logger,
|
|
180
|
+
};
|
|
181
|
+
switch (config.provider) {
|
|
182
|
+
case 'anthropic':
|
|
183
|
+
return new anthropic_provider_js_1.AnthropicProvider(options);
|
|
184
|
+
case 'openai':
|
|
185
|
+
return new openai_provider_js_1.OpenAIProvider(options);
|
|
186
|
+
case 'google':
|
|
187
|
+
return new google_provider_js_1.GoogleProvider(options);
|
|
188
|
+
case 'cohere':
|
|
189
|
+
return new cohere_provider_js_1.CohereProvider(options);
|
|
190
|
+
case 'ollama':
|
|
191
|
+
return new ollama_provider_js_1.OllamaProvider(options);
|
|
192
|
+
case 'ruvector':
|
|
193
|
+
return new ruvector_provider_js_1.RuVectorProvider(options);
|
|
194
|
+
default:
|
|
195
|
+
throw new Error("Unknown provider: ".concat(config.provider));
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* Complete a request with automatic provider selection
|
|
200
|
+
*/
|
|
201
|
+
ProviderManager.prototype.complete = function (request, preferredProvider) {
|
|
202
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
203
|
+
var cached, provider, _a, startTime, response, error_2;
|
|
204
|
+
var _b, _c, _d, _e;
|
|
205
|
+
return __generator(this, function (_f) {
|
|
206
|
+
switch (_f.label) {
|
|
207
|
+
case 0:
|
|
208
|
+
// Check cache first
|
|
209
|
+
if ((_b = this.config.cache) === null || _b === void 0 ? void 0 : _b.enabled) {
|
|
210
|
+
cached = this.getCached(request);
|
|
211
|
+
if (cached) {
|
|
212
|
+
this.logger.debug('Cache hit', { requestId: request.requestId });
|
|
213
|
+
return [2 /*return*/, cached];
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (!preferredProvider) return [3 /*break*/, 1];
|
|
217
|
+
_a = this.providers.get(preferredProvider);
|
|
218
|
+
return [3 /*break*/, 3];
|
|
219
|
+
case 1: return [4 /*yield*/, this.selectProvider(request)];
|
|
220
|
+
case 2:
|
|
221
|
+
_a = _f.sent();
|
|
222
|
+
_f.label = 3;
|
|
223
|
+
case 3:
|
|
224
|
+
provider = _a;
|
|
225
|
+
if (!provider) {
|
|
226
|
+
throw new Error('No available providers');
|
|
227
|
+
}
|
|
228
|
+
startTime = Date.now();
|
|
229
|
+
_f.label = 4;
|
|
230
|
+
case 4:
|
|
231
|
+
_f.trys.push([4, 6, , 7]);
|
|
232
|
+
return [4 /*yield*/, provider.complete(request)];
|
|
233
|
+
case 5:
|
|
234
|
+
response = _f.sent();
|
|
235
|
+
this.updateMetrics(provider.name, Date.now() - startTime, false, ((_c = response.cost) === null || _c === void 0 ? void 0 : _c.totalCost) || 0);
|
|
236
|
+
// Cache response
|
|
237
|
+
if ((_d = this.config.cache) === null || _d === void 0 ? void 0 : _d.enabled) {
|
|
238
|
+
this.setCached(request, response);
|
|
239
|
+
}
|
|
240
|
+
this.emit('complete', { provider: provider.name, response: response });
|
|
241
|
+
return [2 /*return*/, response];
|
|
242
|
+
case 6:
|
|
243
|
+
error_2 = _f.sent();
|
|
244
|
+
this.updateMetrics(provider.name, Date.now() - startTime, true, 0);
|
|
245
|
+
// Try fallback
|
|
246
|
+
if (((_e = this.config.fallback) === null || _e === void 0 ? void 0 : _e.enabled) && (0, types_js_1.isLLMProviderError)(error_2)) {
|
|
247
|
+
return [2 /*return*/, this.completWithFallback(request, provider.name, error_2)];
|
|
248
|
+
}
|
|
249
|
+
throw error_2;
|
|
250
|
+
case 7: return [2 /*return*/];
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
};
|
|
255
|
+
/**
|
|
256
|
+
* Stream complete with automatic provider selection
|
|
257
|
+
*/
|
|
258
|
+
ProviderManager.prototype.streamComplete = function (request, preferredProvider) {
|
|
259
|
+
return __asyncGenerator(this, arguments, function streamComplete_1() {
|
|
260
|
+
var provider, _a, startTime, _b, _c, _d, event_1, e_1_1, error_3;
|
|
261
|
+
var _e, e_1, _f, _g;
|
|
262
|
+
return __generator(this, function (_h) {
|
|
263
|
+
switch (_h.label) {
|
|
264
|
+
case 0:
|
|
265
|
+
if (!preferredProvider) return [3 /*break*/, 1];
|
|
266
|
+
_a = this.providers.get(preferredProvider);
|
|
267
|
+
return [3 /*break*/, 3];
|
|
268
|
+
case 1: return [4 /*yield*/, __await(this.selectProvider(request))];
|
|
269
|
+
case 2:
|
|
270
|
+
_a = _h.sent();
|
|
271
|
+
_h.label = 3;
|
|
272
|
+
case 3:
|
|
273
|
+
provider = _a;
|
|
274
|
+
if (!provider) {
|
|
275
|
+
throw new Error('No available providers');
|
|
276
|
+
}
|
|
277
|
+
startTime = Date.now();
|
|
278
|
+
_h.label = 4;
|
|
279
|
+
case 4:
|
|
280
|
+
_h.trys.push([4, 19, , 20]);
|
|
281
|
+
_h.label = 5;
|
|
282
|
+
case 5:
|
|
283
|
+
_h.trys.push([5, 12, 13, 18]);
|
|
284
|
+
_b = true, _c = __asyncValues(provider.streamComplete(request));
|
|
285
|
+
_h.label = 6;
|
|
286
|
+
case 6: return [4 /*yield*/, __await(_c.next())];
|
|
287
|
+
case 7:
|
|
288
|
+
if (!(_d = _h.sent(), _e = _d.done, !_e)) return [3 /*break*/, 11];
|
|
289
|
+
_g = _d.value;
|
|
290
|
+
_b = false;
|
|
291
|
+
event_1 = _g;
|
|
292
|
+
return [4 /*yield*/, __await(event_1)];
|
|
293
|
+
case 8: return [4 /*yield*/, _h.sent()];
|
|
294
|
+
case 9:
|
|
295
|
+
_h.sent();
|
|
296
|
+
_h.label = 10;
|
|
297
|
+
case 10:
|
|
298
|
+
_b = true;
|
|
299
|
+
return [3 /*break*/, 6];
|
|
300
|
+
case 11: return [3 /*break*/, 18];
|
|
301
|
+
case 12:
|
|
302
|
+
e_1_1 = _h.sent();
|
|
303
|
+
e_1 = { error: e_1_1 };
|
|
304
|
+
return [3 /*break*/, 18];
|
|
305
|
+
case 13:
|
|
306
|
+
_h.trys.push([13, , 16, 17]);
|
|
307
|
+
if (!(!_b && !_e && (_f = _c.return))) return [3 /*break*/, 15];
|
|
308
|
+
return [4 /*yield*/, __await(_f.call(_c))];
|
|
309
|
+
case 14:
|
|
310
|
+
_h.sent();
|
|
311
|
+
_h.label = 15;
|
|
312
|
+
case 15: return [3 /*break*/, 17];
|
|
313
|
+
case 16:
|
|
314
|
+
if (e_1) throw e_1.error;
|
|
315
|
+
return [7 /*endfinally*/];
|
|
316
|
+
case 17: return [7 /*endfinally*/];
|
|
317
|
+
case 18:
|
|
318
|
+
this.updateMetrics(provider.name, Date.now() - startTime, false, 0);
|
|
319
|
+
return [3 /*break*/, 20];
|
|
320
|
+
case 19:
|
|
321
|
+
error_3 = _h.sent();
|
|
322
|
+
this.updateMetrics(provider.name, Date.now() - startTime, true, 0);
|
|
323
|
+
throw error_3;
|
|
324
|
+
case 20: return [2 /*return*/];
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
});
|
|
328
|
+
};
|
|
329
|
+
/**
|
|
330
|
+
* Select provider based on load balancing strategy
|
|
331
|
+
*/
|
|
332
|
+
ProviderManager.prototype.selectProvider = function (request) {
|
|
333
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
334
|
+
var availableProviders, strategy;
|
|
335
|
+
var _a;
|
|
336
|
+
return __generator(this, function (_b) {
|
|
337
|
+
availableProviders = Array.from(this.providers.values()).filter(function (p) { return p.getStatus().available; });
|
|
338
|
+
if (availableProviders.length === 0) {
|
|
339
|
+
// Try to use any provider
|
|
340
|
+
return [2 /*return*/, this.providers.values().next().value];
|
|
341
|
+
}
|
|
342
|
+
strategy = ((_a = this.config.loadBalancing) === null || _a === void 0 ? void 0 : _a.strategy) || 'round-robin';
|
|
343
|
+
switch (strategy) {
|
|
344
|
+
case 'round-robin':
|
|
345
|
+
return [2 /*return*/, this.selectRoundRobin(availableProviders)];
|
|
346
|
+
case 'least-loaded':
|
|
347
|
+
return [2 /*return*/, this.selectLeastLoaded(availableProviders)];
|
|
348
|
+
case 'latency-based':
|
|
349
|
+
return [2 /*return*/, this.selectByLatency(availableProviders)];
|
|
350
|
+
case 'cost-based':
|
|
351
|
+
return [2 /*return*/, this.selectByCost(availableProviders, request)];
|
|
352
|
+
default:
|
|
353
|
+
return [2 /*return*/, availableProviders[0]];
|
|
354
|
+
}
|
|
355
|
+
return [2 /*return*/];
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
};
|
|
359
|
+
ProviderManager.prototype.selectRoundRobin = function (providers) {
|
|
360
|
+
var provider = providers[this.roundRobinIndex % providers.length];
|
|
361
|
+
this.roundRobinIndex++;
|
|
362
|
+
return provider;
|
|
363
|
+
};
|
|
364
|
+
ProviderManager.prototype.selectLeastLoaded = function (providers) {
|
|
365
|
+
return providers.reduce(function (best, current) {
|
|
366
|
+
return current.getStatus().currentLoad < best.getStatus().currentLoad ? current : best;
|
|
367
|
+
});
|
|
368
|
+
};
|
|
369
|
+
ProviderManager.prototype.selectByLatency = function (providers) {
|
|
370
|
+
var _this = this;
|
|
371
|
+
return providers.reduce(function (best, current) {
|
|
372
|
+
var bestMetrics = _this.metrics.get(best.name);
|
|
373
|
+
var currentMetrics = _this.metrics.get(current.name);
|
|
374
|
+
return ((currentMetrics === null || currentMetrics === void 0 ? void 0 : currentMetrics.latency) || Infinity) < ((bestMetrics === null || bestMetrics === void 0 ? void 0 : bestMetrics.latency) || Infinity)
|
|
375
|
+
? current
|
|
376
|
+
: best;
|
|
377
|
+
});
|
|
378
|
+
};
|
|
379
|
+
ProviderManager.prototype.selectByCost = function (providers, request) {
|
|
380
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
381
|
+
var estimates;
|
|
382
|
+
var _this = this;
|
|
383
|
+
return __generator(this, function (_a) {
|
|
384
|
+
switch (_a.label) {
|
|
385
|
+
case 0: return [4 /*yield*/, Promise.all(providers.map(function (p) { return __awaiter(_this, void 0, void 0, function () {
|
|
386
|
+
var _a;
|
|
387
|
+
return __generator(this, function (_b) {
|
|
388
|
+
switch (_b.label) {
|
|
389
|
+
case 0:
|
|
390
|
+
_a = {
|
|
391
|
+
provider: p
|
|
392
|
+
};
|
|
393
|
+
return [4 /*yield*/, p.estimateCost(request)];
|
|
394
|
+
case 1: return [2 /*return*/, (_a.cost = (_b.sent()).estimatedCost.total,
|
|
395
|
+
_a)];
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
}); }))];
|
|
399
|
+
case 1:
|
|
400
|
+
estimates = _a.sent();
|
|
401
|
+
return [2 /*return*/, estimates.reduce(function (best, current) {
|
|
402
|
+
return current.cost < best.cost ? current : best;
|
|
403
|
+
}).provider];
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
};
|
|
408
|
+
/**
|
|
409
|
+
* Complete with fallback on failure
|
|
410
|
+
*/
|
|
411
|
+
ProviderManager.prototype.completWithFallback = function (request, failedProvider, originalError) {
|
|
412
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
413
|
+
var maxAttempts, attempts, lastError, remainingProviders, _i, remainingProviders_1, provider, response, error_4;
|
|
414
|
+
var _a;
|
|
415
|
+
return __generator(this, function (_b) {
|
|
416
|
+
switch (_b.label) {
|
|
417
|
+
case 0:
|
|
418
|
+
maxAttempts = ((_a = this.config.fallback) === null || _a === void 0 ? void 0 : _a.maxAttempts) || 2;
|
|
419
|
+
attempts = 0;
|
|
420
|
+
lastError = originalError;
|
|
421
|
+
remainingProviders = Array.from(this.providers.values()).filter(function (p) { return p.name !== failedProvider; });
|
|
422
|
+
_i = 0, remainingProviders_1 = remainingProviders;
|
|
423
|
+
_b.label = 1;
|
|
424
|
+
case 1:
|
|
425
|
+
if (!(_i < remainingProviders_1.length)) return [3 /*break*/, 6];
|
|
426
|
+
provider = remainingProviders_1[_i];
|
|
427
|
+
if (attempts >= maxAttempts)
|
|
428
|
+
return [3 /*break*/, 6];
|
|
429
|
+
attempts++;
|
|
430
|
+
this.logger.info("Attempting fallback to ".concat(provider.name), {
|
|
431
|
+
attempt: attempts,
|
|
432
|
+
originalProvider: failedProvider,
|
|
433
|
+
});
|
|
434
|
+
_b.label = 2;
|
|
435
|
+
case 2:
|
|
436
|
+
_b.trys.push([2, 4, , 5]);
|
|
437
|
+
return [4 /*yield*/, provider.complete(request)];
|
|
438
|
+
case 3:
|
|
439
|
+
response = _b.sent();
|
|
440
|
+
this.emit('fallback_success', {
|
|
441
|
+
originalProvider: failedProvider,
|
|
442
|
+
fallbackProvider: provider.name,
|
|
443
|
+
attempts: attempts,
|
|
444
|
+
});
|
|
445
|
+
return [2 /*return*/, response];
|
|
446
|
+
case 4:
|
|
447
|
+
error_4 = _b.sent();
|
|
448
|
+
if ((0, types_js_1.isLLMProviderError)(error_4)) {
|
|
449
|
+
lastError = error_4;
|
|
450
|
+
}
|
|
451
|
+
return [3 /*break*/, 5];
|
|
452
|
+
case 5:
|
|
453
|
+
_i++;
|
|
454
|
+
return [3 /*break*/, 1];
|
|
455
|
+
case 6:
|
|
456
|
+
this.emit('fallback_exhausted', {
|
|
457
|
+
originalProvider: failedProvider,
|
|
458
|
+
attempts: attempts,
|
|
459
|
+
});
|
|
460
|
+
throw lastError;
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
};
|
|
465
|
+
/**
|
|
466
|
+
* Update provider metrics
|
|
467
|
+
*/
|
|
468
|
+
ProviderManager.prototype.updateMetrics = function (provider, latency, error, cost) {
|
|
469
|
+
var current = this.metrics.get(provider) || {
|
|
470
|
+
latency: 0,
|
|
471
|
+
errorRate: 0,
|
|
472
|
+
cost: 0,
|
|
473
|
+
lastUsed: 0,
|
|
474
|
+
};
|
|
475
|
+
// Exponential moving average for latency
|
|
476
|
+
var alpha = 0.3;
|
|
477
|
+
var newLatency = current.latency === 0 ? latency : alpha * latency + (1 - alpha) * current.latency;
|
|
478
|
+
// Update error rate
|
|
479
|
+
var errorWeight = error ? 1 : 0;
|
|
480
|
+
var newErrorRate = alpha * errorWeight + (1 - alpha) * current.errorRate;
|
|
481
|
+
this.metrics.set(provider, {
|
|
482
|
+
latency: newLatency,
|
|
483
|
+
errorRate: newErrorRate,
|
|
484
|
+
cost: current.cost + cost,
|
|
485
|
+
lastUsed: Date.now(),
|
|
486
|
+
});
|
|
487
|
+
};
|
|
488
|
+
/**
|
|
489
|
+
* Get cached response
|
|
490
|
+
*/
|
|
491
|
+
ProviderManager.prototype.getCached = function (request) {
|
|
492
|
+
var _a;
|
|
493
|
+
var key = this.getCacheKey(request);
|
|
494
|
+
var entry = this.cache.get(key);
|
|
495
|
+
if (!entry)
|
|
496
|
+
return undefined;
|
|
497
|
+
var ttl = ((_a = this.config.cache) === null || _a === void 0 ? void 0 : _a.ttl) || 300000;
|
|
498
|
+
if (Date.now() - entry.timestamp > ttl) {
|
|
499
|
+
this.cache.delete(key);
|
|
500
|
+
return undefined;
|
|
501
|
+
}
|
|
502
|
+
entry.hits++;
|
|
503
|
+
return entry.response;
|
|
504
|
+
};
|
|
505
|
+
/**
|
|
506
|
+
* Set cached response
|
|
507
|
+
*/
|
|
508
|
+
ProviderManager.prototype.setCached = function (request, response) {
|
|
509
|
+
var _a;
|
|
510
|
+
var key = this.getCacheKey(request);
|
|
511
|
+
// Enforce max size
|
|
512
|
+
var maxSize = ((_a = this.config.cache) === null || _a === void 0 ? void 0 : _a.maxSize) || 1000;
|
|
513
|
+
if (this.cache.size >= maxSize) {
|
|
514
|
+
// Remove oldest entry
|
|
515
|
+
var oldest = Array.from(this.cache.entries()).sort(function (a, b) { return a[1].timestamp - b[1].timestamp; })[0];
|
|
516
|
+
if (oldest)
|
|
517
|
+
this.cache.delete(oldest[0]);
|
|
518
|
+
}
|
|
519
|
+
this.cache.set(key, {
|
|
520
|
+
response: response,
|
|
521
|
+
timestamp: Date.now(),
|
|
522
|
+
hits: 0,
|
|
523
|
+
});
|
|
524
|
+
};
|
|
525
|
+
/**
|
|
526
|
+
* Generate cache key
|
|
527
|
+
*/
|
|
528
|
+
ProviderManager.prototype.getCacheKey = function (request) {
|
|
529
|
+
return JSON.stringify({
|
|
530
|
+
messages: request.messages,
|
|
531
|
+
model: request.model,
|
|
532
|
+
temperature: request.temperature,
|
|
533
|
+
maxTokens: request.maxTokens,
|
|
534
|
+
});
|
|
535
|
+
};
|
|
536
|
+
/**
|
|
537
|
+
* Get a specific provider
|
|
538
|
+
*/
|
|
539
|
+
ProviderManager.prototype.getProvider = function (name) {
|
|
540
|
+
return this.providers.get(name);
|
|
541
|
+
};
|
|
542
|
+
/**
|
|
543
|
+
* List all available providers
|
|
544
|
+
*/
|
|
545
|
+
ProviderManager.prototype.listProviders = function () {
|
|
546
|
+
return Array.from(this.providers.keys());
|
|
547
|
+
};
|
|
548
|
+
/**
|
|
549
|
+
* Health check all providers
|
|
550
|
+
*/
|
|
551
|
+
ProviderManager.prototype.healthCheck = function () {
|
|
552
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
553
|
+
var results;
|
|
554
|
+
var _this = this;
|
|
555
|
+
return __generator(this, function (_a) {
|
|
556
|
+
switch (_a.label) {
|
|
557
|
+
case 0:
|
|
558
|
+
results = new Map();
|
|
559
|
+
return [4 /*yield*/, Promise.all(Array.from(this.providers.entries()).map(function (_a) { return __awaiter(_this, [_a], void 0, function (_b) {
|
|
560
|
+
var result;
|
|
561
|
+
var name = _b[0], provider = _b[1];
|
|
562
|
+
return __generator(this, function (_c) {
|
|
563
|
+
switch (_c.label) {
|
|
564
|
+
case 0: return [4 /*yield*/, provider.healthCheck()];
|
|
565
|
+
case 1:
|
|
566
|
+
result = _c.sent();
|
|
567
|
+
results.set(name, result);
|
|
568
|
+
return [2 /*return*/];
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
}); }))];
|
|
572
|
+
case 1:
|
|
573
|
+
_a.sent();
|
|
574
|
+
return [2 /*return*/, results];
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
});
|
|
578
|
+
};
|
|
579
|
+
/**
|
|
580
|
+
* Estimate cost across providers
|
|
581
|
+
*/
|
|
582
|
+
ProviderManager.prototype.estimateCost = function (request) {
|
|
583
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
584
|
+
var estimates;
|
|
585
|
+
var _this = this;
|
|
586
|
+
return __generator(this, function (_a) {
|
|
587
|
+
switch (_a.label) {
|
|
588
|
+
case 0:
|
|
589
|
+
estimates = new Map();
|
|
590
|
+
return [4 /*yield*/, Promise.all(Array.from(this.providers.entries()).map(function (_a) { return __awaiter(_this, [_a], void 0, function (_b) {
|
|
591
|
+
var estimate;
|
|
592
|
+
var name = _b[0], provider = _b[1];
|
|
593
|
+
return __generator(this, function (_c) {
|
|
594
|
+
switch (_c.label) {
|
|
595
|
+
case 0: return [4 /*yield*/, provider.estimateCost(request)];
|
|
596
|
+
case 1:
|
|
597
|
+
estimate = _c.sent();
|
|
598
|
+
estimates.set(name, estimate);
|
|
599
|
+
return [2 /*return*/];
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
}); }))];
|
|
603
|
+
case 1:
|
|
604
|
+
_a.sent();
|
|
605
|
+
return [2 /*return*/, estimates];
|
|
606
|
+
}
|
|
607
|
+
});
|
|
608
|
+
});
|
|
609
|
+
};
|
|
610
|
+
/**
|
|
611
|
+
* Get aggregated usage statistics
|
|
612
|
+
*/
|
|
613
|
+
ProviderManager.prototype.getUsage = function () {
|
|
614
|
+
return __awaiter(this, arguments, void 0, function (period) {
|
|
615
|
+
var totalRequests, totalTokens, totalCost, totalErrors, totalLatency, count, _i, _a, provider, usage, now, start;
|
|
616
|
+
if (period === void 0) { period = 'day'; }
|
|
617
|
+
return __generator(this, function (_b) {
|
|
618
|
+
switch (_b.label) {
|
|
619
|
+
case 0:
|
|
620
|
+
totalRequests = 0;
|
|
621
|
+
totalTokens = { prompt: 0, completion: 0, total: 0 };
|
|
622
|
+
totalCost = { prompt: 0, completion: 0, total: 0 };
|
|
623
|
+
totalErrors = 0;
|
|
624
|
+
totalLatency = 0;
|
|
625
|
+
count = 0;
|
|
626
|
+
_i = 0, _a = this.providers.values();
|
|
627
|
+
_b.label = 1;
|
|
628
|
+
case 1:
|
|
629
|
+
if (!(_i < _a.length)) return [3 /*break*/, 4];
|
|
630
|
+
provider = _a[_i];
|
|
631
|
+
return [4 /*yield*/, provider.getUsage(period)];
|
|
632
|
+
case 2:
|
|
633
|
+
usage = _b.sent();
|
|
634
|
+
totalRequests += usage.requests;
|
|
635
|
+
totalTokens.prompt += usage.tokens.prompt;
|
|
636
|
+
totalTokens.completion += usage.tokens.completion;
|
|
637
|
+
totalTokens.total += usage.tokens.total;
|
|
638
|
+
totalCost.prompt += usage.cost.prompt;
|
|
639
|
+
totalCost.completion += usage.cost.completion;
|
|
640
|
+
totalCost.total += usage.cost.total;
|
|
641
|
+
totalErrors += usage.errors;
|
|
642
|
+
totalLatency += usage.averageLatency;
|
|
643
|
+
count++;
|
|
644
|
+
_b.label = 3;
|
|
645
|
+
case 3:
|
|
646
|
+
_i++;
|
|
647
|
+
return [3 /*break*/, 1];
|
|
648
|
+
case 4:
|
|
649
|
+
now = new Date();
|
|
650
|
+
start = new Date();
|
|
651
|
+
start.setDate(start.getDate() - 1);
|
|
652
|
+
return [2 /*return*/, {
|
|
653
|
+
period: { start: start, end: now },
|
|
654
|
+
requests: totalRequests,
|
|
655
|
+
tokens: totalTokens,
|
|
656
|
+
cost: __assign(__assign({}, totalCost), { currency: 'USD' }),
|
|
657
|
+
errors: totalErrors,
|
|
658
|
+
averageLatency: count > 0 ? totalLatency / count : 0,
|
|
659
|
+
modelBreakdown: {},
|
|
660
|
+
}];
|
|
661
|
+
}
|
|
662
|
+
});
|
|
663
|
+
});
|
|
664
|
+
};
|
|
665
|
+
/**
|
|
666
|
+
* Get provider metrics
|
|
667
|
+
*/
|
|
668
|
+
ProviderManager.prototype.getMetrics = function () {
|
|
669
|
+
return new Map(this.metrics);
|
|
670
|
+
};
|
|
671
|
+
/**
|
|
672
|
+
* Clear cache
|
|
673
|
+
*/
|
|
674
|
+
ProviderManager.prototype.clearCache = function () {
|
|
675
|
+
this.cache.clear();
|
|
676
|
+
this.logger.info('Cache cleared');
|
|
677
|
+
};
|
|
678
|
+
/**
|
|
679
|
+
* Destroy all providers
|
|
680
|
+
*/
|
|
681
|
+
ProviderManager.prototype.destroy = function () {
|
|
682
|
+
for (var _i = 0, _a = this.providers.values(); _i < _a.length; _i++) {
|
|
683
|
+
var provider = _a[_i];
|
|
684
|
+
provider.destroy();
|
|
685
|
+
}
|
|
686
|
+
this.providers.clear();
|
|
687
|
+
this.cache.clear();
|
|
688
|
+
this.metrics.clear();
|
|
689
|
+
this.removeAllListeners();
|
|
690
|
+
this.logger.info('Provider manager destroyed');
|
|
691
|
+
};
|
|
692
|
+
return ProviderManager;
|
|
693
|
+
}(events_1.EventEmitter));
|
|
694
|
+
exports.ProviderManager = ProviderManager;
|
|
695
|
+
/**
|
|
696
|
+
* Create and initialize a provider manager
|
|
697
|
+
*/
|
|
698
|
+
function createProviderManager(config, logger) {
|
|
699
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
700
|
+
var manager;
|
|
701
|
+
return __generator(this, function (_a) {
|
|
702
|
+
switch (_a.label) {
|
|
703
|
+
case 0:
|
|
704
|
+
manager = new ProviderManager(config, logger);
|
|
705
|
+
return [4 /*yield*/, manager.initialize()];
|
|
706
|
+
case 1:
|
|
707
|
+
_a.sent();
|
|
708
|
+
return [2 /*return*/, manager];
|
|
709
|
+
}
|
|
710
|
+
});
|
|
711
|
+
});
|
|
712
|
+
}
|