@ax-llm/ax 11.0.67 → 12.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.cjs CHANGED
@@ -159,6 +159,7 @@ __export(index_exports, {
159
159
  axAITogetherDefaultConfig: () => axAITogetherDefaultConfig,
160
160
  axBaseAIDefaultConfig: () => axBaseAIDefaultConfig,
161
161
  axBaseAIDefaultCreativeConfig: () => axBaseAIDefaultCreativeConfig,
162
+ axGlobals: () => axGlobals,
162
163
  axModelInfoAnthropic: () => axModelInfoAnthropic,
163
164
  axModelInfoCohere: () => axModelInfoCohere,
164
165
  axModelInfoDeepSeek: () => axModelInfoDeepSeek,
@@ -6727,6 +6728,11 @@ var extractValues = (sig, values, content) => {
6727
6728
  const xstate = { extractedFields: [], streamedIndex: {}, s: -1 };
6728
6729
  streamingExtractValues(sig, values, xstate, content);
6729
6730
  streamingExtractFinalValue(sig, values, xstate, content);
6731
+ for (const field of sig.getOutputFields()) {
6732
+ if (field.isInternal) {
6733
+ delete values[field.name];
6734
+ }
6735
+ }
6730
6736
  };
6731
6737
  var checkMissingRequiredFields = (xstate, values, currentIndex) => {
6732
6738
  const missingFields = [];
@@ -7452,93 +7458,218 @@ var AxInstanceRegistry = class {
7452
7458
  // dsp/sig.ts
7453
7459
  var import_crypto3 = require("crypto");
7454
7460
 
7461
+ // dsp/globals.ts
7462
+ var axGlobals = {
7463
+ signatureStrict: true
7464
+ // Controls reservedNames enforcement in signature parsing/validation
7465
+ };
7466
+
7455
7467
  // dsp/parser.ts
7468
+ var SignatureValidationError = class extends Error {
7469
+ constructor(message, position, context3, suggestion) {
7470
+ super(message);
7471
+ this.position = position;
7472
+ this.context = context3;
7473
+ this.suggestion = suggestion;
7474
+ this.name = "SignatureValidationError";
7475
+ }
7476
+ };
7456
7477
  var SignatureParser = class {
7457
7478
  input;
7458
7479
  position;
7459
7480
  currentFieldName = null;
7481
+ currentSection = "description";
7460
7482
  constructor(input) {
7461
- this.input = input;
7483
+ this.input = input.trim();
7462
7484
  this.position = 0;
7485
+ if (!this.input) {
7486
+ throw new SignatureValidationError(
7487
+ "Empty signature provided",
7488
+ 0,
7489
+ "",
7490
+ 'A signature must contain at least input and output fields separated by "->". Example: "userQuery:string -> aiResponse:string"'
7491
+ );
7492
+ }
7463
7493
  }
7464
7494
  parse() {
7465
7495
  try {
7466
7496
  this.skipWhitespace();
7467
7497
  const optionalDesc = this.parseParsedString();
7468
7498
  this.skipWhitespace();
7499
+ this.currentSection = "inputs";
7469
7500
  const inputs = this.parseFieldList(
7470
7501
  this.parseInputField.bind(this),
7471
7502
  "input"
7472
7503
  );
7473
7504
  this.skipWhitespace();
7474
7505
  if (this.position >= this.input.length) {
7475
- throw new Error(
7476
- 'Incomplete signature: Missing output section. Expected "->" followed by output fields'
7506
+ throw new SignatureValidationError(
7507
+ "Incomplete signature: Missing output section",
7508
+ this.position,
7509
+ this.getErrorContext(),
7510
+ 'Add "->" followed by output fields. Example: "-> responseText:string"'
7477
7511
  );
7478
7512
  }
7479
- this.expect("->");
7513
+ this.expectArrow();
7480
7514
  this.skipWhitespace();
7481
7515
  if (this.position >= this.input.length) {
7482
- throw new Error(
7483
- 'Incomplete signature: No output fields specified after "->"'
7516
+ throw new SignatureValidationError(
7517
+ 'Incomplete signature: No output fields specified after "->"',
7518
+ this.position,
7519
+ this.getErrorContext(),
7520
+ 'Add at least one output field. Example: "-> responseText:string"'
7484
7521
  );
7485
7522
  }
7523
+ this.currentSection = "outputs";
7486
7524
  const outputs = this.parseFieldList(
7487
7525
  this.parseOutputField.bind(this),
7488
7526
  "output"
7489
7527
  );
7528
+ this.skipWhitespace();
7529
+ if (this.position < this.input.length) {
7530
+ const remaining = this.input.slice(this.position);
7531
+ throw new SignatureValidationError(
7532
+ `Unexpected content after signature: "${remaining}"`,
7533
+ this.position,
7534
+ this.getErrorContext(),
7535
+ "Remove any extra content after the output fields"
7536
+ );
7537
+ }
7538
+ this.validateParsedSignature({
7539
+ desc: optionalDesc?.trim(),
7540
+ inputs,
7541
+ outputs
7542
+ });
7490
7543
  return {
7491
7544
  desc: optionalDesc?.trim(),
7492
7545
  inputs,
7493
7546
  outputs
7494
7547
  };
7495
7548
  } catch (error) {
7549
+ if (error instanceof SignatureValidationError) {
7550
+ throw error;
7551
+ }
7496
7552
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
7497
- const context3 = this.getErrorContext();
7498
- throw new Error(`${errorMessage}
7499
- ${context3}`);
7553
+ throw new SignatureValidationError(
7554
+ errorMessage,
7555
+ this.position,
7556
+ this.getErrorContext()
7557
+ );
7558
+ }
7559
+ }
7560
+ validateParsedSignature(signature) {
7561
+ const inputNames = /* @__PURE__ */ new Set();
7562
+ for (const field of signature.inputs) {
7563
+ if (inputNames.has(field.name)) {
7564
+ throw new SignatureValidationError(
7565
+ `Duplicate input field name: "${field.name}"`,
7566
+ 0,
7567
+ "",
7568
+ "Each field name must be unique within the signature"
7569
+ );
7570
+ }
7571
+ inputNames.add(field.name);
7572
+ }
7573
+ const outputNames = /* @__PURE__ */ new Set();
7574
+ for (const field of signature.outputs) {
7575
+ if (outputNames.has(field.name)) {
7576
+ throw new SignatureValidationError(
7577
+ `Duplicate output field name: "${field.name}"`,
7578
+ 0,
7579
+ "",
7580
+ "Each field name must be unique within the signature"
7581
+ );
7582
+ }
7583
+ outputNames.add(field.name);
7584
+ }
7585
+ for (const outputField of signature.outputs) {
7586
+ if (inputNames.has(outputField.name)) {
7587
+ throw new SignatureValidationError(
7588
+ `Field name "${outputField.name}" appears in both inputs and outputs`,
7589
+ 0,
7590
+ "",
7591
+ "Use different names for input and output fields to avoid confusion"
7592
+ );
7593
+ }
7594
+ }
7595
+ if (signature.inputs.length === 0) {
7596
+ throw new SignatureValidationError(
7597
+ "Signature must have at least one input field",
7598
+ 0,
7599
+ "",
7600
+ 'Add an input field before "->". Example: "userInput:string -> ..."'
7601
+ );
7602
+ }
7603
+ if (signature.outputs.length === 0) {
7604
+ throw new SignatureValidationError(
7605
+ "Signature must have at least one output field",
7606
+ 0,
7607
+ "",
7608
+ 'Add an output field after "->". Example: "... -> responseText:string"'
7609
+ );
7500
7610
  }
7501
7611
  }
7502
7612
  getErrorContext() {
7503
- const start = Math.max(0, this.position - 20);
7504
- const end = Math.min(this.input.length, this.position + 20);
7613
+ const start = Math.max(0, this.position - 25);
7614
+ const end = Math.min(this.input.length, this.position + 25);
7505
7615
  const before = this.input.slice(start, this.position);
7506
7616
  const after = this.input.slice(this.position, end);
7507
7617
  const pointer = " ".repeat(before.length) + "^";
7508
- return `Near position ${this.position}:
7509
- ${before}${after}
7510
- ${pointer}`;
7618
+ const lines = [
7619
+ `Position ${this.position} in signature:`,
7620
+ `"${before}${after}"`,
7621
+ ` ${pointer}`
7622
+ ];
7623
+ return lines.join("\n");
7511
7624
  }
7512
7625
  parseFieldList(parseFieldFn, section) {
7513
7626
  const fields = [];
7514
7627
  this.skipWhitespace();
7515
7628
  if (this.position >= this.input.length) {
7516
- throw new Error(`Empty ${section} section: Expected at least one field`);
7629
+ throw new SignatureValidationError(
7630
+ `Empty ${section} section: Expected at least one field`,
7631
+ this.position,
7632
+ this.getErrorContext(),
7633
+ `Add a ${section} field. Example: ${section === "input" ? "userInput:string" : "responseText:string"}`
7634
+ );
7517
7635
  }
7518
7636
  try {
7519
7637
  fields.push(parseFieldFn());
7520
7638
  } catch (error) {
7521
- throw new Error(
7522
- `Invalid first ${section} field: ${error instanceof Error ? error.message : "Unknown error"}`
7639
+ if (error instanceof SignatureValidationError) {
7640
+ throw error;
7641
+ }
7642
+ throw new SignatureValidationError(
7643
+ `Invalid first ${section} field: ${error instanceof Error ? error.message : "Unknown error"}`,
7644
+ this.position,
7645
+ this.getErrorContext()
7523
7646
  );
7524
7647
  }
7525
7648
  this.skipWhitespace();
7526
7649
  while (this.position < this.input.length) {
7527
- if (this.input[this.position] === "-" && this.input[this.position + 1] === ">") {
7650
+ if (this.input[this.position] === "-" && this.position + 1 < this.input.length && this.input[this.position + 1] === ">") {
7528
7651
  break;
7529
7652
  }
7530
7653
  if (this.match(",")) {
7531
7654
  this.skipWhitespace();
7532
7655
  if (this.position >= this.input.length) {
7533
- throw new Error(
7534
- `Unexpected end of input after comma in ${section} section`
7656
+ throw new SignatureValidationError(
7657
+ `Unexpected end of input after comma in ${section} section`,
7658
+ this.position,
7659
+ this.getErrorContext(),
7660
+ `Add another ${section} field after the comma`
7535
7661
  );
7536
7662
  }
7537
7663
  try {
7538
7664
  fields.push(parseFieldFn());
7539
7665
  } catch (error) {
7540
- throw new Error(
7541
- `Invalid ${section} field after comma: ${error instanceof Error ? error.message : "Unknown error"}`
7666
+ if (error instanceof SignatureValidationError) {
7667
+ throw error;
7668
+ }
7669
+ throw new SignatureValidationError(
7670
+ `Invalid ${section} field after comma: ${error instanceof Error ? error.message : "Unknown error"}`,
7671
+ this.position,
7672
+ this.getErrorContext()
7542
7673
  );
7543
7674
  }
7544
7675
  this.skipWhitespace();
@@ -7555,6 +7686,7 @@ ${pointer}`;
7555
7686
  this.skipWhitespace();
7556
7687
  const name = this.parseParsedIdentifier();
7557
7688
  this.currentFieldName = name;
7689
+ this.validateFieldName(name, "input");
7558
7690
  let isOptional = void 0;
7559
7691
  while (true) {
7560
7692
  if (this.match("?")) {
@@ -7562,8 +7694,11 @@ ${pointer}`;
7562
7694
  continue;
7563
7695
  }
7564
7696
  if (this.match("!")) {
7565
- throw new Error(
7566
- `Input field "${name}" does not support the internal marker "!"`
7697
+ throw new SignatureValidationError(
7698
+ `Input field "${name}" cannot use the internal marker "!"`,
7699
+ this.position - 1,
7700
+ this.getErrorContext(),
7701
+ "Internal markers (!) are only allowed on output fields"
7567
7702
  );
7568
7703
  }
7569
7704
  break;
@@ -7573,17 +7708,33 @@ ${pointer}`;
7573
7708
  if (this.match(":")) {
7574
7709
  this.skipWhitespace();
7575
7710
  if (/^class\b/.test(this.input.slice(this.position))) {
7576
- throw new Error(
7577
- `Input field "${name}" does not support the "class" type`
7711
+ throw new SignatureValidationError(
7712
+ `Input field "${name}" cannot use the "class" type`,
7713
+ this.position,
7714
+ this.getErrorContext(),
7715
+ 'Class types are only allowed on output fields. Use "string" type for input classifications'
7578
7716
  );
7579
7717
  } else {
7580
7718
  try {
7581
7719
  const typeName = this.parseTypeNotClass();
7582
7720
  const isArray = this.match("[]");
7583
7721
  type = { name: typeName, isArray };
7722
+ if ((typeName === "image" || typeName === "audio") && isArray) {
7723
+ throw new SignatureValidationError(
7724
+ `Input field "${name}": Arrays of ${typeName} are not supported`,
7725
+ this.position,
7726
+ this.getErrorContext(),
7727
+ `Use a single ${typeName} type instead: "${typeName}"`
7728
+ );
7729
+ }
7584
7730
  } catch (error) {
7585
- throw new Error(
7586
- `Input field "${name}": ${error instanceof Error ? error.message : "Unknown error"}`
7731
+ if (error instanceof SignatureValidationError) {
7732
+ throw error;
7733
+ }
7734
+ throw new SignatureValidationError(
7735
+ `Input field "${name}": ${error instanceof Error ? error.message : "Unknown error"}`,
7736
+ this.position,
7737
+ this.getErrorContext()
7587
7738
  );
7588
7739
  }
7589
7740
  }
@@ -7604,6 +7755,7 @@ ${pointer}`;
7604
7755
  this.skipWhitespace();
7605
7756
  const name = this.parseParsedIdentifier();
7606
7757
  this.currentFieldName = name;
7758
+ this.validateFieldName(name, "output");
7607
7759
  let isOptional = false;
7608
7760
  let isInternal = false;
7609
7761
  while (true) {
@@ -7626,25 +7778,86 @@ ${pointer}`;
7626
7778
  this.skipWhitespace();
7627
7779
  const classNamesString = this.parseParsedString();
7628
7780
  if (!classNamesString) {
7629
- throw new Error(
7630
- `Output field "${name}": Expected class names in quotes after "class" type. Example: class "MyClass1, MyClass2"`
7781
+ throw new SignatureValidationError(
7782
+ `Output field "${name}": Missing class options after "class" type`,
7783
+ this.position,
7784
+ this.getErrorContext(),
7785
+ 'Add class names in quotes. Example: class "positive, negative, neutral"'
7631
7786
  );
7632
7787
  }
7633
7788
  const options = classNamesString.split(/[,\s]+/).map((s2) => s2.trim()).filter((s2) => s2.length > 0);
7634
7789
  if (options.length === 0) {
7635
- throw new Error(
7636
- `Output field "${name}": Empty class list provided. At least one class name is required`
7790
+ throw new SignatureValidationError(
7791
+ `Output field "${name}": Empty class list provided`,
7792
+ this.position,
7793
+ this.getErrorContext(),
7794
+ 'Provide at least one class option. Example: "positive, negative"'
7637
7795
  );
7638
7796
  }
7797
+ if (options.length === 1) {
7798
+ throw new SignatureValidationError(
7799
+ `Output field "${name}": Class type needs at least 2 options`,
7800
+ this.position,
7801
+ this.getErrorContext(),
7802
+ 'Add more class options or use "string" type instead. Example: "positive, negative, neutral"'
7803
+ );
7804
+ }
7805
+ for (const option of options) {
7806
+ if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(option)) {
7807
+ throw new SignatureValidationError(
7808
+ `Output field "${name}": Invalid class option "${option}"`,
7809
+ this.position,
7810
+ this.getErrorContext(),
7811
+ "Class options must start with a letter and contain only letters, numbers, underscores, or hyphens"
7812
+ );
7813
+ }
7814
+ }
7639
7815
  type = { name: "class", isArray, options };
7640
7816
  } else {
7641
7817
  try {
7642
7818
  const typeName = this.parseTypeNotClass();
7643
7819
  const isArray = this.match("[]");
7644
7820
  type = { name: typeName, isArray };
7821
+ if (typeName === "image" && isArray) {
7822
+ throw new SignatureValidationError(
7823
+ `Output field "${name}": Arrays of images are not supported`,
7824
+ this.position,
7825
+ this.getErrorContext(),
7826
+ 'Use a single image type instead: "image"'
7827
+ );
7828
+ }
7829
+ if (typeName === "audio" && isArray) {
7830
+ throw new SignatureValidationError(
7831
+ `Output field "${name}": Arrays of audio are not supported`,
7832
+ this.position,
7833
+ this.getErrorContext(),
7834
+ 'Use a single audio type instead: "audio"'
7835
+ );
7836
+ }
7837
+ if (typeName === "image") {
7838
+ throw new SignatureValidationError(
7839
+ `Output field "${name}": Image type is not supported in output fields`,
7840
+ this.position,
7841
+ this.getErrorContext(),
7842
+ "Image types can only be used in input fields"
7843
+ );
7844
+ }
7845
+ if (typeName === "audio") {
7846
+ throw new SignatureValidationError(
7847
+ `Output field "${name}": Audio type is not supported in output fields`,
7848
+ this.position,
7849
+ this.getErrorContext(),
7850
+ "Audio types can only be used in input fields"
7851
+ );
7852
+ }
7645
7853
  } catch (error) {
7646
- throw new Error(
7647
- `Output field "${name}": ${error instanceof Error ? error.message : "Unknown error"}`
7854
+ if (error instanceof SignatureValidationError) {
7855
+ throw error;
7856
+ }
7857
+ throw new SignatureValidationError(
7858
+ `Output field "${name}": ${error instanceof Error ? error.message : "Unknown error"}`,
7859
+ this.position,
7860
+ this.getErrorContext()
7648
7861
  );
7649
7862
  }
7650
7863
  }
@@ -7659,6 +7872,69 @@ ${pointer}`;
7659
7872
  isInternal
7660
7873
  };
7661
7874
  }
7875
+ validateFieldName(name, fieldType) {
7876
+ if (axGlobals.signatureStrict) {
7877
+ const reservedNames = [
7878
+ "text",
7879
+ "object",
7880
+ "image",
7881
+ "string",
7882
+ "number",
7883
+ "boolean",
7884
+ "json",
7885
+ "array",
7886
+ "datetime",
7887
+ "date",
7888
+ "time",
7889
+ "type",
7890
+ "class",
7891
+ "input",
7892
+ "output",
7893
+ "data",
7894
+ "value",
7895
+ "result",
7896
+ "response",
7897
+ "request",
7898
+ "item",
7899
+ "element"
7900
+ ];
7901
+ if (reservedNames.includes(name.toLowerCase())) {
7902
+ const suggestions = fieldType === "input" ? ["userInput", "questionText", "documentContent", "messageText"] : ["responseText", "analysisResult", "categoryType", "summaryText"];
7903
+ throw new SignatureValidationError(
7904
+ `Field name "${name}" is too generic`,
7905
+ this.position,
7906
+ this.getErrorContext(),
7907
+ `Use a more descriptive name. Examples: ${suggestions.join(", ")}`
7908
+ );
7909
+ }
7910
+ }
7911
+ const camelCaseRegex = /^[a-z][a-zA-Z0-9]*$/;
7912
+ const snakeCaseRegex = /^[a-z]+(_[a-z0-9]+)*$/;
7913
+ if (!camelCaseRegex.test(name) && !snakeCaseRegex.test(name)) {
7914
+ throw new SignatureValidationError(
7915
+ `Invalid field name "${name}"`,
7916
+ this.position,
7917
+ this.getErrorContext(),
7918
+ 'Field names must be in camelCase (e.g., "userInput") or snake_case (e.g., "user_input")'
7919
+ );
7920
+ }
7921
+ if (name.length < 2) {
7922
+ throw new SignatureValidationError(
7923
+ `Field name "${name}" is too short`,
7924
+ this.position,
7925
+ this.getErrorContext(),
7926
+ "Field names must be at least 2 characters long"
7927
+ );
7928
+ }
7929
+ if (name.length > 50) {
7930
+ throw new SignatureValidationError(
7931
+ `Field name "${name}" is too long (${name.length} characters)`,
7932
+ this.position,
7933
+ this.getErrorContext(),
7934
+ "Field names should be 50 characters or less"
7935
+ );
7936
+ }
7937
+ }
7662
7938
  parseTypeNotClass() {
7663
7939
  const types = [
7664
7940
  "string",
@@ -7673,13 +7949,42 @@ ${pointer}`;
7673
7949
  ];
7674
7950
  const foundType = types.find((type) => this.match(type));
7675
7951
  if (!foundType) {
7676
- const currentWord = this.input.slice(this.position).match(/^\w+/)?.[0] || "empty";
7677
- throw new Error(
7678
- `Invalid type "${currentWord}". Expected one of: ${types.join(", ")}`
7952
+ const currentWord = this.input.slice(this.position).match(/^\w+/)?.[0] || "";
7953
+ const suggestion = this.suggestType(currentWord);
7954
+ const baseMessage = `Invalid type "${currentWord || "empty"}"`;
7955
+ const suggestionPart = suggestion ? `. Did you mean "${suggestion}"?` : "";
7956
+ const fullMessage = `${baseMessage}${suggestionPart}`;
7957
+ throw new SignatureValidationError(
7958
+ fullMessage,
7959
+ this.position,
7960
+ this.getErrorContext(),
7961
+ `Expected one of: ${types.join(", ")}`
7679
7962
  );
7680
7963
  }
7681
7964
  return foundType;
7682
7965
  }
7966
+ suggestType(input) {
7967
+ const suggestions = {
7968
+ str: "string",
7969
+ text: "string",
7970
+ int: "number",
7971
+ integer: "number",
7972
+ float: "number",
7973
+ double: "number",
7974
+ bool: "boolean",
7975
+ object: "json",
7976
+ dict: "json",
7977
+ timestamp: "datetime",
7978
+ time: "datetime",
7979
+ img: "image",
7980
+ picture: "image",
7981
+ sound: "audio",
7982
+ voice: "audio",
7983
+ classification: "class",
7984
+ category: "class"
7985
+ };
7986
+ return suggestions[input.toLowerCase()] || null;
7987
+ }
7683
7988
  parseParsedIdentifier() {
7684
7989
  this.skipWhitespace();
7685
7990
  const match = /^[a-zA-Z_][a-zA-Z_0-9]*/.exec(
@@ -7690,9 +7995,28 @@ ${pointer}`;
7690
7995
  return match[0];
7691
7996
  }
7692
7997
  const invalidMatch = /^\S+/.exec(this.input.slice(this.position));
7693
- const invalidId = invalidMatch ? invalidMatch[0] : "empty";
7694
- throw new Error(
7695
- `Invalid identifier "${invalidId}". Identifiers must start with a letter or underscore and contain only letters, numbers, or underscores`
7998
+ const invalidId = invalidMatch ? invalidMatch[0] : "";
7999
+ if (invalidId === "") {
8000
+ throw new SignatureValidationError(
8001
+ "Expected field name but found end of input",
8002
+ this.position,
8003
+ this.getErrorContext(),
8004
+ "Add a field name. Field names must start with a letter or underscore"
8005
+ );
8006
+ }
8007
+ if (/^\d/.test(invalidId)) {
8008
+ throw new SignatureValidationError(
8009
+ `Invalid field name "${invalidId}" - cannot start with a number`,
8010
+ this.position,
8011
+ this.getErrorContext(),
8012
+ 'Field names must start with a letter or underscore. Example: "userInput" or "_internal"'
8013
+ );
8014
+ }
8015
+ throw new SignatureValidationError(
8016
+ `Invalid field name "${invalidId}"`,
8017
+ this.position,
8018
+ this.getErrorContext(),
8019
+ "Field names must start with a letter or underscore and contain only letters, numbers, or underscores"
7696
8020
  );
7697
8021
  }
7698
8022
  parseParsedString() {
@@ -7701,7 +8025,7 @@ ${pointer}`;
7701
8025
  if (this.match(quoteChar)) {
7702
8026
  let content = "";
7703
8027
  let escaped = false;
7704
- let startPos = this.position;
8028
+ const startPos = this.position - 1;
7705
8029
  while (this.position < this.input.length) {
7706
8030
  const char = this.input[this.position];
7707
8031
  this.position++;
@@ -7716,9 +8040,15 @@ ${pointer}`;
7716
8040
  content += char;
7717
8041
  }
7718
8042
  }
7719
- const partialString = this.input.slice(startPos, this.position);
7720
- throw new Error(
7721
- `Unterminated string starting at position ${startPos}: "${partialString}..."`
8043
+ const partialString = this.input.slice(
8044
+ startPos,
8045
+ Math.min(this.position, startPos + 20)
8046
+ );
8047
+ throw new SignatureValidationError(
8048
+ `Unterminated string starting at position ${startPos}`,
8049
+ startPos,
8050
+ this.getErrorContext(),
8051
+ `Add closing ${quoteChar} to complete the string: ${partialString}${quoteChar}`
7722
8052
  );
7723
8053
  }
7724
8054
  }
@@ -7746,11 +8076,15 @@ ${pointer}`;
7746
8076
  }
7747
8077
  return false;
7748
8078
  }
7749
- expect(str) {
7750
- if (!this.match(str)) {
8079
+ expectArrow() {
8080
+ if (!this.match("->")) {
7751
8081
  const found = this.input.slice(this.position, this.position + 10);
7752
- throw new Error(
7753
- `Expected "${str}" but found "${found}..." at position ${this.position}`
8082
+ const suggestion = found.includes(">") ? 'Use "->" (dash followed by greater-than)' : found.includes("-") ? 'Add ">" after the dash' : 'Add "->" to separate input and output fields';
8083
+ throw new SignatureValidationError(
8084
+ `Expected "->" but found "${found}..."`,
8085
+ this.position,
8086
+ this.getErrorContext(),
8087
+ suggestion
7754
8088
  );
7755
8089
  }
7756
8090
  }
@@ -7761,6 +8095,14 @@ function parseSignature(input) {
7761
8095
  }
7762
8096
 
7763
8097
  // dsp/sig.ts
8098
+ var AxSignatureValidationError = class extends Error {
8099
+ constructor(message, fieldName, suggestion) {
8100
+ super(message);
8101
+ this.fieldName = fieldName;
8102
+ this.suggestion = suggestion;
8103
+ this.name = "AxSignatureValidationError";
8104
+ }
8105
+ };
7764
8106
  var AxSignature = class _AxSignature {
7765
8107
  description;
7766
8108
  inputFields;
@@ -7780,8 +8122,18 @@ var AxSignature = class _AxSignature {
7780
8122
  try {
7781
8123
  sig = parseSignature(signature);
7782
8124
  } catch (e) {
7783
- throw new Error(
7784
- `Invalid Signature: ${e.message} (${signature})`
8125
+ if (e instanceof Error) {
8126
+ const suggestion = "suggestion" in e && typeof e.suggestion === "string" ? e.suggestion : 'Please check the signature format. Example: "userInput:string -> responseText:string"';
8127
+ throw new AxSignatureValidationError(
8128
+ `Invalid Signature: ${e.message}`,
8129
+ void 0,
8130
+ suggestion
8131
+ );
8132
+ }
8133
+ throw new AxSignatureValidationError(
8134
+ `Invalid Signature: ${signature}`,
8135
+ void 0,
8136
+ 'Please check the signature format. Example: "userInput:string -> responseText:string"'
7785
8137
  );
7786
8138
  }
7787
8139
  this.description = sig.desc;
@@ -7799,12 +8151,20 @@ var AxSignature = class _AxSignature {
7799
8151
  this.sigHash = signature.hash();
7800
8152
  this.sigString = signature.toString();
7801
8153
  } else {
7802
- throw new Error("invalid signature argument: " + signature);
8154
+ throw new AxSignatureValidationError(
8155
+ "Invalid signature argument type",
8156
+ void 0,
8157
+ "Signature must be a string or another AxSignature instance"
8158
+ );
7803
8159
  }
7804
8160
  }
7805
8161
  parseParsedField = (field) => {
7806
8162
  if (!field.name || field.name.length === 0) {
7807
- throw new Error("Field name is required.");
8163
+ throw new AxSignatureValidationError(
8164
+ "Field name is required",
8165
+ field.name,
8166
+ 'Every field must have a descriptive name. Example: "userInput", "responseText"'
8167
+ );
7808
8168
  }
7809
8169
  const title = this.toTitle(field.name);
7810
8170
  return {
@@ -7819,29 +8179,106 @@ var AxSignature = class _AxSignature {
7819
8179
  parseField = (field) => {
7820
8180
  const title = !field.title || field.title.length === 0 ? this.toTitle(field.name) : field.title;
7821
8181
  if (field.type && (!field.type.name || field.type.name.length === 0)) {
7822
- throw new Error("Field type name is required: " + field.name);
8182
+ throw new AxSignatureValidationError(
8183
+ "Field type name is required",
8184
+ field.name,
8185
+ "Specify a valid type. Available types: string, number, boolean, json, image, audio, date, datetime, class, code"
8186
+ );
7823
8187
  }
7824
8188
  return { ...field, title };
7825
8189
  };
7826
8190
  setDescription = (desc) => {
8191
+ if (typeof desc !== "string") {
8192
+ throw new AxSignatureValidationError(
8193
+ "Description must be a string",
8194
+ void 0,
8195
+ "Provide a string description for the signature"
8196
+ );
8197
+ }
7827
8198
  this.description = desc;
7828
8199
  this.updateHash();
7829
8200
  };
7830
8201
  addInputField = (field) => {
7831
- this.inputFields.push(this.parseField(field));
7832
- this.updateHash();
8202
+ try {
8203
+ const parsedField = this.parseField(field);
8204
+ validateField(parsedField, "input");
8205
+ this.inputFields.push(parsedField);
8206
+ this.updateHash();
8207
+ } catch (error) {
8208
+ if (error instanceof AxSignatureValidationError) {
8209
+ throw error;
8210
+ }
8211
+ throw new AxSignatureValidationError(
8212
+ `Failed to add input field "${field.name}": ${error instanceof Error ? error.message : "Unknown error"}`,
8213
+ field.name
8214
+ );
8215
+ }
7833
8216
  };
7834
8217
  addOutputField = (field) => {
7835
- this.outputFields.push(this.parseField(field));
7836
- this.updateHash();
8218
+ try {
8219
+ const parsedField = this.parseField(field);
8220
+ validateField(parsedField, "output");
8221
+ this.outputFields.push(parsedField);
8222
+ this.updateHash();
8223
+ } catch (error) {
8224
+ if (error instanceof AxSignatureValidationError) {
8225
+ throw error;
8226
+ }
8227
+ throw new AxSignatureValidationError(
8228
+ `Failed to add output field "${field.name}": ${error instanceof Error ? error.message : "Unknown error"}`,
8229
+ field.name
8230
+ );
8231
+ }
7837
8232
  };
7838
8233
  setInputFields = (fields) => {
7839
- this.inputFields = fields.map((v) => this.parseField(v));
7840
- this.updateHash();
8234
+ if (!Array.isArray(fields)) {
8235
+ throw new AxSignatureValidationError(
8236
+ "Input fields must be an array",
8237
+ void 0,
8238
+ "Provide an array of field objects"
8239
+ );
8240
+ }
8241
+ try {
8242
+ const parsedFields = fields.map((v) => {
8243
+ const parsed = this.parseField(v);
8244
+ validateField(parsed, "input");
8245
+ return parsed;
8246
+ });
8247
+ this.inputFields = parsedFields;
8248
+ this.updateHash();
8249
+ } catch (error) {
8250
+ if (error instanceof AxSignatureValidationError) {
8251
+ throw error;
8252
+ }
8253
+ throw new AxSignatureValidationError(
8254
+ `Failed to set input fields: ${error instanceof Error ? error.message : "Unknown error"}`
8255
+ );
8256
+ }
7841
8257
  };
7842
8258
  setOutputFields = (fields) => {
7843
- this.outputFields = fields.map((v) => this.parseField(v));
7844
- this.updateHash();
8259
+ if (!Array.isArray(fields)) {
8260
+ throw new AxSignatureValidationError(
8261
+ "Output fields must be an array",
8262
+ void 0,
8263
+ "Provide an array of field objects"
8264
+ );
8265
+ }
8266
+ try {
8267
+ const parsedFields = fields.map((v) => {
8268
+ const parsed = this.parseField(v);
8269
+ validateField(parsed, "output");
8270
+ return parsed;
8271
+ });
8272
+ this.outputFields = parsedFields;
8273
+ this.updateHash();
8274
+ } catch (error) {
8275
+ if (error instanceof AxSignatureValidationError) {
8276
+ throw error;
8277
+ }
8278
+ throw new AxSignatureValidationError(
8279
+ `Failed to set output fields: ${error instanceof Error ? error.message : "Unknown error"}`
8280
+ );
8281
+ }
7845
8282
  };
7846
8283
  getInputFields = () => this.inputFields;
7847
8284
  getOutputFields = () => this.outputFields;
@@ -7883,23 +8320,77 @@ var AxSignature = class _AxSignature {
7883
8320
  return schema;
7884
8321
  };
7885
8322
  updateHash = () => {
7886
- this.getInputFields().forEach((field) => {
7887
- validateField(field);
7888
- });
7889
- this.getOutputFields().forEach((field) => {
7890
- validateField(field);
7891
- if (field.type?.name === "image") {
7892
- throw new Error("Image type is not supported in output fields.");
8323
+ try {
8324
+ this.getInputFields().forEach((field) => {
8325
+ validateField(field, "input");
8326
+ });
8327
+ this.getOutputFields().forEach((field) => {
8328
+ validateField(field, "output");
8329
+ });
8330
+ this.validateSignatureConsistency();
8331
+ this.sigHash = (0, import_crypto3.createHash)("sha256").update(this.description ?? "").update(JSON.stringify(this.inputFields)).update(JSON.stringify(this.outputFields)).digest("hex");
8332
+ this.sigString = renderSignature(
8333
+ this.description,
8334
+ this.inputFields,
8335
+ this.outputFields
8336
+ );
8337
+ return [this.sigHash, this.sigString];
8338
+ } catch (error) {
8339
+ if (error instanceof AxSignatureValidationError) {
8340
+ throw error;
7893
8341
  }
7894
- });
7895
- this.sigHash = (0, import_crypto3.createHash)("sha256").update(this.description ?? "").update(JSON.stringify(this.inputFields)).update(JSON.stringify(this.outputFields)).digest("hex");
7896
- this.sigString = renderSignature(
7897
- this.description,
7898
- this.inputFields,
7899
- this.outputFields
7900
- );
7901
- return [this.sigHash, this.sigString];
8342
+ throw new AxSignatureValidationError(
8343
+ `Signature validation failed: ${error instanceof Error ? error.message : "Unknown error"}`
8344
+ );
8345
+ }
7902
8346
  };
8347
+ validateSignatureConsistency() {
8348
+ const inputNames = /* @__PURE__ */ new Set();
8349
+ for (const field of this.inputFields) {
8350
+ if (inputNames.has(field.name)) {
8351
+ throw new AxSignatureValidationError(
8352
+ `Duplicate input field name: "${field.name}"`,
8353
+ field.name,
8354
+ "Each field name must be unique within the signature"
8355
+ );
8356
+ }
8357
+ inputNames.add(field.name);
8358
+ }
8359
+ const outputNames = /* @__PURE__ */ new Set();
8360
+ for (const field of this.outputFields) {
8361
+ if (outputNames.has(field.name)) {
8362
+ throw new AxSignatureValidationError(
8363
+ `Duplicate output field name: "${field.name}"`,
8364
+ field.name,
8365
+ "Each field name must be unique within the signature"
8366
+ );
8367
+ }
8368
+ outputNames.add(field.name);
8369
+ }
8370
+ for (const outputField of this.outputFields) {
8371
+ if (inputNames.has(outputField.name)) {
8372
+ throw new AxSignatureValidationError(
8373
+ `Field name "${outputField.name}" appears in both inputs and outputs`,
8374
+ outputField.name,
8375
+ "Use different names for input and output fields to avoid confusion"
8376
+ );
8377
+ }
8378
+ }
8379
+ if (this.inputFields.length === 0) {
8380
+ throw new AxSignatureValidationError(
8381
+ "Signature must have at least one input field",
8382
+ void 0,
8383
+ 'Add an input field. Example: "userInput:string -> ..."'
8384
+ );
8385
+ }
8386
+ if (this.outputFields.length === 0) {
8387
+ throw new AxSignatureValidationError(
8388
+ "Signature must have at least one output field",
8389
+ void 0,
8390
+ 'Add an output field. Example: "... -> responseText:string"'
8391
+ );
8392
+ }
8393
+ }
7903
8394
  hash = () => this.sigHash;
7904
8395
  toString = () => this.sigString;
7905
8396
  toJSON = () => {
@@ -7916,54 +8407,194 @@ function renderField(field) {
7916
8407
  if (field.isOptional) {
7917
8408
  result += "?";
7918
8409
  }
8410
+ if (field.isInternal) {
8411
+ result += "!";
8412
+ }
7919
8413
  if (field.type) {
7920
8414
  result += ":" + field.type.name;
7921
8415
  if (field.type.isArray) {
7922
8416
  result += "[]";
7923
8417
  }
8418
+ if (field.type.name === "class" && field.type.options) {
8419
+ result += ` "${field.type.options.join(", ")}"`;
8420
+ }
7924
8421
  }
7925
- if (field.description) {
8422
+ if (field.description && field.type?.name !== "class") {
7926
8423
  result += ` "${field.description}"`;
7927
8424
  }
7928
8425
  return result;
7929
8426
  }
7930
8427
  function renderSignature(description, inputFields, outputFields) {
7931
- const descriptionPart = description ? `"${description}"` : "";
8428
+ const descriptionPart = description ? `"${description}" ` : "";
7932
8429
  const inputFieldsRendered = inputFields.map(renderField).join(", ");
7933
8430
  const outputFieldsRendered = outputFields.map(renderField).join(", ");
7934
- return `${descriptionPart} ${inputFieldsRendered} -> ${outputFieldsRendered}`;
8431
+ return `${descriptionPart}${inputFieldsRendered} -> ${outputFieldsRendered}`;
7935
8432
  }
7936
8433
  function isValidCase(inputString) {
7937
8434
  const camelCaseRegex = /^[a-z][a-zA-Z0-9]*$/;
7938
8435
  const snakeCaseRegex = /^[a-z]+(_[a-z0-9]+)*$/;
7939
8436
  return camelCaseRegex.test(inputString) || snakeCaseRegex.test(inputString);
7940
8437
  }
7941
- function validateField(field) {
8438
+ function validateField(field, context3) {
7942
8439
  if (!field.name || field.name.length === 0) {
7943
- throw new Error("Field name cannot be blank");
8440
+ throw new AxSignatureValidationError(
8441
+ "Field name cannot be blank",
8442
+ field.name,
8443
+ "Every field must have a descriptive name"
8444
+ );
7944
8445
  }
7945
8446
  if (!isValidCase(field.name)) {
7946
- throw new Error(
7947
- `Invalid field name '${field.name}', it must be camel case or snake case: `
8447
+ throw new AxSignatureValidationError(
8448
+ `Invalid field name '${field.name}' - must be camelCase or snake_case`,
8449
+ field.name,
8450
+ 'Use camelCase (e.g., "userInput") or snake_case (e.g., "user_input")'
7948
8451
  );
7949
8452
  }
7950
- if ([
7951
- "text",
7952
- "object",
7953
- "image",
7954
- "string",
7955
- "number",
7956
- "boolean",
7957
- "json",
7958
- "array",
7959
- "datetime",
7960
- "date",
7961
- "time",
7962
- "type",
7963
- "class"
7964
- ].includes(field.name)) {
7965
- throw new Error(
7966
- `Invalid field name '${field.name}', please make it more descriptive (eg. companyDescription)`
8453
+ if (axGlobals.signatureStrict) {
8454
+ const reservedNames = [
8455
+ "text",
8456
+ "object",
8457
+ "image",
8458
+ "string",
8459
+ "number",
8460
+ "boolean",
8461
+ "json",
8462
+ "array",
8463
+ "datetime",
8464
+ "date",
8465
+ "time",
8466
+ "type",
8467
+ "class",
8468
+ "input",
8469
+ "output",
8470
+ "data",
8471
+ "value",
8472
+ "result",
8473
+ "response",
8474
+ "request",
8475
+ "item",
8476
+ "element"
8477
+ ];
8478
+ if (reservedNames.includes(field.name.toLowerCase())) {
8479
+ const suggestions = context3 === "input" ? [
8480
+ "userInput",
8481
+ "questionText",
8482
+ "documentContent",
8483
+ "messageText",
8484
+ "queryString"
8485
+ ] : [
8486
+ "responseText",
8487
+ "analysisResult",
8488
+ "categoryType",
8489
+ "summaryText",
8490
+ "outputData"
8491
+ ];
8492
+ throw new AxSignatureValidationError(
8493
+ `Field name '${field.name}' is too generic`,
8494
+ field.name,
8495
+ `Use a more descriptive name. Examples for ${context3} fields: ${suggestions.join(", ")}`
8496
+ );
8497
+ }
8498
+ }
8499
+ if (field.name.length < 2) {
8500
+ throw new AxSignatureValidationError(
8501
+ `Field name '${field.name}' is too short`,
8502
+ field.name,
8503
+ "Field names must be at least 2 characters long"
8504
+ );
8505
+ }
8506
+ if (field.name.length > 50) {
8507
+ throw new AxSignatureValidationError(
8508
+ `Field name '${field.name}' is too long (${field.name.length} characters)`,
8509
+ field.name,
8510
+ "Field names should be 50 characters or less"
8511
+ );
8512
+ }
8513
+ if (field.type) {
8514
+ validateFieldType(field, context3);
8515
+ }
8516
+ }
8517
+ function validateFieldType(field, context3) {
8518
+ if (!field.type) return;
8519
+ const { type } = field;
8520
+ if (type.name === "image" || type.name === "audio") {
8521
+ if (context3 === "output") {
8522
+ throw new AxSignatureValidationError(
8523
+ `${type.name} type is not supported in output fields`,
8524
+ field.name,
8525
+ `${type.name} types can only be used in input fields`
8526
+ );
8527
+ }
8528
+ if (type.isArray) {
8529
+ throw new AxSignatureValidationError(
8530
+ `Arrays of ${type.name} are not supported`,
8531
+ field.name,
8532
+ `Use a single ${type.name} type instead`
8533
+ );
8534
+ }
8535
+ }
8536
+ if (type.name === "class") {
8537
+ if (context3 === "input") {
8538
+ throw new AxSignatureValidationError(
8539
+ "Class type is not supported in input fields",
8540
+ field.name,
8541
+ 'Class types are only allowed on output fields. Use "string" type for input classifications'
8542
+ );
8543
+ }
8544
+ if (!type.options || type.options.length === 0) {
8545
+ throw new AxSignatureValidationError(
8546
+ "Class type requires options",
8547
+ field.name,
8548
+ 'Provide class options. Example: class "positive, negative, neutral"'
8549
+ );
8550
+ }
8551
+ if (type.options.length === 1) {
8552
+ throw new AxSignatureValidationError(
8553
+ "Class type needs at least 2 options",
8554
+ field.name,
8555
+ 'Add more class options or use "string" type instead'
8556
+ );
8557
+ }
8558
+ for (const option of type.options) {
8559
+ if (!option || option.trim().length === 0) {
8560
+ throw new AxSignatureValidationError(
8561
+ "Empty class option found",
8562
+ field.name,
8563
+ "All class options must be non-empty strings"
8564
+ );
8565
+ }
8566
+ const trimmedOption = option.trim();
8567
+ if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(trimmedOption)) {
8568
+ throw new AxSignatureValidationError(
8569
+ `Invalid class option "${trimmedOption}"`,
8570
+ field.name,
8571
+ "Class options must start with a letter and contain only letters, numbers, underscores, or hyphens"
8572
+ );
8573
+ }
8574
+ }
8575
+ const uniqueOptions = new Set(
8576
+ type.options.map((opt) => opt.trim().toLowerCase())
8577
+ );
8578
+ if (uniqueOptions.size !== type.options.length) {
8579
+ throw new AxSignatureValidationError(
8580
+ "Duplicate class options found",
8581
+ field.name,
8582
+ "Each class option must be unique (case-insensitive)"
8583
+ );
8584
+ }
8585
+ }
8586
+ if (type.name === "code" && type.isArray) {
8587
+ throw new AxSignatureValidationError(
8588
+ "Arrays of code are not commonly supported",
8589
+ field.name,
8590
+ "Consider using a single code field or an array of strings instead"
8591
+ );
8592
+ }
8593
+ if (field.isInternal && context3 === "input") {
8594
+ throw new AxSignatureValidationError(
8595
+ "Internal marker (!) is not allowed on input fields",
8596
+ field.name,
8597
+ "Internal markers are only allowed on output fields"
7967
8598
  );
7968
8599
  }
7969
8600
  }
@@ -11696,13 +12327,18 @@ var AxMockAIService = class {
11696
12327
  }
11697
12328
  };
11698
12329
  getLastUsedChatModel() {
11699
- throw new Error("Method not implemented.");
12330
+ return this.config.modelInfo?.name ?? "mock-model";
11700
12331
  }
11701
12332
  getLastUsedEmbedModel() {
11702
- throw new Error("Method not implemented.");
12333
+ return this.config.embedModelInfo?.name ?? "mock-embed-model";
11703
12334
  }
11704
12335
  getLastUsedModelConfig() {
11705
- throw new Error("Method not implemented.");
12336
+ return this.config.modelInfo ? {
12337
+ maxTokens: this.config.modelInfo.maxTokens,
12338
+ temperature: 0.7,
12339
+ // Default temperature
12340
+ stream: this.config.features?.streaming ?? false
12341
+ } : void 0;
11706
12342
  }
11707
12343
  getName() {
11708
12344
  return this.config.name ?? "mock-ai-service";
@@ -14106,6 +14742,7 @@ var AxRAG = class extends AxChainOfThought {
14106
14742
  axAITogetherDefaultConfig,
14107
14743
  axBaseAIDefaultConfig,
14108
14744
  axBaseAIDefaultCreativeConfig,
14745
+ axGlobals,
14109
14746
  axModelInfoAnthropic,
14110
14747
  axModelInfoCohere,
14111
14748
  axModelInfoDeepSeek,