@ax-llm/ax 10.0.42 → 10.0.44
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/index.cjs +547 -189
- package/index.cjs.map +1 -1
- package/index.d.cts +77 -5
- package/index.d.ts +77 -5
- package/index.js +549 -197
- package/index.js.map +1 -1
- package/package.json +2 -3
package/index.js
CHANGED
|
@@ -76,22 +76,29 @@ var AxSpanKindValues = /* @__PURE__ */ ((AxSpanKindValues2) => {
|
|
|
76
76
|
// util/apicall.ts
|
|
77
77
|
import path from "path";
|
|
78
78
|
import {
|
|
79
|
+
ReadableStream,
|
|
79
80
|
TextDecoderStream as TextDecoderStreamNative
|
|
80
81
|
} from "stream/web";
|
|
81
82
|
import "@opentelemetry/api";
|
|
82
83
|
|
|
83
84
|
// util/sse.ts
|
|
84
|
-
import { TransformStream } from "stream/web";
|
|
85
|
-
var SSEParser = class extends
|
|
86
|
-
|
|
85
|
+
import { TransformStream as TransformStream2 } from "stream/web";
|
|
86
|
+
var SSEParser = class extends TransformStream2 {
|
|
87
|
+
buffer = "";
|
|
88
|
+
currentEvent = { rawData: "" };
|
|
89
|
+
dataParser;
|
|
90
|
+
onError;
|
|
91
|
+
constructor(options = {}) {
|
|
87
92
|
super({
|
|
88
93
|
transform: (chunk, controller) => this.handleChunk(chunk, controller),
|
|
89
94
|
flush: (controller) => this.handleFlush(controller)
|
|
90
95
|
});
|
|
91
|
-
this.dataParser = dataParser;
|
|
96
|
+
this.dataParser = options.dataParser || JSON.parse;
|
|
97
|
+
this.onError = options.onError || ((error, rawData) => {
|
|
98
|
+
console.warn("Failed to parse event data:", error);
|
|
99
|
+
console.log("Raw data that failed to parse:", rawData);
|
|
100
|
+
});
|
|
92
101
|
}
|
|
93
|
-
buffer = "";
|
|
94
|
-
currentEvent = { rawData: "" };
|
|
95
102
|
handleChunk(chunk, controller) {
|
|
96
103
|
this.buffer += chunk;
|
|
97
104
|
this.processBuffer(controller);
|
|
@@ -99,24 +106,28 @@ var SSEParser = class extends TransformStream {
|
|
|
99
106
|
handleFlush(controller) {
|
|
100
107
|
this.processBuffer(controller);
|
|
101
108
|
if (this.currentEvent.rawData) {
|
|
102
|
-
this.
|
|
109
|
+
this.processEvent(controller);
|
|
103
110
|
}
|
|
104
111
|
}
|
|
105
112
|
processBuffer(controller) {
|
|
106
|
-
const
|
|
113
|
+
const normalizedBuffer = this.buffer.replace(/\r\n|\r/g, "\n");
|
|
114
|
+
const lines = normalizedBuffer.split("\n");
|
|
107
115
|
this.buffer = lines.pop() || "";
|
|
108
116
|
for (const line of lines) {
|
|
109
|
-
if (line
|
|
110
|
-
this.
|
|
117
|
+
if (line === "") {
|
|
118
|
+
this.processEvent(controller);
|
|
111
119
|
} else {
|
|
112
120
|
this.parseLine(line);
|
|
113
121
|
}
|
|
114
122
|
}
|
|
115
123
|
}
|
|
116
124
|
parseLine(line) {
|
|
125
|
+
if (line.startsWith(":")) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
117
128
|
const colonIndex = line.indexOf(":");
|
|
118
129
|
if (colonIndex === -1) {
|
|
119
|
-
this.currentEvent.rawData += this.currentEvent.rawData ? "\n"
|
|
130
|
+
this.currentEvent.rawData += (this.currentEvent.rawData && !this.currentEvent.rawData.endsWith("\n") ? "\n" : "") + line.trim();
|
|
120
131
|
return;
|
|
121
132
|
}
|
|
122
133
|
const field = line.slice(0, colonIndex).trim();
|
|
@@ -126,7 +137,7 @@ var SSEParser = class extends TransformStream {
|
|
|
126
137
|
this.currentEvent.event = value;
|
|
127
138
|
break;
|
|
128
139
|
case "data":
|
|
129
|
-
this.currentEvent.rawData += this.currentEvent.rawData
|
|
140
|
+
this.currentEvent.rawData += (this.currentEvent.rawData && !this.currentEvent.rawData.endsWith("\n") ? "\n" : "") + value;
|
|
130
141
|
break;
|
|
131
142
|
case "id":
|
|
132
143
|
this.currentEvent.id = value;
|
|
@@ -140,21 +151,20 @@ var SSEParser = class extends TransformStream {
|
|
|
140
151
|
}
|
|
141
152
|
}
|
|
142
153
|
}
|
|
143
|
-
|
|
154
|
+
processEvent(controller) {
|
|
144
155
|
if (this.currentEvent.rawData) {
|
|
145
|
-
if (this.currentEvent.
|
|
156
|
+
if (!this.currentEvent.event) {
|
|
157
|
+
this.currentEvent.event = "message";
|
|
158
|
+
}
|
|
159
|
+
if (this.currentEvent.rawData.trim() === "[DONE]") {
|
|
160
|
+
this.currentEvent = { rawData: "" };
|
|
146
161
|
return;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
console.log(
|
|
154
|
-
"Raw data that failed to parse:",
|
|
155
|
-
this.currentEvent.rawData
|
|
156
|
-
);
|
|
157
|
-
}
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
const parsedData = this.dataParser(this.currentEvent.rawData);
|
|
165
|
+
controller.enqueue(parsedData);
|
|
166
|
+
} catch (e) {
|
|
167
|
+
this.onError(e, this.currentEvent.rawData);
|
|
158
168
|
}
|
|
159
169
|
this.currentEvent = { rawData: "" };
|
|
160
170
|
}
|
|
@@ -163,7 +173,7 @@ var SSEParser = class extends TransformStream {
|
|
|
163
173
|
|
|
164
174
|
// util/stream.ts
|
|
165
175
|
import {
|
|
166
|
-
TransformStream as
|
|
176
|
+
TransformStream as TransformStream3
|
|
167
177
|
} from "stream/web";
|
|
168
178
|
var TextDecodeTransformer = class {
|
|
169
179
|
decoder;
|
|
@@ -186,59 +196,312 @@ var TextDecodeTransformer = class {
|
|
|
186
196
|
}
|
|
187
197
|
}
|
|
188
198
|
};
|
|
189
|
-
var TextDecoderStreamPolyfill = class extends
|
|
199
|
+
var TextDecoderStreamPolyfill = class extends TransformStream3 {
|
|
190
200
|
constructor() {
|
|
191
201
|
super(new TextDecodeTransformer());
|
|
192
202
|
}
|
|
193
203
|
};
|
|
194
204
|
|
|
195
205
|
// util/apicall.ts
|
|
206
|
+
var defaultRetryConfig = {
|
|
207
|
+
maxRetries: 3,
|
|
208
|
+
initialDelayMs: 1e3,
|
|
209
|
+
maxDelayMs: 6e4,
|
|
210
|
+
// Increased to 60 seconds
|
|
211
|
+
backoffFactor: 2,
|
|
212
|
+
retryableStatusCodes: [500, 408, 429, 502, 503, 504]
|
|
213
|
+
};
|
|
214
|
+
var defaultTimeoutMs = 3e4;
|
|
196
215
|
var textDecoderStream = TextDecoderStreamNative ?? TextDecoderStreamPolyfill;
|
|
216
|
+
var AxAIServiceError = class extends Error {
|
|
217
|
+
constructor(message, url, requestBody, context = {}) {
|
|
218
|
+
super(message);
|
|
219
|
+
this.url = url;
|
|
220
|
+
this.requestBody = requestBody;
|
|
221
|
+
this.context = context;
|
|
222
|
+
this.name = "AxAIServiceError";
|
|
223
|
+
this.timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
224
|
+
this.errorId = crypto.randomUUID();
|
|
225
|
+
}
|
|
226
|
+
timestamp;
|
|
227
|
+
errorId;
|
|
228
|
+
toString() {
|
|
229
|
+
return `${this.name} [${this.errorId}]: ${this.message}
|
|
230
|
+
Timestamp: ${this.timestamp}
|
|
231
|
+
URL: ${this.url}${this.requestBody ? `
|
|
232
|
+
Request Body: ${JSON.stringify(this.requestBody, null, 2)}` : ""}${this.context ? `
|
|
233
|
+
Context: ${JSON.stringify(this.context, null, 2)}` : ""}`;
|
|
234
|
+
}
|
|
235
|
+
toJSON() {
|
|
236
|
+
return {
|
|
237
|
+
name: this.name,
|
|
238
|
+
errorId: this.errorId,
|
|
239
|
+
message: this.message,
|
|
240
|
+
timestamp: this.timestamp,
|
|
241
|
+
url: this.url,
|
|
242
|
+
requestBody: this.requestBody,
|
|
243
|
+
context: this.context,
|
|
244
|
+
stack: this.stack
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
var AxAIServiceStatusError = class extends AxAIServiceError {
|
|
249
|
+
constructor(status, statusText, url, requestBody, context) {
|
|
250
|
+
super(`HTTP ${status} - ${statusText}`, url, requestBody, {
|
|
251
|
+
httpStatus: status,
|
|
252
|
+
httpStatusText: statusText,
|
|
253
|
+
...context
|
|
254
|
+
});
|
|
255
|
+
this.status = status;
|
|
256
|
+
this.statusText = statusText;
|
|
257
|
+
this.name = "AxAIServiceStatusError";
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
var AxAIServiceNetworkError = class extends AxAIServiceError {
|
|
261
|
+
constructor(originalError, url, requestBody, context) {
|
|
262
|
+
super(`Network Error: ${originalError.message}`, url, requestBody, {
|
|
263
|
+
originalErrorName: originalError.name,
|
|
264
|
+
originalErrorStack: originalError.stack,
|
|
265
|
+
...context
|
|
266
|
+
});
|
|
267
|
+
this.originalError = originalError;
|
|
268
|
+
this.name = "AxAIServiceNetworkError";
|
|
269
|
+
this.stack = originalError.stack;
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
var AxAIServiceResponseError = class extends AxAIServiceError {
|
|
273
|
+
constructor(message, url, requestBody, context) {
|
|
274
|
+
super(message, url, requestBody, context);
|
|
275
|
+
this.name = "AxAIServiceResponseError";
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
var AxAIServiceStreamTerminatedError = class extends AxAIServiceError {
|
|
279
|
+
constructor(url, requestBody, lastChunk, context) {
|
|
280
|
+
super("Stream terminated unexpectedly by remote host", url, requestBody, {
|
|
281
|
+
lastChunk,
|
|
282
|
+
...context
|
|
283
|
+
});
|
|
284
|
+
this.lastChunk = lastChunk;
|
|
285
|
+
this.name = "AxAIServiceStreamTerminatedError";
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
var AxAIServiceTimeoutError = class extends AxAIServiceError {
|
|
289
|
+
constructor(url, timeoutMs, requestBody, context) {
|
|
290
|
+
super(`Request timeout after ${timeoutMs}ms`, url, requestBody, {
|
|
291
|
+
timeoutMs,
|
|
292
|
+
...context
|
|
293
|
+
});
|
|
294
|
+
this.name = "AxAIServiceTimeoutError";
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
var AxAIServiceAuthenticationError = class extends AxAIServiceError {
|
|
298
|
+
constructor(url, requestBody, context) {
|
|
299
|
+
super("Authentication failed", url, requestBody, context);
|
|
300
|
+
this.name = "AxAIServiceAuthenticationError";
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
function calculateRetryDelay(attempt, config) {
|
|
304
|
+
const delay = Math.min(
|
|
305
|
+
config.maxDelayMs,
|
|
306
|
+
config.initialDelayMs * Math.pow(config.backoffFactor, attempt)
|
|
307
|
+
);
|
|
308
|
+
return delay * (0.75 + Math.random() * 0.5);
|
|
309
|
+
}
|
|
310
|
+
function createRequestMetrics() {
|
|
311
|
+
return {
|
|
312
|
+
startTime: Date.now(),
|
|
313
|
+
retryCount: 0
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
function updateRetryMetrics(metrics) {
|
|
317
|
+
metrics.retryCount++;
|
|
318
|
+
metrics.lastRetryTime = Date.now();
|
|
319
|
+
}
|
|
197
320
|
var apiCall = async (api, json) => {
|
|
321
|
+
const retryConfig = { ...defaultRetryConfig, ...api.retry };
|
|
322
|
+
const timeoutMs = api.timeout ?? defaultTimeoutMs;
|
|
323
|
+
const metrics = createRequestMetrics();
|
|
198
324
|
const baseUrl = new URL(process.env["PROXY"] ?? api.url);
|
|
199
325
|
const apiPath = path.join(baseUrl.pathname, api.name ?? "/", baseUrl.search);
|
|
200
326
|
const apiUrl = new URL(apiPath, baseUrl);
|
|
327
|
+
const requestId = crypto.randomUUID();
|
|
201
328
|
if (api.span?.isRecording()) {
|
|
202
329
|
api.span.setAttributes({
|
|
203
330
|
"http.request.method": api.put ? "PUT" : "POST",
|
|
204
|
-
"url.full": apiUrl.href
|
|
331
|
+
"url.full": apiUrl.href,
|
|
332
|
+
"request.id": requestId,
|
|
333
|
+
"request.startTime": metrics.startTime
|
|
205
334
|
});
|
|
206
335
|
}
|
|
207
|
-
let
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
336
|
+
let attempt = 0;
|
|
337
|
+
while (true) {
|
|
338
|
+
const controller = new AbortController();
|
|
339
|
+
let timeoutId = setTimeout(() => {
|
|
340
|
+
controller.abort("Request timeout");
|
|
341
|
+
}, timeoutMs);
|
|
342
|
+
try {
|
|
343
|
+
const res = await (api.fetch ?? fetch)(apiUrl, {
|
|
344
|
+
method: api.put ? "PUT" : "POST",
|
|
345
|
+
headers: {
|
|
346
|
+
"Content-Type": "application/json",
|
|
347
|
+
"X-Request-ID": requestId,
|
|
348
|
+
"X-Retry-Count": attempt.toString(),
|
|
349
|
+
...api.headers
|
|
350
|
+
},
|
|
351
|
+
body: JSON.stringify(json),
|
|
352
|
+
signal: controller.signal
|
|
353
|
+
});
|
|
354
|
+
clearTimeout(timeoutId);
|
|
355
|
+
if (res.status === 401 || res.status === 403) {
|
|
356
|
+
throw new AxAIServiceAuthenticationError(apiUrl.href, json, { metrics });
|
|
357
|
+
}
|
|
358
|
+
if (res.status >= 400 && attempt < retryConfig.maxRetries && retryConfig.retryableStatusCodes.includes(res.status)) {
|
|
359
|
+
const delay = calculateRetryDelay(attempt, retryConfig);
|
|
360
|
+
attempt++;
|
|
361
|
+
updateRetryMetrics(metrics);
|
|
362
|
+
if (api.span?.isRecording()) {
|
|
363
|
+
api.span.addEvent("retry", {
|
|
364
|
+
attempt,
|
|
365
|
+
delay,
|
|
366
|
+
status: res.status,
|
|
367
|
+
"metrics.startTime": metrics.startTime,
|
|
368
|
+
"metrics.retryCount": metrics.retryCount,
|
|
369
|
+
"metrics.lastRetryTime": metrics.lastRetryTime
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
clearTimeout(timeoutId);
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
if (res.status >= 400) {
|
|
376
|
+
throw new AxAIServiceStatusError(
|
|
377
|
+
res.status,
|
|
378
|
+
res.statusText,
|
|
379
|
+
apiUrl.href,
|
|
380
|
+
json,
|
|
381
|
+
{ metrics }
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
if (!api.stream) {
|
|
385
|
+
const resJson = await res.json();
|
|
386
|
+
if (api.span?.isRecording()) {
|
|
387
|
+
api.span.setAttributes({
|
|
388
|
+
"response.time": Date.now() - metrics.startTime,
|
|
389
|
+
"response.retries": metrics.retryCount
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
return resJson;
|
|
393
|
+
}
|
|
394
|
+
if (!res.body) {
|
|
395
|
+
throw new AxAIServiceResponseError(
|
|
396
|
+
"Response body is null",
|
|
397
|
+
apiUrl.href,
|
|
398
|
+
json,
|
|
399
|
+
{ metrics }
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
let lastChunk;
|
|
403
|
+
let chunkCount = 0;
|
|
404
|
+
const trackingStream = new TransformStream({
|
|
405
|
+
transform(chunk, controller2) {
|
|
406
|
+
lastChunk = chunk;
|
|
407
|
+
chunkCount++;
|
|
408
|
+
metrics.streamChunks = chunkCount;
|
|
409
|
+
metrics.lastChunkTime = Date.now();
|
|
410
|
+
controller2.enqueue(chunk);
|
|
411
|
+
},
|
|
412
|
+
flush(controller2) {
|
|
413
|
+
if (api.span?.isRecording()) {
|
|
414
|
+
api.span.setAttributes({
|
|
415
|
+
"stream.chunks": chunkCount,
|
|
416
|
+
"stream.duration": Date.now() - metrics.startTime,
|
|
417
|
+
"response.retries": metrics.retryCount
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
controller2.terminate();
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
const wrappedStream = new ReadableStream({
|
|
424
|
+
start(controller2) {
|
|
425
|
+
const reader = res.body.pipeThrough(new textDecoderStream()).pipeThrough(new SSEParser()).pipeThrough(trackingStream).getReader();
|
|
426
|
+
async function read() {
|
|
427
|
+
try {
|
|
428
|
+
while (true) {
|
|
429
|
+
const { done, value } = await reader.read();
|
|
430
|
+
if (done) {
|
|
431
|
+
controller2.close();
|
|
432
|
+
break;
|
|
433
|
+
} else {
|
|
434
|
+
controller2.enqueue(value);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
} catch (e) {
|
|
438
|
+
const error = e;
|
|
439
|
+
const streamMetrics = {
|
|
440
|
+
...metrics,
|
|
441
|
+
streamDuration: Date.now() - metrics.startTime
|
|
442
|
+
};
|
|
443
|
+
if (error.name === "AbortError" || error.message?.includes("aborted")) {
|
|
444
|
+
controller2.error(
|
|
445
|
+
new AxAIServiceStreamTerminatedError(
|
|
446
|
+
apiUrl.href,
|
|
447
|
+
json,
|
|
448
|
+
lastChunk,
|
|
449
|
+
{ streamMetrics }
|
|
450
|
+
)
|
|
451
|
+
);
|
|
452
|
+
} else {
|
|
453
|
+
controller2.error(
|
|
454
|
+
new AxAIServiceResponseError(
|
|
455
|
+
`Stream processing error: ${error.message}`,
|
|
456
|
+
apiUrl.href,
|
|
457
|
+
json,
|
|
458
|
+
{ streamMetrics }
|
|
459
|
+
)
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
} finally {
|
|
463
|
+
reader.releaseLock();
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
read();
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
return wrappedStream;
|
|
470
|
+
} catch (error) {
|
|
471
|
+
clearTimeout(timeoutId);
|
|
472
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
473
|
+
throw new AxAIServiceTimeoutError(apiUrl.href, timeoutMs, json, {
|
|
474
|
+
metrics
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
if (api.span?.isRecording()) {
|
|
478
|
+
api.span.recordException(error);
|
|
479
|
+
api.span.setAttributes({
|
|
480
|
+
"error.time": Date.now() - metrics.startTime,
|
|
481
|
+
"error.retries": metrics.retryCount
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
if (error instanceof AxAIServiceNetworkError && attempt < retryConfig.maxRetries) {
|
|
485
|
+
const delay = calculateRetryDelay(attempt, retryConfig);
|
|
486
|
+
attempt++;
|
|
487
|
+
updateRetryMetrics(metrics);
|
|
488
|
+
if (api.span?.isRecording()) {
|
|
489
|
+
api.span.addEvent("retry", {
|
|
490
|
+
attempt,
|
|
491
|
+
delay,
|
|
492
|
+
error: error.message,
|
|
493
|
+
"metrics.startTime": metrics.startTime,
|
|
494
|
+
"metrics.retryCount": metrics.retryCount,
|
|
495
|
+
"metrics.lastRetryTime": metrics.lastRetryTime
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
continue;
|
|
499
|
+
}
|
|
500
|
+
if (error instanceof AxAIServiceError) {
|
|
501
|
+
error.context["metrics"] = metrics;
|
|
502
|
+
}
|
|
503
|
+
throw error;
|
|
236
504
|
}
|
|
237
|
-
const reqBody = JSON.stringify(json, null, 2);
|
|
238
|
-
throw new Error(
|
|
239
|
-
`API Response Error: ${apiUrl.href}, ${e}
|
|
240
|
-
Request Body: ${reqBody}`
|
|
241
|
-
);
|
|
242
505
|
}
|
|
243
506
|
};
|
|
244
507
|
|
|
@@ -275,7 +538,7 @@ var ColorLog = class {
|
|
|
275
538
|
|
|
276
539
|
// util/transform.ts
|
|
277
540
|
import {
|
|
278
|
-
TransformStream as
|
|
541
|
+
TransformStream as TransformStream4
|
|
279
542
|
} from "stream/web";
|
|
280
543
|
var TypeTransformer = class {
|
|
281
544
|
buffer;
|
|
@@ -298,7 +561,7 @@ var TypeTransformer = class {
|
|
|
298
561
|
controller.terminate();
|
|
299
562
|
}
|
|
300
563
|
};
|
|
301
|
-
var RespTransformStream = class extends
|
|
564
|
+
var RespTransformStream = class extends TransformStream4 {
|
|
302
565
|
constructor(transformFn, doneCallback) {
|
|
303
566
|
super(new TypeTransformer(transformFn, doneCallback));
|
|
304
567
|
}
|
|
@@ -3261,7 +3524,7 @@ var AxAI = class {
|
|
|
3261
3524
|
};
|
|
3262
3525
|
|
|
3263
3526
|
// dsp/generate.ts
|
|
3264
|
-
import { ReadableStream } from "stream/web";
|
|
3527
|
+
import { ReadableStream as ReadableStream2 } from "stream/web";
|
|
3265
3528
|
import { SpanKind as SpanKind2 } from "@opentelemetry/api";
|
|
3266
3529
|
|
|
3267
3530
|
// ai/util.ts
|
|
@@ -3488,9 +3751,6 @@ var assertStreamingAssertions = (asserts, values, xstate, content, final) => {
|
|
|
3488
3751
|
}
|
|
3489
3752
|
};
|
|
3490
3753
|
|
|
3491
|
-
// dsp/extract.ts
|
|
3492
|
-
import JSON5 from "json5";
|
|
3493
|
-
|
|
3494
3754
|
// dsp/datetime.ts
|
|
3495
3755
|
import moment from "moment-timezone";
|
|
3496
3756
|
|
|
@@ -3521,104 +3781,143 @@ import { createHash } from "crypto";
|
|
|
3521
3781
|
var SignatureParser = class {
|
|
3522
3782
|
input;
|
|
3523
3783
|
position;
|
|
3784
|
+
currentFieldName = null;
|
|
3524
3785
|
constructor(input) {
|
|
3525
3786
|
this.input = input;
|
|
3526
3787
|
this.position = 0;
|
|
3527
3788
|
}
|
|
3528
3789
|
parse() {
|
|
3529
|
-
|
|
3530
|
-
const optionalDesc = this.parseParsedString();
|
|
3531
|
-
this.skipWhitespace();
|
|
3532
|
-
const inputs = this.parseInputParsedFieldList();
|
|
3533
|
-
this.skipWhitespace();
|
|
3534
|
-
this.expect("->");
|
|
3535
|
-
this.skipWhitespace();
|
|
3536
|
-
const outputs = this.parseOutputParsedFieldList();
|
|
3537
|
-
return {
|
|
3538
|
-
desc: optionalDesc?.trim(),
|
|
3539
|
-
inputs,
|
|
3540
|
-
outputs
|
|
3541
|
-
};
|
|
3542
|
-
}
|
|
3543
|
-
parseInputParsedFieldList() {
|
|
3544
|
-
const fields = [];
|
|
3545
|
-
fields.push(this.parseInputParsedField());
|
|
3546
|
-
while (this.match(",")) {
|
|
3790
|
+
try {
|
|
3547
3791
|
this.skipWhitespace();
|
|
3548
|
-
|
|
3549
|
-
}
|
|
3550
|
-
return fields;
|
|
3551
|
-
}
|
|
3552
|
-
parseOutputParsedFieldList() {
|
|
3553
|
-
const fields = [];
|
|
3554
|
-
fields.push(this.parseOutputParsedField());
|
|
3555
|
-
while (this.match(",")) {
|
|
3792
|
+
const optionalDesc = this.parseParsedString();
|
|
3556
3793
|
this.skipWhitespace();
|
|
3557
|
-
|
|
3558
|
-
}
|
|
3559
|
-
return fields;
|
|
3560
|
-
}
|
|
3561
|
-
parseInputParsedField() {
|
|
3562
|
-
this.skipWhitespace();
|
|
3563
|
-
const name = this.parseParsedIdentifier();
|
|
3564
|
-
const isOptional = this.match("?");
|
|
3565
|
-
let type;
|
|
3566
|
-
if (this.match(":")) {
|
|
3794
|
+
const inputs = this.parseFieldList(this.parseField.bind(this), "input");
|
|
3567
3795
|
this.skipWhitespace();
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3796
|
+
if (this.position >= this.input.length) {
|
|
3797
|
+
throw new Error(
|
|
3798
|
+
'Incomplete signature: Missing output section. Expected "->" followed by output fields'
|
|
3799
|
+
);
|
|
3800
|
+
}
|
|
3801
|
+
this.expect("->");
|
|
3802
|
+
this.skipWhitespace();
|
|
3803
|
+
if (this.position >= this.input.length) {
|
|
3804
|
+
throw new Error(
|
|
3805
|
+
'Incomplete signature: No output fields specified after "->"'
|
|
3806
|
+
);
|
|
3807
|
+
}
|
|
3808
|
+
const outputs = this.parseFieldList(this.parseField.bind(this), "output");
|
|
3809
|
+
return {
|
|
3810
|
+
desc: optionalDesc?.trim(),
|
|
3811
|
+
inputs,
|
|
3812
|
+
outputs
|
|
3813
|
+
};
|
|
3814
|
+
} catch (error) {
|
|
3815
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
3816
|
+
const context = this.getErrorContext();
|
|
3817
|
+
throw new Error(`${errorMessage}
|
|
3818
|
+
${context}`);
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3821
|
+
getErrorContext() {
|
|
3822
|
+
const start = Math.max(0, this.position - 20);
|
|
3823
|
+
const end = Math.min(this.input.length, this.position + 20);
|
|
3824
|
+
const before = this.input.slice(start, this.position);
|
|
3825
|
+
const after = this.input.slice(this.position, end);
|
|
3826
|
+
const pointer = " ".repeat(before.length) + "^";
|
|
3827
|
+
return `Near position ${this.position}:
|
|
3828
|
+
${before}${after}
|
|
3829
|
+
${pointer}`;
|
|
3830
|
+
}
|
|
3831
|
+
parseFieldList(parseFieldFn, section) {
|
|
3832
|
+
const fields = [];
|
|
3833
|
+
this.skipWhitespace();
|
|
3834
|
+
if (this.position >= this.input.length) {
|
|
3835
|
+
throw new Error(`Empty ${section} section: Expected at least one field`);
|
|
3836
|
+
}
|
|
3837
|
+
try {
|
|
3838
|
+
fields.push(parseFieldFn());
|
|
3839
|
+
} catch (error) {
|
|
3840
|
+
throw new Error(
|
|
3841
|
+
`Invalid first ${section} field: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
3842
|
+
);
|
|
3571
3843
|
}
|
|
3572
3844
|
this.skipWhitespace();
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3845
|
+
while (this.position < this.input.length) {
|
|
3846
|
+
if (this.input[this.position] === "-" && this.input[this.position + 1] === ">") {
|
|
3847
|
+
break;
|
|
3848
|
+
}
|
|
3849
|
+
if (this.match(",")) {
|
|
3850
|
+
this.skipWhitespace();
|
|
3851
|
+
if (this.position >= this.input.length) {
|
|
3852
|
+
throw new Error(
|
|
3853
|
+
`Unexpected end of input after comma in ${section} section`
|
|
3854
|
+
);
|
|
3855
|
+
}
|
|
3856
|
+
try {
|
|
3857
|
+
fields.push(parseFieldFn());
|
|
3858
|
+
} catch (error) {
|
|
3859
|
+
throw new Error(
|
|
3860
|
+
`Invalid ${section} field after comma: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
3861
|
+
);
|
|
3862
|
+
}
|
|
3863
|
+
this.skipWhitespace();
|
|
3864
|
+
} else {
|
|
3865
|
+
break;
|
|
3866
|
+
}
|
|
3867
|
+
}
|
|
3868
|
+
return fields;
|
|
3580
3869
|
}
|
|
3581
|
-
|
|
3870
|
+
parseField() {
|
|
3582
3871
|
this.skipWhitespace();
|
|
3583
3872
|
const name = this.parseParsedIdentifier();
|
|
3873
|
+
this.currentFieldName = name;
|
|
3584
3874
|
const isOptional = this.match("?");
|
|
3875
|
+
let type;
|
|
3585
3876
|
this.skipWhitespace();
|
|
3586
3877
|
if (this.match(":")) {
|
|
3587
3878
|
this.skipWhitespace();
|
|
3588
3879
|
if (this.match("class")) {
|
|
3589
3880
|
const isArray = this.match("[]");
|
|
3590
3881
|
this.skipWhitespace();
|
|
3591
|
-
const
|
|
3592
|
-
if (!
|
|
3882
|
+
const desc2 = this.parseParsedString();
|
|
3883
|
+
if (!desc2) {
|
|
3593
3884
|
throw new Error(
|
|
3594
|
-
"Expected
|
|
3885
|
+
`Field "${name}": Expected class names in quotes after "class" type. Example: class "MyClass1, MyClass2"`
|
|
3595
3886
|
);
|
|
3596
3887
|
}
|
|
3597
|
-
const
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
}
|
|
3888
|
+
const classes = desc2.split(/[,\s]+/).map((s) => s.trim()).filter((s) => s.length > 0);
|
|
3889
|
+
if (classes.length === 0) {
|
|
3890
|
+
throw new Error(
|
|
3891
|
+
`Field "${name}": Empty class list provided. At least one class name is required`
|
|
3892
|
+
);
|
|
3893
|
+
}
|
|
3894
|
+
type = { name: "class", isArray, classes };
|
|
3603
3895
|
} else {
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
};
|
|
3896
|
+
try {
|
|
3897
|
+
const typeName = this.parseTypeNotClass();
|
|
3898
|
+
const isArray = this.match("[]");
|
|
3899
|
+
type = { name: typeName, isArray };
|
|
3900
|
+
} catch (error) {
|
|
3901
|
+
throw new Error(
|
|
3902
|
+
`Field "${name}": ${error instanceof Error ? error.message : "Unknown error"}`
|
|
3903
|
+
);
|
|
3904
|
+
}
|
|
3614
3905
|
}
|
|
3906
|
+
}
|
|
3907
|
+
this.skipWhitespace();
|
|
3908
|
+
const desc = this.parseParsedString();
|
|
3909
|
+
if (type?.name === "class") {
|
|
3910
|
+
return {
|
|
3911
|
+
name,
|
|
3912
|
+
desc: desc?.trim(),
|
|
3913
|
+
type,
|
|
3914
|
+
isOptional
|
|
3915
|
+
};
|
|
3615
3916
|
} else {
|
|
3616
|
-
this.skipWhitespace();
|
|
3617
|
-
const desc = this.parseParsedString();
|
|
3618
3917
|
return {
|
|
3619
3918
|
name,
|
|
3620
3919
|
desc: desc?.trim(),
|
|
3621
|
-
type
|
|
3920
|
+
type,
|
|
3622
3921
|
isOptional
|
|
3623
3922
|
};
|
|
3624
3923
|
}
|
|
@@ -3634,14 +3933,17 @@ var SignatureParser = class {
|
|
|
3634
3933
|
"datetime",
|
|
3635
3934
|
"date"
|
|
3636
3935
|
];
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3936
|
+
const foundType = types.find((type) => this.match(type));
|
|
3937
|
+
if (!foundType) {
|
|
3938
|
+
const currentWord = this.input.slice(this.position).match(/^\w+/)?.[0] || "empty";
|
|
3939
|
+
throw new Error(
|
|
3940
|
+
`Invalid type "${currentWord}". Expected one of: ${types.join(", ")}`
|
|
3941
|
+
);
|
|
3641
3942
|
}
|
|
3642
|
-
|
|
3943
|
+
return foundType;
|
|
3643
3944
|
}
|
|
3644
3945
|
parseParsedIdentifier() {
|
|
3946
|
+
this.skipWhitespace();
|
|
3645
3947
|
const match = /^[a-zA-Z_][a-zA-Z_0-9]*/.exec(
|
|
3646
3948
|
this.input.slice(this.position)
|
|
3647
3949
|
);
|
|
@@ -3649,40 +3951,69 @@ var SignatureParser = class {
|
|
|
3649
3951
|
this.position += match[0].length;
|
|
3650
3952
|
return match[0];
|
|
3651
3953
|
}
|
|
3652
|
-
|
|
3954
|
+
const invalidMatch = /^\S+/.exec(this.input.slice(this.position));
|
|
3955
|
+
const invalidId = invalidMatch ? invalidMatch[0] : "empty";
|
|
3956
|
+
throw new Error(
|
|
3957
|
+
`Invalid identifier "${invalidId}". Identifiers must start with a letter or underscore and contain only letters, numbers, or underscores`
|
|
3958
|
+
);
|
|
3653
3959
|
}
|
|
3654
3960
|
parseParsedString() {
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
if (
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3961
|
+
const quoteChars = ["'", '"'];
|
|
3962
|
+
for (const quoteChar of quoteChars) {
|
|
3963
|
+
if (this.match(quoteChar)) {
|
|
3964
|
+
let content = "";
|
|
3965
|
+
let escaped = false;
|
|
3966
|
+
let startPos = this.position;
|
|
3967
|
+
while (this.position < this.input.length) {
|
|
3968
|
+
const char = this.input[this.position];
|
|
3969
|
+
this.position++;
|
|
3970
|
+
if (escaped) {
|
|
3971
|
+
content += char;
|
|
3972
|
+
escaped = false;
|
|
3973
|
+
} else if (char === "\\") {
|
|
3974
|
+
escaped = true;
|
|
3975
|
+
} else if (char === quoteChar) {
|
|
3976
|
+
return content;
|
|
3977
|
+
} else {
|
|
3978
|
+
content += char;
|
|
3979
|
+
}
|
|
3980
|
+
}
|
|
3981
|
+
const partialString = this.input.slice(startPos, this.position);
|
|
3982
|
+
throw new Error(
|
|
3983
|
+
`Unterminated string starting at position ${startPos}: "${partialString}..."`
|
|
3984
|
+
);
|
|
3985
|
+
}
|
|
3667
3986
|
}
|
|
3668
3987
|
return void 0;
|
|
3669
3988
|
}
|
|
3670
3989
|
skipWhitespace() {
|
|
3671
|
-
const match = /^[
|
|
3990
|
+
const match = /^[\s\t\r\n]+/.exec(this.input.slice(this.position));
|
|
3672
3991
|
if (match) {
|
|
3673
3992
|
this.position += match[0].length;
|
|
3674
3993
|
}
|
|
3675
3994
|
}
|
|
3676
|
-
match(
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3995
|
+
match(strOrRegex) {
|
|
3996
|
+
let match;
|
|
3997
|
+
if (typeof strOrRegex === "string") {
|
|
3998
|
+
if (this.input.startsWith(strOrRegex, this.position)) {
|
|
3999
|
+
this.position += strOrRegex.length;
|
|
4000
|
+
return true;
|
|
4001
|
+
}
|
|
4002
|
+
} else {
|
|
4003
|
+
match = strOrRegex.exec(this.input.slice(this.position));
|
|
4004
|
+
if (match) {
|
|
4005
|
+
this.position += match[0].length;
|
|
4006
|
+
return true;
|
|
4007
|
+
}
|
|
3680
4008
|
}
|
|
3681
4009
|
return false;
|
|
3682
4010
|
}
|
|
3683
4011
|
expect(str) {
|
|
3684
4012
|
if (!this.match(str)) {
|
|
3685
|
-
|
|
4013
|
+
const found = this.input.slice(this.position, this.position + 10);
|
|
4014
|
+
throw new Error(
|
|
4015
|
+
`Expected "${str}" but found "${found}..." at position ${this.position}`
|
|
4016
|
+
);
|
|
3686
4017
|
}
|
|
3687
4018
|
}
|
|
3688
4019
|
};
|
|
@@ -4916,7 +5247,7 @@ function validateAndParseFieldValue(field, fieldValue) {
|
|
|
4916
5247
|
if (field.type?.name === "json") {
|
|
4917
5248
|
try {
|
|
4918
5249
|
const text = extractBlock(fieldValue);
|
|
4919
|
-
value =
|
|
5250
|
+
value = JSON.parse(text);
|
|
4920
5251
|
return value;
|
|
4921
5252
|
} catch (e) {
|
|
4922
5253
|
throw new ValidationError({
|
|
@@ -4929,7 +5260,7 @@ function validateAndParseFieldValue(field, fieldValue) {
|
|
|
4929
5260
|
if (field.type?.isArray) {
|
|
4930
5261
|
try {
|
|
4931
5262
|
try {
|
|
4932
|
-
value =
|
|
5263
|
+
value = JSON.parse(fieldValue);
|
|
4933
5264
|
} catch {
|
|
4934
5265
|
value = parseMarkdownList(fieldValue);
|
|
4935
5266
|
}
|
|
@@ -4982,9 +5313,6 @@ var extractBlock = (input) => {
|
|
|
4982
5313
|
return input;
|
|
4983
5314
|
};
|
|
4984
5315
|
|
|
4985
|
-
// dsp/functions.ts
|
|
4986
|
-
import JSON52 from "json5";
|
|
4987
|
-
|
|
4988
5316
|
// dsp/jsonschema.ts
|
|
4989
5317
|
var validateJSONSchema = (schema) => {
|
|
4990
5318
|
const errors = [];
|
|
@@ -5042,7 +5370,7 @@ var AxFunctionProcessor = class {
|
|
|
5042
5370
|
executeFunction = async (fnSpec, func, options) => {
|
|
5043
5371
|
let args;
|
|
5044
5372
|
if (typeof func.args === "string" && func.args.length > 0) {
|
|
5045
|
-
args =
|
|
5373
|
+
args = JSON.parse(func.args);
|
|
5046
5374
|
} else {
|
|
5047
5375
|
args = func.args;
|
|
5048
5376
|
}
|
|
@@ -5211,7 +5539,7 @@ var AxGen = class extends AxProgramWithSignature {
|
|
|
5211
5539
|
mem,
|
|
5212
5540
|
options
|
|
5213
5541
|
});
|
|
5214
|
-
if (res instanceof
|
|
5542
|
+
if (res instanceof ReadableStream2) {
|
|
5215
5543
|
yield* this.processStreamingResponse({
|
|
5216
5544
|
ai,
|
|
5217
5545
|
model,
|
|
@@ -5329,37 +5657,35 @@ var AxGen = class extends AxProgramWithSignature {
|
|
|
5329
5657
|
functions
|
|
5330
5658
|
}) {
|
|
5331
5659
|
const values = {};
|
|
5332
|
-
const result
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5660
|
+
for (const result of res.results ?? []) {
|
|
5661
|
+
if (res.modelUsage) {
|
|
5662
|
+
this.usage.push({ ...usageInfo, ...res.modelUsage });
|
|
5663
|
+
}
|
|
5664
|
+
mem.addResult(result, sessionId);
|
|
5665
|
+
if (result.content) {
|
|
5666
|
+
extractValues(this.signature, values, result.content);
|
|
5667
|
+
assertAssertions(this.asserts, values);
|
|
5668
|
+
}
|
|
5669
|
+
if (result.functionCalls) {
|
|
5670
|
+
const funcs = parseFunctionCalls(ai, result.functionCalls, values);
|
|
5671
|
+
if (funcs) {
|
|
5672
|
+
if (!functions) {
|
|
5673
|
+
throw new Error("Functions are not defined");
|
|
5674
|
+
}
|
|
5675
|
+
const fx = await processFunctions(
|
|
5676
|
+
ai,
|
|
5677
|
+
functions,
|
|
5678
|
+
funcs,
|
|
5679
|
+
mem,
|
|
5680
|
+
sessionId,
|
|
5681
|
+
traceId
|
|
5682
|
+
);
|
|
5683
|
+
this.functionsExecuted = /* @__PURE__ */ new Set([...this.functionsExecuted, ...fx]);
|
|
5349
5684
|
}
|
|
5350
|
-
const fx = await processFunctions(
|
|
5351
|
-
ai,
|
|
5352
|
-
functions,
|
|
5353
|
-
funcs,
|
|
5354
|
-
mem,
|
|
5355
|
-
sessionId,
|
|
5356
|
-
traceId
|
|
5357
|
-
);
|
|
5358
|
-
this.functionsExecuted = /* @__PURE__ */ new Set([...this.functionsExecuted, ...fx]);
|
|
5359
5685
|
}
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5686
|
+
if (result.finishReason === "length") {
|
|
5687
|
+
throw new Error("Max tokens reached before completion");
|
|
5688
|
+
}
|
|
5363
5689
|
}
|
|
5364
5690
|
return { ...values };
|
|
5365
5691
|
}
|
|
@@ -5739,6 +6065,25 @@ var AxBalancer = class _AxBalancer {
|
|
|
5739
6065
|
try {
|
|
5740
6066
|
return await this.currentService.chat(req, options);
|
|
5741
6067
|
} catch (e) {
|
|
6068
|
+
if (!(e instanceof AxAIServiceError)) {
|
|
6069
|
+
throw e;
|
|
6070
|
+
}
|
|
6071
|
+
switch (e.constructor) {
|
|
6072
|
+
case AxAIServiceAuthenticationError:
|
|
6073
|
+
throw e;
|
|
6074
|
+
case AxAIServiceStatusError:
|
|
6075
|
+
break;
|
|
6076
|
+
case AxAIServiceNetworkError:
|
|
6077
|
+
break;
|
|
6078
|
+
case AxAIServiceResponseError:
|
|
6079
|
+
break;
|
|
6080
|
+
case AxAIServiceStreamTerminatedError:
|
|
6081
|
+
break;
|
|
6082
|
+
case AxAIServiceTimeoutError:
|
|
6083
|
+
break;
|
|
6084
|
+
default:
|
|
6085
|
+
throw e;
|
|
6086
|
+
}
|
|
5742
6087
|
console.warn(`Service ${this.currentService.getName()} failed`);
|
|
5743
6088
|
if (!this.getNextService()) {
|
|
5744
6089
|
throw e;
|
|
@@ -7424,6 +7769,13 @@ export {
|
|
|
7424
7769
|
AxAIOpenAIModel,
|
|
7425
7770
|
AxAIReka,
|
|
7426
7771
|
AxAIRekaModel,
|
|
7772
|
+
AxAIServiceAuthenticationError,
|
|
7773
|
+
AxAIServiceError,
|
|
7774
|
+
AxAIServiceNetworkError,
|
|
7775
|
+
AxAIServiceResponseError,
|
|
7776
|
+
AxAIServiceStatusError,
|
|
7777
|
+
AxAIServiceStreamTerminatedError,
|
|
7778
|
+
AxAIServiceTimeoutError,
|
|
7427
7779
|
AxAITogether,
|
|
7428
7780
|
AxAgent,
|
|
7429
7781
|
AxApacheTika,
|