@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 CHANGED
@@ -58,6 +58,13 @@ __export(index_exports, {
58
58
  AxAIOpenAIModel: () => AxAIOpenAIModel,
59
59
  AxAIReka: () => AxAIReka,
60
60
  AxAIRekaModel: () => AxAIRekaModel,
61
+ AxAIServiceAuthenticationError: () => AxAIServiceAuthenticationError,
62
+ AxAIServiceError: () => AxAIServiceError,
63
+ AxAIServiceNetworkError: () => AxAIServiceNetworkError,
64
+ AxAIServiceResponseError: () => AxAIServiceResponseError,
65
+ AxAIServiceStatusError: () => AxAIServiceStatusError,
66
+ AxAIServiceStreamTerminatedError: () => AxAIServiceStreamTerminatedError,
67
+ AxAIServiceTimeoutError: () => AxAIServiceTimeoutError,
61
68
  AxAITogether: () => AxAITogether,
62
69
  AxAgent: () => AxAgent,
63
70
  AxApacheTika: () => AxApacheTika,
@@ -182,15 +189,21 @@ var import_api = require("@opentelemetry/api");
182
189
  // util/sse.ts
183
190
  var import_web = require("stream/web");
184
191
  var SSEParser = class extends import_web.TransformStream {
185
- constructor(dataParser = JSON.parse) {
192
+ buffer = "";
193
+ currentEvent = { rawData: "" };
194
+ dataParser;
195
+ onError;
196
+ constructor(options = {}) {
186
197
  super({
187
198
  transform: (chunk, controller) => this.handleChunk(chunk, controller),
188
199
  flush: (controller) => this.handleFlush(controller)
189
200
  });
190
- this.dataParser = dataParser;
201
+ this.dataParser = options.dataParser || JSON.parse;
202
+ this.onError = options.onError || ((error, rawData) => {
203
+ console.warn("Failed to parse event data:", error);
204
+ console.log("Raw data that failed to parse:", rawData);
205
+ });
191
206
  }
192
- buffer = "";
193
- currentEvent = { rawData: "" };
194
207
  handleChunk(chunk, controller) {
195
208
  this.buffer += chunk;
196
209
  this.processBuffer(controller);
@@ -198,24 +211,28 @@ var SSEParser = class extends import_web.TransformStream {
198
211
  handleFlush(controller) {
199
212
  this.processBuffer(controller);
200
213
  if (this.currentEvent.rawData) {
201
- this.emitEvent(controller);
214
+ this.processEvent(controller);
202
215
  }
203
216
  }
204
217
  processBuffer(controller) {
205
- const lines = this.buffer.split(/\r\n|\r|\n/);
218
+ const normalizedBuffer = this.buffer.replace(/\r\n|\r/g, "\n");
219
+ const lines = normalizedBuffer.split("\n");
206
220
  this.buffer = lines.pop() || "";
207
221
  for (const line of lines) {
208
- if (line.trim() === "") {
209
- this.emitEvent(controller);
222
+ if (line === "") {
223
+ this.processEvent(controller);
210
224
  } else {
211
225
  this.parseLine(line);
212
226
  }
213
227
  }
214
228
  }
215
229
  parseLine(line) {
230
+ if (line.startsWith(":")) {
231
+ return;
232
+ }
216
233
  const colonIndex = line.indexOf(":");
217
234
  if (colonIndex === -1) {
218
- this.currentEvent.rawData += this.currentEvent.rawData ? "\n" + line.trim() : line.trim();
235
+ this.currentEvent.rawData += (this.currentEvent.rawData && !this.currentEvent.rawData.endsWith("\n") ? "\n" : "") + line.trim();
219
236
  return;
220
237
  }
221
238
  const field = line.slice(0, colonIndex).trim();
@@ -225,7 +242,7 @@ var SSEParser = class extends import_web.TransformStream {
225
242
  this.currentEvent.event = value;
226
243
  break;
227
244
  case "data":
228
- this.currentEvent.rawData += this.currentEvent.rawData ? "\n" + value : value;
245
+ this.currentEvent.rawData += (this.currentEvent.rawData && !this.currentEvent.rawData.endsWith("\n") ? "\n" : "") + value;
229
246
  break;
230
247
  case "id":
231
248
  this.currentEvent.id = value;
@@ -239,21 +256,20 @@ var SSEParser = class extends import_web.TransformStream {
239
256
  }
240
257
  }
241
258
  }
242
- emitEvent(controller) {
259
+ processEvent(controller) {
243
260
  if (this.currentEvent.rawData) {
244
- if (this.currentEvent.rawData.trim() === "[DONE]" || this.currentEvent.rawData.trim().startsWith("[")) {
261
+ if (!this.currentEvent.event) {
262
+ this.currentEvent.event = "message";
263
+ }
264
+ if (this.currentEvent.rawData.trim() === "[DONE]") {
265
+ this.currentEvent = { rawData: "" };
245
266
  return;
246
- } else {
247
- try {
248
- const parsedData = this.dataParser(this.currentEvent.rawData);
249
- controller.enqueue(parsedData);
250
- } catch (e) {
251
- console.warn("Failed to parse event data:", e);
252
- console.log(
253
- "Raw data that failed to parse:",
254
- this.currentEvent.rawData
255
- );
256
- }
267
+ }
268
+ try {
269
+ const parsedData = this.dataParser(this.currentEvent.rawData);
270
+ controller.enqueue(parsedData);
271
+ } catch (e) {
272
+ this.onError(e, this.currentEvent.rawData);
257
273
  }
258
274
  this.currentEvent = { rawData: "" };
259
275
  }
@@ -290,52 +306,305 @@ var TextDecoderStreamPolyfill = class extends import_web2.TransformStream {
290
306
  };
291
307
 
292
308
  // util/apicall.ts
309
+ var defaultRetryConfig = {
310
+ maxRetries: 3,
311
+ initialDelayMs: 1e3,
312
+ maxDelayMs: 6e4,
313
+ // Increased to 60 seconds
314
+ backoffFactor: 2,
315
+ retryableStatusCodes: [500, 408, 429, 502, 503, 504]
316
+ };
317
+ var defaultTimeoutMs = 3e4;
293
318
  var textDecoderStream = import_web3.TextDecoderStream ?? TextDecoderStreamPolyfill;
319
+ var AxAIServiceError = class extends Error {
320
+ constructor(message, url, requestBody, context = {}) {
321
+ super(message);
322
+ this.url = url;
323
+ this.requestBody = requestBody;
324
+ this.context = context;
325
+ this.name = "AxAIServiceError";
326
+ this.timestamp = (/* @__PURE__ */ new Date()).toISOString();
327
+ this.errorId = crypto.randomUUID();
328
+ }
329
+ timestamp;
330
+ errorId;
331
+ toString() {
332
+ return `${this.name} [${this.errorId}]: ${this.message}
333
+ Timestamp: ${this.timestamp}
334
+ URL: ${this.url}${this.requestBody ? `
335
+ Request Body: ${JSON.stringify(this.requestBody, null, 2)}` : ""}${this.context ? `
336
+ Context: ${JSON.stringify(this.context, null, 2)}` : ""}`;
337
+ }
338
+ toJSON() {
339
+ return {
340
+ name: this.name,
341
+ errorId: this.errorId,
342
+ message: this.message,
343
+ timestamp: this.timestamp,
344
+ url: this.url,
345
+ requestBody: this.requestBody,
346
+ context: this.context,
347
+ stack: this.stack
348
+ };
349
+ }
350
+ };
351
+ var AxAIServiceStatusError = class extends AxAIServiceError {
352
+ constructor(status, statusText, url, requestBody, context) {
353
+ super(`HTTP ${status} - ${statusText}`, url, requestBody, {
354
+ httpStatus: status,
355
+ httpStatusText: statusText,
356
+ ...context
357
+ });
358
+ this.status = status;
359
+ this.statusText = statusText;
360
+ this.name = "AxAIServiceStatusError";
361
+ }
362
+ };
363
+ var AxAIServiceNetworkError = class extends AxAIServiceError {
364
+ constructor(originalError, url, requestBody, context) {
365
+ super(`Network Error: ${originalError.message}`, url, requestBody, {
366
+ originalErrorName: originalError.name,
367
+ originalErrorStack: originalError.stack,
368
+ ...context
369
+ });
370
+ this.originalError = originalError;
371
+ this.name = "AxAIServiceNetworkError";
372
+ this.stack = originalError.stack;
373
+ }
374
+ };
375
+ var AxAIServiceResponseError = class extends AxAIServiceError {
376
+ constructor(message, url, requestBody, context) {
377
+ super(message, url, requestBody, context);
378
+ this.name = "AxAIServiceResponseError";
379
+ }
380
+ };
381
+ var AxAIServiceStreamTerminatedError = class extends AxAIServiceError {
382
+ constructor(url, requestBody, lastChunk, context) {
383
+ super("Stream terminated unexpectedly by remote host", url, requestBody, {
384
+ lastChunk,
385
+ ...context
386
+ });
387
+ this.lastChunk = lastChunk;
388
+ this.name = "AxAIServiceStreamTerminatedError";
389
+ }
390
+ };
391
+ var AxAIServiceTimeoutError = class extends AxAIServiceError {
392
+ constructor(url, timeoutMs, requestBody, context) {
393
+ super(`Request timeout after ${timeoutMs}ms`, url, requestBody, {
394
+ timeoutMs,
395
+ ...context
396
+ });
397
+ this.name = "AxAIServiceTimeoutError";
398
+ }
399
+ };
400
+ var AxAIServiceAuthenticationError = class extends AxAIServiceError {
401
+ constructor(url, requestBody, context) {
402
+ super("Authentication failed", url, requestBody, context);
403
+ this.name = "AxAIServiceAuthenticationError";
404
+ }
405
+ };
406
+ function calculateRetryDelay(attempt, config) {
407
+ const delay = Math.min(
408
+ config.maxDelayMs,
409
+ config.initialDelayMs * Math.pow(config.backoffFactor, attempt)
410
+ );
411
+ return delay * (0.75 + Math.random() * 0.5);
412
+ }
413
+ function createRequestMetrics() {
414
+ return {
415
+ startTime: Date.now(),
416
+ retryCount: 0
417
+ };
418
+ }
419
+ function updateRetryMetrics(metrics) {
420
+ metrics.retryCount++;
421
+ metrics.lastRetryTime = Date.now();
422
+ }
294
423
  var apiCall = async (api, json) => {
424
+ const retryConfig = { ...defaultRetryConfig, ...api.retry };
425
+ const timeoutMs = api.timeout ?? defaultTimeoutMs;
426
+ const metrics = createRequestMetrics();
295
427
  const baseUrl = new URL(process.env["PROXY"] ?? api.url);
296
428
  const apiPath = import_path.default.join(baseUrl.pathname, api.name ?? "/", baseUrl.search);
297
429
  const apiUrl = new URL(apiPath, baseUrl);
430
+ const requestId = crypto.randomUUID();
298
431
  if (api.span?.isRecording()) {
299
432
  api.span.setAttributes({
300
433
  "http.request.method": api.put ? "PUT" : "POST",
301
- "url.full": apiUrl.href
434
+ "url.full": apiUrl.href,
435
+ "request.id": requestId,
436
+ "request.startTime": metrics.startTime
302
437
  });
303
438
  }
304
- let res;
305
- try {
306
- res = await (api.fetch ?? fetch)(apiUrl, {
307
- method: api.put ? "PUT" : "POST",
308
- headers: {
309
- "Content-Type": "application/json",
310
- ...api.headers
311
- },
312
- body: JSON.stringify(json)
313
- });
314
- if (res.status >= 400) {
315
- const reqBody = JSON.stringify(json, null, 2);
316
- throw new Error(
317
- `API Request Error: ${res.status}, ${res.statusText}
318
- :Request Body: ${reqBody}`
319
- );
320
- }
321
- if (!api.stream) {
322
- const resJson = await res.json();
323
- return resJson;
324
- }
325
- if (!res.body) {
326
- throw new Error("Response body is null");
327
- }
328
- const st = res.body.pipeThrough(new textDecoderStream()).pipeThrough(new SSEParser());
329
- return st;
330
- } catch (e) {
331
- if (api.span?.isRecording()) {
332
- api.span.recordException(e);
439
+ let attempt = 0;
440
+ while (true) {
441
+ const controller = new AbortController();
442
+ let timeoutId = setTimeout(() => {
443
+ controller.abort("Request timeout");
444
+ }, timeoutMs);
445
+ try {
446
+ const res = await (api.fetch ?? fetch)(apiUrl, {
447
+ method: api.put ? "PUT" : "POST",
448
+ headers: {
449
+ "Content-Type": "application/json",
450
+ "X-Request-ID": requestId,
451
+ "X-Retry-Count": attempt.toString(),
452
+ ...api.headers
453
+ },
454
+ body: JSON.stringify(json),
455
+ signal: controller.signal
456
+ });
457
+ clearTimeout(timeoutId);
458
+ if (res.status === 401 || res.status === 403) {
459
+ throw new AxAIServiceAuthenticationError(apiUrl.href, json, { metrics });
460
+ }
461
+ if (res.status >= 400 && attempt < retryConfig.maxRetries && retryConfig.retryableStatusCodes.includes(res.status)) {
462
+ const delay = calculateRetryDelay(attempt, retryConfig);
463
+ attempt++;
464
+ updateRetryMetrics(metrics);
465
+ if (api.span?.isRecording()) {
466
+ api.span.addEvent("retry", {
467
+ attempt,
468
+ delay,
469
+ status: res.status,
470
+ "metrics.startTime": metrics.startTime,
471
+ "metrics.retryCount": metrics.retryCount,
472
+ "metrics.lastRetryTime": metrics.lastRetryTime
473
+ });
474
+ }
475
+ clearTimeout(timeoutId);
476
+ continue;
477
+ }
478
+ if (res.status >= 400) {
479
+ throw new AxAIServiceStatusError(
480
+ res.status,
481
+ res.statusText,
482
+ apiUrl.href,
483
+ json,
484
+ { metrics }
485
+ );
486
+ }
487
+ if (!api.stream) {
488
+ const resJson = await res.json();
489
+ if (api.span?.isRecording()) {
490
+ api.span.setAttributes({
491
+ "response.time": Date.now() - metrics.startTime,
492
+ "response.retries": metrics.retryCount
493
+ });
494
+ }
495
+ return resJson;
496
+ }
497
+ if (!res.body) {
498
+ throw new AxAIServiceResponseError(
499
+ "Response body is null",
500
+ apiUrl.href,
501
+ json,
502
+ { metrics }
503
+ );
504
+ }
505
+ let lastChunk;
506
+ let chunkCount = 0;
507
+ const trackingStream = new TransformStream({
508
+ transform(chunk, controller2) {
509
+ lastChunk = chunk;
510
+ chunkCount++;
511
+ metrics.streamChunks = chunkCount;
512
+ metrics.lastChunkTime = Date.now();
513
+ controller2.enqueue(chunk);
514
+ },
515
+ flush(controller2) {
516
+ if (api.span?.isRecording()) {
517
+ api.span.setAttributes({
518
+ "stream.chunks": chunkCount,
519
+ "stream.duration": Date.now() - metrics.startTime,
520
+ "response.retries": metrics.retryCount
521
+ });
522
+ }
523
+ controller2.terminate();
524
+ }
525
+ });
526
+ const wrappedStream = new import_web3.ReadableStream({
527
+ start(controller2) {
528
+ const reader = res.body.pipeThrough(new textDecoderStream()).pipeThrough(new SSEParser()).pipeThrough(trackingStream).getReader();
529
+ async function read() {
530
+ try {
531
+ while (true) {
532
+ const { done, value } = await reader.read();
533
+ if (done) {
534
+ controller2.close();
535
+ break;
536
+ } else {
537
+ controller2.enqueue(value);
538
+ }
539
+ }
540
+ } catch (e) {
541
+ const error = e;
542
+ const streamMetrics = {
543
+ ...metrics,
544
+ streamDuration: Date.now() - metrics.startTime
545
+ };
546
+ if (error.name === "AbortError" || error.message?.includes("aborted")) {
547
+ controller2.error(
548
+ new AxAIServiceStreamTerminatedError(
549
+ apiUrl.href,
550
+ json,
551
+ lastChunk,
552
+ { streamMetrics }
553
+ )
554
+ );
555
+ } else {
556
+ controller2.error(
557
+ new AxAIServiceResponseError(
558
+ `Stream processing error: ${error.message}`,
559
+ apiUrl.href,
560
+ json,
561
+ { streamMetrics }
562
+ )
563
+ );
564
+ }
565
+ } finally {
566
+ reader.releaseLock();
567
+ }
568
+ }
569
+ read();
570
+ }
571
+ });
572
+ return wrappedStream;
573
+ } catch (error) {
574
+ clearTimeout(timeoutId);
575
+ if (error instanceof Error && error.name === "AbortError") {
576
+ throw new AxAIServiceTimeoutError(apiUrl.href, timeoutMs, json, {
577
+ metrics
578
+ });
579
+ }
580
+ if (api.span?.isRecording()) {
581
+ api.span.recordException(error);
582
+ api.span.setAttributes({
583
+ "error.time": Date.now() - metrics.startTime,
584
+ "error.retries": metrics.retryCount
585
+ });
586
+ }
587
+ if (error instanceof AxAIServiceNetworkError && attempt < retryConfig.maxRetries) {
588
+ const delay = calculateRetryDelay(attempt, retryConfig);
589
+ attempt++;
590
+ updateRetryMetrics(metrics);
591
+ if (api.span?.isRecording()) {
592
+ api.span.addEvent("retry", {
593
+ attempt,
594
+ delay,
595
+ error: error.message,
596
+ "metrics.startTime": metrics.startTime,
597
+ "metrics.retryCount": metrics.retryCount,
598
+ "metrics.lastRetryTime": metrics.lastRetryTime
599
+ });
600
+ }
601
+ continue;
602
+ }
603
+ if (error instanceof AxAIServiceError) {
604
+ error.context["metrics"] = metrics;
605
+ }
606
+ throw error;
333
607
  }
334
- const reqBody = JSON.stringify(json, null, 2);
335
- throw new Error(
336
- `API Response Error: ${apiUrl.href}, ${e}
337
- Request Body: ${reqBody}`
338
- );
339
608
  }
340
609
  };
341
610
 
@@ -3583,9 +3852,6 @@ var assertStreamingAssertions = (asserts, values, xstate, content, final) => {
3583
3852
  }
3584
3853
  };
3585
3854
 
3586
- // dsp/extract.ts
3587
- var import_json5 = __toESM(require("json5"), 1);
3588
-
3589
3855
  // dsp/datetime.ts
3590
3856
  var import_moment_timezone = __toESM(require("moment-timezone"), 1);
3591
3857
 
@@ -3616,104 +3882,143 @@ var import_crypto = require("crypto");
3616
3882
  var SignatureParser = class {
3617
3883
  input;
3618
3884
  position;
3885
+ currentFieldName = null;
3619
3886
  constructor(input) {
3620
3887
  this.input = input;
3621
3888
  this.position = 0;
3622
3889
  }
3623
3890
  parse() {
3624
- this.skipWhitespace();
3625
- const optionalDesc = this.parseParsedString();
3626
- this.skipWhitespace();
3627
- const inputs = this.parseInputParsedFieldList();
3628
- this.skipWhitespace();
3629
- this.expect("->");
3630
- this.skipWhitespace();
3631
- const outputs = this.parseOutputParsedFieldList();
3632
- return {
3633
- desc: optionalDesc?.trim(),
3634
- inputs,
3635
- outputs
3636
- };
3637
- }
3638
- parseInputParsedFieldList() {
3639
- const fields = [];
3640
- fields.push(this.parseInputParsedField());
3641
- while (this.match(",")) {
3891
+ try {
3642
3892
  this.skipWhitespace();
3643
- fields.push(this.parseInputParsedField());
3644
- }
3645
- return fields;
3646
- }
3647
- parseOutputParsedFieldList() {
3648
- const fields = [];
3649
- fields.push(this.parseOutputParsedField());
3650
- while (this.match(",")) {
3893
+ const optionalDesc = this.parseParsedString();
3651
3894
  this.skipWhitespace();
3652
- fields.push(this.parseOutputParsedField());
3653
- }
3654
- return fields;
3655
- }
3656
- parseInputParsedField() {
3657
- this.skipWhitespace();
3658
- const name = this.parseParsedIdentifier();
3659
- const isOptional = this.match("?");
3660
- let type;
3661
- if (this.match(":")) {
3895
+ const inputs = this.parseFieldList(this.parseField.bind(this), "input");
3662
3896
  this.skipWhitespace();
3663
- const typeName = this.parseTypeNotClass();
3664
- const isArray = this.match("[]");
3665
- type = { name: typeName, isArray };
3897
+ if (this.position >= this.input.length) {
3898
+ throw new Error(
3899
+ 'Incomplete signature: Missing output section. Expected "->" followed by output fields'
3900
+ );
3901
+ }
3902
+ this.expect("->");
3903
+ this.skipWhitespace();
3904
+ if (this.position >= this.input.length) {
3905
+ throw new Error(
3906
+ 'Incomplete signature: No output fields specified after "->"'
3907
+ );
3908
+ }
3909
+ const outputs = this.parseFieldList(this.parseField.bind(this), "output");
3910
+ return {
3911
+ desc: optionalDesc?.trim(),
3912
+ inputs,
3913
+ outputs
3914
+ };
3915
+ } catch (error) {
3916
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
3917
+ const context = this.getErrorContext();
3918
+ throw new Error(`${errorMessage}
3919
+ ${context}`);
3920
+ }
3921
+ }
3922
+ getErrorContext() {
3923
+ const start = Math.max(0, this.position - 20);
3924
+ const end = Math.min(this.input.length, this.position + 20);
3925
+ const before = this.input.slice(start, this.position);
3926
+ const after = this.input.slice(this.position, end);
3927
+ const pointer = " ".repeat(before.length) + "^";
3928
+ return `Near position ${this.position}:
3929
+ ${before}${after}
3930
+ ${pointer}`;
3931
+ }
3932
+ parseFieldList(parseFieldFn, section) {
3933
+ const fields = [];
3934
+ this.skipWhitespace();
3935
+ if (this.position >= this.input.length) {
3936
+ throw new Error(`Empty ${section} section: Expected at least one field`);
3937
+ }
3938
+ try {
3939
+ fields.push(parseFieldFn());
3940
+ } catch (error) {
3941
+ throw new Error(
3942
+ `Invalid first ${section} field: ${error instanceof Error ? error.message : "Unknown error"}`
3943
+ );
3666
3944
  }
3667
3945
  this.skipWhitespace();
3668
- const desc = this.parseParsedString();
3669
- return {
3670
- name,
3671
- desc: desc?.trim(),
3672
- type,
3673
- isOptional
3674
- };
3946
+ while (this.position < this.input.length) {
3947
+ if (this.input[this.position] === "-" && this.input[this.position + 1] === ">") {
3948
+ break;
3949
+ }
3950
+ if (this.match(",")) {
3951
+ this.skipWhitespace();
3952
+ if (this.position >= this.input.length) {
3953
+ throw new Error(
3954
+ `Unexpected end of input after comma in ${section} section`
3955
+ );
3956
+ }
3957
+ try {
3958
+ fields.push(parseFieldFn());
3959
+ } catch (error) {
3960
+ throw new Error(
3961
+ `Invalid ${section} field after comma: ${error instanceof Error ? error.message : "Unknown error"}`
3962
+ );
3963
+ }
3964
+ this.skipWhitespace();
3965
+ } else {
3966
+ break;
3967
+ }
3968
+ }
3969
+ return fields;
3675
3970
  }
3676
- parseOutputParsedField() {
3971
+ parseField() {
3677
3972
  this.skipWhitespace();
3678
3973
  const name = this.parseParsedIdentifier();
3974
+ this.currentFieldName = name;
3679
3975
  const isOptional = this.match("?");
3976
+ let type;
3680
3977
  this.skipWhitespace();
3681
3978
  if (this.match(":")) {
3682
3979
  this.skipWhitespace();
3683
3980
  if (this.match("class")) {
3684
3981
  const isArray = this.match("[]");
3685
3982
  this.skipWhitespace();
3686
- const desc = this.parseParsedString();
3687
- if (!desc) {
3983
+ const desc2 = this.parseParsedString();
3984
+ if (!desc2) {
3688
3985
  throw new Error(
3689
- "Expected description containing class names after type 'class'"
3986
+ `Field "${name}": Expected class names in quotes after "class" type. Example: class "MyClass1, MyClass2"`
3690
3987
  );
3691
3988
  }
3692
- const classNames = desc.split(",").map((s) => s.trim());
3693
- return {
3694
- name,
3695
- type: { name: "class", isArray, classes: classNames },
3696
- isOptional
3697
- };
3989
+ const classes = desc2.split(/[,\s]+/).map((s) => s.trim()).filter((s) => s.length > 0);
3990
+ if (classes.length === 0) {
3991
+ throw new Error(
3992
+ `Field "${name}": Empty class list provided. At least one class name is required`
3993
+ );
3994
+ }
3995
+ type = { name: "class", isArray, classes };
3698
3996
  } else {
3699
- const typeName = this.parseTypeNotClass();
3700
- const isArray = this.match("[]");
3701
- this.skipWhitespace();
3702
- const desc = this.parseParsedString();
3703
- return {
3704
- name,
3705
- desc: desc?.trim(),
3706
- type: { name: typeName, isArray },
3707
- isOptional
3708
- };
3997
+ try {
3998
+ const typeName = this.parseTypeNotClass();
3999
+ const isArray = this.match("[]");
4000
+ type = { name: typeName, isArray };
4001
+ } catch (error) {
4002
+ throw new Error(
4003
+ `Field "${name}": ${error instanceof Error ? error.message : "Unknown error"}`
4004
+ );
4005
+ }
3709
4006
  }
4007
+ }
4008
+ this.skipWhitespace();
4009
+ const desc = this.parseParsedString();
4010
+ if (type?.name === "class") {
4011
+ return {
4012
+ name,
4013
+ desc: desc?.trim(),
4014
+ type,
4015
+ isOptional
4016
+ };
3710
4017
  } else {
3711
- this.skipWhitespace();
3712
- const desc = this.parseParsedString();
3713
4018
  return {
3714
4019
  name,
3715
4020
  desc: desc?.trim(),
3716
- type: void 0,
4021
+ type,
3717
4022
  isOptional
3718
4023
  };
3719
4024
  }
@@ -3729,14 +4034,17 @@ var SignatureParser = class {
3729
4034
  "datetime",
3730
4035
  "date"
3731
4036
  ];
3732
- for (const type of types) {
3733
- if (this.match(type)) {
3734
- return type;
3735
- }
4037
+ const foundType = types.find((type) => this.match(type));
4038
+ if (!foundType) {
4039
+ const currentWord = this.input.slice(this.position).match(/^\w+/)?.[0] || "empty";
4040
+ throw new Error(
4041
+ `Invalid type "${currentWord}". Expected one of: ${types.join(", ")}`
4042
+ );
3736
4043
  }
3737
- throw new Error(`Expected one of ${types.join(", ")}`);
4044
+ return foundType;
3738
4045
  }
3739
4046
  parseParsedIdentifier() {
4047
+ this.skipWhitespace();
3740
4048
  const match = /^[a-zA-Z_][a-zA-Z_0-9]*/.exec(
3741
4049
  this.input.slice(this.position)
3742
4050
  );
@@ -3744,40 +4052,69 @@ var SignatureParser = class {
3744
4052
  this.position += match[0].length;
3745
4053
  return match[0];
3746
4054
  }
3747
- throw new Error("Expected identifier");
4055
+ const invalidMatch = /^\S+/.exec(this.input.slice(this.position));
4056
+ const invalidId = invalidMatch ? invalidMatch[0] : "empty";
4057
+ throw new Error(
4058
+ `Invalid identifier "${invalidId}". Identifiers must start with a letter or underscore and contain only letters, numbers, or underscores`
4059
+ );
3748
4060
  }
3749
4061
  parseParsedString() {
3750
- if (this.match("'")) {
3751
- const endQuote = this.input.indexOf("'", this.position);
3752
- if (endQuote === -1) throw new Error("Unterminated string");
3753
- const content = this.input.slice(this.position, endQuote);
3754
- this.position = endQuote + 1;
3755
- return content;
3756
- } else if (this.match('"')) {
3757
- const endQuote = this.input.indexOf('"', this.position);
3758
- if (endQuote === -1) throw new Error("Unterminated string");
3759
- const content = this.input.slice(this.position, endQuote);
3760
- this.position = endQuote + 1;
3761
- return content;
4062
+ const quoteChars = ["'", '"'];
4063
+ for (const quoteChar of quoteChars) {
4064
+ if (this.match(quoteChar)) {
4065
+ let content = "";
4066
+ let escaped = false;
4067
+ let startPos = this.position;
4068
+ while (this.position < this.input.length) {
4069
+ const char = this.input[this.position];
4070
+ this.position++;
4071
+ if (escaped) {
4072
+ content += char;
4073
+ escaped = false;
4074
+ } else if (char === "\\") {
4075
+ escaped = true;
4076
+ } else if (char === quoteChar) {
4077
+ return content;
4078
+ } else {
4079
+ content += char;
4080
+ }
4081
+ }
4082
+ const partialString = this.input.slice(startPos, this.position);
4083
+ throw new Error(
4084
+ `Unterminated string starting at position ${startPos}: "${partialString}..."`
4085
+ );
4086
+ }
3762
4087
  }
3763
4088
  return void 0;
3764
4089
  }
3765
4090
  skipWhitespace() {
3766
- const match = /^[ \t\r\n]+/.exec(this.input.slice(this.position));
4091
+ const match = /^[\s\t\r\n]+/.exec(this.input.slice(this.position));
3767
4092
  if (match) {
3768
4093
  this.position += match[0].length;
3769
4094
  }
3770
4095
  }
3771
- match(str) {
3772
- if (this.input.startsWith(str, this.position)) {
3773
- this.position += str.length;
3774
- return true;
4096
+ match(strOrRegex) {
4097
+ let match;
4098
+ if (typeof strOrRegex === "string") {
4099
+ if (this.input.startsWith(strOrRegex, this.position)) {
4100
+ this.position += strOrRegex.length;
4101
+ return true;
4102
+ }
4103
+ } else {
4104
+ match = strOrRegex.exec(this.input.slice(this.position));
4105
+ if (match) {
4106
+ this.position += match[0].length;
4107
+ return true;
4108
+ }
3775
4109
  }
3776
4110
  return false;
3777
4111
  }
3778
4112
  expect(str) {
3779
4113
  if (!this.match(str)) {
3780
- throw new Error(`Expected "${str}"`);
4114
+ const found = this.input.slice(this.position, this.position + 10);
4115
+ throw new Error(
4116
+ `Expected "${str}" but found "${found}..." at position ${this.position}`
4117
+ );
3781
4118
  }
3782
4119
  }
3783
4120
  };
@@ -5011,7 +5348,7 @@ function validateAndParseFieldValue(field, fieldValue) {
5011
5348
  if (field.type?.name === "json") {
5012
5349
  try {
5013
5350
  const text = extractBlock(fieldValue);
5014
- value = import_json5.default.parse(text);
5351
+ value = JSON.parse(text);
5015
5352
  return value;
5016
5353
  } catch (e) {
5017
5354
  throw new ValidationError({
@@ -5024,7 +5361,7 @@ function validateAndParseFieldValue(field, fieldValue) {
5024
5361
  if (field.type?.isArray) {
5025
5362
  try {
5026
5363
  try {
5027
- value = import_json5.default.parse(fieldValue);
5364
+ value = JSON.parse(fieldValue);
5028
5365
  } catch {
5029
5366
  value = parseMarkdownList(fieldValue);
5030
5367
  }
@@ -5077,9 +5414,6 @@ var extractBlock = (input) => {
5077
5414
  return input;
5078
5415
  };
5079
5416
 
5080
- // dsp/functions.ts
5081
- var import_json52 = __toESM(require("json5"), 1);
5082
-
5083
5417
  // dsp/jsonschema.ts
5084
5418
  var validateJSONSchema = (schema) => {
5085
5419
  const errors = [];
@@ -5137,7 +5471,7 @@ var AxFunctionProcessor = class {
5137
5471
  executeFunction = async (fnSpec, func, options) => {
5138
5472
  let args;
5139
5473
  if (typeof func.args === "string" && func.args.length > 0) {
5140
- args = import_json52.default.parse(func.args);
5474
+ args = JSON.parse(func.args);
5141
5475
  } else {
5142
5476
  args = func.args;
5143
5477
  }
@@ -5424,37 +5758,35 @@ var AxGen = class extends AxProgramWithSignature {
5424
5758
  functions
5425
5759
  }) {
5426
5760
  const values = {};
5427
- const result = res.results[0];
5428
- if (!result) {
5429
- throw new Error("No result found");
5430
- }
5431
- if (res.modelUsage) {
5432
- this.usage.push({ ...usageInfo, ...res.modelUsage });
5433
- }
5434
- mem.addResult(result, sessionId);
5435
- if (result.content) {
5436
- extractValues(this.signature, values, result.content);
5437
- assertAssertions(this.asserts, values);
5438
- }
5439
- if (result.functionCalls) {
5440
- const funcs = parseFunctionCalls(ai, result.functionCalls, values);
5441
- if (funcs) {
5442
- if (!functions) {
5443
- throw new Error("Functions are not defined");
5761
+ for (const result of res.results ?? []) {
5762
+ if (res.modelUsage) {
5763
+ this.usage.push({ ...usageInfo, ...res.modelUsage });
5764
+ }
5765
+ mem.addResult(result, sessionId);
5766
+ if (result.content) {
5767
+ extractValues(this.signature, values, result.content);
5768
+ assertAssertions(this.asserts, values);
5769
+ }
5770
+ if (result.functionCalls) {
5771
+ const funcs = parseFunctionCalls(ai, result.functionCalls, values);
5772
+ if (funcs) {
5773
+ if (!functions) {
5774
+ throw new Error("Functions are not defined");
5775
+ }
5776
+ const fx = await processFunctions(
5777
+ ai,
5778
+ functions,
5779
+ funcs,
5780
+ mem,
5781
+ sessionId,
5782
+ traceId
5783
+ );
5784
+ this.functionsExecuted = /* @__PURE__ */ new Set([...this.functionsExecuted, ...fx]);
5444
5785
  }
5445
- const fx = await processFunctions(
5446
- ai,
5447
- functions,
5448
- funcs,
5449
- mem,
5450
- sessionId,
5451
- traceId
5452
- );
5453
- this.functionsExecuted = /* @__PURE__ */ new Set([...this.functionsExecuted, ...fx]);
5454
5786
  }
5455
- }
5456
- if (result.finishReason === "length") {
5457
- throw new Error("Max tokens reached before completion");
5787
+ if (result.finishReason === "length") {
5788
+ throw new Error("Max tokens reached before completion");
5789
+ }
5458
5790
  }
5459
5791
  return { ...values };
5460
5792
  }
@@ -5834,6 +6166,25 @@ var AxBalancer = class _AxBalancer {
5834
6166
  try {
5835
6167
  return await this.currentService.chat(req, options);
5836
6168
  } catch (e) {
6169
+ if (!(e instanceof AxAIServiceError)) {
6170
+ throw e;
6171
+ }
6172
+ switch (e.constructor) {
6173
+ case AxAIServiceAuthenticationError:
6174
+ throw e;
6175
+ case AxAIServiceStatusError:
6176
+ break;
6177
+ case AxAIServiceNetworkError:
6178
+ break;
6179
+ case AxAIServiceResponseError:
6180
+ break;
6181
+ case AxAIServiceStreamTerminatedError:
6182
+ break;
6183
+ case AxAIServiceTimeoutError:
6184
+ break;
6185
+ default:
6186
+ throw e;
6187
+ }
5837
6188
  console.warn(`Service ${this.currentService.getName()} failed`);
5838
6189
  if (!this.getNextService()) {
5839
6190
  throw e;
@@ -7520,6 +7871,13 @@ var AxRAG = class extends AxChainOfThought {
7520
7871
  AxAIOpenAIModel,
7521
7872
  AxAIReka,
7522
7873
  AxAIRekaModel,
7874
+ AxAIServiceAuthenticationError,
7875
+ AxAIServiceError,
7876
+ AxAIServiceNetworkError,
7877
+ AxAIServiceResponseError,
7878
+ AxAIServiceStatusError,
7879
+ AxAIServiceStreamTerminatedError,
7880
+ AxAIServiceTimeoutError,
7523
7881
  AxAITogether,
7524
7882
  AxAgent,
7525
7883
  AxApacheTika,