@flare-ai-sdk/server 1.0.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/dist/index.d.mts +1196 -0
- package/dist/index.d.ts +1196 -0
- package/dist/index.js +2524 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2447 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +28 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,2524 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __defProps = Object.defineProperties;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
7
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
9
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
10
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
11
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
12
|
+
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
|
|
13
|
+
var __typeError = (msg) => {
|
|
14
|
+
throw TypeError(msg);
|
|
15
|
+
};
|
|
16
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
17
|
+
var __spreadValues = (a, b) => {
|
|
18
|
+
for (var prop in b || (b = {}))
|
|
19
|
+
if (__hasOwnProp.call(b, prop))
|
|
20
|
+
__defNormalProp(a, prop, b[prop]);
|
|
21
|
+
if (__getOwnPropSymbols)
|
|
22
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
23
|
+
if (__propIsEnum.call(b, prop))
|
|
24
|
+
__defNormalProp(a, prop, b[prop]);
|
|
25
|
+
}
|
|
26
|
+
return a;
|
|
27
|
+
};
|
|
28
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
29
|
+
var __export = (target, all) => {
|
|
30
|
+
for (var name in all)
|
|
31
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
32
|
+
};
|
|
33
|
+
var __copyProps = (to, from, except, desc) => {
|
|
34
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
35
|
+
for (let key of __getOwnPropNames(from))
|
|
36
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
37
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
38
|
+
}
|
|
39
|
+
return to;
|
|
40
|
+
};
|
|
41
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
42
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
43
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
44
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
45
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
46
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
47
|
+
mod
|
|
48
|
+
));
|
|
49
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
50
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
51
|
+
var __async = (__this, __arguments, generator) => {
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
var fulfilled = (value) => {
|
|
54
|
+
try {
|
|
55
|
+
step(generator.next(value));
|
|
56
|
+
} catch (e) {
|
|
57
|
+
reject(e);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
var rejected = (value) => {
|
|
61
|
+
try {
|
|
62
|
+
step(generator.throw(value));
|
|
63
|
+
} catch (e) {
|
|
64
|
+
reject(e);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
68
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
var __await = function(promise, isYieldStar) {
|
|
72
|
+
this[0] = promise;
|
|
73
|
+
this[1] = isYieldStar;
|
|
74
|
+
};
|
|
75
|
+
var __asyncGenerator = (__this, __arguments, generator) => {
|
|
76
|
+
var resume = (k, v, yes, no) => {
|
|
77
|
+
try {
|
|
78
|
+
var x = generator[k](v), isAwait = (v = x.value) instanceof __await, done = x.done;
|
|
79
|
+
Promise.resolve(isAwait ? v[0] : v).then((y) => isAwait ? resume(k === "return" ? k : "next", v[1] ? { done: y.done, value: y.value } : y, yes, no) : yes({ value: y, done })).catch((e) => resume("throw", e, yes, no));
|
|
80
|
+
} catch (e) {
|
|
81
|
+
no(e);
|
|
82
|
+
}
|
|
83
|
+
}, method = (k) => it[k] = (x) => new Promise((yes, no) => resume(k, x, yes, no)), it = {};
|
|
84
|
+
return generator = generator.apply(__this, __arguments), it[__knownSymbol("asyncIterator")] = () => it, method("next"), method("throw"), method("return"), it;
|
|
85
|
+
};
|
|
86
|
+
var __yieldStar = (value) => {
|
|
87
|
+
var obj = value[__knownSymbol("asyncIterator")], isAwait = false, method, it = {};
|
|
88
|
+
if (obj == null) {
|
|
89
|
+
obj = value[__knownSymbol("iterator")]();
|
|
90
|
+
method = (k) => it[k] = (x) => obj[k](x);
|
|
91
|
+
} else {
|
|
92
|
+
obj = obj.call(value);
|
|
93
|
+
method = (k) => it[k] = (v) => {
|
|
94
|
+
if (isAwait) {
|
|
95
|
+
isAwait = false;
|
|
96
|
+
if (k === "throw") throw v;
|
|
97
|
+
return v;
|
|
98
|
+
}
|
|
99
|
+
isAwait = true;
|
|
100
|
+
return {
|
|
101
|
+
done: false,
|
|
102
|
+
value: new __await(new Promise((resolve) => {
|
|
103
|
+
var x = obj[k](v);
|
|
104
|
+
if (!(x instanceof Object)) __typeError("Object expected");
|
|
105
|
+
resolve(x);
|
|
106
|
+
}), 1)
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
return it[__knownSymbol("iterator")] = () => it, method("next"), "throw" in obj ? method("throw") : it.throw = (x) => {
|
|
111
|
+
throw x;
|
|
112
|
+
}, "return" in obj && method("return"), it;
|
|
113
|
+
};
|
|
114
|
+
var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")]) ? it.call(obj) : (obj = obj[__knownSymbol("iterator")](), it = {}, method = (key, fn) => (fn = obj[key]) && (it[key] = (arg) => new Promise((yes, no, done) => (arg = fn.call(obj, arg), done = arg.done, Promise.resolve(arg.value).then((value) => yes({ value, done }), no)))), method("next"), method("return"), it);
|
|
115
|
+
|
|
116
|
+
// src/index.ts
|
|
117
|
+
var index_exports = {};
|
|
118
|
+
__export(index_exports, {
|
|
119
|
+
AnthropicProvider: () => AnthropicProvider,
|
|
120
|
+
AuthenticationError: () => AuthenticationError,
|
|
121
|
+
BaseProvider: () => BaseProvider,
|
|
122
|
+
CircuitBreaker: () => CircuitBreaker,
|
|
123
|
+
CircuitBreakerError: () => CircuitBreakerError,
|
|
124
|
+
CircuitState: () => CircuitState,
|
|
125
|
+
ContentFilterError: () => ContentFilterError,
|
|
126
|
+
CustomProvider: () => CustomProvider,
|
|
127
|
+
FlareClient: () => FlareClient,
|
|
128
|
+
FlareError: () => FlareError,
|
|
129
|
+
FlareStreamReader: () => FlareStreamReader,
|
|
130
|
+
GoogleProvider: () => GoogleProvider,
|
|
131
|
+
MetricsCollector: () => MetricsCollector,
|
|
132
|
+
NetworkError: () => NetworkError,
|
|
133
|
+
OpenAIProvider: () => OpenAIProvider,
|
|
134
|
+
ParseError: () => ParseError,
|
|
135
|
+
ProviderError: () => ProviderError,
|
|
136
|
+
RateLimitError: () => RateLimitError,
|
|
137
|
+
RateLimiter: () => RateLimiter,
|
|
138
|
+
RequestQueue: () => RequestQueue,
|
|
139
|
+
RetryHandler: () => RetryHandler,
|
|
140
|
+
SarvamProvider: () => SarvamProvider,
|
|
141
|
+
StreamError: () => StreamError,
|
|
142
|
+
TimeoutError: () => TimeoutError,
|
|
143
|
+
TransformStream: () => TransformStream,
|
|
144
|
+
ValidationError: () => ValidationError,
|
|
145
|
+
bufferStream: () => bufferStream,
|
|
146
|
+
createCircuitBreaker: () => createCircuitBreaker,
|
|
147
|
+
createDataStreamWriter: () => createDataStreamWriter,
|
|
148
|
+
createFlareClient: () => createFlareClient,
|
|
149
|
+
createMetricsCollector: () => createMetricsCollector,
|
|
150
|
+
createProvider: () => createProvider,
|
|
151
|
+
createRateLimiter: () => createRateLimiter,
|
|
152
|
+
createRequestQueue: () => createRequestQueue,
|
|
153
|
+
createRetryHandler: () => createRetryHandler,
|
|
154
|
+
getErrorStatusCode: () => getErrorStatusCode,
|
|
155
|
+
getGlobalMetrics: () => getGlobalMetrics,
|
|
156
|
+
isRetryableError: () => isRetryableError,
|
|
157
|
+
measureLatency: () => measureLatency,
|
|
158
|
+
mergeStreams: () => mergeStreams,
|
|
159
|
+
parseSSEStream: () => parseSSEStream,
|
|
160
|
+
throttleStream: () => throttleStream,
|
|
161
|
+
toUiStreamResponse: () => toUiStreamResponse,
|
|
162
|
+
withRetry: () => withRetry
|
|
163
|
+
});
|
|
164
|
+
module.exports = __toCommonJS(index_exports);
|
|
165
|
+
|
|
166
|
+
// src/utils/errors.ts
|
|
167
|
+
var FlareError = class extends Error {
|
|
168
|
+
constructor(message, code, statusCode, retryable = false, details) {
|
|
169
|
+
super(message);
|
|
170
|
+
__publicField(this, "code");
|
|
171
|
+
__publicField(this, "statusCode");
|
|
172
|
+
__publicField(this, "retryable");
|
|
173
|
+
__publicField(this, "details");
|
|
174
|
+
this.name = "FlareError";
|
|
175
|
+
this.code = code;
|
|
176
|
+
this.statusCode = statusCode;
|
|
177
|
+
this.retryable = retryable;
|
|
178
|
+
this.details = details;
|
|
179
|
+
Error.captureStackTrace(this, this.constructor);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
var NetworkError = class extends FlareError {
|
|
183
|
+
constructor(message, details) {
|
|
184
|
+
super(message, "NETWORK_ERROR", void 0, true, details);
|
|
185
|
+
this.name = "NetworkError";
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
var TimeoutError = class extends FlareError {
|
|
189
|
+
constructor(message, details) {
|
|
190
|
+
super(message, "TIMEOUT_ERROR", 408, true, details);
|
|
191
|
+
this.name = "TimeoutError";
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
var RateLimitError = class extends FlareError {
|
|
195
|
+
constructor(message, retryAfter, details) {
|
|
196
|
+
super(message, "RATE_LIMIT_ERROR", 429, true, details);
|
|
197
|
+
__publicField(this, "retryAfter");
|
|
198
|
+
this.name = "RateLimitError";
|
|
199
|
+
this.retryAfter = retryAfter;
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
var AuthenticationError = class extends FlareError {
|
|
203
|
+
constructor(message, details) {
|
|
204
|
+
super(message, "AUTHENTICATION_ERROR", 401, false, details);
|
|
205
|
+
this.name = "AuthenticationError";
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
var ValidationError = class extends FlareError {
|
|
209
|
+
constructor(message, details) {
|
|
210
|
+
super(message, "VALIDATION_ERROR", 400, false, details);
|
|
211
|
+
this.name = "ValidationError";
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
var CircuitBreakerError = class extends FlareError {
|
|
215
|
+
constructor(message, details) {
|
|
216
|
+
super(message, "CIRCUIT_BREAKER_OPEN", 503, true, details);
|
|
217
|
+
this.name = "CircuitBreakerError";
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
var ProviderError = class extends FlareError {
|
|
221
|
+
constructor(provider, message, statusCode, details) {
|
|
222
|
+
super(message, "PROVIDER_ERROR", statusCode, true, details);
|
|
223
|
+
__publicField(this, "provider");
|
|
224
|
+
this.name = "ProviderError";
|
|
225
|
+
this.provider = provider;
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
var StreamError = class extends FlareError {
|
|
229
|
+
constructor(message, details) {
|
|
230
|
+
super(message, "STREAM_ERROR", void 0, false, details);
|
|
231
|
+
this.name = "StreamError";
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
var ParseError = class extends FlareError {
|
|
235
|
+
constructor(message, details) {
|
|
236
|
+
super(message, "PARSE_ERROR", void 0, false, details);
|
|
237
|
+
this.name = "ParseError";
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
var ContentFilterError = class extends FlareError {
|
|
241
|
+
constructor(message, details) {
|
|
242
|
+
super(message, "CONTENT_FILTER_ERROR", 400, false, details);
|
|
243
|
+
this.name = "ContentFilterError";
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
function isRetryableError(error) {
|
|
247
|
+
if (error instanceof FlareError) {
|
|
248
|
+
return error.retryable;
|
|
249
|
+
}
|
|
250
|
+
if (error.message.includes("ECONNREFUSED") || error.message.includes("ETIMEDOUT") || error.message.includes("ENOTFOUND")) {
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
function getErrorStatusCode(error) {
|
|
256
|
+
if (error instanceof FlareError) {
|
|
257
|
+
return error.statusCode;
|
|
258
|
+
}
|
|
259
|
+
return void 0;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// src/utils/metrics.ts
|
|
263
|
+
var LatencyHistogram = class {
|
|
264
|
+
constructor() {
|
|
265
|
+
__publicField(this, "samples", []);
|
|
266
|
+
__publicField(this, "maxSamples", 1e3);
|
|
267
|
+
}
|
|
268
|
+
add(latency) {
|
|
269
|
+
this.samples.push(latency);
|
|
270
|
+
if (this.samples.length > this.maxSamples) {
|
|
271
|
+
this.samples.shift();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
getPercentile(p) {
|
|
275
|
+
if (this.samples.length === 0) return 0;
|
|
276
|
+
const sorted = [...this.samples].sort((a, b) => a - b);
|
|
277
|
+
const index = Math.ceil(p / 100 * sorted.length) - 1;
|
|
278
|
+
return sorted[Math.max(0, index)];
|
|
279
|
+
}
|
|
280
|
+
getAverage() {
|
|
281
|
+
if (this.samples.length === 0) return 0;
|
|
282
|
+
return this.samples.reduce((a, b) => a + b, 0) / this.samples.length;
|
|
283
|
+
}
|
|
284
|
+
clear() {
|
|
285
|
+
this.samples = [];
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
var MetricsCollector = class {
|
|
289
|
+
constructor() {
|
|
290
|
+
__publicField(this, "totalRequests", 0);
|
|
291
|
+
__publicField(this, "successfulRequests", 0);
|
|
292
|
+
__publicField(this, "failedRequests", 0);
|
|
293
|
+
__publicField(this, "latencyHistogram", new LatencyHistogram());
|
|
294
|
+
__publicField(this, "startTime", Date.now());
|
|
295
|
+
__publicField(this, "windowStart", Date.now());
|
|
296
|
+
__publicField(this, "windowRequests", 0);
|
|
297
|
+
__publicField(this, "windowDuration", 6e4);
|
|
298
|
+
}
|
|
299
|
+
// 1 minute window
|
|
300
|
+
/**
|
|
301
|
+
* Record successful request
|
|
302
|
+
* @param latency - Request latency in milliseconds
|
|
303
|
+
*/
|
|
304
|
+
recordSuccess(latency) {
|
|
305
|
+
this.totalRequests++;
|
|
306
|
+
this.successfulRequests++;
|
|
307
|
+
this.latencyHistogram.add(latency);
|
|
308
|
+
this.updateWindow();
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Record failed request
|
|
312
|
+
* @param latency - Request latency in milliseconds
|
|
313
|
+
*/
|
|
314
|
+
recordFailure(latency) {
|
|
315
|
+
this.totalRequests++;
|
|
316
|
+
this.failedRequests++;
|
|
317
|
+
this.latencyHistogram.add(latency);
|
|
318
|
+
this.updateWindow();
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Update rolling window for RPS calculation
|
|
322
|
+
*/
|
|
323
|
+
updateWindow() {
|
|
324
|
+
const now = Date.now();
|
|
325
|
+
if (now - this.windowStart >= this.windowDuration) {
|
|
326
|
+
this.windowRequests = 0;
|
|
327
|
+
this.windowStart = now;
|
|
328
|
+
}
|
|
329
|
+
this.windowRequests++;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Get current metrics
|
|
333
|
+
*/
|
|
334
|
+
getMetrics() {
|
|
335
|
+
const elapsed = (Date.now() - this.windowStart) / 1e3;
|
|
336
|
+
const rps = elapsed > 0 ? this.windowRequests / elapsed : 0;
|
|
337
|
+
return {
|
|
338
|
+
totalRequests: this.totalRequests,
|
|
339
|
+
successfulRequests: this.successfulRequests,
|
|
340
|
+
failedRequests: this.failedRequests,
|
|
341
|
+
avgLatency: this.latencyHistogram.getAverage(),
|
|
342
|
+
p95Latency: this.latencyHistogram.getPercentile(95),
|
|
343
|
+
p99Latency: this.latencyHistogram.getPercentile(99),
|
|
344
|
+
rps
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Get success rate as percentage
|
|
349
|
+
*/
|
|
350
|
+
getSuccessRate() {
|
|
351
|
+
if (this.totalRequests === 0) return 100;
|
|
352
|
+
return this.successfulRequests / this.totalRequests * 100;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Get uptime in milliseconds
|
|
356
|
+
*/
|
|
357
|
+
getUptime() {
|
|
358
|
+
return Date.now() - this.startTime;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Reset all metrics
|
|
362
|
+
*/
|
|
363
|
+
reset() {
|
|
364
|
+
this.totalRequests = 0;
|
|
365
|
+
this.successfulRequests = 0;
|
|
366
|
+
this.failedRequests = 0;
|
|
367
|
+
this.latencyHistogram.clear();
|
|
368
|
+
this.windowStart = Date.now();
|
|
369
|
+
this.windowRequests = 0;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Get detailed statistics
|
|
373
|
+
*/
|
|
374
|
+
getDetailedStats() {
|
|
375
|
+
return __spreadProps(__spreadValues({}, this.getMetrics()), {
|
|
376
|
+
successRate: this.getSuccessRate(),
|
|
377
|
+
uptime: this.getUptime(),
|
|
378
|
+
timestamp: Date.now()
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
var globalMetrics = null;
|
|
383
|
+
function getGlobalMetrics() {
|
|
384
|
+
if (!globalMetrics) {
|
|
385
|
+
globalMetrics = new MetricsCollector();
|
|
386
|
+
}
|
|
387
|
+
return globalMetrics;
|
|
388
|
+
}
|
|
389
|
+
function createMetricsCollector() {
|
|
390
|
+
return new MetricsCollector();
|
|
391
|
+
}
|
|
392
|
+
function measureLatency(_0) {
|
|
393
|
+
return __async(this, arguments, function* (fn, collector = getGlobalMetrics()) {
|
|
394
|
+
const start = Date.now();
|
|
395
|
+
try {
|
|
396
|
+
const result = yield fn();
|
|
397
|
+
collector.recordSuccess(Date.now() - start);
|
|
398
|
+
return result;
|
|
399
|
+
} catch (error) {
|
|
400
|
+
collector.recordFailure(Date.now() - start);
|
|
401
|
+
throw error;
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// src/utils/rate-limiter.ts
|
|
407
|
+
var DEFAULT_CONFIG = {
|
|
408
|
+
maxRequests: 100,
|
|
409
|
+
windowMs: 6e4,
|
|
410
|
+
// 1 minute
|
|
411
|
+
clientId: "default"
|
|
412
|
+
};
|
|
413
|
+
var RateLimiter = class {
|
|
414
|
+
constructor(config = {}) {
|
|
415
|
+
__publicField(this, "buckets", /* @__PURE__ */ new Map());
|
|
416
|
+
__publicField(this, "config");
|
|
417
|
+
__publicField(this, "cleanupInterval");
|
|
418
|
+
this.config = __spreadValues(__spreadValues({}, DEFAULT_CONFIG), config);
|
|
419
|
+
this.startCleanup();
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Acquire a token for rate limiting
|
|
423
|
+
* @param clientId - Client identifier
|
|
424
|
+
* @throws RateLimitError if rate limit exceeded
|
|
425
|
+
*/
|
|
426
|
+
acquire(clientId) {
|
|
427
|
+
return __async(this, null, function* () {
|
|
428
|
+
const id = clientId || this.config.clientId;
|
|
429
|
+
const bucket = this.getBucket(id);
|
|
430
|
+
this.refillBucket(bucket);
|
|
431
|
+
if (bucket.tokens <= 0) {
|
|
432
|
+
const retryAfter = this.calculateRetryAfter(bucket);
|
|
433
|
+
throw new RateLimitError(
|
|
434
|
+
`Rate limit exceeded. Try again in ${Math.ceil(retryAfter / 1e3)}s`,
|
|
435
|
+
retryAfter,
|
|
436
|
+
{ clientId: id, limit: this.config.maxRequests, window: this.config.windowMs }
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
bucket.tokens--;
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Check if request would be allowed without consuming token
|
|
444
|
+
* @param clientId - Client identifier
|
|
445
|
+
* @returns true if request would be allowed
|
|
446
|
+
*/
|
|
447
|
+
check(clientId) {
|
|
448
|
+
const id = clientId || this.config.clientId;
|
|
449
|
+
const bucket = this.getBucket(id);
|
|
450
|
+
this.refillBucket(bucket);
|
|
451
|
+
return bucket.tokens > 0;
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Get remaining tokens for client
|
|
455
|
+
* @param clientId - Client identifier
|
|
456
|
+
* @returns Number of remaining requests
|
|
457
|
+
*/
|
|
458
|
+
getRemaining(clientId) {
|
|
459
|
+
const id = clientId || this.config.clientId;
|
|
460
|
+
const bucket = this.getBucket(id);
|
|
461
|
+
this.refillBucket(bucket);
|
|
462
|
+
return Math.floor(bucket.tokens);
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Reset rate limit for client
|
|
466
|
+
* @param clientId - Client identifier
|
|
467
|
+
*/
|
|
468
|
+
reset(clientId) {
|
|
469
|
+
const id = clientId || this.config.clientId;
|
|
470
|
+
this.buckets.delete(id);
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Get or create bucket for client
|
|
474
|
+
*/
|
|
475
|
+
getBucket(clientId) {
|
|
476
|
+
let bucket = this.buckets.get(clientId);
|
|
477
|
+
if (!bucket) {
|
|
478
|
+
bucket = {
|
|
479
|
+
tokens: this.config.maxRequests,
|
|
480
|
+
lastRefill: Date.now()
|
|
481
|
+
};
|
|
482
|
+
this.buckets.set(clientId, bucket);
|
|
483
|
+
}
|
|
484
|
+
return bucket;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Refill tokens based on elapsed time
|
|
488
|
+
*/
|
|
489
|
+
refillBucket(bucket) {
|
|
490
|
+
const now = Date.now();
|
|
491
|
+
const elapsed = now - bucket.lastRefill;
|
|
492
|
+
if (elapsed <= 0) return;
|
|
493
|
+
const tokensToAdd = elapsed / this.config.windowMs * this.config.maxRequests;
|
|
494
|
+
bucket.tokens = Math.min(this.config.maxRequests, bucket.tokens + tokensToAdd);
|
|
495
|
+
bucket.lastRefill = now;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Calculate retry-after time in milliseconds
|
|
499
|
+
*/
|
|
500
|
+
calculateRetryAfter(bucket) {
|
|
501
|
+
const tokensNeeded = 1 - bucket.tokens;
|
|
502
|
+
return tokensNeeded / this.config.maxRequests * this.config.windowMs;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Start periodic cleanup of old buckets
|
|
506
|
+
*/
|
|
507
|
+
startCleanup() {
|
|
508
|
+
this.cleanupInterval = setInterval(() => {
|
|
509
|
+
const now = Date.now();
|
|
510
|
+
const maxAge = this.config.windowMs * 2;
|
|
511
|
+
for (const [clientId, bucket] of this.buckets.entries()) {
|
|
512
|
+
if (now - bucket.lastRefill > maxAge) {
|
|
513
|
+
this.buckets.delete(clientId);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}, this.config.windowMs);
|
|
517
|
+
if (this.cleanupInterval.unref) {
|
|
518
|
+
this.cleanupInterval.unref();
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Get statistics for monitoring
|
|
523
|
+
*/
|
|
524
|
+
getStats() {
|
|
525
|
+
return {
|
|
526
|
+
totalClients: this.buckets.size,
|
|
527
|
+
config: this.config
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Clean up resources
|
|
532
|
+
*/
|
|
533
|
+
destroy() {
|
|
534
|
+
if (this.cleanupInterval) {
|
|
535
|
+
clearInterval(this.cleanupInterval);
|
|
536
|
+
}
|
|
537
|
+
this.buckets.clear();
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
function createRateLimiter(config) {
|
|
541
|
+
return new RateLimiter(config);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// src/utils/request-queue.ts
|
|
545
|
+
var import_eventemitter3 = __toESM(require("eventemitter3"));
|
|
546
|
+
var DEFAULT_CONFIG2 = {
|
|
547
|
+
concurrency: 10,
|
|
548
|
+
maxQueueSize: 1e3,
|
|
549
|
+
timeout: 3e4
|
|
550
|
+
};
|
|
551
|
+
var RequestQueue = class extends import_eventemitter3.default {
|
|
552
|
+
constructor(config = {}) {
|
|
553
|
+
super();
|
|
554
|
+
__publicField(this, "queue", []);
|
|
555
|
+
__publicField(this, "running", 0);
|
|
556
|
+
__publicField(this, "config");
|
|
557
|
+
__publicField(this, "requestCounter", 0);
|
|
558
|
+
this.config = __spreadValues(__spreadValues({}, DEFAULT_CONFIG2), config);
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Add request to queue
|
|
562
|
+
* @param fn - Async function to execute
|
|
563
|
+
* @param priority - Request priority (higher = processed first)
|
|
564
|
+
* @returns Promise resolving to function result
|
|
565
|
+
*/
|
|
566
|
+
add(fn, priority = 0) {
|
|
567
|
+
return new Promise((resolve, reject) => {
|
|
568
|
+
if (this.queue.length >= this.config.maxQueueSize) {
|
|
569
|
+
reject(new Error("Queue is full"));
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
const item = {
|
|
573
|
+
id: `req_${++this.requestCounter}`,
|
|
574
|
+
priority,
|
|
575
|
+
fn,
|
|
576
|
+
resolve,
|
|
577
|
+
reject,
|
|
578
|
+
timestamp: Date.now()
|
|
579
|
+
};
|
|
580
|
+
const insertIndex = this.queue.findIndex((q) => q.priority < priority);
|
|
581
|
+
if (insertIndex === -1) {
|
|
582
|
+
this.queue.push(item);
|
|
583
|
+
} else {
|
|
584
|
+
this.queue.splice(insertIndex, 0, item);
|
|
585
|
+
}
|
|
586
|
+
this.emit("enqueue", { id: item.id, priority, queueSize: this.queue.length });
|
|
587
|
+
this.process();
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Process queue items
|
|
592
|
+
*/
|
|
593
|
+
process() {
|
|
594
|
+
return __async(this, null, function* () {
|
|
595
|
+
while (this.running < this.config.concurrency && this.queue.length > 0) {
|
|
596
|
+
const item = this.queue.shift();
|
|
597
|
+
this.running++;
|
|
598
|
+
this.emit("start", { id: item.id, running: this.running });
|
|
599
|
+
this.executeItem(item).finally(() => {
|
|
600
|
+
this.running--;
|
|
601
|
+
this.emit("complete", { id: item.id, running: this.running });
|
|
602
|
+
if (this.running === 0 && this.queue.length === 0) {
|
|
603
|
+
this.emit("drain");
|
|
604
|
+
}
|
|
605
|
+
this.process();
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Execute queue item with timeout
|
|
612
|
+
*/
|
|
613
|
+
executeItem(item) {
|
|
614
|
+
return __async(this, null, function* () {
|
|
615
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
616
|
+
setTimeout(() => {
|
|
617
|
+
reject(new Error(`Request timeout after ${this.config.timeout}ms`));
|
|
618
|
+
}, this.config.timeout);
|
|
619
|
+
});
|
|
620
|
+
try {
|
|
621
|
+
const result = yield Promise.race([item.fn(), timeoutPromise]);
|
|
622
|
+
item.resolve(result);
|
|
623
|
+
} catch (error) {
|
|
624
|
+
item.reject(error instanceof Error ? error : new Error(String(error)));
|
|
625
|
+
}
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Get queue size
|
|
630
|
+
*/
|
|
631
|
+
size() {
|
|
632
|
+
return this.queue.length;
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Get number of running requests
|
|
636
|
+
*/
|
|
637
|
+
getRunning() {
|
|
638
|
+
return this.running;
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Check if queue is empty
|
|
642
|
+
*/
|
|
643
|
+
isEmpty() {
|
|
644
|
+
return this.queue.length === 0 && this.running === 0;
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Clear all pending requests
|
|
648
|
+
*/
|
|
649
|
+
clear() {
|
|
650
|
+
const error = new Error("Queue cleared");
|
|
651
|
+
for (const item of this.queue) {
|
|
652
|
+
item.reject(error);
|
|
653
|
+
}
|
|
654
|
+
this.queue = [];
|
|
655
|
+
this.emit("clear");
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Wait for queue to drain
|
|
659
|
+
*/
|
|
660
|
+
drain() {
|
|
661
|
+
return __async(this, null, function* () {
|
|
662
|
+
if (this.isEmpty()) return;
|
|
663
|
+
return new Promise((resolve) => {
|
|
664
|
+
this.once("drain", resolve);
|
|
665
|
+
});
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Get queue statistics
|
|
670
|
+
*/
|
|
671
|
+
getStats() {
|
|
672
|
+
return {
|
|
673
|
+
queueSize: this.queue.length,
|
|
674
|
+
running: this.running,
|
|
675
|
+
concurrency: this.config.concurrency,
|
|
676
|
+
maxQueueSize: this.config.maxQueueSize
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* Update configuration
|
|
681
|
+
*/
|
|
682
|
+
updateConfig(config) {
|
|
683
|
+
this.config = __spreadValues(__spreadValues({}, this.config), config);
|
|
684
|
+
this.process();
|
|
685
|
+
}
|
|
686
|
+
};
|
|
687
|
+
function createRequestQueue(config) {
|
|
688
|
+
return new RequestQueue(config);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// src/utils/retry.ts
|
|
692
|
+
var DEFAULT_RETRY_CONFIG = {
|
|
693
|
+
maxRetries: 3,
|
|
694
|
+
initialDelay: 1e3,
|
|
695
|
+
maxDelay: 3e4,
|
|
696
|
+
backoffMultiplier: 2,
|
|
697
|
+
jitter: true
|
|
698
|
+
};
|
|
699
|
+
function calculateDelay(attempt, config) {
|
|
700
|
+
const exponentialDelay = Math.min(
|
|
701
|
+
config.initialDelay * Math.pow(config.backoffMultiplier, attempt),
|
|
702
|
+
config.maxDelay
|
|
703
|
+
);
|
|
704
|
+
if (config.jitter) {
|
|
705
|
+
return Math.random() * exponentialDelay;
|
|
706
|
+
}
|
|
707
|
+
return exponentialDelay;
|
|
708
|
+
}
|
|
709
|
+
function sleep(ms) {
|
|
710
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
711
|
+
}
|
|
712
|
+
function withRetry(_0) {
|
|
713
|
+
return __async(this, arguments, function* (fn, config = {}, onRetry) {
|
|
714
|
+
const retryConfig = __spreadValues(__spreadValues({}, DEFAULT_RETRY_CONFIG), config);
|
|
715
|
+
let lastError;
|
|
716
|
+
for (let attempt = 0; attempt <= retryConfig.maxRetries; attempt++) {
|
|
717
|
+
try {
|
|
718
|
+
return yield fn();
|
|
719
|
+
} catch (error) {
|
|
720
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
721
|
+
if (!isRetryableError(lastError) || attempt === retryConfig.maxRetries) {
|
|
722
|
+
throw lastError;
|
|
723
|
+
}
|
|
724
|
+
const delay = calculateDelay(attempt, retryConfig);
|
|
725
|
+
if (onRetry) {
|
|
726
|
+
onRetry(attempt + 1, lastError, delay);
|
|
727
|
+
}
|
|
728
|
+
yield sleep(delay);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
throw lastError;
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
var RetryHandler = class {
|
|
735
|
+
constructor(config = {}) {
|
|
736
|
+
__publicField(this, "config");
|
|
737
|
+
this.config = __spreadValues(__spreadValues({}, DEFAULT_RETRY_CONFIG), config);
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Execute function with retry logic
|
|
741
|
+
*/
|
|
742
|
+
execute(fn, onRetry) {
|
|
743
|
+
return __async(this, null, function* () {
|
|
744
|
+
return withRetry(fn, this.config, onRetry);
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
/**
|
|
748
|
+
* Update retry configuration
|
|
749
|
+
*/
|
|
750
|
+
updateConfig(config) {
|
|
751
|
+
this.config = __spreadValues(__spreadValues({}, this.config), config);
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Get current configuration
|
|
755
|
+
*/
|
|
756
|
+
getConfig() {
|
|
757
|
+
return __spreadValues({}, this.config);
|
|
758
|
+
}
|
|
759
|
+
};
|
|
760
|
+
function createRetryHandler(config) {
|
|
761
|
+
return new RetryHandler(config);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// src/utils/circuit-breaker.ts
|
|
765
|
+
var import_eventemitter32 = __toESM(require("eventemitter3"));
|
|
766
|
+
var CircuitState = /* @__PURE__ */ ((CircuitState2) => {
|
|
767
|
+
CircuitState2["CLOSED"] = "closed";
|
|
768
|
+
CircuitState2["OPEN"] = "open";
|
|
769
|
+
CircuitState2["HALF_OPEN"] = "half-open";
|
|
770
|
+
return CircuitState2;
|
|
771
|
+
})(CircuitState || {});
|
|
772
|
+
var DEFAULT_CONFIG3 = {
|
|
773
|
+
failureThreshold: 5,
|
|
774
|
+
resetTimeout: 6e4,
|
|
775
|
+
halfOpenRequests: 1
|
|
776
|
+
};
|
|
777
|
+
var CircuitBreaker = class extends import_eventemitter32.default {
|
|
778
|
+
constructor(config = {}) {
|
|
779
|
+
super();
|
|
780
|
+
__publicField(this, "state", "closed" /* CLOSED */);
|
|
781
|
+
__publicField(this, "failureCount", 0);
|
|
782
|
+
__publicField(this, "successCount", 0);
|
|
783
|
+
__publicField(this, "lastFailureTime");
|
|
784
|
+
__publicField(this, "resetTimer");
|
|
785
|
+
__publicField(this, "config");
|
|
786
|
+
this.config = __spreadValues(__spreadValues({}, DEFAULT_CONFIG3), config);
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
789
|
+
* Execute a function with circuit breaker protection
|
|
790
|
+
* @param fn - Async function to execute
|
|
791
|
+
* @returns Promise resolving to function result
|
|
792
|
+
* @throws CircuitBreakerError if circuit is open
|
|
793
|
+
*/
|
|
794
|
+
execute(fn) {
|
|
795
|
+
return __async(this, null, function* () {
|
|
796
|
+
if (this.state === "open" /* OPEN */) {
|
|
797
|
+
throw new CircuitBreakerError("Circuit breaker is open", {
|
|
798
|
+
state: this.state,
|
|
799
|
+
failureCount: this.failureCount,
|
|
800
|
+
lastFailureTime: this.lastFailureTime
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
try {
|
|
804
|
+
const result = yield fn();
|
|
805
|
+
this.onSuccess();
|
|
806
|
+
return result;
|
|
807
|
+
} catch (error) {
|
|
808
|
+
this.onFailure();
|
|
809
|
+
throw error;
|
|
810
|
+
}
|
|
811
|
+
});
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* Handle successful execution
|
|
815
|
+
*/
|
|
816
|
+
onSuccess() {
|
|
817
|
+
this.failureCount = 0;
|
|
818
|
+
if (this.state === "half-open" /* HALF_OPEN */) {
|
|
819
|
+
this.successCount++;
|
|
820
|
+
if (this.successCount >= this.config.halfOpenRequests) {
|
|
821
|
+
this.close();
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* Handle failed execution
|
|
827
|
+
*/
|
|
828
|
+
onFailure() {
|
|
829
|
+
this.failureCount++;
|
|
830
|
+
this.lastFailureTime = Date.now();
|
|
831
|
+
this.successCount = 0;
|
|
832
|
+
if (this.failureCount >= this.config.failureThreshold) {
|
|
833
|
+
this.open();
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* Open the circuit (block requests)
|
|
838
|
+
*/
|
|
839
|
+
open() {
|
|
840
|
+
if (this.state === "open" /* OPEN */) return;
|
|
841
|
+
this.state = "open" /* OPEN */;
|
|
842
|
+
this.emit("open", { failureCount: this.failureCount });
|
|
843
|
+
this.resetTimer = setTimeout(() => {
|
|
844
|
+
this.halfOpen();
|
|
845
|
+
}, this.config.resetTimeout);
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* Enter half-open state (test if service recovered)
|
|
849
|
+
*/
|
|
850
|
+
halfOpen() {
|
|
851
|
+
if (this.state === "closed" /* CLOSED */) return;
|
|
852
|
+
this.state = "half-open" /* HALF_OPEN */;
|
|
853
|
+
this.successCount = 0;
|
|
854
|
+
this.emit("half-open");
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* Close the circuit (allow requests)
|
|
858
|
+
*/
|
|
859
|
+
close() {
|
|
860
|
+
if (this.state === "closed" /* CLOSED */) return;
|
|
861
|
+
this.state = "closed" /* CLOSED */;
|
|
862
|
+
this.failureCount = 0;
|
|
863
|
+
this.successCount = 0;
|
|
864
|
+
this.lastFailureTime = void 0;
|
|
865
|
+
if (this.resetTimer) {
|
|
866
|
+
clearTimeout(this.resetTimer);
|
|
867
|
+
this.resetTimer = void 0;
|
|
868
|
+
}
|
|
869
|
+
this.emit("close");
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* Get current circuit state
|
|
873
|
+
*/
|
|
874
|
+
getState() {
|
|
875
|
+
return this.state;
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* Get circuit statistics
|
|
879
|
+
*/
|
|
880
|
+
getStats() {
|
|
881
|
+
return {
|
|
882
|
+
state: this.state,
|
|
883
|
+
failureCount: this.failureCount,
|
|
884
|
+
successCount: this.successCount,
|
|
885
|
+
lastFailureTime: this.lastFailureTime
|
|
886
|
+
};
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Manually reset the circuit breaker
|
|
890
|
+
*/
|
|
891
|
+
reset() {
|
|
892
|
+
this.close();
|
|
893
|
+
}
|
|
894
|
+
/**
|
|
895
|
+
* Clean up resources
|
|
896
|
+
*/
|
|
897
|
+
destroy() {
|
|
898
|
+
if (this.resetTimer) {
|
|
899
|
+
clearTimeout(this.resetTimer);
|
|
900
|
+
}
|
|
901
|
+
this.removeAllListeners();
|
|
902
|
+
}
|
|
903
|
+
};
|
|
904
|
+
function createCircuitBreaker(config) {
|
|
905
|
+
return new CircuitBreaker(config);
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
// src/providers/base.ts
|
|
909
|
+
var BaseProvider = class {
|
|
910
|
+
constructor(config) {
|
|
911
|
+
__publicField(this, "config");
|
|
912
|
+
this.config = config;
|
|
913
|
+
}
|
|
914
|
+
makeRequest(url, options, stream = false) {
|
|
915
|
+
return __async(this, null, function* () {
|
|
916
|
+
const headers = __spreadValues({
|
|
917
|
+
"Content-Type": "application/json"
|
|
918
|
+
}, options.headers || {});
|
|
919
|
+
if (this.config.apiKey) {
|
|
920
|
+
headers["Authorization"] = `Bearer ${this.config.apiKey}`;
|
|
921
|
+
}
|
|
922
|
+
const response = yield fetch(url, __spreadProps(__spreadValues({}, options), {
|
|
923
|
+
headers
|
|
924
|
+
}));
|
|
925
|
+
if (!response.ok && !stream) {
|
|
926
|
+
const errorText = yield response.text();
|
|
927
|
+
throw new Error(`Provider request failed: ${response.status} ${errorText}`);
|
|
928
|
+
}
|
|
929
|
+
return response;
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
formatMessages(request) {
|
|
933
|
+
const messages = [];
|
|
934
|
+
if (request.systemPrompt) {
|
|
935
|
+
messages.push({ role: "system", content: request.systemPrompt });
|
|
936
|
+
}
|
|
937
|
+
messages.push(...request.messages);
|
|
938
|
+
return messages;
|
|
939
|
+
}
|
|
940
|
+
getEndpoint(path) {
|
|
941
|
+
const baseUrl = this.config.baseUrl || this.getDefaultBaseUrl();
|
|
942
|
+
return `${baseUrl}${path}`;
|
|
943
|
+
}
|
|
944
|
+
};
|
|
945
|
+
|
|
946
|
+
// src/providers/anthropic/anthropic.ts
|
|
947
|
+
var AnthropicProvider = class extends BaseProvider {
|
|
948
|
+
getDefaultBaseUrl() {
|
|
949
|
+
return "https://api.anthropic.com/v1";
|
|
950
|
+
}
|
|
951
|
+
generateText(request) {
|
|
952
|
+
return __async(this, null, function* () {
|
|
953
|
+
var _a;
|
|
954
|
+
const messages = this.formatMessages(request);
|
|
955
|
+
const systemPrompt = (_a = messages.find((m) => m.role === "system")) == null ? void 0 : _a.content;
|
|
956
|
+
const userMessages = messages.filter((m) => m.role !== "system");
|
|
957
|
+
const response = yield this.makeRequest(
|
|
958
|
+
this.getEndpoint("/messages"),
|
|
959
|
+
{
|
|
960
|
+
method: "POST",
|
|
961
|
+
headers: {
|
|
962
|
+
"anthropic-version": "2023-06-01"
|
|
963
|
+
},
|
|
964
|
+
body: JSON.stringify({
|
|
965
|
+
model: this.config.model,
|
|
966
|
+
messages: userMessages,
|
|
967
|
+
system: systemPrompt,
|
|
968
|
+
max_tokens: this.config.maxTokens || 1024,
|
|
969
|
+
temperature: this.config.temperature
|
|
970
|
+
})
|
|
971
|
+
}
|
|
972
|
+
);
|
|
973
|
+
const data = yield response.json();
|
|
974
|
+
return {
|
|
975
|
+
text: data.content[0].text,
|
|
976
|
+
usage: {
|
|
977
|
+
promptTokens: data.usage.input_tokens,
|
|
978
|
+
completionTokens: data.usage.output_tokens,
|
|
979
|
+
totalTokens: data.usage.input_tokens + data.usage.output_tokens
|
|
980
|
+
},
|
|
981
|
+
finishReason: data.stop_reason
|
|
982
|
+
};
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
streamText(request) {
|
|
986
|
+
return __asyncGenerator(this, null, function* () {
|
|
987
|
+
var _a;
|
|
988
|
+
const messages = this.formatMessages(request);
|
|
989
|
+
const systemPrompt = (_a = messages.find((m) => m.role === "system")) == null ? void 0 : _a.content;
|
|
990
|
+
const userMessages = messages.filter((m) => m.role !== "system");
|
|
991
|
+
const response = yield new __await(this.makeRequest(
|
|
992
|
+
this.getEndpoint("/messages"),
|
|
993
|
+
{
|
|
994
|
+
method: "POST",
|
|
995
|
+
headers: {
|
|
996
|
+
"anthropic-version": "2023-06-01"
|
|
997
|
+
},
|
|
998
|
+
body: JSON.stringify({
|
|
999
|
+
model: this.config.model,
|
|
1000
|
+
messages: userMessages,
|
|
1001
|
+
system: systemPrompt,
|
|
1002
|
+
max_tokens: this.config.maxTokens || 1024,
|
|
1003
|
+
stream: true
|
|
1004
|
+
})
|
|
1005
|
+
},
|
|
1006
|
+
true
|
|
1007
|
+
));
|
|
1008
|
+
const reader = response.body.getReader();
|
|
1009
|
+
const decoder = new TextDecoder();
|
|
1010
|
+
let buffer = "";
|
|
1011
|
+
try {
|
|
1012
|
+
while (true) {
|
|
1013
|
+
const { done, value } = yield new __await(reader.read());
|
|
1014
|
+
if (done) break;
|
|
1015
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1016
|
+
const lines = buffer.split("\n");
|
|
1017
|
+
buffer = lines.pop() || "";
|
|
1018
|
+
for (const line of lines) {
|
|
1019
|
+
if (line.startsWith("data: ")) {
|
|
1020
|
+
try {
|
|
1021
|
+
const data = JSON.parse(line.slice(6));
|
|
1022
|
+
if (data.type === "content_block_delta") {
|
|
1023
|
+
yield { type: "content", content: data.delta.text };
|
|
1024
|
+
}
|
|
1025
|
+
} catch (e) {
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
} finally {
|
|
1031
|
+
reader.releaseLock();
|
|
1032
|
+
}
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
1035
|
+
generateObject(request) {
|
|
1036
|
+
return __async(this, null, function* () {
|
|
1037
|
+
const textResponse = yield this.generateText(__spreadProps(__spreadValues({}, request), {
|
|
1038
|
+
messages: [
|
|
1039
|
+
...request.messages,
|
|
1040
|
+
{
|
|
1041
|
+
role: "user",
|
|
1042
|
+
content: `Respond with valid JSON matching this schema: ${JSON.stringify(request.schema)}`
|
|
1043
|
+
}
|
|
1044
|
+
]
|
|
1045
|
+
}));
|
|
1046
|
+
const object = JSON.parse(textResponse.text);
|
|
1047
|
+
return {
|
|
1048
|
+
object,
|
|
1049
|
+
text: textResponse.text,
|
|
1050
|
+
usage: textResponse.usage
|
|
1051
|
+
};
|
|
1052
|
+
});
|
|
1053
|
+
}
|
|
1054
|
+
streamObject(request) {
|
|
1055
|
+
return __asyncGenerator(this, null, function* () {
|
|
1056
|
+
let accumulatedText = "";
|
|
1057
|
+
try {
|
|
1058
|
+
for (var iter = __forAwait(this.streamText(request)), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
1059
|
+
const chunk = temp.value;
|
|
1060
|
+
if (chunk.type === "content") {
|
|
1061
|
+
accumulatedText += chunk.content;
|
|
1062
|
+
try {
|
|
1063
|
+
const partial = JSON.parse(accumulatedText);
|
|
1064
|
+
yield { type: "partial", partial, text: accumulatedText };
|
|
1065
|
+
} catch (e) {
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
} catch (temp) {
|
|
1070
|
+
error = [temp];
|
|
1071
|
+
} finally {
|
|
1072
|
+
try {
|
|
1073
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
1074
|
+
} finally {
|
|
1075
|
+
if (error)
|
|
1076
|
+
throw error[0];
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
try {
|
|
1080
|
+
const object = JSON.parse(accumulatedText);
|
|
1081
|
+
yield { type: "complete", object, text: accumulatedText };
|
|
1082
|
+
} catch (e) {
|
|
1083
|
+
yield { type: "error", error: new Error("Invalid JSON in response") };
|
|
1084
|
+
}
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
};
|
|
1088
|
+
|
|
1089
|
+
// src/providers/custom/custom.ts
|
|
1090
|
+
var CustomProvider = class extends BaseProvider {
|
|
1091
|
+
constructor() {
|
|
1092
|
+
super(...arguments);
|
|
1093
|
+
/**
|
|
1094
|
+
* Request format for custom provider
|
|
1095
|
+
*/
|
|
1096
|
+
__publicField(this, "requestFormat", "openai");
|
|
1097
|
+
}
|
|
1098
|
+
getDefaultBaseUrl() {
|
|
1099
|
+
return this.config.baseUrl || "http://localhost:8000/v1";
|
|
1100
|
+
}
|
|
1101
|
+
/**
|
|
1102
|
+
* Set request format for custom provider
|
|
1103
|
+
*/
|
|
1104
|
+
setRequestFormat(format) {
|
|
1105
|
+
this.requestFormat = format;
|
|
1106
|
+
}
|
|
1107
|
+
generateText(request) {
|
|
1108
|
+
return __async(this, null, function* () {
|
|
1109
|
+
const messages = this.formatMessages(request);
|
|
1110
|
+
try {
|
|
1111
|
+
const requestBody = this.formatRequestBody(messages, false);
|
|
1112
|
+
const response = yield this.makeRequest(this.getEndpoint("/chat/completions"), {
|
|
1113
|
+
method: "POST",
|
|
1114
|
+
body: JSON.stringify(requestBody)
|
|
1115
|
+
});
|
|
1116
|
+
const data = yield response.json();
|
|
1117
|
+
return this.parseTextResponse(data);
|
|
1118
|
+
} catch (error) {
|
|
1119
|
+
throw new ProviderError(
|
|
1120
|
+
"custom",
|
|
1121
|
+
error instanceof Error ? error.message : "Unknown error",
|
|
1122
|
+
void 0,
|
|
1123
|
+
{ originalError: error }
|
|
1124
|
+
);
|
|
1125
|
+
}
|
|
1126
|
+
});
|
|
1127
|
+
}
|
|
1128
|
+
streamText(request) {
|
|
1129
|
+
return __asyncGenerator(this, null, function* () {
|
|
1130
|
+
const messages = this.formatMessages(request);
|
|
1131
|
+
try {
|
|
1132
|
+
const requestBody = this.formatRequestBody(messages, true);
|
|
1133
|
+
const response = yield new __await(this.makeRequest(
|
|
1134
|
+
this.getEndpoint("/chat/completions"),
|
|
1135
|
+
{
|
|
1136
|
+
method: "POST",
|
|
1137
|
+
body: JSON.stringify(requestBody)
|
|
1138
|
+
},
|
|
1139
|
+
true
|
|
1140
|
+
));
|
|
1141
|
+
yield* __yieldStar(this.parseStreamResponse(response));
|
|
1142
|
+
} catch (error) {
|
|
1143
|
+
yield {
|
|
1144
|
+
type: "error",
|
|
1145
|
+
error: new ProviderError(
|
|
1146
|
+
"custom",
|
|
1147
|
+
error instanceof Error ? error.message : "Streaming error",
|
|
1148
|
+
void 0,
|
|
1149
|
+
{ originalError: error }
|
|
1150
|
+
)
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
1153
|
+
});
|
|
1154
|
+
}
|
|
1155
|
+
generateObject(request) {
|
|
1156
|
+
return __async(this, null, function* () {
|
|
1157
|
+
const enhancedRequest = __spreadProps(__spreadValues({}, request), {
|
|
1158
|
+
messages: [
|
|
1159
|
+
...request.messages,
|
|
1160
|
+
{
|
|
1161
|
+
role: "user",
|
|
1162
|
+
content: `Respond with valid JSON matching this schema: ${JSON.stringify(request.schema)}. Only return the JSON object.`
|
|
1163
|
+
}
|
|
1164
|
+
]
|
|
1165
|
+
});
|
|
1166
|
+
const textResponse = yield this.generateText(enhancedRequest);
|
|
1167
|
+
let jsonText = textResponse.text.trim();
|
|
1168
|
+
const codeBlockMatch = jsonText.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
|
|
1169
|
+
if (codeBlockMatch) {
|
|
1170
|
+
jsonText = codeBlockMatch[1];
|
|
1171
|
+
}
|
|
1172
|
+
try {
|
|
1173
|
+
const object = JSON.parse(jsonText);
|
|
1174
|
+
return {
|
|
1175
|
+
object,
|
|
1176
|
+
text: textResponse.text,
|
|
1177
|
+
usage: textResponse.usage
|
|
1178
|
+
};
|
|
1179
|
+
} catch (error) {
|
|
1180
|
+
throw new ProviderError(
|
|
1181
|
+
"custom",
|
|
1182
|
+
`Failed to parse JSON response: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
1183
|
+
void 0,
|
|
1184
|
+
{ responseText: textResponse.text }
|
|
1185
|
+
);
|
|
1186
|
+
}
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
streamObject(request) {
|
|
1190
|
+
return __asyncGenerator(this, null, function* () {
|
|
1191
|
+
let accumulatedText = "";
|
|
1192
|
+
try {
|
|
1193
|
+
for (var iter = __forAwait(this.streamText(request)), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
1194
|
+
const chunk = temp.value;
|
|
1195
|
+
if (chunk.type === "content") {
|
|
1196
|
+
accumulatedText += chunk.content;
|
|
1197
|
+
let jsonText2 = accumulatedText.trim();
|
|
1198
|
+
const codeBlockMatch2 = jsonText2.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
|
|
1199
|
+
if (codeBlockMatch2) {
|
|
1200
|
+
jsonText2 = codeBlockMatch2[1];
|
|
1201
|
+
}
|
|
1202
|
+
try {
|
|
1203
|
+
const partial = JSON.parse(jsonText2);
|
|
1204
|
+
yield { type: "partial", partial, text: accumulatedText };
|
|
1205
|
+
} catch (e) {
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
} catch (temp) {
|
|
1210
|
+
error = [temp];
|
|
1211
|
+
} finally {
|
|
1212
|
+
try {
|
|
1213
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
1214
|
+
} finally {
|
|
1215
|
+
if (error)
|
|
1216
|
+
throw error[0];
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
let jsonText = accumulatedText.trim();
|
|
1220
|
+
const codeBlockMatch = jsonText.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
|
|
1221
|
+
if (codeBlockMatch) {
|
|
1222
|
+
jsonText = codeBlockMatch[1];
|
|
1223
|
+
}
|
|
1224
|
+
try {
|
|
1225
|
+
const object = JSON.parse(jsonText);
|
|
1226
|
+
yield { type: "complete", object, text: accumulatedText };
|
|
1227
|
+
} catch (e) {
|
|
1228
|
+
yield { type: "error", error: new Error("Invalid JSON in response") };
|
|
1229
|
+
}
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
1232
|
+
/**
|
|
1233
|
+
* Format request body based on provider format
|
|
1234
|
+
*/
|
|
1235
|
+
formatRequestBody(messages, stream) {
|
|
1236
|
+
var _a;
|
|
1237
|
+
if (this.requestFormat === "anthropic") {
|
|
1238
|
+
const systemPrompt = (_a = messages.find((m) => m.role === "system")) == null ? void 0 : _a.content;
|
|
1239
|
+
const userMessages = messages.filter((m) => m.role !== "system");
|
|
1240
|
+
return {
|
|
1241
|
+
model: this.config.model,
|
|
1242
|
+
messages: userMessages,
|
|
1243
|
+
system: systemPrompt,
|
|
1244
|
+
max_tokens: this.config.maxTokens || 1024,
|
|
1245
|
+
temperature: this.config.temperature,
|
|
1246
|
+
top_p: this.config.topP,
|
|
1247
|
+
stream
|
|
1248
|
+
};
|
|
1249
|
+
}
|
|
1250
|
+
return {
|
|
1251
|
+
model: this.config.model,
|
|
1252
|
+
messages,
|
|
1253
|
+
max_tokens: this.config.maxTokens,
|
|
1254
|
+
temperature: this.config.temperature,
|
|
1255
|
+
top_p: this.config.topP,
|
|
1256
|
+
frequency_penalty: this.config.frequencyPenalty,
|
|
1257
|
+
presence_penalty: this.config.presencePenalty,
|
|
1258
|
+
stop: this.config.stop,
|
|
1259
|
+
stream
|
|
1260
|
+
};
|
|
1261
|
+
}
|
|
1262
|
+
/**
|
|
1263
|
+
* Parse text response based on provider format
|
|
1264
|
+
*/
|
|
1265
|
+
parseTextResponse(data) {
|
|
1266
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1267
|
+
if (data.choices && ((_a = data.choices[0]) == null ? void 0 : _a.message)) {
|
|
1268
|
+
return {
|
|
1269
|
+
text: data.choices[0].message.content,
|
|
1270
|
+
usage: {
|
|
1271
|
+
promptTokens: ((_b = data.usage) == null ? void 0 : _b.prompt_tokens) || 0,
|
|
1272
|
+
completionTokens: ((_c = data.usage) == null ? void 0 : _c.completion_tokens) || 0,
|
|
1273
|
+
totalTokens: ((_d = data.usage) == null ? void 0 : _d.total_tokens) || 0
|
|
1274
|
+
},
|
|
1275
|
+
finishReason: data.choices[0].finish_reason || "stop"
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1278
|
+
if (data.content && Array.isArray(data.content)) {
|
|
1279
|
+
return {
|
|
1280
|
+
text: ((_e = data.content[0]) == null ? void 0 : _e.text) || "",
|
|
1281
|
+
usage: {
|
|
1282
|
+
promptTokens: ((_f = data.usage) == null ? void 0 : _f.input_tokens) || 0,
|
|
1283
|
+
completionTokens: ((_g = data.usage) == null ? void 0 : _g.output_tokens) || 0,
|
|
1284
|
+
totalTokens: (((_h = data.usage) == null ? void 0 : _h.input_tokens) || 0) + (((_i = data.usage) == null ? void 0 : _i.output_tokens) || 0)
|
|
1285
|
+
},
|
|
1286
|
+
finishReason: data.stop_reason || "stop"
|
|
1287
|
+
};
|
|
1288
|
+
}
|
|
1289
|
+
return {
|
|
1290
|
+
text: data.text || data.response || JSON.stringify(data),
|
|
1291
|
+
usage: {
|
|
1292
|
+
promptTokens: 0,
|
|
1293
|
+
completionTokens: 0,
|
|
1294
|
+
totalTokens: 0
|
|
1295
|
+
},
|
|
1296
|
+
finishReason: "stop"
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1299
|
+
/**
|
|
1300
|
+
* Parse streaming response
|
|
1301
|
+
*/
|
|
1302
|
+
parseStreamResponse(response) {
|
|
1303
|
+
return __asyncGenerator(this, null, function* () {
|
|
1304
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
1305
|
+
const reader = response.body.getReader();
|
|
1306
|
+
const decoder = new TextDecoder();
|
|
1307
|
+
let buffer = "";
|
|
1308
|
+
try {
|
|
1309
|
+
while (true) {
|
|
1310
|
+
const { done, value } = yield new __await(reader.read());
|
|
1311
|
+
if (done) break;
|
|
1312
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1313
|
+
const lines = buffer.split("\n");
|
|
1314
|
+
buffer = lines.pop() || "";
|
|
1315
|
+
for (const line of lines) {
|
|
1316
|
+
if (line.startsWith("data: ")) {
|
|
1317
|
+
const data = line.slice(6);
|
|
1318
|
+
if (data === "[DONE]") continue;
|
|
1319
|
+
try {
|
|
1320
|
+
const parsed = JSON.parse(data);
|
|
1321
|
+
if ((_c = (_b = (_a = parsed.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.delta) == null ? void 0 : _c.content) {
|
|
1322
|
+
yield { type: "content", content: parsed.choices[0].delta.content };
|
|
1323
|
+
}
|
|
1324
|
+
if (parsed.type === "content_block_delta" && ((_d = parsed.delta) == null ? void 0 : _d.text)) {
|
|
1325
|
+
yield { type: "content", content: parsed.delta.text };
|
|
1326
|
+
}
|
|
1327
|
+
if (parsed.content && !parsed.choices) {
|
|
1328
|
+
yield { type: "content", content: parsed.content };
|
|
1329
|
+
}
|
|
1330
|
+
if (((_f = (_e = parsed.choices) == null ? void 0 : _e[0]) == null ? void 0 : _f.finish_reason) || parsed.stop_reason) {
|
|
1331
|
+
yield {
|
|
1332
|
+
type: "done",
|
|
1333
|
+
done: {
|
|
1334
|
+
finishReason: ((_h = (_g = parsed.choices) == null ? void 0 : _g[0]) == null ? void 0 : _h.finish_reason) || parsed.stop_reason || "stop",
|
|
1335
|
+
usage: {
|
|
1336
|
+
promptTokens: ((_i = parsed.usage) == null ? void 0 : _i.prompt_tokens) || ((_j = parsed.usage) == null ? void 0 : _j.input_tokens) || 0,
|
|
1337
|
+
completionTokens: ((_k = parsed.usage) == null ? void 0 : _k.completion_tokens) || ((_l = parsed.usage) == null ? void 0 : _l.output_tokens) || 0,
|
|
1338
|
+
totalTokens: ((_m = parsed.usage) == null ? void 0 : _m.total_tokens) || 0
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1343
|
+
} catch (e) {
|
|
1344
|
+
console.error("Failed to parse streaming chunk:", e);
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
} finally {
|
|
1350
|
+
reader.releaseLock();
|
|
1351
|
+
}
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
};
|
|
1355
|
+
|
|
1356
|
+
// src/providers/google/google.ts
|
|
1357
|
+
var GoogleProvider = class extends BaseProvider {
|
|
1358
|
+
getDefaultBaseUrl() {
|
|
1359
|
+
return "https://generativelanguage.googleapis.com/v1beta";
|
|
1360
|
+
}
|
|
1361
|
+
/**
|
|
1362
|
+
* Format messages for Google's API format
|
|
1363
|
+
*/
|
|
1364
|
+
formatGoogleMessages(messages) {
|
|
1365
|
+
return messages.map((msg) => ({
|
|
1366
|
+
role: msg.role === "assistant" ? "model" : msg.role,
|
|
1367
|
+
parts: [{ text: msg.content }]
|
|
1368
|
+
}));
|
|
1369
|
+
}
|
|
1370
|
+
generateText(request) {
|
|
1371
|
+
return __async(this, null, function* () {
|
|
1372
|
+
var _a, _b, _c, _d;
|
|
1373
|
+
const messages = this.formatMessages(request);
|
|
1374
|
+
const systemPrompt = (_a = messages.find((m) => m.role === "system")) == null ? void 0 : _a.content;
|
|
1375
|
+
const conversationMessages = messages.filter((m) => m.role !== "system");
|
|
1376
|
+
const endpoint = this.getEndpoint(
|
|
1377
|
+
`/models/${this.config.model}:generateContent?key=${this.config.apiKey}`
|
|
1378
|
+
);
|
|
1379
|
+
try {
|
|
1380
|
+
const response = yield this.makeRequest(endpoint, {
|
|
1381
|
+
method: "POST",
|
|
1382
|
+
body: JSON.stringify({
|
|
1383
|
+
contents: this.formatGoogleMessages(conversationMessages),
|
|
1384
|
+
systemInstruction: systemPrompt ? {
|
|
1385
|
+
parts: [{ text: systemPrompt }]
|
|
1386
|
+
} : void 0,
|
|
1387
|
+
generationConfig: {
|
|
1388
|
+
maxOutputTokens: this.config.maxTokens,
|
|
1389
|
+
temperature: this.config.temperature,
|
|
1390
|
+
topP: this.config.topP,
|
|
1391
|
+
stopSequences: this.config.stop
|
|
1392
|
+
}
|
|
1393
|
+
})
|
|
1394
|
+
});
|
|
1395
|
+
const data = yield response.json();
|
|
1396
|
+
if (!data.candidates || data.candidates.length === 0) {
|
|
1397
|
+
throw new ProviderError(
|
|
1398
|
+
"google",
|
|
1399
|
+
"No candidates returned from Google API",
|
|
1400
|
+
response.status,
|
|
1401
|
+
{ response: data }
|
|
1402
|
+
);
|
|
1403
|
+
}
|
|
1404
|
+
const candidate = data.candidates[0];
|
|
1405
|
+
const text = candidate.content.parts.map((p) => p.text).join("");
|
|
1406
|
+
return {
|
|
1407
|
+
text,
|
|
1408
|
+
usage: {
|
|
1409
|
+
promptTokens: ((_b = data.usageMetadata) == null ? void 0 : _b.promptTokenCount) || 0,
|
|
1410
|
+
completionTokens: ((_c = data.usageMetadata) == null ? void 0 : _c.candidatesTokenCount) || 0,
|
|
1411
|
+
totalTokens: ((_d = data.usageMetadata) == null ? void 0 : _d.totalTokenCount) || 0
|
|
1412
|
+
},
|
|
1413
|
+
finishReason: this.mapGoogleFinishReason(candidate.finishReason),
|
|
1414
|
+
metadata: {
|
|
1415
|
+
safetyRatings: candidate.safetyRatings
|
|
1416
|
+
}
|
|
1417
|
+
};
|
|
1418
|
+
} catch (error) {
|
|
1419
|
+
throw new ProviderError(
|
|
1420
|
+
"google",
|
|
1421
|
+
error instanceof Error ? error.message : "Unknown error",
|
|
1422
|
+
void 0,
|
|
1423
|
+
{ originalError: error }
|
|
1424
|
+
);
|
|
1425
|
+
}
|
|
1426
|
+
});
|
|
1427
|
+
}
|
|
1428
|
+
streamText(request) {
|
|
1429
|
+
return __asyncGenerator(this, null, function* () {
|
|
1430
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1431
|
+
const messages = this.formatMessages(request);
|
|
1432
|
+
const systemPrompt = (_a = messages.find((m) => m.role === "system")) == null ? void 0 : _a.content;
|
|
1433
|
+
const conversationMessages = messages.filter((m) => m.role !== "system");
|
|
1434
|
+
const endpoint = this.getEndpoint(
|
|
1435
|
+
`/models/${this.config.model}:streamGenerateContent?key=${this.config.apiKey}`
|
|
1436
|
+
);
|
|
1437
|
+
try {
|
|
1438
|
+
const response = yield new __await(this.makeRequest(
|
|
1439
|
+
endpoint,
|
|
1440
|
+
{
|
|
1441
|
+
method: "POST",
|
|
1442
|
+
body: JSON.stringify({
|
|
1443
|
+
contents: this.formatGoogleMessages(conversationMessages),
|
|
1444
|
+
systemInstruction: systemPrompt ? {
|
|
1445
|
+
parts: [{ text: systemPrompt }]
|
|
1446
|
+
} : void 0,
|
|
1447
|
+
generationConfig: {
|
|
1448
|
+
maxOutputTokens: this.config.maxTokens,
|
|
1449
|
+
temperature: this.config.temperature,
|
|
1450
|
+
topP: this.config.topP
|
|
1451
|
+
}
|
|
1452
|
+
})
|
|
1453
|
+
},
|
|
1454
|
+
true
|
|
1455
|
+
));
|
|
1456
|
+
const reader = response.body.getReader();
|
|
1457
|
+
const decoder = new TextDecoder();
|
|
1458
|
+
let buffer = "";
|
|
1459
|
+
while (true) {
|
|
1460
|
+
const { done, value } = yield new __await(reader.read());
|
|
1461
|
+
if (done) break;
|
|
1462
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1463
|
+
const lines = buffer.split("\n");
|
|
1464
|
+
buffer = lines.pop() || "";
|
|
1465
|
+
for (const line of lines) {
|
|
1466
|
+
if (!line.trim() || !line.startsWith("data: ")) continue;
|
|
1467
|
+
try {
|
|
1468
|
+
const jsonStr = line.slice(6).trim();
|
|
1469
|
+
if (!jsonStr) continue;
|
|
1470
|
+
const data = JSON.parse(jsonStr);
|
|
1471
|
+
if (data.candidates && ((_c = (_b = data.candidates[0]) == null ? void 0 : _b.content) == null ? void 0 : _c.parts)) {
|
|
1472
|
+
const text = data.candidates[0].content.parts.map((p) => p.text).join("");
|
|
1473
|
+
if (text) {
|
|
1474
|
+
yield { type: "content", content: text };
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
if (data.candidates && ((_d = data.candidates[0]) == null ? void 0 : _d.finishReason)) {
|
|
1478
|
+
yield {
|
|
1479
|
+
type: "done",
|
|
1480
|
+
done: {
|
|
1481
|
+
finishReason: this.mapGoogleFinishReason(data.candidates[0].finishReason),
|
|
1482
|
+
usage: {
|
|
1483
|
+
promptTokens: ((_e = data.usageMetadata) == null ? void 0 : _e.promptTokenCount) || 0,
|
|
1484
|
+
completionTokens: ((_f = data.usageMetadata) == null ? void 0 : _f.candidatesTokenCount) || 0,
|
|
1485
|
+
totalTokens: ((_g = data.usageMetadata) == null ? void 0 : _g.totalTokenCount) || 0
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
};
|
|
1489
|
+
}
|
|
1490
|
+
} catch (e) {
|
|
1491
|
+
console.error("Failed to parse Google streaming response:", e);
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
} catch (error) {
|
|
1496
|
+
yield {
|
|
1497
|
+
type: "error",
|
|
1498
|
+
error: new ProviderError(
|
|
1499
|
+
"google",
|
|
1500
|
+
error instanceof Error ? error.message : "Streaming error",
|
|
1501
|
+
void 0,
|
|
1502
|
+
{ originalError: error }
|
|
1503
|
+
)
|
|
1504
|
+
};
|
|
1505
|
+
}
|
|
1506
|
+
});
|
|
1507
|
+
}
|
|
1508
|
+
generateObject(request) {
|
|
1509
|
+
return __async(this, null, function* () {
|
|
1510
|
+
const enhancedRequest = __spreadProps(__spreadValues({}, request), {
|
|
1511
|
+
messages: [
|
|
1512
|
+
...request.messages,
|
|
1513
|
+
{
|
|
1514
|
+
role: "user",
|
|
1515
|
+
content: `Respond with valid JSON matching this schema: ${JSON.stringify(request.schema)}. Only return the JSON object, no other text.`
|
|
1516
|
+
}
|
|
1517
|
+
]
|
|
1518
|
+
});
|
|
1519
|
+
const textResponse = yield this.generateText(enhancedRequest);
|
|
1520
|
+
let jsonText = textResponse.text.trim();
|
|
1521
|
+
const jsonMatch = jsonText.match(/```json\s*([\s\S]*?)\s*```/);
|
|
1522
|
+
if (jsonMatch) {
|
|
1523
|
+
jsonText = jsonMatch[1];
|
|
1524
|
+
}
|
|
1525
|
+
try {
|
|
1526
|
+
const object = JSON.parse(jsonText);
|
|
1527
|
+
return {
|
|
1528
|
+
object,
|
|
1529
|
+
text: textResponse.text,
|
|
1530
|
+
usage: textResponse.usage
|
|
1531
|
+
};
|
|
1532
|
+
} catch (error) {
|
|
1533
|
+
throw new ProviderError(
|
|
1534
|
+
"google",
|
|
1535
|
+
`Failed to parse JSON response: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
1536
|
+
void 0,
|
|
1537
|
+
{ responseText: textResponse.text }
|
|
1538
|
+
);
|
|
1539
|
+
}
|
|
1540
|
+
});
|
|
1541
|
+
}
|
|
1542
|
+
streamObject(request) {
|
|
1543
|
+
return __asyncGenerator(this, null, function* () {
|
|
1544
|
+
let accumulatedText = "";
|
|
1545
|
+
try {
|
|
1546
|
+
for (var iter = __forAwait(this.streamText(request)), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
1547
|
+
const chunk = temp.value;
|
|
1548
|
+
if (chunk.type === "content") {
|
|
1549
|
+
accumulatedText += chunk.content;
|
|
1550
|
+
let jsonText2 = accumulatedText.trim();
|
|
1551
|
+
const jsonMatch2 = jsonText2.match(/```json\s*([\s\S]*?)\s*```/);
|
|
1552
|
+
if (jsonMatch2) {
|
|
1553
|
+
jsonText2 = jsonMatch2[1];
|
|
1554
|
+
}
|
|
1555
|
+
try {
|
|
1556
|
+
const partial = JSON.parse(jsonText2);
|
|
1557
|
+
yield { type: "partial", partial, text: accumulatedText };
|
|
1558
|
+
} catch (e) {
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
} catch (temp) {
|
|
1563
|
+
error = [temp];
|
|
1564
|
+
} finally {
|
|
1565
|
+
try {
|
|
1566
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
1567
|
+
} finally {
|
|
1568
|
+
if (error)
|
|
1569
|
+
throw error[0];
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
let jsonText = accumulatedText.trim();
|
|
1573
|
+
const jsonMatch = jsonText.match(/```json\s*([\s\S]*?)\s*```/);
|
|
1574
|
+
if (jsonMatch) {
|
|
1575
|
+
jsonText = jsonMatch[1];
|
|
1576
|
+
}
|
|
1577
|
+
try {
|
|
1578
|
+
const object = JSON.parse(jsonText);
|
|
1579
|
+
yield { type: "complete", object, text: accumulatedText };
|
|
1580
|
+
} catch (e) {
|
|
1581
|
+
yield {
|
|
1582
|
+
type: "error",
|
|
1583
|
+
error: new Error(`Invalid JSON in response: ${accumulatedText.substring(0, 100)}...`)
|
|
1584
|
+
};
|
|
1585
|
+
}
|
|
1586
|
+
});
|
|
1587
|
+
}
|
|
1588
|
+
/**
|
|
1589
|
+
* Map Google's finish reason to standard format
|
|
1590
|
+
*/
|
|
1591
|
+
mapGoogleFinishReason(reason) {
|
|
1592
|
+
const mapping = {
|
|
1593
|
+
"STOP": "stop",
|
|
1594
|
+
"MAX_TOKENS": "length",
|
|
1595
|
+
"SAFETY": "content_filter",
|
|
1596
|
+
"RECITATION": "content_filter",
|
|
1597
|
+
"OTHER": "stop"
|
|
1598
|
+
};
|
|
1599
|
+
return mapping[reason] || "stop";
|
|
1600
|
+
}
|
|
1601
|
+
};
|
|
1602
|
+
|
|
1603
|
+
// src/providers/openai/openai.ts
|
|
1604
|
+
var OpenAIProvider = class extends BaseProvider {
|
|
1605
|
+
getDefaultBaseUrl() {
|
|
1606
|
+
return "https://api.openai.com/v1";
|
|
1607
|
+
}
|
|
1608
|
+
generateText(request) {
|
|
1609
|
+
return __async(this, null, function* () {
|
|
1610
|
+
const response = yield this.makeRequest(
|
|
1611
|
+
this.getEndpoint("/chat/completions"),
|
|
1612
|
+
{
|
|
1613
|
+
method: "POST",
|
|
1614
|
+
body: JSON.stringify({
|
|
1615
|
+
model: this.config.model,
|
|
1616
|
+
messages: this.formatMessages(request),
|
|
1617
|
+
max_tokens: this.config.maxTokens,
|
|
1618
|
+
temperature: this.config.temperature,
|
|
1619
|
+
top_p: this.config.topP,
|
|
1620
|
+
frequency_penalty: this.config.frequencyPenalty,
|
|
1621
|
+
presence_penalty: this.config.presencePenalty,
|
|
1622
|
+
stop: this.config.stop
|
|
1623
|
+
})
|
|
1624
|
+
}
|
|
1625
|
+
);
|
|
1626
|
+
const data = yield response.json();
|
|
1627
|
+
return {
|
|
1628
|
+
text: data.choices[0].message.content,
|
|
1629
|
+
usage: {
|
|
1630
|
+
promptTokens: data.usage.prompt_tokens,
|
|
1631
|
+
completionTokens: data.usage.completion_tokens,
|
|
1632
|
+
totalTokens: data.usage.total_tokens
|
|
1633
|
+
},
|
|
1634
|
+
finishReason: data.choices[0].finish_reason
|
|
1635
|
+
};
|
|
1636
|
+
});
|
|
1637
|
+
}
|
|
1638
|
+
streamText(request) {
|
|
1639
|
+
return __asyncGenerator(this, null, function* () {
|
|
1640
|
+
var _a, _b;
|
|
1641
|
+
const response = yield new __await(this.makeRequest(
|
|
1642
|
+
this.getEndpoint("/chat/completions"),
|
|
1643
|
+
{
|
|
1644
|
+
method: "POST",
|
|
1645
|
+
body: JSON.stringify({
|
|
1646
|
+
model: this.config.model,
|
|
1647
|
+
messages: this.formatMessages(request),
|
|
1648
|
+
max_tokens: this.config.maxTokens,
|
|
1649
|
+
temperature: this.config.temperature,
|
|
1650
|
+
stream: true
|
|
1651
|
+
})
|
|
1652
|
+
},
|
|
1653
|
+
true
|
|
1654
|
+
));
|
|
1655
|
+
const reader = response.body.getReader();
|
|
1656
|
+
const decoder = new TextDecoder();
|
|
1657
|
+
let buffer = "";
|
|
1658
|
+
try {
|
|
1659
|
+
while (true) {
|
|
1660
|
+
const { done, value } = yield new __await(reader.read());
|
|
1661
|
+
if (done) break;
|
|
1662
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1663
|
+
const lines = buffer.split("\n");
|
|
1664
|
+
buffer = lines.pop() || "";
|
|
1665
|
+
for (const line of lines) {
|
|
1666
|
+
if (line.startsWith("data: ")) {
|
|
1667
|
+
const data = line.slice(6);
|
|
1668
|
+
if (data === "[DONE]") continue;
|
|
1669
|
+
try {
|
|
1670
|
+
const parsed = JSON.parse(data);
|
|
1671
|
+
const content = (_b = (_a = parsed.choices[0]) == null ? void 0 : _a.delta) == null ? void 0 : _b.content;
|
|
1672
|
+
if (content) {
|
|
1673
|
+
yield { type: "content", content };
|
|
1674
|
+
}
|
|
1675
|
+
} catch (e) {
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
} finally {
|
|
1681
|
+
reader.releaseLock();
|
|
1682
|
+
}
|
|
1683
|
+
});
|
|
1684
|
+
}
|
|
1685
|
+
generateObject(request) {
|
|
1686
|
+
return __async(this, null, function* () {
|
|
1687
|
+
const textResponse = yield this.generateText(__spreadProps(__spreadValues({}, request), {
|
|
1688
|
+
messages: [
|
|
1689
|
+
...request.messages,
|
|
1690
|
+
{
|
|
1691
|
+
role: "system",
|
|
1692
|
+
content: `Respond with valid JSON matching this schema: ${JSON.stringify(request.schema)}`
|
|
1693
|
+
}
|
|
1694
|
+
]
|
|
1695
|
+
}));
|
|
1696
|
+
const object = JSON.parse(textResponse.text);
|
|
1697
|
+
return {
|
|
1698
|
+
object,
|
|
1699
|
+
text: textResponse.text,
|
|
1700
|
+
usage: textResponse.usage
|
|
1701
|
+
};
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
streamObject(request) {
|
|
1705
|
+
return __asyncGenerator(this, null, function* () {
|
|
1706
|
+
let accumulatedText = "";
|
|
1707
|
+
try {
|
|
1708
|
+
for (var iter = __forAwait(this.streamText(request)), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
1709
|
+
const chunk = temp.value;
|
|
1710
|
+
if (chunk.type === "content") {
|
|
1711
|
+
accumulatedText += chunk.content;
|
|
1712
|
+
try {
|
|
1713
|
+
const partial = JSON.parse(accumulatedText);
|
|
1714
|
+
yield { type: "partial", partial, text: accumulatedText };
|
|
1715
|
+
} catch (e) {
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
} catch (temp) {
|
|
1720
|
+
error = [temp];
|
|
1721
|
+
} finally {
|
|
1722
|
+
try {
|
|
1723
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
1724
|
+
} finally {
|
|
1725
|
+
if (error)
|
|
1726
|
+
throw error[0];
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
try {
|
|
1730
|
+
const object = JSON.parse(accumulatedText);
|
|
1731
|
+
yield { type: "complete", object, text: accumulatedText };
|
|
1732
|
+
} catch (e) {
|
|
1733
|
+
yield { type: "error", error: new Error("Invalid JSON in response") };
|
|
1734
|
+
}
|
|
1735
|
+
});
|
|
1736
|
+
}
|
|
1737
|
+
};
|
|
1738
|
+
|
|
1739
|
+
// src/providers/sarvam/sarvam.ts
|
|
1740
|
+
var SarvamProvider = class extends BaseProvider {
|
|
1741
|
+
getDefaultBaseUrl() {
|
|
1742
|
+
return "https://api.sarvam.ai/v1";
|
|
1743
|
+
}
|
|
1744
|
+
generateText(request) {
|
|
1745
|
+
return __async(this, null, function* () {
|
|
1746
|
+
var _a, _b, _c;
|
|
1747
|
+
const messages = this.formatMessages(request);
|
|
1748
|
+
try {
|
|
1749
|
+
const response = yield this.makeRequest(this.getEndpoint("/chat/completions"), {
|
|
1750
|
+
method: "POST",
|
|
1751
|
+
body: JSON.stringify({
|
|
1752
|
+
model: this.config.model,
|
|
1753
|
+
messages: messages.map((m) => ({
|
|
1754
|
+
role: m.role,
|
|
1755
|
+
content: m.content
|
|
1756
|
+
})),
|
|
1757
|
+
max_tokens: this.config.maxTokens,
|
|
1758
|
+
temperature: this.config.temperature,
|
|
1759
|
+
top_p: this.config.topP,
|
|
1760
|
+
stop: this.config.stop
|
|
1761
|
+
})
|
|
1762
|
+
});
|
|
1763
|
+
const data = yield response.json();
|
|
1764
|
+
if (!data.choices || data.choices.length === 0) {
|
|
1765
|
+
throw new ProviderError(
|
|
1766
|
+
"sarvam",
|
|
1767
|
+
"No choices returned from Sarvam API",
|
|
1768
|
+
response.status,
|
|
1769
|
+
{ response: data }
|
|
1770
|
+
);
|
|
1771
|
+
}
|
|
1772
|
+
return {
|
|
1773
|
+
text: data.choices[0].message.content,
|
|
1774
|
+
usage: {
|
|
1775
|
+
promptTokens: ((_a = data.usage) == null ? void 0 : _a.prompt_tokens) || 0,
|
|
1776
|
+
completionTokens: ((_b = data.usage) == null ? void 0 : _b.completion_tokens) || 0,
|
|
1777
|
+
totalTokens: ((_c = data.usage) == null ? void 0 : _c.total_tokens) || 0
|
|
1778
|
+
},
|
|
1779
|
+
finishReason: this.mapSarvamFinishReason(data.choices[0].finish_reason)
|
|
1780
|
+
};
|
|
1781
|
+
} catch (error) {
|
|
1782
|
+
throw new ProviderError(
|
|
1783
|
+
"sarvam",
|
|
1784
|
+
error instanceof Error ? error.message : "Unknown error",
|
|
1785
|
+
void 0,
|
|
1786
|
+
{ originalError: error }
|
|
1787
|
+
);
|
|
1788
|
+
}
|
|
1789
|
+
});
|
|
1790
|
+
}
|
|
1791
|
+
streamText(request) {
|
|
1792
|
+
return __asyncGenerator(this, null, function* () {
|
|
1793
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1794
|
+
const messages = this.formatMessages(request);
|
|
1795
|
+
try {
|
|
1796
|
+
const response = yield new __await(this.makeRequest(
|
|
1797
|
+
this.getEndpoint("/chat/completions"),
|
|
1798
|
+
{
|
|
1799
|
+
method: "POST",
|
|
1800
|
+
body: JSON.stringify({
|
|
1801
|
+
model: this.config.model,
|
|
1802
|
+
messages: messages.map((m) => ({
|
|
1803
|
+
role: m.role,
|
|
1804
|
+
content: m.content
|
|
1805
|
+
})),
|
|
1806
|
+
max_tokens: this.config.maxTokens,
|
|
1807
|
+
temperature: this.config.temperature,
|
|
1808
|
+
stream: true
|
|
1809
|
+
})
|
|
1810
|
+
},
|
|
1811
|
+
true
|
|
1812
|
+
));
|
|
1813
|
+
const reader = response.body.getReader();
|
|
1814
|
+
const decoder = new TextDecoder();
|
|
1815
|
+
let buffer = "";
|
|
1816
|
+
while (true) {
|
|
1817
|
+
const { done, value } = yield new __await(reader.read());
|
|
1818
|
+
if (done) break;
|
|
1819
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1820
|
+
const lines = buffer.split("\n");
|
|
1821
|
+
buffer = lines.pop() || "";
|
|
1822
|
+
for (const line of lines) {
|
|
1823
|
+
if (line.startsWith("data: ")) {
|
|
1824
|
+
const data = line.slice(6);
|
|
1825
|
+
if (data === "[DONE]") continue;
|
|
1826
|
+
try {
|
|
1827
|
+
const parsed = JSON.parse(data);
|
|
1828
|
+
const content = (_c = (_b = (_a = parsed.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.delta) == null ? void 0 : _c.content;
|
|
1829
|
+
if (content) {
|
|
1830
|
+
yield { type: "content", content };
|
|
1831
|
+
}
|
|
1832
|
+
if ((_e = (_d = parsed.choices) == null ? void 0 : _d[0]) == null ? void 0 : _e.finish_reason) {
|
|
1833
|
+
yield {
|
|
1834
|
+
type: "done",
|
|
1835
|
+
done: {
|
|
1836
|
+
finishReason: this.mapSarvamFinishReason(parsed.choices[0].finish_reason),
|
|
1837
|
+
usage: {
|
|
1838
|
+
promptTokens: ((_f = parsed.usage) == null ? void 0 : _f.prompt_tokens) || 0,
|
|
1839
|
+
completionTokens: ((_g = parsed.usage) == null ? void 0 : _g.completion_tokens) || 0,
|
|
1840
|
+
totalTokens: ((_h = parsed.usage) == null ? void 0 : _h.total_tokens) || 0
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1843
|
+
};
|
|
1844
|
+
}
|
|
1845
|
+
} catch (e) {
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
} catch (error) {
|
|
1851
|
+
yield {
|
|
1852
|
+
type: "error",
|
|
1853
|
+
error: new ProviderError(
|
|
1854
|
+
"sarvam",
|
|
1855
|
+
error instanceof Error ? error.message : "Streaming error",
|
|
1856
|
+
void 0,
|
|
1857
|
+
{ originalError: error }
|
|
1858
|
+
)
|
|
1859
|
+
};
|
|
1860
|
+
}
|
|
1861
|
+
});
|
|
1862
|
+
}
|
|
1863
|
+
generateObject(request) {
|
|
1864
|
+
return __async(this, null, function* () {
|
|
1865
|
+
const enhancedRequest = __spreadProps(__spreadValues({}, request), {
|
|
1866
|
+
messages: [
|
|
1867
|
+
...request.messages,
|
|
1868
|
+
{
|
|
1869
|
+
role: "user",
|
|
1870
|
+
content: `Respond with valid JSON matching this schema: ${JSON.stringify(request.schema)}`
|
|
1871
|
+
}
|
|
1872
|
+
]
|
|
1873
|
+
});
|
|
1874
|
+
const textResponse = yield this.generateText(enhancedRequest);
|
|
1875
|
+
try {
|
|
1876
|
+
const object = JSON.parse(textResponse.text);
|
|
1877
|
+
return {
|
|
1878
|
+
object,
|
|
1879
|
+
text: textResponse.text,
|
|
1880
|
+
usage: textResponse.usage
|
|
1881
|
+
};
|
|
1882
|
+
} catch (error) {
|
|
1883
|
+
throw new ProviderError(
|
|
1884
|
+
"sarvam",
|
|
1885
|
+
`Failed to parse JSON response: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
1886
|
+
void 0,
|
|
1887
|
+
{ responseText: textResponse.text }
|
|
1888
|
+
);
|
|
1889
|
+
}
|
|
1890
|
+
});
|
|
1891
|
+
}
|
|
1892
|
+
streamObject(request) {
|
|
1893
|
+
return __asyncGenerator(this, null, function* () {
|
|
1894
|
+
let accumulatedText = "";
|
|
1895
|
+
try {
|
|
1896
|
+
for (var iter = __forAwait(this.streamText(request)), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
1897
|
+
const chunk = temp.value;
|
|
1898
|
+
if (chunk.type === "content") {
|
|
1899
|
+
accumulatedText += chunk.content;
|
|
1900
|
+
try {
|
|
1901
|
+
const partial = JSON.parse(accumulatedText);
|
|
1902
|
+
yield { type: "partial", partial, text: accumulatedText };
|
|
1903
|
+
} catch (e) {
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
} catch (temp) {
|
|
1908
|
+
error = [temp];
|
|
1909
|
+
} finally {
|
|
1910
|
+
try {
|
|
1911
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
1912
|
+
} finally {
|
|
1913
|
+
if (error)
|
|
1914
|
+
throw error[0];
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
try {
|
|
1918
|
+
const object = JSON.parse(accumulatedText);
|
|
1919
|
+
yield { type: "complete", object, text: accumulatedText };
|
|
1920
|
+
} catch (e) {
|
|
1921
|
+
yield { type: "error", error: new Error("Invalid JSON in response") };
|
|
1922
|
+
}
|
|
1923
|
+
});
|
|
1924
|
+
}
|
|
1925
|
+
/**
|
|
1926
|
+
* Map Sarvam's finish reason to standard format
|
|
1927
|
+
*/
|
|
1928
|
+
mapSarvamFinishReason(reason) {
|
|
1929
|
+
const mapping = {
|
|
1930
|
+
"stop": "stop",
|
|
1931
|
+
"length": "length",
|
|
1932
|
+
"max_tokens": "length",
|
|
1933
|
+
"content_filter": "content_filter"
|
|
1934
|
+
};
|
|
1935
|
+
return mapping[reason] || "stop";
|
|
1936
|
+
}
|
|
1937
|
+
};
|
|
1938
|
+
|
|
1939
|
+
// src/providers/factory.ts
|
|
1940
|
+
function createProvider(config) {
|
|
1941
|
+
switch (config.provider) {
|
|
1942
|
+
case "openai":
|
|
1943
|
+
return new OpenAIProvider(config);
|
|
1944
|
+
case "anthropic":
|
|
1945
|
+
return new AnthropicProvider(config);
|
|
1946
|
+
case "google":
|
|
1947
|
+
return new GoogleProvider(config);
|
|
1948
|
+
case "sarvam":
|
|
1949
|
+
return new SarvamProvider(config);
|
|
1950
|
+
case "custom":
|
|
1951
|
+
return new CustomProvider(config);
|
|
1952
|
+
default:
|
|
1953
|
+
throw new Error(`Unknown extended provider: ${config.provider}`);
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
// src/stream/stream-reader.ts
|
|
1958
|
+
var TransformStream = class {
|
|
1959
|
+
constructor(transformer) {
|
|
1960
|
+
__publicField(this, "transformer");
|
|
1961
|
+
this.transformer = transformer;
|
|
1962
|
+
}
|
|
1963
|
+
transform(source) {
|
|
1964
|
+
return __asyncGenerator(this, null, function* () {
|
|
1965
|
+
try {
|
|
1966
|
+
for (var iter = __forAwait(source), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
1967
|
+
const chunk = temp.value;
|
|
1968
|
+
yield yield new __await(this.transformer(chunk));
|
|
1969
|
+
}
|
|
1970
|
+
} catch (temp) {
|
|
1971
|
+
error = [temp];
|
|
1972
|
+
} finally {
|
|
1973
|
+
try {
|
|
1974
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
1975
|
+
} finally {
|
|
1976
|
+
if (error)
|
|
1977
|
+
throw error[0];
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
});
|
|
1981
|
+
}
|
|
1982
|
+
};
|
|
1983
|
+
var FlareStreamReader = class {
|
|
1984
|
+
constructor(source) {
|
|
1985
|
+
__publicField(this, "source");
|
|
1986
|
+
__publicField(this, "done", false);
|
|
1987
|
+
this.source = source[Symbol.asyncIterator]();
|
|
1988
|
+
}
|
|
1989
|
+
read() {
|
|
1990
|
+
return __async(this, null, function* () {
|
|
1991
|
+
if (this.done) {
|
|
1992
|
+
return { value: void 0, done: true };
|
|
1993
|
+
}
|
|
1994
|
+
const result = yield this.source.next();
|
|
1995
|
+
this.done = result.done || false;
|
|
1996
|
+
return { value: result.value, done: this.done };
|
|
1997
|
+
});
|
|
1998
|
+
}
|
|
1999
|
+
cancel() {
|
|
2000
|
+
this.done = true;
|
|
2001
|
+
if (this.source.return) {
|
|
2002
|
+
this.source.return();
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
[Symbol.asyncIterator]() {
|
|
2006
|
+
return __asyncGenerator(this, null, function* () {
|
|
2007
|
+
while (!this.done) {
|
|
2008
|
+
const { value, done } = yield new __await(this.read());
|
|
2009
|
+
if (done) break;
|
|
2010
|
+
yield value;
|
|
2011
|
+
}
|
|
2012
|
+
});
|
|
2013
|
+
}
|
|
2014
|
+
};
|
|
2015
|
+
function createDataStreamWriter() {
|
|
2016
|
+
let controller = null;
|
|
2017
|
+
const encoder = new TextEncoder();
|
|
2018
|
+
const readable = new ReadableStream({
|
|
2019
|
+
start(ctrl) {
|
|
2020
|
+
controller = ctrl;
|
|
2021
|
+
},
|
|
2022
|
+
cancel() {
|
|
2023
|
+
controller = null;
|
|
2024
|
+
}
|
|
2025
|
+
});
|
|
2026
|
+
const write = (data) => {
|
|
2027
|
+
if (controller) {
|
|
2028
|
+
controller.enqueue(encoder.encode(data));
|
|
2029
|
+
}
|
|
2030
|
+
};
|
|
2031
|
+
return {
|
|
2032
|
+
readable,
|
|
2033
|
+
/**
|
|
2034
|
+
* Write data event
|
|
2035
|
+
*/
|
|
2036
|
+
writeData(data) {
|
|
2037
|
+
write(`data: ${JSON.stringify(data)}
|
|
2038
|
+
|
|
2039
|
+
`);
|
|
2040
|
+
},
|
|
2041
|
+
/**
|
|
2042
|
+
* Write error event
|
|
2043
|
+
*/
|
|
2044
|
+
writeError(error) {
|
|
2045
|
+
write(`event: error
|
|
2046
|
+
data: ${JSON.stringify({
|
|
2047
|
+
message: error.message,
|
|
2048
|
+
code: error.code
|
|
2049
|
+
})}
|
|
2050
|
+
|
|
2051
|
+
`);
|
|
2052
|
+
},
|
|
2053
|
+
/**
|
|
2054
|
+
* Write custom event
|
|
2055
|
+
*/
|
|
2056
|
+
writeEvent(event, data) {
|
|
2057
|
+
write(`event: ${event}
|
|
2058
|
+
data: ${JSON.stringify(data)}
|
|
2059
|
+
|
|
2060
|
+
`);
|
|
2061
|
+
},
|
|
2062
|
+
/**
|
|
2063
|
+
* Close the stream
|
|
2064
|
+
*/
|
|
2065
|
+
close() {
|
|
2066
|
+
if (controller) {
|
|
2067
|
+
controller.close();
|
|
2068
|
+
controller = null;
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
};
|
|
2072
|
+
}
|
|
2073
|
+
function toUiStreamResponse(stream, headers) {
|
|
2074
|
+
const writer = createDataStreamWriter();
|
|
2075
|
+
(() => __async(null, null, function* () {
|
|
2076
|
+
try {
|
|
2077
|
+
try {
|
|
2078
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield iter.next()).done; more = false) {
|
|
2079
|
+
const chunk = temp.value;
|
|
2080
|
+
writer.writeData(chunk);
|
|
2081
|
+
}
|
|
2082
|
+
} catch (temp) {
|
|
2083
|
+
error = [temp];
|
|
2084
|
+
} finally {
|
|
2085
|
+
try {
|
|
2086
|
+
more && (temp = iter.return) && (yield temp.call(iter));
|
|
2087
|
+
} finally {
|
|
2088
|
+
if (error)
|
|
2089
|
+
throw error[0];
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2092
|
+
writer.close();
|
|
2093
|
+
} catch (error2) {
|
|
2094
|
+
writer.writeError(error2 instanceof Error ? error2 : new Error(String(error2)));
|
|
2095
|
+
writer.close();
|
|
2096
|
+
}
|
|
2097
|
+
}))();
|
|
2098
|
+
return new Response(writer.readable, {
|
|
2099
|
+
headers: __spreadValues({
|
|
2100
|
+
"Content-Type": "text/event-stream",
|
|
2101
|
+
"Cache-Control": "no-cache",
|
|
2102
|
+
"Connection": "keep-alive"
|
|
2103
|
+
}, headers)
|
|
2104
|
+
});
|
|
2105
|
+
}
|
|
2106
|
+
function parseSSEStream(response) {
|
|
2107
|
+
return __asyncGenerator(this, null, function* () {
|
|
2108
|
+
if (!response.body) {
|
|
2109
|
+
throw new StreamError("Response body is null");
|
|
2110
|
+
}
|
|
2111
|
+
const reader = response.body.getReader();
|
|
2112
|
+
const decoder = new TextDecoder();
|
|
2113
|
+
let buffer = "";
|
|
2114
|
+
try {
|
|
2115
|
+
while (true) {
|
|
2116
|
+
const { done, value } = yield new __await(reader.read());
|
|
2117
|
+
if (done) break;
|
|
2118
|
+
buffer += decoder.decode(value, { stream: true });
|
|
2119
|
+
const lines = buffer.split("\n\n");
|
|
2120
|
+
buffer = lines.pop() || "";
|
|
2121
|
+
for (const line of lines) {
|
|
2122
|
+
if (!line.trim()) continue;
|
|
2123
|
+
const match = line.match(/^data: (.+)$/m);
|
|
2124
|
+
if (match) {
|
|
2125
|
+
try {
|
|
2126
|
+
yield JSON.parse(match[1]);
|
|
2127
|
+
} catch (e) {
|
|
2128
|
+
console.error("Failed to parse SSE data:", e);
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
} finally {
|
|
2134
|
+
reader.releaseLock();
|
|
2135
|
+
}
|
|
2136
|
+
});
|
|
2137
|
+
}
|
|
2138
|
+
function mergeStreams(...streams) {
|
|
2139
|
+
return __asyncGenerator(this, null, function* () {
|
|
2140
|
+
const iterators = streams.map((s) => s[Symbol.asyncIterator]());
|
|
2141
|
+
const pending = new Set(iterators);
|
|
2142
|
+
while (pending.size > 0) {
|
|
2143
|
+
const results = yield new __await(Promise.race(
|
|
2144
|
+
Array.from(pending).map((it) => __async(null, null, function* () {
|
|
2145
|
+
return { it, result: yield it.next() };
|
|
2146
|
+
}))
|
|
2147
|
+
));
|
|
2148
|
+
if (results.result.done) {
|
|
2149
|
+
pending.delete(results.it);
|
|
2150
|
+
} else {
|
|
2151
|
+
yield results.result.value;
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
});
|
|
2155
|
+
}
|
|
2156
|
+
function bufferStream(stream, size) {
|
|
2157
|
+
return __asyncGenerator(this, null, function* () {
|
|
2158
|
+
let buffer = [];
|
|
2159
|
+
try {
|
|
2160
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
2161
|
+
const item = temp.value;
|
|
2162
|
+
buffer.push(item);
|
|
2163
|
+
if (buffer.length >= size) {
|
|
2164
|
+
yield buffer;
|
|
2165
|
+
buffer = [];
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
} catch (temp) {
|
|
2169
|
+
error = [temp];
|
|
2170
|
+
} finally {
|
|
2171
|
+
try {
|
|
2172
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
2173
|
+
} finally {
|
|
2174
|
+
if (error)
|
|
2175
|
+
throw error[0];
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
if (buffer.length > 0) {
|
|
2179
|
+
yield buffer;
|
|
2180
|
+
}
|
|
2181
|
+
});
|
|
2182
|
+
}
|
|
2183
|
+
function throttleStream(stream, delayMs) {
|
|
2184
|
+
return __asyncGenerator(this, null, function* () {
|
|
2185
|
+
try {
|
|
2186
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
2187
|
+
const item = temp.value;
|
|
2188
|
+
yield item;
|
|
2189
|
+
yield new __await(new Promise((resolve) => setTimeout(resolve, delayMs)));
|
|
2190
|
+
}
|
|
2191
|
+
} catch (temp) {
|
|
2192
|
+
error = [temp];
|
|
2193
|
+
} finally {
|
|
2194
|
+
try {
|
|
2195
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
2196
|
+
} finally {
|
|
2197
|
+
if (error)
|
|
2198
|
+
throw error[0];
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2201
|
+
});
|
|
2202
|
+
}
|
|
2203
|
+
|
|
2204
|
+
// src/stream/stream-client.ts
|
|
2205
|
+
var import_eventemitter33 = __toESM(require("eventemitter3"));
|
|
2206
|
+
var DEFAULT_CONFIG4 = {
|
|
2207
|
+
maxTokens: 1024,
|
|
2208
|
+
temperature: 0.7,
|
|
2209
|
+
enableQueueing: true,
|
|
2210
|
+
enablePooling: true,
|
|
2211
|
+
enableMetrics: true,
|
|
2212
|
+
retry: {
|
|
2213
|
+
maxRetries: 3,
|
|
2214
|
+
initialDelay: 1e3,
|
|
2215
|
+
maxDelay: 3e4
|
|
2216
|
+
},
|
|
2217
|
+
circuitBreaker: {
|
|
2218
|
+
failureThreshold: 5,
|
|
2219
|
+
resetTimeout: 6e4
|
|
2220
|
+
},
|
|
2221
|
+
rateLimit: {
|
|
2222
|
+
maxRequests: 100,
|
|
2223
|
+
windowMs: 6e4
|
|
2224
|
+
}
|
|
2225
|
+
};
|
|
2226
|
+
var FlareClient = class extends import_eventemitter33.default {
|
|
2227
|
+
constructor(config) {
|
|
2228
|
+
super();
|
|
2229
|
+
__publicField(this, "config");
|
|
2230
|
+
__publicField(this, "provider");
|
|
2231
|
+
__publicField(this, "retryHandler");
|
|
2232
|
+
__publicField(this, "circuitBreaker");
|
|
2233
|
+
__publicField(this, "rateLimiter");
|
|
2234
|
+
__publicField(this, "requestQueue");
|
|
2235
|
+
__publicField(this, "metrics");
|
|
2236
|
+
__publicField(this, "startTime", Date.now());
|
|
2237
|
+
this.config = __spreadValues(__spreadValues({}, DEFAULT_CONFIG4), config);
|
|
2238
|
+
this.provider = createProvider(this.config);
|
|
2239
|
+
this.retryHandler = new RetryHandler(this.config.retry);
|
|
2240
|
+
this.circuitBreaker = new CircuitBreaker(this.config.circuitBreaker);
|
|
2241
|
+
this.rateLimiter = new RateLimiter(this.config.rateLimit);
|
|
2242
|
+
this.metrics = new MetricsCollector();
|
|
2243
|
+
if (this.config.enableQueueing) {
|
|
2244
|
+
this.requestQueue = new RequestQueue({
|
|
2245
|
+
concurrency: this.config.poolSize || 10
|
|
2246
|
+
});
|
|
2247
|
+
}
|
|
2248
|
+
this.setupEventListeners();
|
|
2249
|
+
}
|
|
2250
|
+
/**
|
|
2251
|
+
* Setup event listeners for monitoring
|
|
2252
|
+
*/
|
|
2253
|
+
setupEventListeners() {
|
|
2254
|
+
this.circuitBreaker.on("open", () => {
|
|
2255
|
+
this.emit("circuit-breaker:open");
|
|
2256
|
+
if (this.config.debug) {
|
|
2257
|
+
console.warn("[FlareClient] Circuit breaker opened");
|
|
2258
|
+
}
|
|
2259
|
+
});
|
|
2260
|
+
this.circuitBreaker.on("close", () => {
|
|
2261
|
+
this.emit("circuit-breaker:close");
|
|
2262
|
+
if (this.config.debug) {
|
|
2263
|
+
console.log("[FlareClient] Circuit breaker closed");
|
|
2264
|
+
}
|
|
2265
|
+
});
|
|
2266
|
+
if (this.requestQueue) {
|
|
2267
|
+
this.requestQueue.on("enqueue", (data) => {
|
|
2268
|
+
this.emit("queue:enqueue", data);
|
|
2269
|
+
});
|
|
2270
|
+
this.requestQueue.on("drain", () => {
|
|
2271
|
+
this.emit("queue:drain");
|
|
2272
|
+
});
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
/**
|
|
2276
|
+
* Generate text synchronously
|
|
2277
|
+
* @param request - Text generation request
|
|
2278
|
+
* @returns Generated text response
|
|
2279
|
+
*/
|
|
2280
|
+
generateText(request) {
|
|
2281
|
+
return __async(this, null, function* () {
|
|
2282
|
+
var _a, _b;
|
|
2283
|
+
const startTime = Date.now();
|
|
2284
|
+
try {
|
|
2285
|
+
yield this.rateLimiter.acquire((_a = this.config.rateLimit) == null ? void 0 : _a.clientId);
|
|
2286
|
+
const execute = () => __async(this, null, function* () {
|
|
2287
|
+
return yield this.circuitBreaker.execute(() => __async(this, null, function* () {
|
|
2288
|
+
const mergedConfig = __spreadValues(__spreadValues({}, this.config), request.config);
|
|
2289
|
+
return yield this.provider.generateText(__spreadProps(__spreadValues({}, request), {
|
|
2290
|
+
config: mergedConfig
|
|
2291
|
+
}));
|
|
2292
|
+
}));
|
|
2293
|
+
});
|
|
2294
|
+
let result;
|
|
2295
|
+
if (this.requestQueue && this.config.enableQueueing) {
|
|
2296
|
+
result = yield this.requestQueue.add(
|
|
2297
|
+
() => this.retryHandler.execute(execute),
|
|
2298
|
+
((_b = request.config) == null ? void 0 : _b.queuePriority) || 0
|
|
2299
|
+
);
|
|
2300
|
+
} else {
|
|
2301
|
+
result = yield this.retryHandler.execute(execute);
|
|
2302
|
+
}
|
|
2303
|
+
this.metrics.recordSuccess(Date.now() - startTime);
|
|
2304
|
+
this.emit("request:success", { latency: Date.now() - startTime });
|
|
2305
|
+
return result;
|
|
2306
|
+
} catch (error) {
|
|
2307
|
+
this.metrics.recordFailure(Date.now() - startTime);
|
|
2308
|
+
this.emit("request:error", { error, latency: Date.now() - startTime });
|
|
2309
|
+
throw error;
|
|
2310
|
+
}
|
|
2311
|
+
});
|
|
2312
|
+
}
|
|
2313
|
+
/**
|
|
2314
|
+
* Stream text generation
|
|
2315
|
+
* @param request - Text generation request
|
|
2316
|
+
* @returns Async iterable of text chunks
|
|
2317
|
+
*/
|
|
2318
|
+
streamText(request) {
|
|
2319
|
+
return __asyncGenerator(this, null, function* () {
|
|
2320
|
+
var _a;
|
|
2321
|
+
const startTime = Date.now();
|
|
2322
|
+
try {
|
|
2323
|
+
yield new __await(this.rateLimiter.acquire((_a = this.config.rateLimit) == null ? void 0 : _a.clientId));
|
|
2324
|
+
const stream = this.provider.streamText(request);
|
|
2325
|
+
try {
|
|
2326
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
2327
|
+
const chunk = temp.value;
|
|
2328
|
+
yield chunk;
|
|
2329
|
+
}
|
|
2330
|
+
} catch (temp) {
|
|
2331
|
+
error = [temp];
|
|
2332
|
+
} finally {
|
|
2333
|
+
try {
|
|
2334
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
2335
|
+
} finally {
|
|
2336
|
+
if (error)
|
|
2337
|
+
throw error[0];
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
this.metrics.recordSuccess(Date.now() - startTime);
|
|
2341
|
+
this.emit("request:success", { latency: Date.now() - startTime, streaming: true });
|
|
2342
|
+
} catch (error2) {
|
|
2343
|
+
this.metrics.recordFailure(Date.now() - startTime);
|
|
2344
|
+
this.emit("request:error", { error: error2, latency: Date.now() - startTime, streaming: true });
|
|
2345
|
+
throw error2;
|
|
2346
|
+
}
|
|
2347
|
+
});
|
|
2348
|
+
}
|
|
2349
|
+
/**
|
|
2350
|
+
* Generate structured object
|
|
2351
|
+
* @param request - Object generation request
|
|
2352
|
+
* @returns Generated object response
|
|
2353
|
+
*/
|
|
2354
|
+
generateObject(request) {
|
|
2355
|
+
return __async(this, null, function* () {
|
|
2356
|
+
var _a, _b;
|
|
2357
|
+
const startTime = Date.now();
|
|
2358
|
+
try {
|
|
2359
|
+
yield this.rateLimiter.acquire((_a = this.config.rateLimit) == null ? void 0 : _a.clientId);
|
|
2360
|
+
const execute = () => __async(this, null, function* () {
|
|
2361
|
+
return yield this.circuitBreaker.execute(() => __async(this, null, function* () {
|
|
2362
|
+
return yield this.provider.generateObject(request);
|
|
2363
|
+
}));
|
|
2364
|
+
});
|
|
2365
|
+
let result;
|
|
2366
|
+
if (this.requestQueue && this.config.enableQueueing) {
|
|
2367
|
+
result = yield this.requestQueue.add(
|
|
2368
|
+
() => this.retryHandler.execute(execute),
|
|
2369
|
+
((_b = request.config) == null ? void 0 : _b.queuePriority) || 0
|
|
2370
|
+
);
|
|
2371
|
+
} else {
|
|
2372
|
+
result = yield this.retryHandler.execute(execute);
|
|
2373
|
+
}
|
|
2374
|
+
this.metrics.recordSuccess(Date.now() - startTime);
|
|
2375
|
+
return result;
|
|
2376
|
+
} catch (error) {
|
|
2377
|
+
this.metrics.recordFailure(Date.now() - startTime);
|
|
2378
|
+
throw error;
|
|
2379
|
+
}
|
|
2380
|
+
});
|
|
2381
|
+
}
|
|
2382
|
+
/**
|
|
2383
|
+
* Stream object generation
|
|
2384
|
+
* @param request - Object generation request
|
|
2385
|
+
* @returns Async iterable of object chunks
|
|
2386
|
+
*/
|
|
2387
|
+
streamObject(request) {
|
|
2388
|
+
return __asyncGenerator(this, null, function* () {
|
|
2389
|
+
var _a;
|
|
2390
|
+
const startTime = Date.now();
|
|
2391
|
+
try {
|
|
2392
|
+
yield new __await(this.rateLimiter.acquire((_a = this.config.rateLimit) == null ? void 0 : _a.clientId));
|
|
2393
|
+
const stream = this.provider.streamObject(request);
|
|
2394
|
+
try {
|
|
2395
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
2396
|
+
const chunk = temp.value;
|
|
2397
|
+
yield chunk;
|
|
2398
|
+
}
|
|
2399
|
+
} catch (temp) {
|
|
2400
|
+
error = [temp];
|
|
2401
|
+
} finally {
|
|
2402
|
+
try {
|
|
2403
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
2404
|
+
} finally {
|
|
2405
|
+
if (error)
|
|
2406
|
+
throw error[0];
|
|
2407
|
+
}
|
|
2408
|
+
}
|
|
2409
|
+
this.metrics.recordSuccess(Date.now() - startTime);
|
|
2410
|
+
} catch (error2) {
|
|
2411
|
+
this.metrics.recordFailure(Date.now() - startTime);
|
|
2412
|
+
throw error2;
|
|
2413
|
+
}
|
|
2414
|
+
});
|
|
2415
|
+
}
|
|
2416
|
+
/**
|
|
2417
|
+
* Get health status
|
|
2418
|
+
*/
|
|
2419
|
+
getHealth() {
|
|
2420
|
+
var _a, _b;
|
|
2421
|
+
const metrics = this.metrics.getMetrics();
|
|
2422
|
+
let status = "healthy";
|
|
2423
|
+
if (this.circuitBreaker.getState() === "open") {
|
|
2424
|
+
status = "unhealthy";
|
|
2425
|
+
} else if (metrics.failedRequests > metrics.successfulRequests * 0.1) {
|
|
2426
|
+
status = "degraded";
|
|
2427
|
+
}
|
|
2428
|
+
return {
|
|
2429
|
+
status,
|
|
2430
|
+
timestamp: Date.now(),
|
|
2431
|
+
uptime: Date.now() - this.startTime,
|
|
2432
|
+
circuitBreaker: this.circuitBreaker.getState(),
|
|
2433
|
+
activeConnections: (_a = this.requestQueue) == null ? void 0 : _a.getRunning(),
|
|
2434
|
+
queueSize: (_b = this.requestQueue) == null ? void 0 : _b.size(),
|
|
2435
|
+
metrics
|
|
2436
|
+
};
|
|
2437
|
+
}
|
|
2438
|
+
/**
|
|
2439
|
+
* Get performance metrics
|
|
2440
|
+
*/
|
|
2441
|
+
getMetrics() {
|
|
2442
|
+
return this.metrics.getDetailedStats();
|
|
2443
|
+
}
|
|
2444
|
+
/**
|
|
2445
|
+
* Update configuration
|
|
2446
|
+
*/
|
|
2447
|
+
updateConfig(config) {
|
|
2448
|
+
this.config = __spreadValues(__spreadValues({}, this.config), config);
|
|
2449
|
+
if (config.retry) {
|
|
2450
|
+
this.retryHandler.updateConfig(config.retry);
|
|
2451
|
+
}
|
|
2452
|
+
if (config.rateLimit) {
|
|
2453
|
+
this.rateLimiter = new RateLimiter(config.rateLimit);
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
/**
|
|
2457
|
+
* Reset circuit breaker
|
|
2458
|
+
*/
|
|
2459
|
+
resetCircuitBreaker() {
|
|
2460
|
+
this.circuitBreaker.reset();
|
|
2461
|
+
}
|
|
2462
|
+
/**
|
|
2463
|
+
* Clean up resources
|
|
2464
|
+
*/
|
|
2465
|
+
destroy() {
|
|
2466
|
+
this.circuitBreaker.destroy();
|
|
2467
|
+
this.rateLimiter.destroy();
|
|
2468
|
+
if (this.requestQueue) {
|
|
2469
|
+
this.requestQueue.clear();
|
|
2470
|
+
}
|
|
2471
|
+
this.removeAllListeners();
|
|
2472
|
+
}
|
|
2473
|
+
};
|
|
2474
|
+
function createFlareClient(config) {
|
|
2475
|
+
return new FlareClient(config);
|
|
2476
|
+
}
|
|
2477
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
2478
|
+
0 && (module.exports = {
|
|
2479
|
+
AnthropicProvider,
|
|
2480
|
+
AuthenticationError,
|
|
2481
|
+
BaseProvider,
|
|
2482
|
+
CircuitBreaker,
|
|
2483
|
+
CircuitBreakerError,
|
|
2484
|
+
CircuitState,
|
|
2485
|
+
ContentFilterError,
|
|
2486
|
+
CustomProvider,
|
|
2487
|
+
FlareClient,
|
|
2488
|
+
FlareError,
|
|
2489
|
+
FlareStreamReader,
|
|
2490
|
+
GoogleProvider,
|
|
2491
|
+
MetricsCollector,
|
|
2492
|
+
NetworkError,
|
|
2493
|
+
OpenAIProvider,
|
|
2494
|
+
ParseError,
|
|
2495
|
+
ProviderError,
|
|
2496
|
+
RateLimitError,
|
|
2497
|
+
RateLimiter,
|
|
2498
|
+
RequestQueue,
|
|
2499
|
+
RetryHandler,
|
|
2500
|
+
SarvamProvider,
|
|
2501
|
+
StreamError,
|
|
2502
|
+
TimeoutError,
|
|
2503
|
+
TransformStream,
|
|
2504
|
+
ValidationError,
|
|
2505
|
+
bufferStream,
|
|
2506
|
+
createCircuitBreaker,
|
|
2507
|
+
createDataStreamWriter,
|
|
2508
|
+
createFlareClient,
|
|
2509
|
+
createMetricsCollector,
|
|
2510
|
+
createProvider,
|
|
2511
|
+
createRateLimiter,
|
|
2512
|
+
createRequestQueue,
|
|
2513
|
+
createRetryHandler,
|
|
2514
|
+
getErrorStatusCode,
|
|
2515
|
+
getGlobalMetrics,
|
|
2516
|
+
isRetryableError,
|
|
2517
|
+
measureLatency,
|
|
2518
|
+
mergeStreams,
|
|
2519
|
+
parseSSEStream,
|
|
2520
|
+
throttleStream,
|
|
2521
|
+
toUiStreamResponse,
|
|
2522
|
+
withRetry
|
|
2523
|
+
});
|
|
2524
|
+
//# sourceMappingURL=index.js.map
|