@ax-llm/ax 10.0.41 → 10.0.43

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
@@ -3583,9 +3583,6 @@ var assertStreamingAssertions = (asserts, values, xstate, content, final) => {
3583
3583
  }
3584
3584
  };
3585
3585
 
3586
- // dsp/extract.ts
3587
- var import_json5 = __toESM(require("json5"), 1);
3588
-
3589
3586
  // dsp/datetime.ts
3590
3587
  var import_moment_timezone = __toESM(require("moment-timezone"), 1);
3591
3588
 
@@ -3616,104 +3613,143 @@ var import_crypto = require("crypto");
3616
3613
  var SignatureParser = class {
3617
3614
  input;
3618
3615
  position;
3616
+ currentFieldName = null;
3619
3617
  constructor(input) {
3620
3618
  this.input = input;
3621
3619
  this.position = 0;
3622
3620
  }
3623
3621
  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(",")) {
3622
+ try {
3642
3623
  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(",")) {
3624
+ const optionalDesc = this.parseParsedString();
3651
3625
  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(":")) {
3626
+ const inputs = this.parseFieldList(this.parseField.bind(this), "input");
3627
+ this.skipWhitespace();
3628
+ if (this.position >= this.input.length) {
3629
+ throw new Error(
3630
+ 'Incomplete signature: Missing output section. Expected "->" followed by output fields'
3631
+ );
3632
+ }
3633
+ this.expect("->");
3662
3634
  this.skipWhitespace();
3663
- const typeName = this.parseTypeNotClass();
3664
- const isArray = this.match("[]");
3665
- type = { name: typeName, isArray };
3635
+ if (this.position >= this.input.length) {
3636
+ throw new Error(
3637
+ 'Incomplete signature: No output fields specified after "->"'
3638
+ );
3639
+ }
3640
+ const outputs = this.parseFieldList(this.parseField.bind(this), "output");
3641
+ return {
3642
+ desc: optionalDesc?.trim(),
3643
+ inputs,
3644
+ outputs
3645
+ };
3646
+ } catch (error) {
3647
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
3648
+ const context = this.getErrorContext();
3649
+ throw new Error(`${errorMessage}
3650
+ ${context}`);
3651
+ }
3652
+ }
3653
+ getErrorContext() {
3654
+ const start = Math.max(0, this.position - 20);
3655
+ const end = Math.min(this.input.length, this.position + 20);
3656
+ const before = this.input.slice(start, this.position);
3657
+ const after = this.input.slice(this.position, end);
3658
+ const pointer = " ".repeat(before.length) + "^";
3659
+ return `Near position ${this.position}:
3660
+ ${before}${after}
3661
+ ${pointer}`;
3662
+ }
3663
+ parseFieldList(parseFieldFn, section) {
3664
+ const fields = [];
3665
+ this.skipWhitespace();
3666
+ if (this.position >= this.input.length) {
3667
+ throw new Error(`Empty ${section} section: Expected at least one field`);
3668
+ }
3669
+ try {
3670
+ fields.push(parseFieldFn());
3671
+ } catch (error) {
3672
+ throw new Error(
3673
+ `Invalid first ${section} field: ${error instanceof Error ? error.message : "Unknown error"}`
3674
+ );
3666
3675
  }
3667
3676
  this.skipWhitespace();
3668
- const desc = this.parseParsedString();
3669
- return {
3670
- name,
3671
- desc: desc?.trim(),
3672
- type,
3673
- isOptional
3674
- };
3677
+ while (this.position < this.input.length) {
3678
+ if (this.input[this.position] === "-" && this.input[this.position + 1] === ">") {
3679
+ break;
3680
+ }
3681
+ if (this.match(",")) {
3682
+ this.skipWhitespace();
3683
+ if (this.position >= this.input.length) {
3684
+ throw new Error(
3685
+ `Unexpected end of input after comma in ${section} section`
3686
+ );
3687
+ }
3688
+ try {
3689
+ fields.push(parseFieldFn());
3690
+ } catch (error) {
3691
+ throw new Error(
3692
+ `Invalid ${section} field after comma: ${error instanceof Error ? error.message : "Unknown error"}`
3693
+ );
3694
+ }
3695
+ this.skipWhitespace();
3696
+ } else {
3697
+ break;
3698
+ }
3699
+ }
3700
+ return fields;
3675
3701
  }
