@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.
@@ -0,0 +1,543 @@
1
+ "use strict";
2
+ /**
3
+ * V3 OpenAI Provider
4
+ *
5
+ * Supports GPT-4o, GPT-4, o1, and other OpenAI models.
6
+ *
7
+ * @module @sparkleideas/providers/openai-provider
8
+ */
9
+ var __extends = (this && this.__extends) || (function () {
10
+ var extendStatics = function (d, b) {
11
+ extendStatics = Object.setPrototypeOf ||
12
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
13
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
14
+ return extendStatics(d, b);
15
+ };
16
+ return function (d, b) {
17
+ if (typeof b !== "function" && b !== null)
18
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
19
+ extendStatics(d, b);
20
+ function __() { this.constructor = d; }
21
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
22
+ };
23
+ })();
24
+ var __assign = (this && this.__assign) || function () {
25
+ __assign = Object.assign || function(t) {
26
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
27
+ s = arguments[i];
28
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
29
+ t[p] = s[p];
30
+ }
31
+ return t;
32
+ };
33
+ return __assign.apply(this, arguments);
34
+ };
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ var __generator = (this && this.__generator) || function (thisArg, body) {
45
+ 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);
46
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
47
+ function verb(n) { return function (v) { return step([n, v]); }; }
48
+ function step(op) {
49
+ if (f) throw new TypeError("Generator is already executing.");
50
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
51
+ 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;
52
+ if (y = 0, t) op = [op[0] & 2, t.value];
53
+ switch (op[0]) {
54
+ case 0: case 1: t = op; break;
55
+ case 4: _.label++; return { value: op[1], done: false };
56
+ case 5: _.label++; y = op[1]; op = [0]; continue;
57
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
58
+ default:
59
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
60
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
61
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
62
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
63
+ if (t[2]) _.ops.pop();
64
+ _.trys.pop(); continue;
65
+ }
66
+ op = body.call(thisArg, _);
67
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
68
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
69
+ }
70
+ };
71
+ var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
72
+ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
73
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
74
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
75
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
76
+ function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
77
+ 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]); } }
78
+ function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
79
+ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
80
+ function fulfill(value) { resume("next", value); }
81
+ function reject(value) { resume("throw", value); }
82
+ function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
83
+ };
84
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
85
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
86
+ if (ar || !(i in from)) {
87
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
88
+ ar[i] = from[i];
89
+ }
90
+ }
91
+ return to.concat(ar || Array.prototype.slice.call(from));
92
+ };
93
+ Object.defineProperty(exports, "__esModule", { value: true });
94
+ exports.OpenAIProvider = void 0;
95
+ var base_provider_js_1 = require("./base-provider.js");
96
+ var types_js_1 = require("./types.js");
97
+ var OpenAIProvider = /** @class */ (function (_super) {
98
+ __extends(OpenAIProvider, _super);
99
+ function OpenAIProvider(options) {
100
+ var _this = _super.call(this, options) || this;
101
+ _this.name = 'openai';
102
+ _this.capabilities = {
103
+ supportedModels: [
104
+ 'gpt-4o',
105
+ 'gpt-4o-mini',
106
+ 'gpt-4-turbo',
107
+ 'gpt-4',
108
+ 'gpt-3.5-turbo',
109
+ 'o1-preview',
110
+ 'o1-mini',
111
+ 'o3-mini',
112
+ ],
113
+ maxContextLength: {
114
+ 'gpt-4o': 128000,
115
+ 'gpt-4o-mini': 128000,
116
+ 'gpt-4-turbo': 128000,
117
+ 'gpt-4': 8192,
118
+ 'gpt-3.5-turbo': 16384,
119
+ 'o1-preview': 128000,
120
+ 'o1-mini': 128000,
121
+ 'o3-mini': 200000,
122
+ },
123
+ maxOutputTokens: {
124
+ 'gpt-4o': 16384,
125
+ 'gpt-4o-mini': 16384,
126
+ 'gpt-4-turbo': 4096,
127
+ 'gpt-4': 8192,
128
+ 'gpt-3.5-turbo': 4096,
129
+ 'o1-preview': 32768,
130
+ 'o1-mini': 65536,
131
+ 'o3-mini': 100000,
132
+ },
133
+ supportsStreaming: true,
134
+ supportsToolCalling: true,
135
+ supportsSystemMessages: true,
136
+ supportsVision: true,
137
+ supportsAudio: true,
138
+ supportsFineTuning: true,
139
+ supportsEmbeddings: true,
140
+ supportsBatching: true,
141
+ rateLimit: {
142
+ requestsPerMinute: 10000,
143
+ tokensPerMinute: 2000000,
144
+ concurrentRequests: 500,
145
+ },
146
+ pricing: {
147
+ 'gpt-4o': {
148
+ promptCostPer1k: 0.0025,
149
+ completionCostPer1k: 0.01,
150
+ currency: 'USD',
151
+ },
152
+ 'gpt-4o-mini': {
153
+ promptCostPer1k: 0.00015,
154
+ completionCostPer1k: 0.0006,
155
+ currency: 'USD',
156
+ },
157
+ 'gpt-4-turbo': {
158
+ promptCostPer1k: 0.01,
159
+ completionCostPer1k: 0.03,
160
+ currency: 'USD',
161
+ },
162
+ 'gpt-4': {
163
+ promptCostPer1k: 0.03,
164
+ completionCostPer1k: 0.06,
165
+ currency: 'USD',
166
+ },
167
+ 'gpt-3.5-turbo': {
168
+ promptCostPer1k: 0.0005,
169
+ completionCostPer1k: 0.0015,
170
+ currency: 'USD',
171
+ },
172
+ 'o1-preview': {
173
+ promptCostPer1k: 0.015,
174
+ completionCostPer1k: 0.06,
175
+ currency: 'USD',
176
+ },
177
+ 'o1-mini': {
178
+ promptCostPer1k: 0.003,
179
+ completionCostPer1k: 0.012,
180
+ currency: 'USD',
181
+ },
182
+ 'o3-mini': {
183
+ promptCostPer1k: 0.0011,
184
+ completionCostPer1k: 0.0044,
185
+ currency: 'USD',
186
+ },
187
+ },
188
+ };
189
+ _this.baseUrl = 'https://api.openai.com/v1';
190
+ _this.headers = {};
191
+ return _this;
192
+ }
193
+ OpenAIProvider.prototype.doInitialize = function () {
194
+ return __awaiter(this, void 0, void 0, function () {
195
+ var _a;
196
+ return __generator(this, function (_b) {
197
+ if (!this.config.apiKey) {
198
+ throw new types_js_1.AuthenticationError('OpenAI API key is required', 'openai');
199
+ }
200
+ this.baseUrl = this.config.apiUrl || 'https://api.openai.com/v1';
201
+ this.headers = {
202
+ Authorization: "Bearer ".concat(this.config.apiKey),
203
+ 'Content-Type': 'application/json',
204
+ };
205
+ if ((_a = this.config.providerOptions) === null || _a === void 0 ? void 0 : _a.organization) {
206
+ this.headers['OpenAI-Organization'] = this.config.providerOptions.organization;
207
+ }
208
+ return [2 /*return*/];
209
+ });
210
+ });
211
+ };
212
+ OpenAIProvider.prototype.doComplete = function (request) {
213
+ return __awaiter(this, void 0, void 0, function () {
214
+ var openAIRequest, controller, timeout, response, data, error_1;
215
+ return __generator(this, function (_a) {
216
+ switch (_a.label) {
217
+ case 0:
218
+ openAIRequest = this.buildRequest(request);
219
+ controller = new AbortController();
220
+ timeout = setTimeout(function () { return controller.abort(); }, this.config.timeout || 60000);
221
+ _a.label = 1;
222
+ case 1:
223
+ _a.trys.push([1, 6, , 7]);
224
+ return [4 /*yield*/, fetch("".concat(this.baseUrl, "/chat/completions"), {
225
+ method: 'POST',
226
+ headers: this.headers,
227
+ body: JSON.stringify(openAIRequest),
228
+ signal: controller.signal,
229
+ })];
230
+ case 2:
231
+ response = _a.sent();
232
+ clearTimeout(timeout);
233
+ if (!!response.ok) return [3 /*break*/, 4];
234
+ return [4 /*yield*/, this.handleErrorResponse(response)];
235
+ case 3:
236
+ _a.sent();
237
+ _a.label = 4;
238
+ case 4: return [4 /*yield*/, response.json()];
239
+ case 5:
240
+ data = _a.sent();
241
+ return [2 /*return*/, this.transformResponse(data, request)];
242
+ case 6:
243
+ error_1 = _a.sent();
244
+ clearTimeout(timeout);
245
+ throw this.transformError(error_1);
246
+ case 7: return [2 /*return*/];
247
+ }
248
+ });
249
+ });
250
+ };
251
+ OpenAIProvider.prototype.doStreamComplete = function (request) {
252
+ return __asyncGenerator(this, arguments, function doStreamComplete_1() {
253
+ var openAIRequest, controller, timeout, response, reader, decoder, buffer, _a, done, value, lines, _i, lines_1, line, data, promptTokens, model, baseModel, pricing, promptCostPer1k, completionCostPer1k, chunk, delta, _b, _c, toolCall, _d, error_2;
254
+ var _e, _f, _g, _h;
255
+ return __generator(this, function (_j) {
256
+ switch (_j.label) {
257
+ case 0:
258
+ openAIRequest = this.buildRequest(request, true);
259
+ controller = new AbortController();
260
+ timeout = setTimeout(function () { return controller.abort(); }, (this.config.timeout || 60000) * 2);
261
+ _j.label = 1;
262
+ case 1:
263
+ _j.trys.push([1, 23, 24, 25]);
264
+ return [4 /*yield*/, __await(fetch("".concat(this.baseUrl, "/chat/completions"), {
265
+ method: 'POST',
266
+ headers: this.headers,
267
+ body: JSON.stringify(openAIRequest),
268
+ signal: controller.signal,
269
+ }))];
270
+ case 2:
271
+ response = _j.sent();
272
+ if (!!response.ok) return [3 /*break*/, 4];
273
+ return [4 /*yield*/, __await(this.handleErrorResponse(response))];
274
+ case 3:
275
+ _j.sent();
276
+ _j.label = 4;
277
+ case 4:
278
+ reader = response.body.getReader();
279
+ decoder = new TextDecoder();
280
+ buffer = '';
281
+ _j.label = 5;
282
+ case 5:
283
+ if (!true) return [3 /*break*/, 22];
284
+ return [4 /*yield*/, __await(reader.read())];
285
+ case 6:
286
+ _a = _j.sent(), done = _a.done, value = _a.value;
287
+ if (done)
288
+ return [3 /*break*/, 22];
289
+ buffer += decoder.decode(value, { stream: true });
290
+ lines = buffer.split('\n');
291
+ buffer = lines.pop() || '';
292
+ _i = 0, lines_1 = lines;
293
+ _j.label = 7;
294
+ case 7:
295
+ if (!(_i < lines_1.length)) return [3 /*break*/, 21];
296
+ line = lines_1[_i];
297
+ if (!line.startsWith('data: ')) return [3 /*break*/, 20];
298
+ data = line.slice(6);
299
+ if (!(data === '[DONE]')) return [3 /*break*/, 10];
300
+ promptTokens = this.estimateTokens(JSON.stringify(request.messages));
301
+ model = request.model || this.config.model;
302
+ baseModel = model.includes('/') ? model.split('/').pop() : model;
303
+ pricing = this.capabilities.pricing[model] || this.capabilities.pricing[baseModel];
304
+ promptCostPer1k = (_e = pricing === null || pricing === void 0 ? void 0 : pricing.promptCostPer1k) !== null && _e !== void 0 ? _e : 0;
305
+ completionCostPer1k = (_f = pricing === null || pricing === void 0 ? void 0 : pricing.completionCostPer1k) !== null && _f !== void 0 ? _f : 0;
306
+ return [4 /*yield*/, __await({
307
+ type: 'done',
308
+ usage: {
309
+ promptTokens: promptTokens,
310
+ completionTokens: 100, // Estimate
311
+ totalTokens: promptTokens + 100,
312
+ },
313
+ cost: {
314
+ promptCost: (promptTokens / 1000) * promptCostPer1k,
315
+ completionCost: (100 / 1000) * completionCostPer1k,
316
+ totalCost: (promptTokens / 1000) * promptCostPer1k +
317
+ (100 / 1000) * completionCostPer1k,
318
+ currency: 'USD',
319
+ },
320
+ })];
321
+ case 8: return [4 /*yield*/, _j.sent()];
322
+ case 9:
323
+ _j.sent();
324
+ return [3 /*break*/, 20];
325
+ case 10:
326
+ _j.trys.push([10, 19, , 20]);
327
+ chunk = JSON.parse(data);
328
+ delta = (_h = (_g = chunk.choices) === null || _g === void 0 ? void 0 : _g[0]) === null || _h === void 0 ? void 0 : _h.delta;
329
+ if (!(delta === null || delta === void 0 ? void 0 : delta.content)) return [3 /*break*/, 13];
330
+ return [4 /*yield*/, __await({
331
+ type: 'content',
332
+ delta: { content: delta.content },
333
+ })];
334
+ case 11: return [4 /*yield*/, _j.sent()];
335
+ case 12:
336
+ _j.sent();
337
+ _j.label = 13;
338
+ case 13:
339
+ if (!(delta === null || delta === void 0 ? void 0 : delta.tool_calls)) return [3 /*break*/, 18];
340
+ _b = 0, _c = delta.tool_calls;
341
+ _j.label = 14;
342
+ case 14:
343
+ if (!(_b < _c.length)) return [3 /*break*/, 18];
344
+ toolCall = _c[_b];
345
+ return [4 /*yield*/, __await({
346
+ type: 'tool_call',
347
+ delta: {
348
+ toolCall: {
349
+ id: toolCall.id,
350
+ type: 'function',
351
+ function: toolCall.function,
352
+ },
353
+ },
354
+ })];
355
+ case 15: return [4 /*yield*/, _j.sent()];
356
+ case 16:
357
+ _j.sent();
358
+ _j.label = 17;
359
+ case 17:
360
+ _b++;
361
+ return [3 /*break*/, 14];
362
+ case 18: return [3 /*break*/, 20];
363
+ case 19:
364
+ _d = _j.sent();
365
+ return [3 /*break*/, 20];
366
+ case 20:
367
+ _i++;
368
+ return [3 /*break*/, 7];
369
+ case 21: return [3 /*break*/, 5];
370
+ case 22: return [3 /*break*/, 25];
371
+ case 23:
372
+ error_2 = _j.sent();
373
+ clearTimeout(timeout);
374
+ throw this.transformError(error_2);
375
+ case 24:
376
+ clearTimeout(timeout);
377
+ return [7 /*endfinally*/];
378
+ case 25: return [2 /*return*/];
379
+ }
380
+ });
381
+ });
382
+ };
383
+ OpenAIProvider.prototype.listModels = function () {
384
+ return __awaiter(this, void 0, void 0, function () {
385
+ return __generator(this, function (_a) {
386
+ return [2 /*return*/, this.capabilities.supportedModels];
387
+ });
388
+ });
389
+ };
390
+ OpenAIProvider.prototype.getModelInfo = function (model) {
391
+ return __awaiter(this, void 0, void 0, function () {
392
+ var descriptions;
393
+ return __generator(this, function (_a) {
394
+ descriptions = {
395
+ 'gpt-4o': 'Most capable GPT-4 model with vision and audio',
396
+ 'gpt-4o-mini': 'Affordable and intelligent small model',
397
+ 'gpt-4-turbo': 'GPT-4 Turbo with vision',
398
+ 'gpt-4': 'High capability model',
399
+ 'gpt-3.5-turbo': 'Fast and efficient model',
400
+ 'o1-preview': 'Reasoning model for complex tasks',
401
+ 'o1-mini': 'Fast reasoning model',
402
+ 'o3-mini': 'Latest reasoning model',
403
+ };
404
+ return [2 /*return*/, {
405
+ model: model,
406
+ name: model,
407
+ description: descriptions[model] || 'OpenAI language model',
408
+ contextLength: this.capabilities.maxContextLength[model] || 8192,
409
+ maxOutputTokens: this.capabilities.maxOutputTokens[model] || 4096,
410
+ supportedFeatures: __spreadArray([
411
+ 'chat',
412
+ 'completion',
413
+ 'tool_calling'
414
+ ], (model.includes('gpt-4') ? ['vision'] : []), true),
415
+ pricing: this.capabilities.pricing[model],
416
+ }];
417
+ });
418
+ });
419
+ };
420
+ OpenAIProvider.prototype.doHealthCheck = function () {
421
+ return __awaiter(this, void 0, void 0, function () {
422
+ var response, error_3;
423
+ return __generator(this, function (_a) {
424
+ switch (_a.label) {
425
+ case 0:
426
+ _a.trys.push([0, 2, , 3]);
427
+ return [4 /*yield*/, fetch("".concat(this.baseUrl, "/models"), {
428
+ headers: this.headers,
429
+ })];
430
+ case 1:
431
+ response = _a.sent();
432
+ return [2 /*return*/, __assign({ healthy: response.ok, timestamp: new Date() }, (response.ok ? {} : { error: "HTTP ".concat(response.status) }))];
433
+ case 2:
434
+ error_3 = _a.sent();
435
+ return [2 /*return*/, {
436
+ healthy: false,
437
+ error: error_3 instanceof Error ? error_3.message : 'Unknown error',
438
+ timestamp: new Date(),
439
+ }];
440
+ case 3: return [2 /*return*/];
441
+ }
442
+ });
443
+ });
444
+ };
445
+ OpenAIProvider.prototype.buildRequest = function (request, stream) {
446
+ var _a, _b, _c, _d;
447
+ if (stream === void 0) { stream = false; }
448
+ var openAIRequest = {
449
+ model: request.model || this.config.model,
450
+ messages: request.messages.map(function (msg) { return (__assign(__assign(__assign({ role: msg.role, content: typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content) }, (msg.name && { name: msg.name })), (msg.toolCallId && { tool_call_id: msg.toolCallId })), (msg.toolCalls && { tool_calls: msg.toolCalls }))); }),
451
+ stream: stream,
452
+ };
453
+ if (request.temperature !== undefined || this.config.temperature !== undefined) {
454
+ openAIRequest.temperature = (_a = request.temperature) !== null && _a !== void 0 ? _a : this.config.temperature;
455
+ }
456
+ if (request.maxTokens || this.config.maxTokens) {
457
+ openAIRequest.max_tokens = request.maxTokens || this.config.maxTokens;
458
+ }
459
+ if (request.topP !== undefined || this.config.topP !== undefined) {
460
+ openAIRequest.top_p = (_b = request.topP) !== null && _b !== void 0 ? _b : this.config.topP;
461
+ }
462
+ if (request.frequencyPenalty !== undefined || this.config.frequencyPenalty !== undefined) {
463
+ openAIRequest.frequency_penalty = (_c = request.frequencyPenalty) !== null && _c !== void 0 ? _c : this.config.frequencyPenalty;
464
+ }
465
+ if (request.presencePenalty !== undefined || this.config.presencePenalty !== undefined) {
466
+ openAIRequest.presence_penalty = (_d = request.presencePenalty) !== null && _d !== void 0 ? _d : this.config.presencePenalty;
467
+ }
468
+ if (request.stopSequences || this.config.stopSequences) {
469
+ openAIRequest.stop = request.stopSequences || this.config.stopSequences;
470
+ }
471
+ if (request.tools) {
472
+ openAIRequest.tools = request.tools;
473
+ openAIRequest.tool_choice = request.toolChoice;
474
+ }
475
+ return openAIRequest;
476
+ };
477
+ OpenAIProvider.prototype.transformResponse = function (data, request) {
478
+ var _a, _b;
479
+ var choice = data.choices[0];
480
+ var model = request.model || this.config.model;
481
+ // Handle OpenRouter and other compatible APIs with different model naming
482
+ var baseModel = model.includes('/') ? model.split('/').pop() : model;
483
+ var pricing = this.capabilities.pricing[model] || this.capabilities.pricing[baseModel];
484
+ // Default pricing if model not found
485
+ var promptCostPer1k = (_a = pricing === null || pricing === void 0 ? void 0 : pricing.promptCostPer1k) !== null && _a !== void 0 ? _a : 0;
486
+ var completionCostPer1k = (_b = pricing === null || pricing === void 0 ? void 0 : pricing.completionCostPer1k) !== null && _b !== void 0 ? _b : 0;
487
+ var promptCost = (data.usage.prompt_tokens / 1000) * promptCostPer1k;
488
+ var completionCost = (data.usage.completion_tokens / 1000) * completionCostPer1k;
489
+ return {
490
+ id: data.id,
491
+ model: model,
492
+ provider: 'openai',
493
+ content: choice.message.content || '',
494
+ toolCalls: choice.message.tool_calls,
495
+ usage: {
496
+ promptTokens: data.usage.prompt_tokens,
497
+ completionTokens: data.usage.completion_tokens,
498
+ totalTokens: data.usage.total_tokens,
499
+ },
500
+ cost: {
501
+ promptCost: promptCost,
502
+ completionCost: completionCost,
503
+ totalCost: promptCost + completionCost,
504
+ currency: 'USD',
505
+ },
506
+ finishReason: choice.finish_reason,
507
+ };
508
+ };
509
+ OpenAIProvider.prototype.handleErrorResponse = function (response) {
510
+ return __awaiter(this, void 0, void 0, function () {
511
+ var errorText, errorData, message, retryAfter;
512
+ var _a;
513
+ return __generator(this, function (_b) {
514
+ switch (_b.label) {
515
+ case 0: return [4 /*yield*/, response.text()];
516
+ case 1:
517
+ errorText = _b.sent();
518
+ try {
519
+ errorData = JSON.parse(errorText);
520
+ }
521
+ catch (_c) {
522
+ errorData = { error: { message: errorText } };
523
+ }
524
+ message = ((_a = errorData.error) === null || _a === void 0 ? void 0 : _a.message) || 'Unknown error';
525
+ switch (response.status) {
526
+ case 401:
527
+ throw new types_js_1.AuthenticationError(message, 'openai', errorData);
528
+ case 429:
529
+ retryAfter = response.headers.get('retry-after');
530
+ throw new types_js_1.RateLimitError(message, 'openai', retryAfter ? parseInt(retryAfter) : undefined, errorData);
531
+ case 404:
532
+ throw new types_js_1.ModelNotFoundError(this.config.model, 'openai', errorData);
533
+ default:
534
+ throw new types_js_1.LLMProviderError(message, "OPENAI_".concat(response.status), 'openai', response.status, response.status >= 500, errorData);
535
+ }
536
+ return [2 /*return*/];
537
+ }
538
+ });
539
+ });
540
+ };
541
+ return OpenAIProvider;
542
+ }(base_provider_js_1.BaseProvider));
543
+ exports.OpenAIProvider = OpenAIProvider;
@@ -0,0 +1,117 @@
1
+ /**
2
+ * V3 Provider Manager
3
+ *
4
+ * Orchestrates multiple LLM providers with:
5
+ * - Load balancing (round-robin, latency-based, cost-based)
6
+ * - Automatic failover
7
+ * - Request caching
8
+ * - Cost optimization
9
+ *
10
+ * @module @sparkleideas/providers/provider-manager
11
+ */
12
+ import { EventEmitter } from 'events';
13
+ import { ILLMProvider, LLMProvider, LLMRequest, LLMResponse, LLMStreamEvent, ProviderManagerConfig, HealthCheckResult, CostEstimate, UsageStats, UsagePeriod } from './types.js';
14
+ import { ILogger } from './base-provider.js';
15
+ /**
16
+ * Provider metrics for load balancing
17
+ */
18
+ interface ProviderMetrics {
19
+ latency: number;
20
+ errorRate: number;
21
+ cost: number;
22
+ lastUsed: number;
23
+ }
24
+ /**
25
+ * Provider Manager - Orchestrates multiple LLM providers
26
+ */
27
+ export declare class ProviderManager extends EventEmitter {
28
+ private config;
29
+ private providers;
30
+ private cache;
31
+ private metrics;
32
+ private roundRobinIndex;
33
+ private logger;
34
+ constructor(config: ProviderManagerConfig, logger?: ILogger);
35
+ /**
36
+ * Initialize all configured providers
37
+ */
38
+ initialize(): Promise<void>;
39
+ /**
40
+ * Create a provider instance
41
+ */
42
+ private createProvider;
43
+ /**
44
+ * Complete a request with automatic provider selection
45
+ */
46
+ complete(request: LLMRequest, preferredProvider?: LLMProvider): Promise<LLMResponse>;
47
+ /**
48
+ * Stream complete with automatic provider selection
49
+ */
50
+ streamComplete(request: LLMRequest, preferredProvider?: LLMProvider): AsyncIterable<LLMStreamEvent>;
51
+ /**
52
+ * Select provider based on load balancing strategy
53
+ */
54
+ private selectProvider;
55
+ private selectRoundRobin;
56
+ private selectLeastLoaded;
57
+ private selectByLatency;
58
+ private selectByCost;
59
+ /**
60
+ * Complete with fallback on failure
61
+ */
62
+ private completWithFallback;
63
+ /**
64
+ * Update provider metrics
65
+ */
66
+ private updateMetrics;
67
+ /**
68
+ * Get cached response
69
+ */
70
+ private getCached;
71
+ /**
72
+ * Set cached response
73
+ */
74
+ private setCached;
75
+ /**
76
+ * Generate cache key
77
+ */
78
+ private getCacheKey;
79
+ /**
80
+ * Get a specific provider
81
+ */
82
+ getProvider(name: LLMProvider): ILLMProvider | undefined;
83
+ /**
84
+ * List all available providers
85
+ */
86
+ listProviders(): LLMProvider[];
87
+ /**
88
+ * Health check all providers
89
+ */
90
+ healthCheck(): Promise<Map<LLMProvider, HealthCheckResult>>;
91
+ /**
92
+ * Estimate cost across providers
93
+ */
94
+ estimateCost(request: LLMRequest): Promise<Map<LLMProvider, CostEstimate>>;
95
+ /**
96
+ * Get aggregated usage statistics
97
+ */
98
+ getUsage(period?: UsagePeriod): Promise<UsageStats>;
99
+ /**
100
+ * Get provider metrics
101
+ */
102
+ getMetrics(): Map<LLMProvider, ProviderMetrics>;
103
+ /**
104
+ * Clear cache
105
+ */
106
+ clearCache(): void;
107
+ /**
108
+ * Destroy all providers
109
+ */
110
+ destroy(): void;
111
+ }
112
+ /**
113
+ * Create and initialize a provider manager
114
+ */
115
+ export declare function createProviderManager(config: ProviderManagerConfig, logger?: ILogger): Promise<ProviderManager>;
116
+ export {};
117
+ //# sourceMappingURL=provider-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-manager.d.ts","sourceRoot":"","sources":["../src/provider-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EACL,YAAY,EACZ,WAAW,EAEX,UAAU,EACV,WAAW,EACX,cAAc,EAEd,qBAAqB,EAErB,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,WAAW,EAGZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAuB,OAAO,EAAiB,MAAM,oBAAoB,CAAC;AAiBjF;;GAEG;AACH,UAAU,eAAe;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,YAAY;IAQ7C,OAAO,CAAC,MAAM;IAPhB,OAAO,CAAC,SAAS,CAA6C;IAC9D,OAAO,CAAC,KAAK,CAAsC;IACnD,OAAO,CAAC,OAAO,CAAgD;IAC/D,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,MAAM,CAAU;gBAGd,MAAM,EAAE,qBAAqB,EACrC,MAAM,CAAC,EAAE,OAAO;IAMlB;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA6BjC;;OAEG;IACH,OAAO,CAAC,cAAc;IAwBtB;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,iBAAiB,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IA4C1F;;OAEG;IACI,cAAc,CACnB,OAAO,EAAE,UAAU,EACnB,iBAAiB,CAAC,EAAE,WAAW,GAC9B,aAAa,CAAC,cAAc,CAAC;IAuBhC;;OAEG;YACW,cAAc;IA0B5B,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,eAAe;YAUT,YAAY;IAgB1B;;OAEG;YACW,mBAAmB;IA6CjC;;OAEG;IACH,OAAO,CAAC,aAAa;IA6BrB;;OAEG;IACH,OAAO,CAAC,SAAS;IAgBjB;;OAEG;IACH,OAAO,CAAC,SAAS;IAoBjB;;OAEG;IACH,OAAO,CAAC,WAAW;IASnB;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,YAAY,GAAG,SAAS;IAIxD;;OAEG;IACH,aAAa,IAAI,WAAW,EAAE;IAI9B;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;IAajE;;OAEG;IACG,YAAY,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAahF;;OAEG;IACG,QAAQ,CAAC,MAAM,GAAE,WAAmB,GAAG,OAAO,CAAC,UAAU,CAAC;IAqChE;;OAEG;IACH,UAAU,IAAI,GAAG,CAAC,WAAW,EAAE,eAAe,CAAC;IAI/C;;OAEG;IACH,UAAU,IAAI,IAAI;IAKlB;;OAEG;IACH,OAAO,IAAI,IAAI;CAUhB;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,qBAAqB,EAC7B,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,eAAe,CAAC,CAI1B"}