@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.js CHANGED
@@ -3488,9 +3488,6 @@ var assertStreamingAssertions = (asserts, values, xstate, content, final) => {
3488
3488
  }
3489
3489
  };
3490
3490
 
3491
- // dsp/extract.ts
3492
- import JSON5 from "json5";
3493
-
3494
3491
  // dsp/datetime.ts
3495
3492
  import moment from "moment-timezone";
3496
3493
 
@@ -3521,104 +3518,143 @@ import { createHash } from "crypto";
3521
3518
  var SignatureParser = class {
3522
3519
  input;
3523
3520
  position;
3521
+ currentFieldName = null;
3524
3522
  constructor(input) {
3525
3523
  this.input = input;
3526
3524
  this.position = 0;
3527
3525
  }
3528
3526
  parse() {
3529
- this.skipWhitespace();
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(",")) {
3527
+ try {
3547
3528
  this.skipWhitespace();
3548
- fields.push(this.parseInputParsedField());
3549
- }
3550
- return fields;
3551
- }
3552
- parseOutputParsedFieldList() {
3553
- const fields = [];
3554
- fields.push(this.parseOutputParsedField());
3555
- while (this.match(",")) {
3529
+ const optionalDesc = this.parseParsedString();
3556
3530
  this.skipWhitespace();
3557
- fields.push(this.parseOutputParsedField());
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(":")) {
3531
+ const inputs = this.parseFieldList(this.parseField.bind(this), "input");
3532
+ this.skipWhitespace();
3533
+ if (this.position >= this.input.length) {
3534
+ throw new Error(
3535
+ 'Incomplete signature: Missing output section. Expected "->" followed by output fields'
3536
+ );
3537
+ }
3538
+ this.expect("->");
3567
3539
  this.skipWhitespace();
3568
- const typeName = this.parseTypeNotClass();
3569
- const isArray = this.match("[]");
3570
- type = { name: typeName, isArray };
3540
+ if (this.position >= this.input.length) {
3541
+ throw new Error(
3542
+ 'Incomplete signature: No output fields specified after "->"'
3543
+ );
3544
+ }
3545
+ const outputs = this.parseFieldList(this.parseField.bind(this), "output");
3546
+ return {
3547
+ desc: optionalDesc?.trim(),
3548
+ inputs,
3549
+ outputs
3550
+ };
3551
+ } catch (error) {
3552
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
3553
+ const context = this.getErrorContext();
3554
+ throw new Error(`${errorMessage}
3555
+ ${context}`);
3556
+ }
3557
+ }
3558
+ getErrorContext() {
3559
+ const start = Math.max(0, this.position - 20);
3560
+ const end = Math.min(this.input.length, this.position + 20);
3561
+ const before = this.input.slice(start, this.position);
3562
+ const after = this.input.slice(this.position, end);
3563
+ const pointer = " ".repeat(before.length) + "^";
3564
+ return `Near position ${this.position}:
3565
+ ${before}${after}
3566
+ ${pointer}`;
3567
+ }
3568
+ parseFieldList(parseFieldFn, section) {
3569
+ const fields = [];
3570
+ this.skipWhitespace();
3571
+ if (this.position >= this.input.length) {
3572
+ throw new Error(`Empty ${section} section: Expected at least one field`);
3573
+ }
3574
+ try {
3575
+ fields.push(parseFieldFn());
3576
+ } catch (error) {
3577
+ throw new Error(
3578
+ `Invalid first ${section} field: ${error instanceof Error ? error.message : "Unknown error"}`
3579
+ );
3571
3580
  }
3572
3581
  this.skipWhitespace();
3573
- const desc = this.parseParsedString();
3574
- return {
3575
- name,
3576
- desc: desc?.trim(),
3577
- type,
3578
- isOptional
3579
- };
3582
+ while (this.position < this.input.length) {
3583
+ if (this.input[this.position] === "-" && this.input[this.position + 1] === ">") {
3584
+ break;
3585
+ }
3586
+ if (this.match(",")) {
3587
+ this.skipWhitespace();
3588
+ if (this.position >= this.input.length) {
3589
+ throw new Error(
3590
+ `Unexpected end of input after comma in ${section} section`
3591
+ );
3592
+ }
3593
+ try {
3594
+ fields.push(parseFieldFn());
3595
+ } catch (error) {
3596
+ throw new Error(
3597
+ `Invalid ${section} field after comma: ${error instanceof Error ? error.message : "Unknown error"}`
3598
+ );
3599
+ }
3600
+ this.skipWhitespace();
3601
+ } else {
3602
+ break;
3603
+ }
3604
+ }
3605
+ return fields;
3580
3606
  }
3581
- parseOutputParsedField() {
3607
+ parseField() {
3582
3608
  this.skipWhitespace();
3583
3609
  const name = this.parseParsedIdentifier();
3610
+ this.currentFieldName = name;
3584
3611
  const isOptional = this.match("?");
3612
+ let type;
3585
3613
  this.skipWhitespace();
3586
3614
  if (this.match(":")) {
3587
3615
  this.skipWhitespace();
3588
3616
  if (this.match("class")) {
3589
3617
  const isArray = this.match("[]");
3590
3618
  this.skipWhitespace();
3591
- const desc = this.parseParsedString();
3592
- if (!desc) {
3619
+ const desc2 = this.parseParsedString();
3620
+ if (!desc2) {
3593
3621
  throw new Error(
3594
- "Expected description containing class names after type 'class'"
3622
+ `Field "${name}": Expected class names in quotes after "class" type. Example: class "MyClass1, MyClass2"`
3595
3623
  );
3596
3624
  }
3597
- const classNames = desc.split(",").map((s) => s.trim());
3598
- return {
3599
- name,
3600
- type: { name: "class", isArray, classes: classNames },
3601
- isOptional
3602
- };
3625
+ const classes = desc2.split(/[,\s]+/).map((s) => s.trim()).filter((s) => s.length > 0);
3626
+ if (classes.length === 0) {
3627
+ throw new Error(
3628
+ `Field "${name}": Empty class list provided. At least one class name is required`
3629
+ );
3630
+ }
3631
+ type = { name: "class", isArray, classes };
3603
3632
  } else {
3604
- const typeName = this.parseTypeNotClass();
3605
- const isArray = this.match("[]");
3606
- this.skipWhitespace();
3607
- const desc = this.parseParsedString();
3608
- return {
3609
- name,
3610
- desc: desc?.trim(),
3611
- type: { name: typeName, isArray },
3612
- isOptional
3613
- };
3633
+ try {
3634
+ const typeName = this.parseTypeNotClass();
3635
+ const isArray = this.match("[]");
3636
+ type = { name: typeName, isArray };
3637
+ } catch (error) {
3638
+ throw new Error(
3639
+ `Field "${name}": ${error instanceof Error ? error.message : "Unknown error"}`
3640
+ );
3641
+ }
3614
3642
  }
3643
+ }
3644
+ this.skipWhitespace();
3645
+ const desc = this.parseParsedString();
3646
+ if (type?.name === "class") {
3647
+ return {
3648
+ name,
3649
+ desc: desc?.trim(),
3650
+ type,
3651
+ isOptional
3652
+ };
3615
3653
  } else {
3616
- this.skipWhitespace();
3617
- const desc = this.parseParsedString();
3618
3654
  return {
3619
3655
  name,
3620
3656
  desc: desc?.trim(),
3621
- type: void 0,
3657
+ type,
3622
3658
  isOptional
3623
3659
  };
3624
3660
  }
@@ -3634,14 +3670,17 @@ var SignatureParser = class {
3634
3670
  "datetime",
3635
3671
  "date"
3636
3672
  ];
3637
- for (const type of types) {
3638
- if (this.match(type)) {
3639
- return type;
3640
- }
3673
+ const foundType = types.find((type) => this.match(type));
3674
+ if (!foundType) {
3675
+ const currentWord = this.input.slice(this.position).match(/^\w+/)?.[0] || "empty";
3676
+ throw new Error(
3677
+ `Invalid type "${currentWord}". Expected one of: ${types.join(", ")}`
3678
+ );
3641
3679
  }
3642
- throw new Error(`Expected one of ${types.join(", ")}`);
3680
+ return foundType;
3643
3681
  }
3644
3682
  parseParsedIdentifier() {
3683
+ this.skipWhitespace();
3645
3684
  const match = /^[a-zA-Z_][a-zA-Z_0-9]*/.exec(
3646
3685
  this.input.slice(this.position)
3647
3686
  );
@@ -3649,40 +3688,69 @@ var SignatureParser = class {
3649
3688
  this.position += match[0].length;
3650
3689
  return match[0];
3651
3690
  }
3652
- throw new Error("Expected identifier");
3691
+ const invalidMatch = /^\S+/.exec(this.input.slice(this.position));
3692
+ const invalidId = invalidMatch ? invalidMatch[0] : "empty";
3693
+ throw new Error(
3694
+ `Invalid identifier "${invalidId}". Identifiers must start with a letter or underscore and contain only letters, numbers, or underscores`
3695
+ );
3653
3696
  }
3654
3697
  parseParsedString() {
3655
- if (this.match("'")) {
3656
- const endQuote = this.input.indexOf("'", this.position);
3657
- if (endQuote === -1) throw new Error("Unterminated string");
3658
- const content = this.input.slice(this.position, endQuote);
3659
- this.position = endQuote + 1;
3660
- return content;
3661
- } else if (this.match('"')) {
3662
- const endQuote = this.input.indexOf('"', this.position);
3663
- if (endQuote === -1) throw new Error("Unterminated string");
3664
- const content = this.input.slice(this.position, endQuote);
3665
- this.position = endQuote + 1;
3666
- return content;
3698
+ const quoteChars = ["'", '"'];
3699
+ for (const quoteChar of quoteChars) {
3700
+ if (this.match(quoteChar)) {
3701
+ let content = "";
3702
+ let escaped = false;
3703
+ let startPos = this.position;
3704
+ while (this.position < this.input.length) {
3705
+ const char = this.input[this.position];
3706
+ this.position++;
3707
+ if (escaped) {
3708
+ content += char;
3709
+ escaped = false;
3710
+ } else if (char === "\\") {
3711
+ escaped = true;
3712
+ } else if (char === quoteChar) {
3713
+ return content;
3714
+ } else {
3715
+ content += char;
3716
+ }
3717
+ }
3718
+ const partialString = this.input.slice(startPos, this.position);
3719
+ throw new Error(
3720
+ `Unterminated string starting at position ${startPos}: "${partialString}..."`
3721
+ );
3722
+ }
3667
3723
  }
3668
3724
  return void 0;
3669
3725
  }
3670
3726
  skipWhitespace() {
3671
- const match = /^[ \t\r\n]+/.exec(this.input.slice(this.position));
3727
+ const match = /^[\s\t\r\n]+/.exec(this.input.slice(this.position));
3672
3728
  if (match) {
3673
3729
  this.position += match[0].length;
3674
3730
  }
3675
3731
  }
3676
- match(str) {
3677
- if (this.input.startsWith(str, this.position)) {
3678
- this.position += str.length;
3679
- return true;
3732
+ match(strOrRegex) {
3733
+ let match;
3734
+ if (typeof strOrRegex === "string") {
3735
+ if (this.input.startsWith(strOrRegex, this.position)) {
3736
+ this.position += strOrRegex.length;
3737
+ return true;
3738
+ }
3739
+ } else {
3740
+ match = strOrRegex.exec(this.input.slice(this.position));
3741
+ if (match) {
3742
+ this.position += match[0].length;
3743
+ return true;
3744
+ }
3680
3745
  }
3681
3746
  return false;
3682
3747
  }
3683
3748
  expect(str) {
3684
3749
  if (!this.match(str)) {
3685
- throw new Error(`Expected "${str}"`);
3750
+ const found = this.input.slice(this.position, this.position + 10);
3751
+ throw new Error(
3752
+ `Expected "${str}" but found "${found}..." at position ${this.position}`
3753
+ );
3686
3754
  }
3687
3755
  }
3688
3756
  };
@@ -4783,9 +4851,6 @@ var checkMissingRequiredFields = (xstate, values, currentIndex) => {
4783
4851
  }
4784
4852
  };
4785
4853
  var streamingExtractValues = (sig, values, xstate, content) => {
4786
- if (content.endsWith("\n")) {
4787
- return true;
4788
- }
4789
4854
  const fields = sig.getOutputFields();
4790
4855
  for (const [index, field] of fields.entries()) {
4791
4856
  if (field.name in values) {
@@ -4801,10 +4866,6 @@ var streamingExtractValues = (sig, values, xstate, content) => {
4801
4866
  return true;
4802
4867
  }
4803
4868
  let prefixLen = prefix.length;
4804
- if (e - 1 >= 0 && content[e - 1] === "\n") {
4805
- e -= 1;
4806
- prefixLen += 1;
4807
- }
4808
4869
  if (xstate.currField) {
4809
4870
  const val = content.substring(xstate.s, e).trim();
4810
4871
  const parsedValue = validateAndParseFieldValue(xstate.currField, val);
@@ -4871,7 +4932,7 @@ var convertValueToType = (field, val) => {
4871
4932
  return val;
4872
4933
  }
4873
4934
  };
4874
- function* streamValues(sig, values, xstate, content) {
4935
+ function* streamValues(sig, values, xstate, content, final = false) {
4875
4936
  if (!xstate.currField) {
4876
4937
  return;
4877
4938
  }
@@ -4879,13 +4940,17 @@ function* streamValues(sig, values, xstate, content) {
4879
4940
  if (!xstate.streamedIndex) {
4880
4941
  xstate.streamedIndex = { [fieldName]: 0 };
4881
4942
  }
4882
- if (!xstate.currField.type || !xstate.currField.type.isArray && xstate.currField.type.name === "string") {
4883
- const pos = xstate.streamedIndex[fieldName] ?? 0;
4884
- const s = xstate.s + pos;
4885
- const v = content.substring(s);
4886
- yield { [fieldName]: pos === 0 ? v.trimStart() : v };
4887
- xstate.streamedIndex[fieldName] = pos + v.length;
4888
- return;
4943
+ if (!final) {
4944
+ if (!xstate.currField.type || !xstate.currField.type.isArray && xstate.currField.type.name === "string") {
4945
+ const pos = xstate.streamedIndex[fieldName] ?? 0;
4946
+ const s = xstate.s + pos;
4947
+ const v = content.substring(s);
4948
+ const v1 = v.replace(/[\s\n\t]+$/, "");
4949
+ const v2 = pos === 0 ? v1.trimStart() : v1;
4950
+ yield { [fieldName]: v2 };
4951
+ xstate.streamedIndex[fieldName] = pos + v1.length;
4952
+ return;
4953
+ }
4889
4954
  }
4890
4955
  for (const key of Object.keys(values)) {
4891
4956
  const value = values[key];
@@ -4919,7 +4984,7 @@ function validateAndParseFieldValue(field, fieldValue) {
4919
4984
  if (field.type?.name === "json") {
4920
4985
  try {
4921
4986
  const text = extractBlock(fieldValue);
4922
- value = JSON5.parse(text);
4987
+ value = JSON.parse(text);
4923
4988
  return value;
4924
4989
  } catch (e) {
4925
4990
  throw new ValidationError({
@@ -4932,7 +4997,7 @@ function validateAndParseFieldValue(field, fieldValue) {
4932
4997
  if (field.type?.isArray) {
4933
4998
  try {
4934
4999
  try {
4935
- value = JSON5.parse(fieldValue);
5000
+ value = JSON.parse(fieldValue);
4936
5001
  } catch {
4937
5002
  value = parseMarkdownList(fieldValue);
4938
5003
  }
@@ -4985,9 +5050,6 @@ var extractBlock = (input) => {
4985
5050
  return input;
4986
5051
  };
4987
5052
 
4988
- // dsp/functions.ts
4989
- import JSON52 from "json5";
4990
-
4991
5053
  // dsp/jsonschema.ts
4992
5054
  var validateJSONSchema = (schema) => {
4993
5055
  const errors = [];
@@ -5045,7 +5107,7 @@ var AxFunctionProcessor = class {
5045
5107
  executeFunction = async (fnSpec, func, options) => {
5046
5108
  let args;
5047
5109
  if (typeof func.args === "string" && func.args.length > 0) {
5048
- args = JSON52.parse(func.args);
5110
+ args = JSON.parse(func.args);
5049
5111
  } else {
5050
5112
  args = func.args;
5051
5113
  }
@@ -5311,6 +5373,7 @@ var AxGen = class extends AxProgramWithSignature {
5311
5373
  );
5312
5374
  this.functionsExecuted = /* @__PURE__ */ new Set([...this.functionsExecuted, ...fx]);
5313
5375
  }
5376
+ streamingExtractFinalValue(this.signature, values, xstate, content);
5314
5377
  assertStreamingAssertions(
5315
5378
  this.streamingAsserts,
5316
5379
  values,
@@ -5318,9 +5381,8 @@ var AxGen = class extends AxProgramWithSignature {
5318
5381
  content,
5319
5382
  true
5320
5383
  );
5321
- streamingExtractFinalValue(this.signature, values, xstate, content);
5322
5384
  assertAssertions(this.asserts, values);
5323
- yield* streamValues(this.signature, values, xstate, content);
5385
+ yield* streamValues(this.signature, values, xstate, content, true);
5324
5386
  }
5325
5387
  async processResponse({
5326
5388
  ai,
@@ -5332,37 +5394,35 @@ var AxGen = class extends AxProgramWithSignature {
5332
5394
  functions
5333
5395
  }) {
5334
5396
  const values = {};
5335
- const result = res.results[0];
5336
- if (!result) {
5337
- throw new Error("No result found");
5338
- }
5339
- if (res.modelUsage) {
5340
- this.usage.push({ ...usageInfo, ...res.modelUsage });
5341
- }
5342
- mem.addResult(result, sessionId);
5343
- if (result.content) {
5344
- extractValues(this.signature, values, result.content);
5345
- assertAssertions(this.asserts, values);
5346
- }
5347
- if (result.functionCalls) {
5348
- const funcs = parseFunctionCalls(ai, result.functionCalls, values);
5349
- if (funcs) {
5350
- if (!functions) {
5351
- throw new Error("Functions are not defined");
5397
+ for (const result of res.results ?? []) {
5398
+ if (res.modelUsage) {
5399
+ this.usage.push({ ...usageInfo, ...res.modelUsage });
5400
+ }
5401
+ mem.addResult(result, sessionId);
5402
+ if (result.content) {
5403
+ extractValues(this.signature, values, result.content);
5404
+ assertAssertions(this.asserts, values);
5405
+ }
5406
+ if (result.functionCalls) {
5407
+ const funcs = parseFunctionCalls(ai, result.functionCalls, values);
5408
+ if (funcs) {
5409
+ if (!functions) {
5410
+ throw new Error("Functions are not defined");
5411
+ }
5412
+ const fx = await processFunctions(
5413
+ ai,
5414
+ functions,
5415
+ funcs,
5416
+ mem,
5417
+ sessionId,
5418
+ traceId
5419
+ );
5420
+ this.functionsExecuted = /* @__PURE__ */ new Set([...this.functionsExecuted, ...fx]);
5352
5421
  }
5353
- const fx = await processFunctions(
5354
- ai,
5355
- functions,
5356
- funcs,
5357
- mem,
5358
- sessionId,
5359
- traceId
5360
- );
5361
- this.functionsExecuted = /* @__PURE__ */ new Set([...this.functionsExecuted, ...fx]);
5362
5422
  }
5363
- }
5364
- if (result.finishReason === "length") {
5365
- throw new Error("Max tokens reached before completion");
5423
+ if (result.finishReason === "length") {
5424
+ throw new Error("Max tokens reached before completion");
5425
+ }
5366
5426
  }
5367
5427
  return { ...values };
5368
5428
  }