3676
- parseOutputParsedField() {
3702
+ parseField() {
3677
3703
  this.skipWhitespace();
3678
3704
  const name = this.parseParsedIdentifier();
3705
+ this.currentFieldName = name;
3679
3706
  const isOptional = this.match("?");
3707
+ let type;
3680
3708
  this.skipWhitespace();
3681
3709
  if (this.match(":")) {
3682
3710
  this.skipWhitespace();
3683
3711
  if (this.match("class")) {
3684
3712
  const isArray = this.match("[]");
3685
3713
  this.skipWhitespace();
3686
- const desc = this.parseParsedString();
3687
- if (!desc) {
3714
+ const desc2 = this.parseParsedString();
3715
+ if (!desc2) {
3688
3716
  throw new Error(
3689
- "Expected description containing class names after type 'class'"
3717
+ `Field "${name}": Expected class names in quotes after "class" type. Example: class "MyClass1, MyClass2"`
3690
3718
  );
3691
3719
  }
3692
- const classNames = desc.split(",").map((s) => s.trim());
3693
- return {
3694
- name,
3695
- type: { name: "class", isArray, classes: classNames },
3696
- isOptional
3697
- };
3720
+ const classes = desc2.split(/[,\s]+/).map((s) => s.trim()).filter((s) => s.length > 0);
3721
+ if (classes.length === 0) {
3722
+ throw new Error(
3723
+ `Field "${name}": Empty class list provided. At least one class name is required`
3724
+ );
3725
+ }
3726
+ type = { name: "class", isArray, classes };
3698
3727
  } 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
- };
3728
+ try {
3729
+ const typeName = this.parseTypeNotClass();
3730
+ const isArray = this.match("[]");
3731
+ type = { name: typeName, isArray };
3732
+ } catch (error) {
3733
+ throw new Error(
3734
+ `Field "${name}": ${error instanceof Error ? error.message : "Unknown error"}`
3735
+ );
3736
+ }
3709
3737
  }
3738
+ }
3739
+ this.skipWhitespace();
3740
+ const desc = this.parseParsedString();
3741
+ if (type?.name === "class") {
3742
+ return {
3743
+ name,
3744
+ desc: desc?.trim(),
3745
+ type,
3746
+ isOptional
3747
+ };
3710
3748
  } else {
3711
- this.skipWhitespace();
3712
- const desc = this.parseParsedString();
3713
3749
  return {
3714
3750
  name,
3715
3751
  desc: desc?.trim(),
3716
- type: void 0,
3752
+ type,
3717
3753
  isOptional
3718
3754
  };
3719
3755
  }
@@ -3729,14 +3765,17 @@ var SignatureParser = class {
3729
3765
  "datetime",
3730
3766
  "date"
3731
3767
  ];
3732
- for (const type of types) {
3733
- if (this.match(type)) {
3734
- return type;
3735
- }
3768
+ const foundType = types.find((type) => this.match(type));
3769
+ if (!foundType) {
3770
+ const currentWord = this.input.slice(this.position).match(/^\w+/)?.[0] || "empty";
3771
+ throw new Error(
3772
+ `Invalid type "${currentWord}". Expected one of: ${types.join(", ")}`
3773
+ );
3736
3774
  }
3737
- throw new Error(`Expected one of ${types.join(", ")}`);
3775
+ return foundType;
3738
3776
  }
3739
3777
  parseParsedIdentifier() {
3778
+ this.skipWhitespace();
3740
3779
  const match = /^[a-zA-Z_][a-zA-Z_0-9]*/.exec(
3741
3780
  this.input.slice(this.position)
3742
3781
  );
@@ -3744,40 +3783,69 @@ var SignatureParser = class {
3744
3783
  this.position += match[0].length;
3745
3784
  return match[0];
3746
3785
  }
3747
- throw new Error("Expected identifier");
3786
+ const invalidMatch = /^\S+/.exec(this.input.slice(this.position));
3787
+ const invalidId = invalidMatch ? invalidMatch[0] : "empty";
3788
+ throw new Error(
3789
+ `Invalid identifier "${invalidId}". Identifiers must start with a letter or underscore and contain only letters, numbers, or underscores`
3790
+ );
3748
3791
  }
3749
3792
  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;
3793
+ const quoteChars = ["'", '"'];
3794
+ for (const quoteChar of quoteChars) {
3795
+ if (this.match(quoteChar)) {
3796
+ let content = "";
3797
+ let escaped = false;
3798
+ let startPos = this.position;
3799
+ while (this.position < this.input.length) {
3800
+ const char = this.input[this.position];
3801
+ this.position++;
3802
+ if (escaped) {
3803
+ content += char;
3804
+ escaped = false;
3805
+ } else if (char === "\\") {
3806
+ escaped = true;
3807
+ } else if (char === quoteChar) {
3808
+ return content;
3809
+ } else {
3810
+ content += char;
3811
+ }
3812
+ }
3813
+ const partialString = this.input.slice(startPos, this.position);
3814
+ throw new Error(
3815
+ `Unterminated string starting at position ${startPos}: "${partialString}..."`
3816
+ );
3817
+ }
3762
3818
  }
3763
3819
  return void 0;
3764
3820
  }
