@ax-llm/ax 11.0.66 → 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.js CHANGED
@@ -783,14 +783,14 @@ var logResponseResult = (r, logger = defaultLogger) => {
783
783
  logger(r.content, { tags: ["responseContent"] });
784
784
  }
785
785
  if (r.functionCalls && r.functionCalls.length > 0) {
786
- for (const [i, f] of r.functionCalls.entries()) {
787
- if (f.function.name) {
788
- logger(`[${i + 1}] ${f.function.name}`, {
786
+ for (const [i, f2] of r.functionCalls.entries()) {
787
+ if (f2.function.name) {
788
+ logger(`[${i + 1}] ${f2.function.name}`, {
789
789
  tags: ["functionName"]
790
790
  });
791
791
  }
792
- if (f.function.params) {
793
- const params = typeof f.function.params === "string" ? f.function.params : JSON.stringify(f.function.params, null, 2);
792
+ if (f2.function.params) {
793
+ const params = typeof f2.function.params === "string" ? f2.function.params : JSON.stringify(f2.function.params, null, 2);
794
794
  logger(params, { tags: ["functionArg"] });
795
795
  }
796
796
  }
@@ -2917,7 +2917,7 @@ function createHistory(chatPrompt) {
2917
2917
  case "function": {
2918
2918
  const functionCalls = chatPrompt.map((v) => {
2919
2919
  if (v.role === "assistant") {
2920
- return v.functionCalls?.find((f) => f.id === chat.functionId);
2920
+ return v.functionCalls?.find((f2) => f2.id === chat.functionId);
2921
2921
  }
2922
2922
  return void 0;
2923
2923
  }).filter((v) => v !== void 0);
@@ -3237,11 +3237,11 @@ var AxAIGoogleGeminiImpl = class {
3237
3237
  case "assistant": {
3238
3238
  let parts = [];
3239
3239
  if (msg.functionCalls) {
3240
- parts = msg.functionCalls.map((f) => {
3241
- const args = typeof f.function.params === "string" ? JSON.parse(f.function.params) : f.function.params;
3240
+ parts = msg.functionCalls.map((f2) => {
3241
+ const args = typeof f2.function.params === "string" ? JSON.parse(f2.function.params) : f2.function.params;
3242
3242
  return {
3243
3243
  functionCall: {
3244
- name: f.function.name,
3244
+ name: f2.function.name,
3245
3245
  args
3246
3246
  }
3247
3247
  };
@@ -4298,7 +4298,7 @@ var AxAIOpenAIResponsesImpl = class {
4298
4298
  currentResult.thought = item.encrypted_content;
4299
4299
  } else {
4300
4300
  currentResult.thought = item.summary.map(
4301
- (s) => typeof s === "object" ? JSON.stringify(s) : s
4301
+ (s2) => typeof s2 === "object" ? JSON.stringify(s2) : s2
4302
4302
  ).join("\n");
4303
4303
  }
4304
4304
  break;
@@ -4622,7 +4622,7 @@ var AxAIOpenAIResponsesImpl = class {
4622
4622
  baseResult.thought = reasoningItem.encrypted_content;
4623
4623
  } else if (reasoningItem.summary) {
4624
4624
  baseResult.thought = reasoningItem.summary.map(
4625
- (s) => typeof s === "object" ? JSON.stringify(s) : s
4625
+ (s2) => typeof s2 === "object" ? JSON.stringify(s2) : s2
4626
4626
  ).join("\n");
4627
4627
  }
4628
4628
  }
@@ -5998,7 +5998,7 @@ var AxPromptTemplate = class {
5998
5998
  task.push(
5999
5999
  `You will be provided with the following fields: ${inArgs}. Your task is to generate new fields: ${outArgs}.`
6000
6000
  );
6001
- const funcs = this.functions?.map((f) => "toFunction" in f ? f.toFunction() : f)?.flat();
6001
+ const funcs = this.functions?.map((f2) => "toFunction" in f2 ? f2.toFunction() : f2)?.flat();
6002
6002
  const funcList = funcs?.map((fn) => `- \`${fn.name}\`: ${formatDescription(fn.description)}`).join("\n");
6003
6003
  if (funcList && funcList.length > 0) {
6004
6004
  task.push(`## Available Functions
@@ -6560,6 +6560,11 @@ var extractValues = (sig, values, content) => {
6560
6560
  const xstate = { extractedFields: [], streamedIndex: {}, s: -1 };
6561
6561
  streamingExtractValues(sig, values, xstate, content);
6562
6562
  streamingExtractFinalValue(sig, values, xstate, content);
6563
+ for (const field of sig.getOutputFields()) {
6564
+ if (field.isInternal) {
6565
+ delete values[field.name];
6566
+ }
6567
+ }
6563
6568
  };
6564
6569
  var checkMissingRequiredFields = (xstate, values, currentIndex) => {
6565
6570
  const missingFields = [];
@@ -6692,7 +6697,7 @@ var convertValueToType = (field, val, required = false) => {
6692
6697
  return val;
6693
6698
  }
6694
6699
  };
6695
- function* yieldDelta(content, field, s, e, xstate) {
6700
+ function* yieldDelta(content, field, s2, e, xstate) {
6696
6701
  const { name: fieldName, isInternal } = field;
6697
6702
  const { isArray: fieldIsArray, name: fieldTypeName } = field.type ?? {};
6698
6703
  if (isInternal || fieldIsArray || fieldTypeName && fieldTypeName !== "string" && fieldTypeName !== "code") {
@@ -6700,7 +6705,7 @@ function* yieldDelta(content, field, s, e, xstate) {
6700
6705
  }
6701
6706
  const pos = xstate.streamedIndex[fieldName] ?? 0;
6702
6707
  const isFirstChunk = pos === 0;
6703
- const d1 = content.substring(s + pos, e);
6708
+ const d1 = content.substring(s2 + pos, e);
6704
6709
  if (d1.length === 0) {
6705
6710
  return;
6706
6711
  }
@@ -6719,8 +6724,8 @@ function* yieldDelta(content, field, s, e, xstate) {
6719
6724
  }
6720
6725
  function* streamValues(sig, content, values, xstate) {
6721
6726
  for (const prevField of xstate.prevFields ?? []) {
6722
- const { field, s, e } = prevField;
6723
- yield* yieldDelta(content, field, s, e, xstate);
6727
+ const { field, s: s2, e } = prevField;
6728
+ yield* yieldDelta(content, field, s2, e, xstate);
6724
6729
  }
6725
6730
  xstate.prevFields = void 0;
6726
6731
  if (!xstate.currField || xstate.currField.isInternal) {
@@ -6735,17 +6740,17 @@ function* streamValues(sig, content, values, xstate) {
6735
6740
  );
6736
6741
  const outputFields = sig.getOutputFields();
6737
6742
  for (const key of Object.keys(values)) {
6738
- const field = outputFields.find((f) => f.name === key);
6743
+ const field = outputFields.find((f2) => f2.name === key);
6739
6744
  if (!field || field.isInternal) {
6740
6745
  continue;
6741
6746
  }
6742
6747
  const value = values[key];
6743
6748
  if (Array.isArray(value)) {
6744
- const s = xstate.streamedIndex?.[key] ?? 0;
6745
- const v = value.slice(s);
6749
+ const s2 = xstate.streamedIndex?.[key] ?? 0;
6750
+ const v = value.slice(s2);
6746
6751
  if (v && v.length > 0) {
6747
6752
  yield { [key]: v };
6748
- xstate.streamedIndex[key] = s + v.length;
6753
+ xstate.streamedIndex[key] = s2 + v.length;
6749
6754
  }
6750
6755
  continue;
6751
6756
  }
@@ -7168,11 +7173,11 @@ var parseFunctions = (newFuncs, existingFuncs) => {
7168
7173
  if (newFuncs.length === 0) {
7169
7174
  return [...existingFuncs ?? []];
7170
7175
  }
7171
- const functions = newFuncs.map((f) => {
7172
- if ("toFunction" in f) {
7173
- return f.toFunction();
7176
+ const functions = newFuncs.map((f2) => {
7177
+ if ("toFunction" in f2) {
7178
+ return f2.toFunction();
7174
7179
  }
7175
- return f;
7180
+ return f2;
7176
7181
  }).flat();
7177
7182
  for (const fn of functions.filter((v) => v.parameters)) {
7178
7183
  if (fn.parameters) {
@@ -7257,10 +7262,10 @@ function parseFunctionCalls(ai, functionCalls, values, model) {
7257
7262
  if (!ai.getFeatures(model).functions) {
7258
7263
  throw new Error("Functions are not supported by the AI service");
7259
7264
  }
7260
- const funcs = functionCalls.map((f) => ({
7261
- id: f.id,
7262
- name: f.function.name,
7263
- args: f.function.params
7265
+ const funcs = functionCalls.map((f2) => ({
7266
+ id: f2.id,
7267
+ name: f2.function.name,
7268
+ args: f2.function.params
7264
7269
  }));
7265
7270
  return funcs;
7266
7271
  }
@@ -7285,93 +7290,218 @@ var AxInstanceRegistry = class {
7285
7290
  // dsp/sig.ts
7286
7291
  import { createHash } from "crypto";
7287
7292
 
7293
+ // dsp/globals.ts
7294
+ var axGlobals = {
7295
+ signatureStrict: true
7296
+ // Controls reservedNames enforcement in signature parsing/validation
7297
+ };
7298
+
7288
7299
  // dsp/parser.ts
7300
+ var SignatureValidationError = class extends Error {
7301
+ constructor(message, position, context3, suggestion) {
7302
+ super(message);
7303
+ this.position = position;
7304
+ this.context = context3;
7305
+ this.suggestion = suggestion;
7306
+ this.name = "SignatureValidationError";
7307
+ }
7308
+ };
7289
7309
  var SignatureParser = class {
7290
7310
  input;
7291
7311
  position;
7292
7312
  currentFieldName = null;
7313
+ currentSection = "description";
7293
7314
  constructor(input) {
7294
- this.input = input;
7315
+ this.input = input.trim();
7295
7316
  this.position = 0;
7317
+ if (!this.input) {
7318
+ throw new SignatureValidationError(
7319
+ "Empty signature provided",
7320
+ 0,
7321
+ "",
7322
+ 'A signature must contain at least input and output fields separated by "->". Example: "userQuery:string -> aiResponse:string"'
7323
+ );
7324
+ }
7296
7325
  }
7297
7326
  parse() {
7298
7327
  try {
7299
7328
  this.skipWhitespace();
7300
7329
  const optionalDesc = this.parseParsedString();
7301
7330
  this.skipWhitespace();
7331
+ this.currentSection = "inputs";
7302
7332
  const inputs = this.parseFieldList(
7303
7333
  this.parseInputField.bind(this),
7304
7334
  "input"
7305
7335
  );
7306
7336
  this.skipWhitespace();
7307
7337
  if (this.position >= this.input.length) {
7308
- throw new Error(
7309
- 'Incomplete signature: Missing output section. Expected "->" followed by output fields'
7338
+ throw new SignatureValidationError(
7339
+ "Incomplete signature: Missing output section",
7340
+ this.position,
7341
+ this.getErrorContext(),
7342
+ 'Add "->" followed by output fields. Example: "-> responseText:string"'
7310
7343
  );
7311
7344
  }
7312
- this.expect("->");
7345
+ this.expectArrow();
7313
7346
  this.skipWhitespace();
7314
7347
  if (this.position >= this.input.length) {
7315
- throw new Error(
7316
- 'Incomplete signature: No output fields specified after "->"'
7348
+ throw new SignatureValidationError(
7349
+ 'Incomplete signature: No output fields specified after "->"',
7350
+ this.position,
7351
+ this.getErrorContext(),
7352
+ 'Add at least one output field. Example: "-> responseText:string"'
7317
7353
  );
7318
7354
  }
7355
+ this.currentSection = "outputs";
7319
7356
  const outputs = this.parseFieldList(
7320
7357
  this.parseOutputField.bind(this),
7321
7358
  "output"
7322
7359
  );
7360
+ this.skipWhitespace();
7361
+ if (this.position < this.input.length) {
7362
+ const remaining = this.input.slice(this.position);
7363
+ throw new SignatureValidationError(
7364
+ `Unexpected content after signature: "${remaining}"`,
7365
+ this.position,
7366
+ this.getErrorContext(),
7367
+ "Remove any extra content after the output fields"
7368
+ );
7369
+ }
7370
+ this.validateParsedSignature({
7371
+ desc: optionalDesc?.trim(),
7372
+ inputs,
7373
+ outputs
7374
+ });
7323
7375
  return {
7324
7376
  desc: optionalDesc?.trim(),
7325
7377
  inputs,
7326
7378
  outputs
7327
7379
  };
7328
7380
  } catch (error) {
7381
+ if (error instanceof SignatureValidationError) {
7382
+ throw error;
7383
+ }
7329
7384
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
7330
- const context3 = this.getErrorContext();
7331
- throw new Error(`${errorMessage}
7332
- ${context3}`);
7385
+ throw new SignatureValidationError(
7386
+ errorMessage,
7387
+ this.position,
7388
+ this.getErrorContext()
7389
+ );
7390
+ }
7391
+ }
7392
+ validateParsedSignature(signature) {
7393
+ const inputNames = /* @__PURE__ */ new Set();
7394
+ for (const field of signature.inputs) {
7395
+ if (inputNames.has(field.name)) {
7396
+ throw new SignatureValidationError(
7397
+ `Duplicate input field name: "${field.name}"`,
7398
+ 0,
7399
+ "",
7400
+ "Each field name must be unique within the signature"
7401
+ );
7402
+ }
7403
+ inputNames.add(field.name);
7404
+ }
7405
+ const outputNames = /* @__PURE__ */ new Set();
7406
+ for (const field of signature.outputs) {
7407
+ if (outputNames.has(field.name)) {
7408
+ throw new SignatureValidationError(
7409
+ `Duplicate output field name: "${field.name}"`,
7410
+ 0,
7411
+ "",
7412
+ "Each field name must be unique within the signature"
7413
+ );
7414
+ }
7415
+ outputNames.add(field.name);
7416
+ }
7417
+ for (const outputField of signature.outputs) {
7418
+ if (inputNames.has(outputField.name)) {
7419
+ throw new SignatureValidationError(
7420
+ `Field name "${outputField.name}" appears in both inputs and outputs`,
7421
+ 0,
7422
+ "",
7423
+ "Use different names for input and output fields to avoid confusion"
7424
+ );
7425
+ }
7426
+ }
7427
+ if (signature.inputs.length === 0) {
7428
+ throw new SignatureValidationError(
7429
+ "Signature must have at least one input field",
7430
+ 0,
7431
+ "",
7432
+ 'Add an input field before "->". Example: "userInput:string -> ..."'
7433
+ );
7434
+ }
7435
+ if (signature.outputs.length === 0) {
7436
+ throw new SignatureValidationError(
7437
+ "Signature must have at least one output field",
7438
+ 0,
7439
+ "",
7440
+ 'Add an output field after "->". Example: "... -> responseText:string"'
7441
+ );
7333
7442
  }
7334
7443
  }
7335
7444
  getErrorContext() {
7336
- const start = Math.max(0, this.position - 20);
7337
- const end = Math.min(this.input.length, this.position + 20);
7445
+ const start = Math.max(0, this.position - 25);
7446
+ const end = Math.min(this.input.length, this.position + 25);
7338
7447
  const before = this.input.slice(start, this.position);
7339
7448
  const after = this.input.slice(this.position, end);
7340
7449
  const pointer = " ".repeat(before.length) + "^";
7341
- return `Near position ${this.position}:
7342
- ${before}${after}
7343
- ${pointer}`;
7450
+ const lines = [
7451
+ `Position ${this.position} in signature:`,
7452
+ `"${before}${after}"`,
7453
+ ` ${pointer}`
7454
+ ];
7455
+ return lines.join("\n");
7344
7456
  }
7345
7457
  parseFieldList(parseFieldFn, section) {
7346
7458
  const fields = [];
7347
7459
  this.skipWhitespace();
7348
7460
  if (this.position >= this.input.length) {
7349
- throw new Error(`Empty ${section} section: Expected at least one field`);
7461
+ throw new SignatureValidationError(
7462
+ `Empty ${section} section: Expected at least one field`,
7463
+ this.position,
7464
+ this.getErrorContext(),
7465
+ `Add a ${section} field. Example: ${section === "input" ? "userInput:string" : "responseText:string"}`
7466
+ );
7350
7467
  }
7351
7468
  try {
7352
7469
  fields.push(parseFieldFn());
7353
7470
  } catch (error) {
7354
- throw new Error(
7355
- `Invalid first ${section} field: ${error instanceof Error ? error.message : "Unknown error"}`
7471
+ if (error instanceof SignatureValidationError) {
7472
+ throw error;
7473
+ }
7474
+ throw new SignatureValidationError(
7475
+ `Invalid first ${section} field: ${error instanceof Error ? error.message : "Unknown error"}`,
7476
+ this.position,
7477
+ this.getErrorContext()
7356
7478
  );
7357
7479
  }
7358
7480
  this.skipWhitespace();
7359
7481
  while (this.position < this.input.length) {
7360
- if (this.input[this.position] === "-" && this.input[this.position + 1] === ">") {
7482
+ if (this.input[this.position] === "-" && this.position + 1 < this.input.length && this.input[this.position + 1] === ">") {
7361
7483
  break;
7362
7484
  }
7363
7485
  if (this.match(",")) {
7364
7486
  this.skipWhitespace();
7365
7487
  if (this.position >= this.input.length) {
7366
- throw new Error(
7367
- `Unexpected end of input after comma in ${section} section`
7488
+ throw new SignatureValidationError(
7489
+ `Unexpected end of input after comma in ${section} section`,
7490
+ this.position,
7491
+ this.getErrorContext(),
7492
+ `Add another ${section} field after the comma`
7368
7493
  );
7369
7494
  }
7370
7495
  try {
7371
7496
  fields.push(parseFieldFn());
7372
7497
  } catch (error) {
7373
- throw new Error(
7374
- `Invalid ${section} field after comma: ${error instanceof Error ? error.message : "Unknown error"}`
7498
+ if (error instanceof SignatureValidationError) {
7499
+ throw error;
7500
+ }
7501
+ throw new SignatureValidationError(
7502
+ `Invalid ${section} field after comma: ${error instanceof Error ? error.message : "Unknown error"}`,
7503
+ this.position,
7504
+ this.getErrorContext()
7375
7505
  );
7376
7506
  }
7377
7507
  this.skipWhitespace();
@@ -7388,6 +7518,7 @@ ${pointer}`;
7388
7518
  this.skipWhitespace();
7389
7519
  const name = this.parseParsedIdentifier();
7390
7520
  this.currentFieldName = name;
7521
+ this.validateFieldName(name, "input");
7391
7522
  let isOptional = void 0;
7392
7523
  while (true) {
7393
7524
  if (this.match("?")) {
@@ -7395,8 +7526,11 @@ ${pointer}`;
7395
7526
  continue;
7396
7527
  }
7397
7528
  if (this.match("!")) {
7398
- throw new Error(
7399
- `Input field "${name}" does not support the internal marker "!"`
7529
+ throw new SignatureValidationError(
7530
+ `Input field "${name}" cannot use the internal marker "!"`,
7531
+ this.position - 1,
7532
+ this.getErrorContext(),
7533
+ "Internal markers (!) are only allowed on output fields"
7400
7534
  );
7401
7535
  }
7402
7536
  break;
@@ -7406,17 +7540,33 @@ ${pointer}`;
7406
7540
  if (this.match(":")) {
7407
7541
  this.skipWhitespace();
7408
7542
  if (/^class\b/.test(this.input.slice(this.position))) {
7409
- throw new Error(
7410
- `Input field "${name}" does not support the "class" type`
7543
+ throw new SignatureValidationError(
7544
+ `Input field "${name}" cannot use the "class" type`,
7545
+ this.position,
7546
+ this.getErrorContext(),
7547
+ 'Class types are only allowed on output fields. Use "string" type for input classifications'
7411
7548
  );
7412
7549
  } else {
7413
7550
  try {
7414
7551
  const typeName = this.parseTypeNotClass();
7415
7552
  const isArray = this.match("[]");
7416
7553
  type = { name: typeName, isArray };
7554
+ if ((typeName === "image" || typeName === "audio") && isArray) {
7555
+ throw new SignatureValidationError(
7556
+ `Input field "${name}": Arrays of ${typeName} are not supported`,
7557
+ this.position,
7558
+ this.getErrorContext(),
7559
+ `Use a single ${typeName} type instead: "${typeName}"`
7560
+ );
7561
+ }
7417
7562
  } catch (error) {
7418
- throw new Error(
7419
- `Input field "${name}": ${error instanceof Error ? error.message : "Unknown error"}`
7563
+ if (error instanceof SignatureValidationError) {
7564
+ throw error;
7565
+ }
7566
+ throw new SignatureValidationError(
7567
+ `Input field "${name}": ${error instanceof Error ? error.message : "Unknown error"}`,
7568
+ this.position,
7569
+ this.getErrorContext()
7420
7570
  );
7421
7571
  }
7422
7572
  }
@@ -7437,6 +7587,7 @@ ${pointer}`;
7437
7587
  this.skipWhitespace();
7438
7588
  const name = this.parseParsedIdentifier();
7439
7589
  this.currentFieldName = name;
7590
+ this.validateFieldName(name, "output");
7440
7591
  let isOptional = false;
7441
7592
  let isInternal = false;
7442
7593
  while (true) {
@@ -7459,25 +7610,86 @@ ${pointer}`;
7459
7610
  this.skipWhitespace();
7460
7611
  const classNamesString = this.parseParsedString();
7461
7612
  if (!classNamesString) {
7462
- throw new Error(
7463
- `Output field "${name}": Expected class names in quotes after "class" type. Example: class "MyClass1, MyClass2"`
7613
+ throw new SignatureValidationError(
7614
+ `Output field "${name}": Missing class options after "class" type`,
7615
+ this.position,
7616
+ this.getErrorContext(),
7617
+ 'Add class names in quotes. Example: class "positive, negative, neutral"'
7464
7618
  );
7465
7619
  }
7466
- const options = classNamesString.split(/[,\s]+/).map((s) => s.trim()).filter((s) => s.length > 0);
7620
+ const options = classNamesString.split(/[,\s]+/).map((s2) => s2.trim()).filter((s2) => s2.length > 0);
7467
7621
  if (options.length === 0) {
7468
- throw new Error(
7469
- `Output field "${name}": Empty class list provided. At least one class name is required`
7622
+ throw new SignatureValidationError(
7623
+ `Output field "${name}": Empty class list provided`,
7624
+ this.position,
7625
+ this.getErrorContext(),
7626
+ 'Provide at least one class option. Example: "positive, negative"'
7470
7627
  );
7471
7628
  }
7629
+ if (options.length === 1) {
7630
+ throw new SignatureValidationError(
7631
+ `Output field "${name}": Class type needs at least 2 options`,
7632
+ this.position,
7633
+ this.getErrorContext(),
7634
+ 'Add more class options or use "string" type instead. Example: "positive, negative, neutral"'
7635
+ );
7636
+ }
7637
+ for (const option of options) {
7638
+ if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(option)) {
7639
+ throw new SignatureValidationError(
7640
+ `Output field "${name}": Invalid class option "${option}"`,
7641
+ this.position,
7642
+ this.getErrorContext(),
7643
+ "Class options must start with a letter and contain only letters, numbers, underscores, or hyphens"
7644
+ );
7645
+ }
7646
+ }
7472
7647
  type = { name: "class", isArray, options };
7473
7648
  } else {
7474
7649
  try {
7475
7650
  const typeName = this.parseTypeNotClass();
7476
7651
  const isArray = this.match("[]");
7477
7652
  type = { name: typeName, isArray };
7653
+ if (typeName === "image" && isArray) {
7654
+ throw new SignatureValidationError(
7655
+ `Output field "${name}": Arrays of images are not supported`,
7656
+ this.position,
7657
+ this.getErrorContext(),
7658
+ 'Use a single image type instead: "image"'
7659
+ );
7660
+ }
7661
+ if (typeName === "audio" && isArray) {
7662
+ throw new SignatureValidationError(
7663
+ `Output field "${name}": Arrays of audio are not supported`,
7664
+ this.position,
7665
+ this.getErrorContext(),
7666
+ 'Use a single audio type instead: "audio"'
7667
+ );
7668
+ }
7669
+ if (typeName === "image") {
7670
+ throw new SignatureValidationError(
7671
+ `Output field "${name}": Image type is not supported in output fields`,
7672
+ this.position,
7673
+ this.getErrorContext(),
7674
+ "Image types can only be used in input fields"
7675
+ );
7676
+ }
7677
+ if (typeName === "audio") {
7678
+ throw new SignatureValidationError(
7679
+ `Output field "${name}": Audio type is not supported in output fields`,
7680
+ this.position,
7681
+ this.getErrorContext(),
7682
+ "Audio types can only be used in input fields"
7683
+ );
7684
+ }
7478
7685
  } catch (error) {
7479
- throw new Error(
7480
- `Output field "${name}": ${error instanceof Error ? error.message : "Unknown error"}`
7686
+ if (error instanceof SignatureValidationError) {
7687
+ throw error;
7688
+ }
7689
+ throw new SignatureValidationError(
7690
+ `Output field "${name}": ${error instanceof Error ? error.message : "Unknown error"}`,
7691
+ this.position,
7692
+ this.getErrorContext()
7481
7693
  );
7482
7694
  }
7483
7695
  }
@@ -7492,6 +7704,69 @@ ${pointer}`;
7492
7704
  isInternal
7493
7705
  };
7494
7706
  }
7707
+ validateFieldName(name, fieldType) {
7708
+ if (axGlobals.signatureStrict) {
7709
+ const reservedNames = [
7710
+ "text",
7711
+ "object",
7712
+ "image",
7713
+ "string",
7714
+ "number",
7715
+ "boolean",
7716
+ "json",
7717
+ "array",
7718
+ "datetime",
7719
+ "date",
7720
+ "time",
7721
+ "type",
7722
+ "class",
7723
+ "input",
7724
+ "output",
7725
+ "data",
7726
+ "value",
7727
+ "result",
7728
+ "response",
7729
+ "request",
7730
+ "item",
7731
+ "element"
7732
+ ];
7733
+ if (reservedNames.includes(name.toLowerCase())) {
7734
+ const suggestions = fieldType === "input" ? ["userInput", "questionText", "documentContent", "messageText"] : ["responseText", "analysisResult", "categoryType", "summaryText"];
7735
+ throw new SignatureValidationError(
7736
+ `Field name "${name}" is too generic`,
7737
+ this.position,
7738
+ this.getErrorContext(),
7739
+ `Use a more descriptive name. Examples: ${suggestions.join(", ")}`
7740
+ );
7741
+ }
7742
+ }
7743
+ const camelCaseRegex = /^[a-z][a-zA-Z0-9]*$/;
7744
+ const snakeCaseRegex = /^[a-z]+(_[a-z0-9]+)*$/;
7745
+ if (!camelCaseRegex.test(name) && !snakeCaseRegex.test(name)) {
7746
+ throw new SignatureValidationError(
7747
+ `Invalid field name "${name}"`,
7748
+ this.position,
7749
+ this.getErrorContext(),
7750
+ 'Field names must be in camelCase (e.g., "userInput") or snake_case (e.g., "user_input")'
7751
+ );
7752
+ }
7753
+ if (name.length < 2) {
7754
+ throw new SignatureValidationError(
7755
+ `Field name "${name}" is too short`,
7756
+ this.position,
7757
+ this.getErrorContext(),
7758
+ "Field names must be at least 2 characters long"
7759
+ );
7760
+ }
7761
+ if (name.length > 50) {
7762
+ throw new SignatureValidationError(
7763
+ `Field name "${name}" is too long (${name.length} characters)`,
7764
+ this.position,
7765
+ this.getErrorContext(),
7766
+ "Field names should be 50 characters or less"
7767
+ );
7768
+ }
7769
+ }
7495
7770
  parseTypeNotClass() {
7496
7771
  const types = [
7497
7772
  "string",
@@ -7506,13 +7781,42 @@ ${pointer}`;
7506
7781
  ];
7507
7782
  const foundType = types.find((type) => this.match(type));
7508
7783
  if (!foundType) {
7509
- const currentWord = this.input.slice(this.position).match(/^\w+/)?.[0] || "empty";
7510
- throw new Error(
7511
- `Invalid type "${currentWord}". Expected one of: ${types.join(", ")}`
7784
+ const currentWord = this.input.slice(this.position).match(/^\w+/)?.[0] || "";
7785
+ const suggestion = this.suggestType(currentWord);
7786
+ const baseMessage = `Invalid type "${currentWord || "empty"}"`;
7787
+ const suggestionPart = suggestion ? `. Did you mean "${suggestion}"?` : "";
7788
+ const fullMessage = `${baseMessage}${suggestionPart}`;
7789
+ throw new SignatureValidationError(
7790
+ fullMessage,
7791
+ this.position,
7792
+ this.getErrorContext(),
7793
+ `Expected one of: ${types.join(", ")}`
7512
7794
  );
7513
7795
  }
7514
7796
  return foundType;
7515
7797
  }
7798
+ suggestType(input) {
7799
+ const suggestions = {
7800
+ str: "string",
7801
+ text: "string",
7802
+ int: "number",
7803
+ integer: "number",
7804
+ float: "number",
7805
+ double: "number",
7806
+ bool: "boolean",
7807
+ object: "json",
7808
+ dict: "json",
7809
+ timestamp: "datetime",
7810
+ time: "datetime",
7811
+ img: "image",
7812
+ picture: "image",
7813
+ sound: "audio",
7814
+ voice: "audio",
7815
+ classification: "class",
7816
+ category: "class"
7817
+ };
7818
+ return suggestions[input.toLowerCase()] || null;
7819
+ }
7516
7820
  parseParsedIdentifier() {
7517
7821
  this.skipWhitespace();
7518
7822
  const match = /^[a-zA-Z_][a-zA-Z_0-9]*/.exec(
@@ -7523,9 +7827,28 @@ ${pointer}`;
7523
7827
  return match[0];
7524
7828
  }
7525
7829
  const invalidMatch = /^\S+/.exec(this.input.slice(this.position));
7526
- const invalidId = invalidMatch ? invalidMatch[0] : "empty";
7527
- throw new Error(
7528
- `Invalid identifier "${invalidId}". Identifiers must start with a letter or underscore and contain only letters, numbers, or underscores`
7830
+ const invalidId = invalidMatch ? invalidMatch[0] : "";
7831
+ if (invalidId === "") {
7832
+ throw new SignatureValidationError(
7833
+ "Expected field name but found end of input",
7834
+ this.position,
7835
+ this.getErrorContext(),
7836
+ "Add a field name. Field names must start with a letter or underscore"
7837
+ );
7838
+ }
7839
+ if (/^\d/.test(invalidId)) {
7840
+ throw new SignatureValidationError(
7841
+ `Invalid field name "${invalidId}" - cannot start with a number`,
7842
+ this.position,
7843
+ this.getErrorContext(),
7844
+ 'Field names must start with a letter or underscore. Example: "userInput" or "_internal"'
7845
+ );
7846
+ }
7847
+ throw new SignatureValidationError(
7848
+ `Invalid field name "${invalidId}"`,
7849
+ this.position,
7850
+ this.getErrorContext(),
7851
+ "Field names must start with a letter or underscore and contain only letters, numbers, or underscores"
7529
7852
  );
7530
7853
  }
7531
7854
  parseParsedString() {
@@ -7534,7 +7857,7 @@ ${pointer}`;
7534
7857
  if (this.match(quoteChar)) {
7535
7858
  let content = "";
7536
7859
  let escaped = false;
7537
- let startPos = this.position;
7860
+ const startPos = this.position - 1;
7538
7861
  while (this.position < this.input.length) {
7539
7862
  const char = this.input[this.position];
7540
7863
  this.position++;
@@ -7549,9 +7872,15 @@ ${pointer}`;
7549
7872
  content += char;
7550
7873
  }
7551
7874
  }
7552
- const partialString = this.input.slice(startPos, this.position);
7553
- throw new Error(
7554
- `Unterminated string starting at position ${startPos}: "${partialString}..."`
7875
+ const partialString = this.input.slice(
7876
+ startPos,
7877
+ Math.min(this.position, startPos + 20)
7878
+ );
7879
+ throw new SignatureValidationError(
7880
+ `Unterminated string starting at position ${startPos}`,
7881
+ startPos,
7882
+ this.getErrorContext(),
7883
+ `Add closing ${quoteChar} to complete the string: ${partialString}${quoteChar}`
7555
7884
  );
7556
7885
  }
7557
7886
  }
@@ -7579,11 +7908,15 @@ ${pointer}`;
7579
7908
  }
7580
7909
  return false;
7581
7910
  }
7582
- expect(str) {
7583
- if (!this.match(str)) {
7911
+ expectArrow() {
7912
+ if (!this.match("->")) {
7584
7913
  const found = this.input.slice(this.position, this.position + 10);
7585
- throw new Error(
7586
- `Expected "${str}" but found "${found}..." at position ${this.position}`
7914
+ const suggestion = found.includes(">") ? 'Use "->" (dash followed by greater-than)' : found.includes("-") ? 'Add ">" after the dash' : 'Add "->" to separate input and output fields';
7915
+ throw new SignatureValidationError(
7916
+ `Expected "->" but found "${found}..."`,
7917
+ this.position,
7918
+ this.getErrorContext(),
7919
+ suggestion
7587
7920
  );
7588
7921
  }
7589
7922
  }
@@ -7594,6 +7927,14 @@ function parseSignature(input) {
7594
7927
  }
7595
7928
 
7596
7929
  // dsp/sig.ts
7930
+ var AxSignatureValidationError = class extends Error {
7931
+ constructor(message, fieldName, suggestion) {
7932
+ super(message);
7933
+ this.fieldName = fieldName;
7934
+ this.suggestion = suggestion;
7935
+ this.name = "AxSignatureValidationError";
7936
+ }
7937
+ };
7597
7938
  var AxSignature = class _AxSignature {
7598
7939
  description;
7599
7940
  inputFields;
@@ -7613,8 +7954,18 @@ var AxSignature = class _AxSignature {
7613
7954
  try {
7614
7955
  sig = parseSignature(signature);
7615
7956
  } catch (e) {
7616
- throw new Error(
7617
- `Invalid Signature: ${e.message} (${signature})`
7957
+ if (e instanceof Error) {
7958
+ const suggestion = "suggestion" in e && typeof e.suggestion === "string" ? e.suggestion : 'Please check the signature format. Example: "userInput:string -> responseText:string"';
7959
+ throw new AxSignatureValidationError(
7960
+ `Invalid Signature: ${e.message}`,
7961
+ void 0,
7962
+ suggestion
7963
+ );
7964
+ }
7965
+ throw new AxSignatureValidationError(
7966
+ `Invalid Signature: ${signature}`,
7967
+ void 0,
7968
+ 'Please check the signature format. Example: "userInput:string -> responseText:string"'
7618
7969
  );
7619
7970
  }
7620
7971
  this.description = sig.desc;
@@ -7632,12 +7983,20 @@ var AxSignature = class _AxSignature {
7632
7983
  this.sigHash = signature.hash();
7633
7984
  this.sigString = signature.toString();
7634
7985
  } else {
7635
- throw new Error("invalid signature argument: " + signature);
7986
+ throw new AxSignatureValidationError(
7987
+ "Invalid signature argument type",
7988
+ void 0,
7989
+ "Signature must be a string or another AxSignature instance"
7990
+ );
7636
7991
  }
7637
7992
  }
7638
7993
  parseParsedField = (field) => {
7639
7994
  if (!field.name || field.name.length === 0) {
7640
- throw new Error("Field name is required.");
7995
+ throw new AxSignatureValidationError(
7996
+ "Field name is required",
7997
+ field.name,
7998
+ 'Every field must have a descriptive name. Example: "userInput", "responseText"'
7999
+ );
7641
8000
  }
7642
8001
  const title = this.toTitle(field.name);
7643
8002
  return {
@@ -7652,29 +8011,106 @@ var AxSignature = class _AxSignature {
7652
8011
  parseField = (field) => {
7653
8012
  const title = !field.title || field.title.length === 0 ? this.toTitle(field.name) : field.title;
7654
8013
  if (field.type && (!field.type.name || field.type.name.length === 0)) {
7655
- throw new Error("Field type name is required: " + field.name);
8014
+ throw new AxSignatureValidationError(
8015
+ "Field type name is required",
8016
+ field.name,
8017
+ "Specify a valid type. Available types: string, number, boolean, json, image, audio, date, datetime, class, code"
8018
+ );
7656
8019
  }
7657
8020
  return { ...field, title };
7658
8021
  };
7659
8022
  setDescription = (desc) => {
8023
+ if (typeof desc !== "string") {
8024
+ throw new AxSignatureValidationError(
8025
+ "Description must be a string",
8026
+ void 0,
8027
+ "Provide a string description for the signature"
8028
+ );
8029
+ }
7660
8030
  this.description = desc;
7661
8031
  this.updateHash();
7662
8032
  };
7663
8033
  addInputField = (field) => {
7664
- this.inputFields.push(this.parseField(field));
7665
- this.updateHash();
8034
+ try {
8035
+ const parsedField = this.parseField(field);
8036
+ validateField(parsedField, "input");
8037
+ this.inputFields.push(parsedField);
8038
+ this.updateHash();
8039
+ } catch (error) {
8040
+ if (error instanceof AxSignatureValidationError) {
8041
+ throw error;
8042
+ }
8043
+ throw new AxSignatureValidationError(
8044
+ `Failed to add input field "${field.name}": ${error instanceof Error ? error.message : "Unknown error"}`,
8045
+ field.name
8046
+ );
8047
+ }
7666
8048
  };
7667
8049
  addOutputField = (field) => {
7668
- this.outputFields.push(this.parseField(field));
7669
- this.updateHash();
8050
+ try {
8051
+ const parsedField = this.parseField(field);
8052
+ validateField(parsedField, "output");
8053
+ this.outputFields.push(parsedField);
8054
+ this.updateHash();
8055
+ } catch (error) {
8056
+ if (error instanceof AxSignatureValidationError) {
8057
+ throw error;
8058
+ }
8059
+ throw new AxSignatureValidationError(
8060
+ `Failed to add output field "${field.name}": ${error instanceof Error ? error.message : "Unknown error"}`,
8061
+ field.name
8062
+ );
8063
+ }
7670
8064
  };
7671
8065
  setInputFields = (fields) => {
7672
- this.inputFields = fields.map((v) => this.parseField(v));
7673
- this.updateHash();
8066
+ if (!Array.isArray(fields)) {
8067
+ throw new AxSignatureValidationError(
8068
+ "Input fields must be an array",
8069
+ void 0,
8070
+ "Provide an array of field objects"
8071
+ );
8072
+ }
8073
+ try {
8074
+ const parsedFields = fields.map((v) => {
8075
+ const parsed = this.parseField(v);
8076
+ validateField(parsed, "input");
8077
+ return parsed;
8078
+ });
8079
+ this.inputFields = parsedFields;
8080
+ this.updateHash();
8081
+ } catch (error) {
8082
+ if (error instanceof AxSignatureValidationError) {
8083
+ throw error;
8084
+ }
8085
+ throw new AxSignatureValidationError(
8086
+ `Failed to set input fields: ${error instanceof Error ? error.message : "Unknown error"}`
8087
+ );
8088
+ }
7674
8089
  };
7675
8090
  setOutputFields = (fields) => {
7676
- this.outputFields = fields.map((v) => this.parseField(v));
7677
- this.updateHash();
8091
+ if (!Array.isArray(fields)) {
8092
+ throw new AxSignatureValidationError(
8093
+ "Output fields must be an array",
8094
+ void 0,
8095
+ "Provide an array of field objects"
8096
+ );
8097
+ }
8098
+ try {
8099
+ const parsedFields = fields.map((v) => {
8100
+ const parsed = this.parseField(v);
8101
+ validateField(parsed, "output");
8102
+ return parsed;
8103
+ });
8104
+ this.outputFields = parsedFields;
8105
+ this.updateHash();
8106
+ } catch (error) {
8107
+ if (error instanceof AxSignatureValidationError) {
8108
+ throw error;
8109
+ }
8110
+ throw new AxSignatureValidationError(
8111
+ `Failed to set output fields: ${error instanceof Error ? error.message : "Unknown error"}`
8112
+ );
8113
+ }
7678
8114
  };
7679
8115
  getInputFields = () => this.inputFields;
7680
8116
  getOutputFields = () => this.outputFields;
@@ -7687,25 +8123,25 @@ var AxSignature = class _AxSignature {
7687
8123
  toJSONSchema = () => {
7688
8124
  const properties = {};
7689
8125
  const required = [];
7690
- for (const f of this.inputFields) {
7691
- const type = f.type ? f.type.name : "string";
7692
- if (f.type?.isArray) {
7693
- properties[f.name] = {
7694
- description: f.description,
8126
+ for (const f2 of this.inputFields) {
8127
+ const type = f2.type ? f2.type.name : "string";
8128
+ if (f2.type?.isArray) {
8129
+ properties[f2.name] = {
8130
+ description: f2.description,
7695
8131
  type: "array",
7696
8132
  items: {
7697
8133
  type,
7698
- description: f.description
8134
+ description: f2.description
7699
8135
  }
7700
8136
  };
7701
8137
  } else {
7702
- properties[f.name] = {
7703
- description: f.description,
8138
+ properties[f2.name] = {
8139
+ description: f2.description,
7704
8140
  type
7705
8141
  };
7706
8142
  }
7707
- if (!f.isOptional) {
7708
- required.push(f.name);
8143
+ if (!f2.isOptional) {
8144
+ required.push(f2.name);
7709
8145
  }
7710
8146
  }
7711
8147
  const schema = {
@@ -7716,23 +8152,77 @@ var AxSignature = class _AxSignature {
7716
8152
  return schema;
7717
8153
  };
7718
8154
  updateHash = () => {
7719
- this.getInputFields().forEach((field) => {
7720
- validateField(field);
7721
- });
7722
- this.getOutputFields().forEach((field) => {
7723
- validateField(field);
7724
- if (field.type?.name === "image") {
7725
- throw new Error("Image type is not supported in output fields.");
8155
+ try {
8156
+ this.getInputFields().forEach((field) => {
8157
+ validateField(field, "input");
8158
+ });
8159
+ this.getOutputFields().forEach((field) => {
8160
+ validateField(field, "output");
8161
+ });
8162
+ this.validateSignatureConsistency();
8163
+ this.sigHash = createHash("sha256").update(this.description ?? "").update(JSON.stringify(this.inputFields)).update(JSON.stringify(this.outputFields)).digest("hex");
8164
+ this.sigString = renderSignature(
8165
+ this.description,
8166
+ this.inputFields,
8167
+ this.outputFields
8168
+ );
8169
+ return [this.sigHash, this.sigString];
8170
+ } catch (error) {
8171
+ if (error instanceof AxSignatureValidationError) {
8172
+ throw error;
7726
8173
  }
7727
- });
7728
- this.sigHash = createHash("sha256").update(this.description ?? "").update(JSON.stringify(this.inputFields)).update(JSON.stringify(this.outputFields)).digest("hex");
7729
- this.sigString = renderSignature(
7730
- this.description,
7731
- this.inputFields,
7732
- this.outputFields
7733
- );
7734
- return [this.sigHash, this.sigString];
8174
+ throw new AxSignatureValidationError(
8175
+ `Signature validation failed: ${error instanceof Error ? error.message : "Unknown error"}`
8176
+ );
8177
+ }
7735
8178
  };
8179
+ validateSignatureConsistency() {
8180
+ const inputNames = /* @__PURE__ */ new Set();
8181
+ for (const field of this.inputFields) {
8182
+ if (inputNames.has(field.name)) {
8183
+ throw new AxSignatureValidationError(
8184
+ `Duplicate input field name: "${field.name}"`,
8185
+ field.name,
8186
+ "Each field name must be unique within the signature"
8187
+ );
8188
+ }
8189
+ inputNames.add(field.name);
8190
+ }
8191
+ const outputNames = /* @__PURE__ */ new Set();
8192
+ for (const field of this.outputFields) {
8193
+ if (outputNames.has(field.name)) {
8194
+ throw new AxSignatureValidationError(
8195
+ `Duplicate output field name: "${field.name}"`,
8196
+ field.name,
8197
+ "Each field name must be unique within the signature"
8198
+ );
8199
+ }
8200
+ outputNames.add(field.name);
8201
+ }
8202
+ for (const outputField of this.outputFields) {
8203
+ if (inputNames.has(outputField.name)) {
8204
+ throw new AxSignatureValidationError(
8205
+ `Field name "${outputField.name}" appears in both inputs and outputs`,
8206
+ outputField.name,
8207
+ "Use different names for input and output fields to avoid confusion"
8208
+ );
8209
+ }
8210
+ }
8211
+ if (this.inputFields.length === 0) {
8212
+ throw new AxSignatureValidationError(
8213
+ "Signature must have at least one input field",
8214
+ void 0,
8215
+ 'Add an input field. Example: "userInput:string -> ..."'
8216
+ );
8217
+ }
8218
+ if (this.outputFields.length === 0) {
8219
+ throw new AxSignatureValidationError(
8220
+ "Signature must have at least one output field",
8221
+ void 0,
8222
+ 'Add an output field. Example: "... -> responseText:string"'
8223
+ );
8224
+ }
8225
+ }
7736
8226
  hash = () => this.sigHash;
7737
8227
  toString = () => this.sigString;
7738
8228
  toJSON = () => {
@@ -7749,54 +8239,194 @@ function renderField(field) {
7749
8239
  if (field.isOptional) {
7750
8240
  result += "?";
7751
8241
  }
8242
+ if (field.isInternal) {
8243
+ result += "!";
8244
+ }
7752
8245
  if (field.type) {
7753
8246
  result += ":" + field.type.name;
7754
8247
  if (field.type.isArray) {
7755
8248
  result += "[]";
7756
8249
  }
8250
+ if (field.type.name === "class" && field.type.options) {
8251
+ result += ` "${field.type.options.join(", ")}"`;
8252
+ }
7757
8253
  }
7758
- if (field.description) {
8254
+ if (field.description && field.type?.name !== "class") {
7759
8255
  result += ` "${field.description}"`;
7760
8256
  }
7761
8257
  return result;
7762
8258
  }
7763
8259
  function renderSignature(description, inputFields, outputFields) {
7764
- const descriptionPart = description ? `"${description}"` : "";
8260
+ const descriptionPart = description ? `"${description}" ` : "";
7765
8261
  const inputFieldsRendered = inputFields.map(renderField).join(", ");
7766
8262
  const outputFieldsRendered = outputFields.map(renderField).join(", ");
7767
- return `${descriptionPart} ${inputFieldsRendered} -> ${outputFieldsRendered}`;
8263
+ return `${descriptionPart}${inputFieldsRendered} -> ${outputFieldsRendered}`;
7768
8264
  }
7769
8265
  function isValidCase(inputString) {
7770
8266
  const camelCaseRegex = /^[a-z][a-zA-Z0-9]*$/;
7771
8267
  const snakeCaseRegex = /^[a-z]+(_[a-z0-9]+)*$/;
7772
8268
  return camelCaseRegex.test(inputString) || snakeCaseRegex.test(inputString);
7773
8269
  }
7774
- function validateField(field) {
8270
+ function validateField(field, context3) {
7775
8271
  if (!field.name || field.name.length === 0) {
7776
- throw new Error("Field name cannot be blank");
8272
+ throw new AxSignatureValidationError(
8273
+ "Field name cannot be blank",
8274
+ field.name,
8275
+ "Every field must have a descriptive name"
8276
+ );
7777
8277
  }
7778
8278
  if (!isValidCase(field.name)) {
7779
- throw new Error(
7780
- `Invalid field name '${field.name}', it must be camel case or snake case: `
8279
+ throw new AxSignatureValidationError(
8280
+ `Invalid field name '${field.name}' - must be camelCase or snake_case`,
8281
+ field.name,
8282
+ 'Use camelCase (e.g., "userInput") or snake_case (e.g., "user_input")'
7781
8283
  );
7782
8284
  }
7783
- if ([
7784
- "text",
7785
- "object",
7786
- "image",
7787
- "string",
7788
- "number",
7789
- "boolean",
7790
- "json",
7791
- "array",
7792
- "datetime",
7793
- "date",
7794
- "time",
7795
- "type",
7796
- "class"
7797
- ].includes(field.name)) {
7798
- throw new Error(
7799
- `Invalid field name '${field.name}', please make it more descriptive (eg. companyDescription)`
8285
+ if (axGlobals.signatureStrict) {
8286
+ const reservedNames = [
8287
+ "text",
8288
+ "object",
8289
+ "image",
8290
+ "string",
8291
+ "number",
8292
+ "boolean",
8293
+ "json",
8294
+ "array",
8295
+ "datetime",
8296
+ "date",
8297
+ "time",
8298
+ "type",
8299
+ "class",
8300
+ "input",
8301
+ "output",
8302
+ "data",
8303
+ "value",
8304
+ "result",
8305
+ "response",
8306
+ "request",
8307
+ "item",
8308
+ "element"
8309
+ ];
8310
+ if (reservedNames.includes(field.name.toLowerCase())) {
8311
+ const suggestions = context3 === "input" ? [
8312
+ "userInput",
8313
+ "questionText",
8314
+ "documentContent",
8315
+ "messageText",
8316
+ "queryString"
8317
+ ] : [
8318
+ "responseText",
8319
+ "analysisResult",
8320
+ "categoryType",
8321
+ "summaryText",
8322
+ "outputData"
8323
+ ];
8324
+ throw new AxSignatureValidationError(
8325
+ `Field name '${field.name}' is too generic`,
8326
+ field.name,
8327
+ `Use a more descriptive name. Examples for ${context3} fields: ${suggestions.join(", ")}`
8328
+ );
8329
+ }
8330
+ }
8331
+ if (field.name.length < 2) {
8332
+ throw new AxSignatureValidationError(
8333
+ `Field name '${field.name}' is too short`,
8334
+ field.name,
8335
+ "Field names must be at least 2 characters long"
8336
+ );
8337
+ }
8338
+ if (field.name.length > 50) {
8339
+ throw new AxSignatureValidationError(
8340
+ `Field name '${field.name}' is too long (${field.name.length} characters)`,
8341
+ field.name,
8342
+ "Field names should be 50 characters or less"
8343
+ );
8344
+ }
8345
+ if (field.type) {
8346
+ validateFieldType(field, context3);
8347
+ }
8348
+ }
8349
+ function validateFieldType(field, context3) {
8350
+ if (!field.type) return;
8351
+ const { type } = field;
8352
+ if (type.name === "image" || type.name === "audio") {
8353
+ if (context3 === "output") {
8354
+ throw new AxSignatureValidationError(
8355
+ `${type.name} type is not supported in output fields`,
8356
+ field.name,
8357
+ `${type.name} types can only be used in input fields`
8358
+ );
8359
+ }
8360
+ if (type.isArray) {
8361
+ throw new AxSignatureValidationError(
8362
+ `Arrays of ${type.name} are not supported`,
8363
+ field.name,
8364
+ `Use a single ${type.name} type instead`
8365
+ );
8366
+ }
8367
+ }
8368
+ if (type.name === "class") {
8369
+ if (context3 === "input") {
8370
+ throw new AxSignatureValidationError(
8371
+ "Class type is not supported in input fields",
8372
+ field.name,
8373
+ 'Class types are only allowed on output fields. Use "string" type for input classifications'
8374
+ );
8375
+ }
8376
+ if (!type.options || type.options.length === 0) {
8377
+ throw new AxSignatureValidationError(
8378
+ "Class type requires options",
8379
+ field.name,
8380
+ 'Provide class options. Example: class "positive, negative, neutral"'
8381
+ );
8382
+ }
8383
+ if (type.options.length === 1) {
8384
+ throw new AxSignatureValidationError(
8385
+ "Class type needs at least 2 options",
8386
+ field.name,
8387
+ 'Add more class options or use "string" type instead'
8388
+ );
8389
+ }
8390
+ for (const option of type.options) {
8391
+ if (!option || option.trim().length === 0) {
8392
+ throw new AxSignatureValidationError(
8393
+ "Empty class option found",
8394
+ field.name,
8395
+ "All class options must be non-empty strings"
8396
+ );
8397
+ }
8398
+ const trimmedOption = option.trim();
8399
+ if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(trimmedOption)) {
8400
+ throw new AxSignatureValidationError(
8401
+ `Invalid class option "${trimmedOption}"`,
8402
+ field.name,
8403
+ "Class options must start with a letter and contain only letters, numbers, underscores, or hyphens"
8404
+ );
8405
+ }
8406
+ }
8407
+ const uniqueOptions = new Set(
8408
+ type.options.map((opt) => opt.trim().toLowerCase())
8409
+ );
8410
+ if (uniqueOptions.size !== type.options.length) {
8411
+ throw new AxSignatureValidationError(
8412
+ "Duplicate class options found",
8413
+ field.name,
8414
+ "Each class option must be unique (case-insensitive)"
8415
+ );
8416
+ }
8417
+ }
8418
+ if (type.name === "code" && type.isArray) {
8419
+ throw new AxSignatureValidationError(
8420
+ "Arrays of code are not commonly supported",
8421
+ field.name,
8422
+ "Consider using a single code field or an array of strings instead"
8423
+ );
8424
+ }
8425
+ if (field.isInternal && context3 === "input") {
8426
+ throw new AxSignatureValidationError(
8427
+ "Internal marker (!) is not allowed on input fields",
8428
+ field.name,
8429
+ "Internal markers are only allowed on output fields"
7800
8430
  );
7801
8431
  }
7802
8432
  }
@@ -7871,11 +8501,11 @@ var AxProgramWithSignature = class {
7871
8501
  const fields = [...sig.getInputFields(), ...sig.getOutputFields()];
7872
8502
  this.examples = traces.map((e) => {
7873
8503
  const res = {};
7874
- for (const f of fields) {
7875
- const value = e[f.name];
8504
+ for (const f2 of fields) {
8505
+ const value = e[f2.name];
7876
8506
  if (value !== void 0) {
7877
- validateValue(f, value);
7878
- res[f.name] = value;
8507
+ validateValue(f2, value);
8508
+ res[f2.name] = value;
7879
8509
  }
7880
8510
  }
7881
8511
  return res;
@@ -8029,7 +8659,7 @@ var AxGen = class extends AxProgramWithSignature {
8029
8659
  this.streamingAsserts.push({ fieldName, fn, message });
8030
8660
  };
8031
8661
  addFieldProcessorInternal = (fieldName, fn, streaming = false) => {
8032
- const field = this.signature.getOutputFields().find((f) => f.name === fieldName);
8662
+ const field = this.signature.getOutputFields().find((f2) => f2.name === fieldName);
8033
8663
  if (!field) {
8034
8664
  throw new Error(`addFieldProcessor: field ${fieldName} not found`);
8035
8665
  }
@@ -8075,7 +8705,7 @@ var AxGen = class extends AxProgramWithSignature {
8075
8705
  if (chatPrompt.length === 0) {
8076
8706
  throw new Error("No chat prompt found");
8077
8707
  }
8078
- const functions = _functions?.map((f) => "toFunction" in f ? f.toFunction() : f)?.flat();
8708
+ const functions = _functions?.map((f2) => "toFunction" in f2 ? f2.toFunction() : f2)?.flat();
8079
8709
  let functionCall = _functionCall ?? this.options?.functionCall;
8080
8710
  if (!firstStep && (functionCall === "required" || typeof functionCall === "function")) {
8081
8711
  functionCall = void 0;
@@ -8113,7 +8743,7 @@ var AxGen = class extends AxProgramWithSignature {
8113
8743
  const { sessionId, traceId, functions: _functions } = options ?? {};
8114
8744
  const fastFail = options?.fastFail ?? this.options?.fastFail;
8115
8745
  const model = options.model;
8116
- const functions = _functions?.map((f) => "toFunction" in f ? f.toFunction() : f)?.flat();
8746
+ const functions = _functions?.map((f2) => "toFunction" in f2 ? f2.toFunction() : f2)?.flat();
8117
8747
  const res = await this.forwardSendRequest({
8118
8748
  ai,
8119
8749
  mem,
@@ -8438,7 +9068,7 @@ Content: ${result.content}`
8438
9068
  if (span) {
8439
9069
  span.addEvent("validation.error", {
8440
9070
  message: e.toString(),
8441
- fixing_instructions: errorFields?.map((f) => f.title).join(", ") ?? ""
9071
+ fixing_instructions: errorFields?.map((f2) => f2.title).join(", ") ?? ""
8442
9072
  });
8443
9073
  }
8444
9074
  } else if (e instanceof AxAssertionError) {
@@ -8448,7 +9078,7 @@ Content: ${result.content}`
8448
9078
  if (span) {
8449
9079
  span.addEvent("assertion.error", {
8450
9080
  message: e1.toString(),
8451
- fixing_instructions: errorFields?.map((f) => f.title).join(", ") ?? ""
9081
+ fixing_instructions: errorFields?.map((f2) => f2.title).join(", ") ?? ""
8452
9082
  });
8453
9083
  }
8454
9084
  } else if (e instanceof AxAIServiceStreamTerminatedError) {
@@ -8503,7 +9133,7 @@ Content: ${result.content}`
8503
9133
  });
8504
9134
  return;
8505
9135
  }
8506
- const funcNames = functions?.map((f) => f.name).join(",");
9136
+ const funcNames = functions?.map((f2) => f2.name).join(",");
8507
9137
  const attributes = {
8508
9138
  signature: JSON.stringify(this.signature.toJSON(), null, 2),
8509
9139
  ...this.examples ? { examples: JSON.stringify(this.examples, null, 2) } : {},
@@ -8762,7 +9392,7 @@ var AxAgent = class {
8762
9392
  const sig = this.program.getSignature();
8763
9393
  const outFields = sig.getOutputFields();
8764
9394
  const result = Object.keys(ret).map((k) => {
8765
- const field = outFields.find((f) => f.name === k);
9395
+ const field = outFields.find((f2) => f2.name === k);
8766
9396
  if (field) {
8767
9397
  return `${field.title}: ${ret[k]}`;
8768
9398
  }
@@ -8791,12 +9421,12 @@ var AxAgent = class {
8791
9421
  const parentKeys = parentSchema.map((p) => p.name);
8792
9422
  const debug = this.getDebug(ai, options);
8793
9423
  const agentFuncs = this.agents?.map((agent) => {
8794
- const f = agent.getFeatures();
9424
+ const f2 = agent.getFeatures();
8795
9425
  const processOptions = {
8796
9426
  debug,
8797
9427
  disableSmartModelRouting: !!this.disableSmartModelRouting,
8798
- excludeFieldsFromPassthrough: f.excludeFieldsFromPassthrough,
8799
- canConfigureSmartModelRouting: f.canConfigureSmartModelRouting
9428
+ excludeFieldsFromPassthrough: f2.excludeFieldsFromPassthrough,
9429
+ canConfigureSmartModelRouting: f2.canConfigureSmartModelRouting
8800
9430
  };
8801
9431
  return processChildAgentFunction(
8802
9432
  agent.getFunction(),
@@ -11529,13 +12159,18 @@ var AxMockAIService = class {
11529
12159
  }
11530
12160
  };
11531
12161
  getLastUsedChatModel() {
11532
- throw new Error("Method not implemented.");
12162
+ return this.config.modelInfo?.name ?? "mock-model";
11533
12163
  }
11534
12164
  getLastUsedEmbedModel() {
11535
- throw new Error("Method not implemented.");
12165
+ return this.config.embedModelInfo?.name ?? "mock-embed-model";
11536
12166
  }
11537
12167
  getLastUsedModelConfig() {
11538
- throw new Error("Method not implemented.");
12168
+ return this.config.modelInfo ? {
12169
+ maxTokens: this.config.modelInfo.maxTokens,
12170
+ temperature: 0.7,
12171
+ // Default temperature
12172
+ stream: this.config.features?.streaming ?? false
12173
+ } : void 0;
11539
12174
  }
11540
12175
  getName() {
11541
12176
  return this.config.name ?? "mock-ai-service";
@@ -11768,7 +12403,7 @@ var AxTestPrompt = class {
11768
12403
  };
11769
12404
 
11770
12405
  // dsp/template.ts
11771
- function ax(strings, ...values) {
12406
+ function s(strings, ...values) {
11772
12407
  let result = "";
11773
12408
  for (let i = 0; i < strings.length; i++) {
11774
12409
  result += strings[i] ?? "";
@@ -11796,6 +12431,34 @@ function ax(strings, ...values) {
11796
12431
  }
11797
12432
  return new AxSignature(result);
11798
12433
  }
12434
+ function ax(strings, ...values) {
12435
+ let result = "";
12436
+ for (let i = 0; i < strings.length; i++) {
12437
+ result += strings[i] ?? "";
12438
+ if (i < values.length) {
12439
+ const val = values[i];
12440
+ if (isAxFieldType(val)) {
12441
+ const fieldNameMatch = result.match(/(\w+)\s*:\s*$/);
12442
+ if (fieldNameMatch && (val.isOptional || val.isInternal)) {
12443
+ const fieldName = fieldNameMatch[1];
12444
+ let modifiedFieldName = fieldName;
12445
+ if (val.isOptional) modifiedFieldName += "?";
12446
+ if (val.isInternal) modifiedFieldName += "!";
12447
+ result = result.replace(/(\w+)(\s*:\s*)$/, `${modifiedFieldName}$2`);
12448
+ }
12449
+ const { isOptional: _o, isInternal: _i, ...typeNoFlags } = val;
12450
+ result += convertFieldTypeToString(typeNoFlags);
12451
+ } else if (isAxFieldDescriptor(val)) {
12452
+ result += convertFieldDescriptorToString(val);
12453
+ } else if (typeof val === "string" || val instanceof AxSignature) {
12454
+ result += convertValueToSignatureString(val);
12455
+ } else {
12456
+ throw new Error("Unsupported template interpolation value");
12457
+ }
12458
+ }
12459
+ }
12460
+ return new AxGen(result);
12461
+ }
11799
12462
  function convertValueToSignatureString(value) {
11800
12463
  if (typeof value === "string") {
11801
12464
  return value;
@@ -11851,7 +12514,7 @@ function isAxFieldType(value) {
11851
12514
  function isAxFieldDescriptor(value) {
11852
12515
  return value !== null && typeof value === "object" && value !== void 0 && "name" in value && typeof value.name === "string";
11853
12516
  }
11854
- var axField = {
12517
+ var f = {
11855
12518
  string: (desc) => ({
11856
12519
  type: "string",
11857
12520
  description: desc
@@ -13232,12 +13895,12 @@ function countTokens(tokens) {
13232
13895
  }
13233
13896
  return counter;
13234
13897
  }
13235
- function normalizeText(s) {
13236
- s = s.normalize("NFD");
13237
- s = s.replace(/\b(a|an|the)\b/g, " ");
13238
- s = s.split(/\s+/).join(" ");
13239
- s = s.replace(/[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/g, "");
13240
- return s.toLowerCase();
13898
+ function normalizeText(s2) {
13899
+ s2 = s2.normalize("NFD");
13900
+ s2 = s2.replace(/\b(a|an|the)\b/g, " ");
13901
+ s2 = s2.split(/\s+/).join(" ");
13902
+ s2 = s2.replace(/[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/g, "");
13903
+ return s2.toLowerCase();
13241
13904
  }
13242
13905
  function emScore(prediction, groundTruth) {
13243
13906
  return normalizeText(prediction) === normalizeText(groundTruth) ? 1 : 0;
@@ -13651,7 +14314,7 @@ var AxMultiServiceRouter = class {
13651
14314
  * Returns a composite ID built from the IDs of the underlying services.
13652
14315
  */
13653
14316
  getId() {
13654
- return "MultiServiceRouter:" + Array.from(this.services.values()).map((s) => s.service.getId()).join(",");
14317
+ return "MultiServiceRouter:" + Array.from(this.services.values()).map((s2) => s2.service.getId()).join(",");
13655
14318
  }
13656
14319
  /**
13657
14320
  * Returns the name of this router.
@@ -13910,7 +14573,7 @@ export {
13910
14573
  axAITogetherDefaultConfig,
13911
14574
  axBaseAIDefaultConfig,
13912
14575
  axBaseAIDefaultCreativeConfig,
13913
- axField,
14576
+ axGlobals,
13914
14577
  axModelInfoAnthropic,
13915
14578
  axModelInfoCohere,
13916
14579
  axModelInfoDeepSeek,
@@ -13923,6 +14586,8 @@ export {
13923
14586
  axModelInfoReka,
13924
14587
  axModelInfoTogether,
13925
14588
  axSpanAttributes,
13926
- axSpanEvents
14589
+ axSpanEvents,
14590
+ f,
14591
+ s
13927
14592
  };
13928
14593
  //# sourceMappingURL=index.js.map