3765
3821
  skipWhitespace() {
3766
- const match = /^[ \t\r\n]+/.exec(this.input.slice(this.position));
3822
+ const match = /^[\s\t\r\n]+/.exec(this.input.slice(this.position));
3767
3823
  if (match) {
3768
3824
  this.position += match[0].length;
3769
3825
  }
3770
3826
  }
3771
- match(str) {
3772
- if (this.input.startsWith(str, this.position)) {
3773
- this.position += str.length;
3774
- return true;
3827
+ match(strOrRegex) {
3828
+ let match;
3829
+ if (typeof strOrRegex === "string") {
3830
+ if (this.input.startsWith(strOrRegex, this.position)) {
3831
+ this.position += strOrRegex.length;
3832
+ return true;
3833
+ }
3834
+ } else {
3835
+ match = strOrRegex.exec(this.input.slice(this.position));
3836
+ if (match) {
3837
+ this.position += match[0].length;
3838
+ return true;
3839
+ }
3775
3840
  }
3776
3841
  return false;
3777
3842
  }
3778
3843
  expect(str) {
3779
3844
  if (!this.match(str)) {
3780
- throw new Error(`Expected "${str}"`);
3845
+ const found = this.input.slice(this.position, this.position + 10);
3846
+ throw new Error(
3847
+ `Expected "${str}" but found "${found}..." at position ${this.position}`
3848
+ );
3781
3849
  }
3782
3850
  }
3783
3851
  };
@@ -4878,9 +4946,6 @@ var checkMissingRequiredFields = (xstate, values, currentIndex) => {
4878
4946
  }
4879
4947
  };
4880
4948
  var streamingExtractValues = (sig, values, xstate, content) => {
4881
- if (content.endsWith("\n")) {
4882
- return true;
4883
- }
4884
4949
  const fields = sig.getOutputFields();
4885
4950
  for (const [index, field] of fields.entries()) {
4886
4951
  if (field.name in values) {
@@ -4896,10 +4961,6 @@ var streamingExtractValues = (sig, values, xstate, content) => {
4896
4961
  return true;
4897
4962
  }
4898
4963
  let prefixLen = prefix.length;
4899
- if (e - 1 >= 0 && content[e - 1] === "\n") {
4900
- e -= 1;
4901
- prefixLen += 1;
4902
- }
4903
4964
  if (xstate.currField) {
4904
4965
  const val = content.substring(xstate.s, e).trim();
4905
4966
  const parsedValue = validateAndParseFieldValue(xstate.currField, val);
@@ -4966,7 +5027,7 @@ var convertValueToType = (field, val) => {
4966
5027
  return val;
4967
5028
  }
4968
5029
  };
4969
- function* streamValues(sig, values, xstate, content) {
5030
+ function* streamValues(sig, values, xstate, content, final = false) {
4970
5031
  if (!xstate.currField) {
4971
5032
  return;
4972
5033
  }
@@ -4974,13 +5035,17 @@ function* streamValues(sig, values, xstate, content) {
4974
5035
  if (!xstate.streamedIndex) {
4975
5036
  xstate.streamedIndex = { [fieldName]: 0 };
4976
5037
  }
4977
- if (!xstate.currField.type || !xstate.currField.type.isArray && xstate.currField.type.name === "string") {
4978
- const pos = xstate.streamedIndex[fieldName] ?? 0;
4979
- const s = xstate.s + pos;
4980
- const v = content.substring(s);
4981
- yield { [fieldName]: pos === 0 ? v.trimStart() : v };
4982
- xstate.streamedIndex[fieldName] = pos + v.length;
4983
- return;
5038
+ if (!final) {
5039
+ if (!xstate.currField.type || !xstate.currField.type.isArray && xstate.currField.type.name === "string") {
5040
+ const pos = xstate.streamedIndex[fieldName] ?? 0;
5041
+ const s = xstate.s + pos;
5042
+ const v = content.substring(s);
5043
+ const v1 = v.replace(/[\s\n\t]+$/, "");
5044
+ const v2 = pos === 0 ? v1.trimStart() : v1;
5045
+ yield { [fieldName]: v2 };
5046
+ xstate.streamedIndex[fieldName] = pos + v1.length;
5047
+ return;
5048
+ }
4984
5049
  }
4985
5050
  for (const key of Object.keys(values)) {
4986
5051
  const value = values[key];
@@ -5014,7 +5079,7 @@ function validateAndParseFieldValue(field, fieldValue) {
5014
5079
  if (field.type?.name === "json") {
5015
5080
  try {
5016
5081
  const text = extractBlock(fieldValue);
5017
- value = import_json5.default.parse(text);
5082
+ value = JSON.parse(text);
5018
5083
  return value;
5019
5084
  } catch (e) {
5020
5085
  throw new ValidationError({
@@ -5027,7 +5092,7 @@ function validateAndParseFieldValue(field, fieldValue) {
5027
5092
  if (field.type?.isArray) {
5028
5093
  try {
5029
5094
  try {
5030
- value = import_json5.default.parse(fieldValue);
5095
+ value = JSON.parse(fieldValue);
5031
5096
  } catch {
5032
5097
  value = parseMarkdownList(fieldValue);
5033
5098
  }
@@ -5080,9 +5145,6 @@ var extractBlock = (input) => {
5080
5145
  return input;
5081
5146
  };
5082
5147
 
5083
- // dsp/functions.ts
5084
- var import_json52 = __toESM(require("json5"), 1);
5085
-
5086
5148
  // dsp/jsonschema.ts
5087
5149
  var validateJSONSchema = (schema) => {
5088
5150
  const errors = [];
@@ -5140,7 +5202,7 @@ var AxFunctionProcessor = class {
5140
5202
  executeFunction = async (fnSpec, func, options) => {
5141
5203
  let args;
5142
5204
  if (typeof func.args === "string" && func.args.length > 0) {
5143
- args = import_json52.default.parse(func.args);
5205
+ args = JSON.parse(func.args);
5144
5206
  } else {
5145
5207
  args = func.args;
5146
5208
  }
@@ -5406,6 +5468,7 @@ var AxGen = class extends AxProgramWithSignature {
5406
5468
  );
5407
5469
  this.functionsExecuted = /* @__PURE__ */ new Set([...this.functionsExecuted, ...fx]);
5408
5470
  }
5471
+ streamingExtractFinalValue(this.signature, values, xstate, content);
5409
5472
  assertStreamingAssertions(
5410
5473
  this.streamingAsserts,
5411
5474
  values,
@@ -5413,9 +5476,8 @@ var AxGen = class extends AxProgramWithSignature {
5413
5476
  content,
5414
5477
  true
5415
5478
  );
5416
- streamingExtractFinalValue(this.signature, values, xstate, content);
5417
5479
  assertAssertions(this.asserts, values);
5418
- yield* streamValues(this.signature, values, xstate, content);
5480
+ yield* streamValues(this.signature, values, xstate, content, true);
5419
5481
  }
5420
5482
  async processResponse({
5421
5483
  ai,
@@ -5427,37 +5489,35 @@ var AxGen = class extends AxProgramWithSignature {
5427
5489
  functions
5428
5490
  }) {
5429
5491
  const values = {};
5430
- const result = res.results[0];
5431
- if (!result) {
5432
- throw new Error("No result found");
5433
- }
5434
- if (res.modelUsage) {
5435
- this.usage.push({ ...usageInfo, ...res.modelUsage });
5436
- }
5437
- mem.addResult(result, sessionId);
5438
- if (result.content) {
5439
- extractValues(this.signature, values, result.content);
5440
- assertAssertions(this.asserts, values);
5441
- }
5442
- if (result.functionCalls) {
5443
- const funcs = parseFunctionCalls(ai, result.functionCalls, values);
5444
- if (funcs) {
5445
- if (!functions) {
5446
- throw new Error("Functions are not defined");
5492
+ for (const result of res.results ?? []) {
5493
+ if (res.modelUsage) {
5494
+ this.usage.push({ ...usageInfo, ...res.modelUsage });
5495
+ }
5496
+ mem.addResult(result, sessionId);
5497
+ if (result.content) {
5498
+ extractValues(this.signature, values, result.content);
5499
+ assertAssertions(this.asserts, values);
5500
+ }
5501
+ if (result.functionCalls) {
5502
+ const funcs = parseFunctionCalls(ai, result.functionCalls, values);
5503
+ if (funcs) {
5504
+ if (!functions) {
5505
+ throw new Error("Functions are not defined");
5506
+ }
5507
+ const fx = await processFunctions(
5508
+ ai,
5509
+ functions,
5510
+ funcs,
5511
+ mem,
5512
+ sessionId,
5513
+ traceId
5514
+ );
5515
+ this.functionsExecuted = /* @__PURE__ */ new Set([...this.functionsExecuted, ...fx]);
5447
5516
  }
5448
- const fx = await processFunctions(
5449
- ai,
5450
- functions,
5451
- funcs,
5452
- mem,
5453
- sessionId,
5454
- traceId
5455
- );
5456
- this.functionsExecuted = /* @__PURE__ */ new Set([...this.functionsExecuted, ...fx]);
5457
5517
  }
5458
- }
5459
- if (result.finishReason === "length") {
5460
- throw new Error("Max tokens reached before completion");
5518
+ if (result.finishReason === "length") {
5519
+ throw new Error("Max tokens reached before completion");
5520
+ }
5461
5521
  }
5462
5522
  return { ...values };
5463
5523
  }