@ax-llm/ax 11.0.67 → 12.0.1
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 +774 -106
- package/index.cjs.map +1 -1
- package/index.d.cts +39 -33
- package/index.d.ts +39 -33
- package/index.js +773 -106
- package/index.js.map +1 -1
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1098,6 +1098,7 @@ var AxBaseAI = class {
|
|
|
1098
1098
|
if (chatReq.functions && chatReq.functions.length > 0) {
|
|
1099
1099
|
functions = chatReq.functions.map((fn2) => this.cleanupFunctionSchema(fn2));
|
|
1100
1100
|
}
|
|
1101
|
+
validateChatPrompt(chatReq.chatPrompt);
|
|
1101
1102
|
const req = {
|
|
1102
1103
|
...chatReq,
|
|
1103
1104
|
model,
|
|
@@ -1439,6 +1440,31 @@ function setChatResponseEvents(res, span, excludeContentFromTrace) {
|
|
|
1439
1440
|
});
|
|
1440
1441
|
}
|
|
1441
1442
|
}
|
|
1443
|
+
function validateAxMessageArray(values) {
|
|
1444
|
+
for (let i = 0; i < values.length; i++) {
|
|
1445
|
+
const message = values[i];
|
|
1446
|
+
if (!message || typeof message !== "object") {
|
|
1447
|
+
throw new Error(
|
|
1448
|
+
`AxMessage array validation failed: Item at index ${i} is not a valid message object`
|
|
1449
|
+
);
|
|
1450
|
+
}
|
|
1451
|
+
if ("content" in message && typeof message.content === "string" && message.content.trim() === "") {
|
|
1452
|
+
throw new Error(
|
|
1453
|
+
`AxMessage array validation failed: Item at index ${i} has empty content`
|
|
1454
|
+
);
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
function validateChatPrompt(chatPrompt) {
|
|
1459
|
+
for (let i = 0; i < chatPrompt.length; i++) {
|
|
1460
|
+
const message = chatPrompt[i];
|
|
1461
|
+
if (message && "content" in message && typeof message.content === "string" && message.content.trim() === "") {
|
|
1462
|
+
throw new Error(
|
|
1463
|
+
`Chat prompt validation failed: Message at index ${i} has empty content`
|
|
1464
|
+
);
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1442
1468
|
function validateModels(models) {
|
|
1443
1469
|
const keys = /* @__PURE__ */ new Set();
|
|
1444
1470
|
for (const model of models) {
|
|
@@ -3215,7 +3241,9 @@ var AxAIGoogleGeminiImpl = class {
|
|
|
3215
3241
|
const contents = req.chatPrompt.filter((p) => p.role !== "system").map((msg, i) => {
|
|
3216
3242
|
switch (msg.role) {
|
|
3217
3243
|
case "user": {
|
|
3218
|
-
const parts = Array.isArray(
|
|
3244
|
+
const parts = Array.isArray(
|
|
3245
|
+
msg.content
|
|
3246
|
+
) ? msg.content.map((c, i2) => {
|
|
3219
3247
|
switch (c.type) {
|
|
3220
3248
|
case "text":
|
|
3221
3249
|
return { text: c.text };
|
|
@@ -3276,12 +3304,14 @@ var AxAIGoogleGeminiImpl = class {
|
|
|
3276
3304
|
}
|
|
3277
3305
|
];
|
|
3278
3306
|
return {
|
|
3279
|
-
role: "
|
|
3307
|
+
role: "model",
|
|
3280
3308
|
parts
|
|
3281
3309
|
};
|
|
3282
3310
|
}
|
|
3283
3311
|
default:
|
|
3284
|
-
throw new Error(
|
|
3312
|
+
throw new Error(
|
|
3313
|
+
`Invalid role: ${JSON.stringify(msg)} (index: ${i})`
|
|
3314
|
+
);
|
|
3285
3315
|
}
|
|
3286
3316
|
});
|
|
3287
3317
|
let tools = [];
|
|
@@ -6560,6 +6590,11 @@ var extractValues = (sig, values, content) => {
|
|
|
6560
6590
|
const xstate = { extractedFields: [], streamedIndex: {}, s: -1 };
|
|
6561
6591
|
streamingExtractValues(sig, values, xstate, content);
|
|
6562
6592
|
streamingExtractFinalValue(sig, values, xstate, content);
|
|
6593
|
+
for (const field of sig.getOutputFields()) {
|
|
6594
|
+
if (field.isInternal) {
|
|
6595
|
+
delete values[field.name];
|
|
6596
|
+
}
|
|
6597
|
+
}
|
|
6563
6598
|
};
|
|
6564
6599
|
var checkMissingRequiredFields = (xstate, values, currentIndex) => {
|
|
6565
6600
|
const missingFields = [];
|
|
@@ -7285,93 +7320,218 @@ var AxInstanceRegistry = class {
|
|
|
7285
7320
|
// dsp/sig.ts
|
|
7286
7321
|
import { createHash } from "crypto";
|
|
7287
7322
|
|
|
7323
|
+
// dsp/globals.ts
|
|
7324
|
+
var axGlobals = {
|
|
7325
|
+
signatureStrict: true
|
|
7326
|
+
// Controls reservedNames enforcement in signature parsing/validation
|
|
7327
|
+
};
|
|
7328
|
+
|
|
7288
7329
|
// dsp/parser.ts
|
|
7330
|
+
var SignatureValidationError = class extends Error {
|
|
7331
|
+
constructor(message, position, context3, suggestion) {
|
|
7332
|
+
super(message);
|
|
7333
|
+
this.position = position;
|
|
7334
|
+
this.context = context3;
|
|
7335
|
+
this.suggestion = suggestion;
|
|
7336
|
+
this.name = "SignatureValidationError";
|
|
7337
|
+
}
|
|
7338
|
+
};
|
|
7289
7339
|
var SignatureParser = class {
|
|
7290
7340
|
input;
|
|
7291
7341
|
position;
|
|
7292
7342
|
currentFieldName = null;
|
|
7343
|
+
currentSection = "description";
|
|
7293
7344
|
constructor(input) {
|
|
7294
|
-
this.input = input;
|
|
7345
|
+
this.input = input.trim();
|
|
7295
7346
|
this.position = 0;
|
|
7347
|
+
if (!this.input) {
|
|
7348
|
+
throw new SignatureValidationError(
|
|
7349
|
+
"Empty signature provided",
|
|
7350
|
+
0,
|
|
7351
|
+
"",
|
|
7352
|
+
'A signature must contain at least input and output fields separated by "->". Example: "userQuery:string -> aiResponse:string"'
|
|
7353
|
+
);
|
|
7354
|
+
}
|
|
7296
7355
|
}
|
|
7297
7356
|
parse() {
|
|
7298
7357
|
try {
|
|
7299
7358
|
this.skipWhitespace();
|
|
7300
7359
|
const optionalDesc = this.parseParsedString();
|
|
7301
7360
|
this.skipWhitespace();
|
|
7361
|
+
this.currentSection = "inputs";
|
|
7302
7362
|
const inputs = this.parseFieldList(
|
|
7303
7363
|
this.parseInputField.bind(this),
|
|
7304
7364
|
"input"
|
|
7305
7365
|
);
|
|
7306
7366
|
this.skipWhitespace();
|
|
7307
7367
|
if (this.position >= this.input.length) {
|
|
7308
|
-
throw new
|
|
7309
|
-
|
|
7368
|
+
throw new SignatureValidationError(
|
|
7369
|
+
"Incomplete signature: Missing output section",
|
|
7370
|
+
this.position,
|
|
7371
|
+
this.getErrorContext(),
|
|
7372
|
+
'Add "->" followed by output fields. Example: "-> responseText:string"'
|
|
7310
7373
|
);
|
|
7311
7374
|
}
|
|
7312
|
-
this.
|
|
7375
|
+
this.expectArrow();
|
|
7313
7376
|
this.skipWhitespace();
|
|
7314
7377
|
if (this.position >= this.input.length) {
|
|
7315
|
-
throw new
|
|
7316
|
-
'Incomplete signature: No output fields specified after "->"'
|
|
7378
|
+
throw new SignatureValidationError(
|
|
7379
|
+
'Incomplete signature: No output fields specified after "->"',
|
|
7380
|
+
this.position,
|
|
7381
|
+
this.getErrorContext(),
|
|
7382
|
+
'Add at least one output field. Example: "-> responseText:string"'
|
|
7317
7383
|
);
|
|
7318
7384
|
}
|
|
7385
|
+
this.currentSection = "outputs";
|
|
7319
7386
|
const outputs = this.parseFieldList(
|
|
7320
7387
|
this.parseOutputField.bind(this),
|
|
7321
7388
|
"output"
|
|
7322
7389
|
);
|
|
7390
|
+
this.skipWhitespace();
|
|
7391
|
+
if (this.position < this.input.length) {
|
|
7392
|
+
const remaining = this.input.slice(this.position);
|
|
7393
|
+
throw new SignatureValidationError(
|
|
7394
|
+
`Unexpected content after signature: "${remaining}"`,
|
|
7395
|
+
this.position,
|
|
7396
|
+
this.getErrorContext(),
|
|
7397
|
+
"Remove any extra content after the output fields"
|
|
7398
|
+
);
|
|
7399
|
+
}
|
|
7400
|
+
this.validateParsedSignature({
|
|
7401
|
+
desc: optionalDesc?.trim(),
|
|
7402
|
+
inputs,
|
|
7403
|
+
outputs
|
|
7404
|
+
});
|
|
7323
7405
|
return {
|
|
7324
7406
|
desc: optionalDesc?.trim(),
|
|
7325
7407
|
inputs,
|
|
7326
7408
|
outputs
|
|
7327
7409
|
};
|
|
7328
7410
|
} catch (error) {
|
|
7411
|
+
if (error instanceof SignatureValidationError) {
|
|
7412
|
+
throw error;
|
|
7413
|
+
}
|
|
7329
7414
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
7330
|
-
|
|
7331
|
-
|
|
7332
|
-
|
|
7415
|
+
throw new SignatureValidationError(
|
|
7416
|
+
errorMessage,
|
|
7417
|
+
this.position,
|
|
7418
|
+
this.getErrorContext()
|
|
7419
|
+
);
|
|
7420
|
+
}
|
|
7421
|
+
}
|
|
7422
|
+
validateParsedSignature(signature) {
|
|
7423
|
+
const inputNames = /* @__PURE__ */ new Set();
|
|
7424
|
+
for (const field of signature.inputs) {
|
|
7425
|
+
if (inputNames.has(field.name)) {
|
|
7426
|
+
throw new SignatureValidationError(
|
|
7427
|
+
`Duplicate input field name: "${field.name}"`,
|
|
7428
|
+
0,
|
|
7429
|
+
"",
|
|
7430
|
+
"Each field name must be unique within the signature"
|
|
7431
|
+
);
|
|
7432
|
+
}
|
|
7433
|
+
inputNames.add(field.name);
|
|
7434
|
+
}
|
|
7435
|
+
const outputNames = /* @__PURE__ */ new Set();
|
|
7436
|
+
for (const field of signature.outputs) {
|
|
7437
|
+
if (outputNames.has(field.name)) {
|
|
7438
|
+
throw new SignatureValidationError(
|
|
7439
|
+
`Duplicate output field name: "${field.name}"`,
|
|
7440
|
+
0,
|
|
7441
|
+
"",
|
|
7442
|
+
"Each field name must be unique within the signature"
|
|
7443
|
+
);
|
|
7444
|
+
}
|
|
7445
|
+
outputNames.add(field.name);
|
|
7446
|
+
}
|
|
7447
|
+
for (const outputField of signature.outputs) {
|
|
7448
|
+
if (inputNames.has(outputField.name)) {
|
|
7449
|
+
throw new SignatureValidationError(
|
|
7450
|
+
`Field name "${outputField.name}" appears in both inputs and outputs`,
|
|
7451
|
+
0,
|
|
7452
|
+
"",
|
|
7453
|
+
"Use different names for input and output fields to avoid confusion"
|
|
7454
|
+
);
|
|
7455
|
+
}
|
|
7456
|
+
}
|
|
7457
|
+
if (signature.inputs.length === 0) {
|
|
7458
|
+
throw new SignatureValidationError(
|
|
7459
|
+
"Signature must have at least one input field",
|
|
7460
|
+
0,
|
|
7461
|
+
"",
|
|
7462
|
+
'Add an input field before "->". Example: "userInput:string -> ..."'
|
|
7463
|
+
);
|
|
7464
|
+
}
|
|
7465
|
+
if (signature.outputs.length === 0) {
|
|
7466
|
+
throw new SignatureValidationError(
|
|
7467
|
+
"Signature must have at least one output field",
|
|
7468
|
+
0,
|
|
7469
|
+
"",
|
|
7470
|
+
'Add an output field after "->". Example: "... -> responseText:string"'
|
|
7471
|
+
);
|
|
7333
7472
|
}
|
|
7334
7473
|
}
|
|
7335
7474
|
getErrorContext() {
|
|
7336
|
-
const start = Math.max(0, this.position -
|
|
7337
|
-
const end = Math.min(this.input.length, this.position +
|
|
7475
|
+
const start = Math.max(0, this.position - 25);
|
|
7476
|
+
const end = Math.min(this.input.length, this.position + 25);
|
|
7338
7477
|
const before = this.input.slice(start, this.position);
|
|
7339
7478
|
const after = this.input.slice(this.position, end);
|
|
7340
7479
|
const pointer = " ".repeat(before.length) + "^";
|
|
7341
|
-
|
|
7342
|
-
${
|
|
7343
|
-
${
|
|
7480
|
+
const lines = [
|
|
7481
|
+
`Position ${this.position} in signature:`,
|
|
7482
|
+
`"${before}${after}"`,
|
|
7483
|
+
` ${pointer}`
|
|
7484
|
+
];
|
|
7485
|
+
return lines.join("\n");
|
|
7344
7486
|
}
|
|
7345
7487
|
parseFieldList(parseFieldFn, section) {
|
|
7346
7488
|
const fields = [];
|
|
7347
7489
|
this.skipWhitespace();
|
|
7348
7490
|
if (this.position >= this.input.length) {
|
|
7349
|
-
throw new
|
|
7491
|
+
throw new SignatureValidationError(
|
|
7492
|
+
`Empty ${section} section: Expected at least one field`,
|
|
7493
|
+
this.position,
|
|
7494
|
+
this.getErrorContext(),
|
|
7495
|
+
`Add a ${section} field. Example: ${section === "input" ? "userInput:string" : "responseText:string"}`
|
|
7496
|
+
);
|
|
7350
7497
|
}
|
|
7351
7498
|
try {
|
|
7352
7499
|
fields.push(parseFieldFn());
|
|
7353
7500
|
} catch (error) {
|
|
7354
|
-
|
|
7355
|
-
|
|
7501
|
+
if (error instanceof SignatureValidationError) {
|
|
7502
|
+
throw error;
|
|
7503
|
+
}
|
|
7504
|
+
throw new SignatureValidationError(
|
|
7505
|
+
`Invalid first ${section} field: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
7506
|
+
this.position,
|
|
7507
|
+
this.getErrorContext()
|
|
7356
7508
|
);
|
|
7357
7509
|
}
|
|
7358
7510
|
this.skipWhitespace();
|
|
7359
7511
|
while (this.position < this.input.length) {
|
|
7360
|
-
if (this.input[this.position] === "-" && this.input[this.position + 1] === ">") {
|
|
7512
|
+
if (this.input[this.position] === "-" && this.position + 1 < this.input.length && this.input[this.position + 1] === ">") {
|
|
7361
7513
|
break;
|
|
7362
7514
|
}
|
|
7363
7515
|
if (this.match(",")) {
|
|
7364
7516
|
this.skipWhitespace();
|
|
7365
7517
|
if (this.position >= this.input.length) {
|
|
7366
|
-
throw new
|
|
7367
|
-
`Unexpected end of input after comma in ${section} section
|
|
7518
|
+
throw new SignatureValidationError(
|
|
7519
|
+
`Unexpected end of input after comma in ${section} section`,
|
|
7520
|
+
this.position,
|
|
7521
|
+
this.getErrorContext(),
|
|
7522
|
+
`Add another ${section} field after the comma`
|
|
7368
7523
|
);
|
|
7369
7524
|
}
|
|
7370
7525
|
try {
|
|
7371
7526
|
fields.push(parseFieldFn());
|
|
7372
7527
|
} catch (error) {
|
|
7373
|
-
|
|
7374
|
-
|
|
7528
|
+
if (error instanceof SignatureValidationError) {
|
|
7529
|
+
throw error;
|
|
7530
|
+
}
|
|
7531
|
+
throw new SignatureValidationError(
|
|
7532
|
+
`Invalid ${section} field after comma: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
7533
|
+
this.position,
|
|
7534
|
+
this.getErrorContext()
|
|
7375
7535
|
);
|
|
7376
7536
|
}
|
|
7377
7537
|
this.skipWhitespace();
|
|
@@ -7388,6 +7548,7 @@ ${pointer}`;
|
|
|
7388
7548
|
this.skipWhitespace();
|
|
7389
7549
|
const name = this.parseParsedIdentifier();
|
|
7390
7550
|
this.currentFieldName = name;
|
|
7551
|
+
this.validateFieldName(name, "input");
|
|
7391
7552
|
let isOptional = void 0;
|
|
7392
7553
|
while (true) {
|
|
7393
7554
|
if (this.match("?")) {
|
|
@@ -7395,8 +7556,11 @@ ${pointer}`;
|
|
|
7395
7556
|
continue;
|
|
7396
7557
|
}
|
|
7397
7558
|
if (this.match("!")) {
|
|
7398
|
-
throw new
|
|
7399
|
-
`Input field "${name}"
|
|
7559
|
+
throw new SignatureValidationError(
|
|
7560
|
+
`Input field "${name}" cannot use the internal marker "!"`,
|
|
7561
|
+
this.position - 1,
|
|
7562
|
+
this.getErrorContext(),
|
|
7563
|
+
"Internal markers (!) are only allowed on output fields"
|
|
7400
7564
|
);
|
|
7401
7565
|
}
|
|
7402
7566
|
break;
|
|
@@ -7406,17 +7570,33 @@ ${pointer}`;
|
|
|
7406
7570
|
if (this.match(":")) {
|
|
7407
7571
|
this.skipWhitespace();
|
|
7408
7572
|
if (/^class\b/.test(this.input.slice(this.position))) {
|
|
7409
|
-
throw new
|
|
7410
|
-
`Input field "${name}"
|
|
7573
|
+
throw new SignatureValidationError(
|
|
7574
|
+
`Input field "${name}" cannot use the "class" type`,
|
|
7575
|
+
this.position,
|
|
7576
|
+
this.getErrorContext(),
|
|
7577
|
+
'Class types are only allowed on output fields. Use "string" type for input classifications'
|
|
7411
7578
|
);
|
|
7412
7579
|
} else {
|
|
7413
7580
|
try {
|
|
7414
7581
|
const typeName = this.parseTypeNotClass();
|
|
7415
7582
|
const isArray = this.match("[]");
|
|
7416
7583
|
type = { name: typeName, isArray };
|
|
7584
|
+
if ((typeName === "image" || typeName === "audio") && isArray) {
|
|
7585
|
+
throw new SignatureValidationError(
|
|
7586
|
+
`Input field "${name}": Arrays of ${typeName} are not supported`,
|
|
7587
|
+
this.position,
|
|
7588
|
+
this.getErrorContext(),
|
|
7589
|
+
`Use a single ${typeName} type instead: "${typeName}"`
|
|
7590
|
+
);
|
|
7591
|
+
}
|
|
7417
7592
|
} catch (error) {
|
|
7418
|
-
|
|
7419
|
-
|
|
7593
|
+
if (error instanceof SignatureValidationError) {
|
|
7594
|
+
throw error;
|
|
7595
|
+
}
|
|
7596
|
+
throw new SignatureValidationError(
|
|
7597
|
+
`Input field "${name}": ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
7598
|
+
this.position,
|
|
7599
|
+
this.getErrorContext()
|
|
7420
7600
|
);
|
|
7421
7601
|
}
|
|
7422
7602
|
}
|
|
@@ -7437,6 +7617,7 @@ ${pointer}`;
|
|
|
7437
7617
|
this.skipWhitespace();
|
|
7438
7618
|
const name = this.parseParsedIdentifier();
|
|
7439
7619
|
this.currentFieldName = name;
|
|
7620
|
+
this.validateFieldName(name, "output");
|
|
7440
7621
|
let isOptional = false;
|
|
7441
7622
|
let isInternal = false;
|
|
7442
7623
|
while (true) {
|
|
@@ -7459,25 +7640,86 @@ ${pointer}`;
|
|
|
7459
7640
|
this.skipWhitespace();
|
|
7460
7641
|
const classNamesString = this.parseParsedString();
|
|
7461
7642
|
if (!classNamesString) {
|
|
7462
|
-
throw new
|
|
7463
|
-
`Output field "${name}":
|
|
7643
|
+
throw new SignatureValidationError(
|
|
7644
|
+
`Output field "${name}": Missing class options after "class" type`,
|
|
7645
|
+
this.position,
|
|
7646
|
+
this.getErrorContext(),
|
|
7647
|
+
'Add class names in quotes. Example: class "positive, negative, neutral"'
|
|
7464
7648
|
);
|
|
7465
7649
|
}
|
|
7466
7650
|
const options = classNamesString.split(/[,\s]+/).map((s2) => s2.trim()).filter((s2) => s2.length > 0);
|
|
7467
7651
|
if (options.length === 0) {
|
|
7468
|
-
throw new
|
|
7469
|
-
`Output field "${name}": Empty class list provided
|
|
7652
|
+
throw new SignatureValidationError(
|
|
7653
|
+
`Output field "${name}": Empty class list provided`,
|
|
7654
|
+
this.position,
|
|
7655
|
+
this.getErrorContext(),
|
|
7656
|
+
'Provide at least one class option. Example: "positive, negative"'
|
|
7470
7657
|
);
|
|
7471
7658
|
}
|
|
7659
|
+
if (options.length === 1) {
|
|
7660
|
+
throw new SignatureValidationError(
|
|
7661
|
+
`Output field "${name}": Class type needs at least 2 options`,
|
|
7662
|
+
this.position,
|
|
7663
|
+
this.getErrorContext(),
|
|
7664
|
+
'Add more class options or use "string" type instead. Example: "positive, negative, neutral"'
|
|
7665
|
+
);
|
|
7666
|
+
}
|
|
7667
|
+
for (const option of options) {
|
|
7668
|
+
if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(option)) {
|
|
7669
|
+
throw new SignatureValidationError(
|
|
7670
|
+
`Output field "${name}": Invalid class option "${option}"`,
|
|
7671
|
+
this.position,
|
|
7672
|
+
this.getErrorContext(),
|
|
7673
|
+
"Class options must start with a letter and contain only letters, numbers, underscores, or hyphens"
|
|
7674
|
+
);
|
|
7675
|
+
}
|
|
7676
|
+
}
|
|
7472
7677
|
type = { name: "class", isArray, options };
|
|
7473
7678
|
} else {
|
|
7474
7679
|
try {
|
|
7475
7680
|
const typeName = this.parseTypeNotClass();
|
|
7476
7681
|
const isArray = this.match("[]");
|
|
7477
7682
|
type = { name: typeName, isArray };
|
|
7683
|
+
if (typeName === "image" && isArray) {
|
|
7684
|
+
throw new SignatureValidationError(
|
|
7685
|
+
`Output field "${name}": Arrays of images are not supported`,
|
|
7686
|
+
this.position,
|
|
7687
|
+
this.getErrorContext(),
|
|
7688
|
+
'Use a single image type instead: "image"'
|
|
7689
|
+
);
|
|
7690
|
+
}
|
|
7691
|
+
if (typeName === "audio" && isArray) {
|
|
7692
|
+
throw new SignatureValidationError(
|
|
7693
|
+
`Output field "${name}": Arrays of audio are not supported`,
|
|
7694
|
+
this.position,
|
|
7695
|
+
this.getErrorContext(),
|
|
7696
|
+
'Use a single audio type instead: "audio"'
|
|
7697
|
+
);
|
|
7698
|
+
}
|
|
7699
|
+
if (typeName === "image") {
|
|
7700
|
+
throw new SignatureValidationError(
|
|
7701
|
+
`Output field "${name}": Image type is not supported in output fields`,
|
|
7702
|
+
this.position,
|
|
7703
|
+
this.getErrorContext(),
|
|
7704
|
+
"Image types can only be used in input fields"
|
|
7705
|
+
);
|
|
7706
|
+
}
|
|
7707
|
+
if (typeName === "audio") {
|
|
7708
|
+
throw new SignatureValidationError(
|
|
7709
|
+
`Output field "${name}": Audio type is not supported in output fields`,
|
|
7710
|
+
this.position,
|
|
7711
|
+
this.getErrorContext(),
|
|
7712
|
+
"Audio types can only be used in input fields"
|
|
7713
|
+
);
|
|
7714
|
+
}
|
|
7478
7715
|
} catch (error) {
|
|
7479
|
-
|
|
7480
|
-
|
|
7716
|
+
if (error instanceof SignatureValidationError) {
|
|
7717
|
+
throw error;
|
|
7718
|
+
}
|
|
7719
|
+
throw new SignatureValidationError(
|
|
7720
|
+
`Output field "${name}": ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
7721
|
+
this.position,
|
|
7722
|
+
this.getErrorContext()
|
|
7481
7723
|
);
|
|
7482
7724
|
}
|
|
7483
7725
|
}
|
|
@@ -7492,6 +7734,69 @@ ${pointer}`;
|
|
|
7492
7734
|
isInternal
|
|
7493
7735
|
};
|
|
7494
7736
|
}
|
|
7737
|
+
validateFieldName(name, fieldType) {
|
|
7738
|
+
if (axGlobals.signatureStrict) {
|
|
7739
|
+
const reservedNames = [
|
|
7740
|
+
"text",
|
|
7741
|
+
"object",
|
|
7742
|
+
"image",
|
|
7743
|
+
"string",
|
|
7744
|
+
"number",
|
|
7745
|
+
"boolean",
|
|
7746
|
+
"json",
|
|
7747
|
+
"array",
|
|
7748
|
+
"datetime",
|
|
7749
|
+
"date",
|
|
7750
|
+
"time",
|
|
7751
|
+
"type",
|
|
7752
|
+
"class",
|
|
7753
|
+
"input",
|
|
7754
|
+
"output",
|
|
7755
|
+
"data",
|
|
7756
|
+
"value",
|
|
7757
|
+
"result",
|
|
7758
|
+
"response",
|
|
7759
|
+
"request",
|
|
7760
|
+
"item",
|
|
7761
|
+
"element"
|
|
7762
|
+
];
|
|
7763
|
+
if (reservedNames.includes(name.toLowerCase())) {
|
|
7764
|
+
const suggestions = fieldType === "input" ? ["userInput", "questionText", "documentContent", "messageText"] : ["responseText", "analysisResult", "categoryType", "summaryText"];
|
|
7765
|
+
throw new SignatureValidationError(
|
|
7766
|
+
`Field name "${name}" is too generic`,
|
|
7767
|
+
this.position,
|
|
7768
|
+
this.getErrorContext(),
|
|
7769
|
+
`Use a more descriptive name. Examples: ${suggestions.join(", ")}`
|
|
7770
|
+
);
|
|
7771
|
+
}
|
|
7772
|
+
}
|
|
7773
|
+
const camelCaseRegex = /^[a-z][a-zA-Z0-9]*$/;
|
|
7774
|
+
const snakeCaseRegex = /^[a-z]+(_[a-z0-9]+)*$/;
|
|
7775
|
+
if (!camelCaseRegex.test(name) && !snakeCaseRegex.test(name)) {
|
|
7776
|
+
throw new SignatureValidationError(
|
|
7777
|
+
`Invalid field name "${name}"`,
|
|
7778
|
+
this.position,
|
|
7779
|
+
this.getErrorContext(),
|
|
7780
|
+
'Field names must be in camelCase (e.g., "userInput") or snake_case (e.g., "user_input")'
|
|
7781
|
+
);
|
|
7782
|
+
}
|
|
7783
|
+
if (name.length < 2) {
|
|
7784
|
+
throw new SignatureValidationError(
|
|
7785
|
+
`Field name "${name}" is too short`,
|
|
7786
|
+
this.position,
|
|
7787
|
+
this.getErrorContext(),
|
|
7788
|
+
"Field names must be at least 2 characters long"
|
|
7789
|
+
);
|
|
7790
|
+
}
|
|
7791
|
+
if (name.length > 50) {
|
|
7792
|
+
throw new SignatureValidationError(
|
|
7793
|
+
`Field name "${name}" is too long (${name.length} characters)`,
|
|
7794
|
+
this.position,
|
|
7795
|
+
this.getErrorContext(),
|
|
7796
|
+
"Field names should be 50 characters or less"
|
|
7797
|
+
);
|
|
7798
|
+
}
|
|
7799
|
+
}
|
|
7495
7800
|
parseTypeNotClass() {
|
|
7496
7801
|
const types = [
|
|
7497
7802
|
"string",
|
|
@@ -7506,13 +7811,42 @@ ${pointer}`;
|
|
|
7506
7811
|
];
|
|
7507
7812
|
const foundType = types.find((type) => this.match(type));
|
|
7508
7813
|
if (!foundType) {
|
|
7509
|
-
const currentWord = this.input.slice(this.position).match(/^\w+/)?.[0] || "
|
|
7510
|
-
|
|
7511
|
-
|
|
7814
|
+
const currentWord = this.input.slice(this.position).match(/^\w+/)?.[0] || "";
|
|
7815
|
+
const suggestion = this.suggestType(currentWord);
|
|
7816
|
+
const baseMessage = `Invalid type "${currentWord || "empty"}"`;
|
|
7817
|
+
const suggestionPart = suggestion ? `. Did you mean "${suggestion}"?` : "";
|
|
7818
|
+
const fullMessage = `${baseMessage}${suggestionPart}`;
|
|
7819
|
+
throw new SignatureValidationError(
|
|
7820
|
+
fullMessage,
|
|
7821
|
+
this.position,
|
|
7822
|
+
this.getErrorContext(),
|
|
7823
|
+
`Expected one of: ${types.join(", ")}`
|
|
7512
7824
|
);
|
|
7513
7825
|
}
|
|
7514
7826
|
return foundType;
|
|
7515
7827
|
}
|
|
7828
|
+
suggestType(input) {
|
|
7829
|
+
const suggestions = {
|
|
7830
|
+
str: "string",
|
|
7831
|
+
text: "string",
|
|
7832
|
+
int: "number",
|
|
7833
|
+
integer: "number",
|
|
7834
|
+
float: "number",
|
|
7835
|
+
double: "number",
|
|
7836
|
+
bool: "boolean",
|
|
7837
|
+
object: "json",
|
|
7838
|
+
dict: "json",
|
|
7839
|
+
timestamp: "datetime",
|
|
7840
|
+
time: "datetime",
|
|
7841
|
+
img: "image",
|
|
7842
|
+
picture: "image",
|
|
7843
|
+
sound: "audio",
|
|
7844
|
+
voice: "audio",
|
|
7845
|
+
classification: "class",
|
|
7846
|
+
category: "class"
|
|
7847
|
+
};
|
|
7848
|
+
return suggestions[input.toLowerCase()] || null;
|
|
7849
|
+
}
|
|
7516
7850
|
parseParsedIdentifier() {
|
|
7517
7851
|
this.skipWhitespace();
|
|
7518
7852
|
const match = /^[a-zA-Z_][a-zA-Z_0-9]*/.exec(
|
|
@@ -7523,9 +7857,28 @@ ${pointer}`;
|
|
|
7523
7857
|
return match[0];
|
|
7524
7858
|
}
|
|
7525
7859
|
const invalidMatch = /^\S+/.exec(this.input.slice(this.position));
|
|
7526
|
-
const invalidId = invalidMatch ? invalidMatch[0] : "
|
|
7527
|
-
|
|
7528
|
-
|
|
7860
|
+
const invalidId = invalidMatch ? invalidMatch[0] : "";
|
|
7861
|
+
if (invalidId === "") {
|
|
7862
|
+
throw new SignatureValidationError(
|
|
7863
|
+
"Expected field name but found end of input",
|
|
7864
|
+
this.position,
|
|
7865
|
+
this.getErrorContext(),
|
|
7866
|
+
"Add a field name. Field names must start with a letter or underscore"
|
|
7867
|
+
);
|
|
7868
|
+
}
|
|
7869
|
+
if (/^\d/.test(invalidId)) {
|
|
7870
|
+
throw new SignatureValidationError(
|
|
7871
|
+
`Invalid field name "${invalidId}" - cannot start with a number`,
|
|
7872
|
+
this.position,
|
|
7873
|
+
this.getErrorContext(),
|
|
7874
|
+
'Field names must start with a letter or underscore. Example: "userInput" or "_internal"'
|
|
7875
|
+
);
|
|
7876
|
+
}
|
|
7877
|
+
throw new SignatureValidationError(
|
|
7878
|
+
`Invalid field name "${invalidId}"`,
|
|
7879
|
+
this.position,
|
|
7880
|
+
this.getErrorContext(),
|
|
7881
|
+
"Field names must start with a letter or underscore and contain only letters, numbers, or underscores"
|
|
7529
7882
|
);
|
|
7530
7883
|
}
|
|
7531
7884
|
parseParsedString() {
|
|
@@ -7534,7 +7887,7 @@ ${pointer}`;
|
|
|
7534
7887
|
if (this.match(quoteChar)) {
|
|
7535
7888
|
let content = "";
|
|
7536
7889
|
let escaped = false;
|
|
7537
|
-
|
|
7890
|
+
const startPos = this.position - 1;
|
|
7538
7891
|
while (this.position < this.input.length) {
|
|
7539
7892
|
const char = this.input[this.position];
|
|
7540
7893
|
this.position++;
|
|
@@ -7549,9 +7902,15 @@ ${pointer}`;
|
|
|
7549
7902
|
content += char;
|
|
7550
7903
|
}
|
|
7551
7904
|
}
|
|
7552
|
-
const partialString = this.input.slice(
|
|
7553
|
-
|
|
7554
|
-
|
|
7905
|
+
const partialString = this.input.slice(
|
|
7906
|
+
startPos,
|
|
7907
|
+
Math.min(this.position, startPos + 20)
|
|
7908
|
+
);
|
|
7909
|
+
throw new SignatureValidationError(
|
|
7910
|
+
`Unterminated string starting at position ${startPos}`,
|
|
7911
|
+
startPos,
|
|
7912
|
+
this.getErrorContext(),
|
|
7913
|
+
`Add closing ${quoteChar} to complete the string: ${partialString}${quoteChar}`
|
|
7555
7914
|
);
|
|
7556
7915
|
}
|
|
7557
7916
|
}
|
|
@@ -7579,11 +7938,15 @@ ${pointer}`;
|
|
|
7579
7938
|
}
|
|
7580
7939
|
return false;
|
|
7581
7940
|
}
|
|
7582
|
-
|
|
7583
|
-
if (!this.match(
|
|
7941
|
+
expectArrow() {
|
|
7942
|
+
if (!this.match("->")) {
|
|
7584
7943
|
const found = this.input.slice(this.position, this.position + 10);
|
|
7585
|
-
|
|
7586
|
-
|
|
7944
|
+
const suggestion = found.includes(">") ? 'Use "->" (dash followed by greater-than)' : found.includes("-") ? 'Add ">" after the dash' : 'Add "->" to separate input and output fields';
|
|
7945
|
+
throw new SignatureValidationError(
|
|
7946
|
+
`Expected "->" but found "${found}..."`,
|
|
7947
|
+
this.position,
|
|
7948
|
+
this.getErrorContext(),
|
|
7949
|
+
suggestion
|
|
7587
7950
|
);
|
|
7588
7951
|
}
|
|
7589
7952
|
}
|
|
@@ -7594,6 +7957,14 @@ function parseSignature(input) {
|
|
|
7594
7957
|
}
|
|
7595
7958
|
|
|
7596
7959
|
// dsp/sig.ts
|
|
7960
|
+
var AxSignatureValidationError = class extends Error {
|
|
7961
|
+
constructor(message, fieldName, suggestion) {
|
|
7962
|
+
super(message);
|
|
7963
|
+
this.fieldName = fieldName;
|
|
7964
|
+
this.suggestion = suggestion;
|
|
7965
|
+
this.name = "AxSignatureValidationError";
|
|
7966
|
+
}
|
|
7967
|
+
};
|
|
7597
7968
|
var AxSignature = class _AxSignature {
|
|
7598
7969
|
description;
|
|
7599
7970
|
inputFields;
|
|
@@ -7613,8 +7984,18 @@ var AxSignature = class _AxSignature {
|
|
|
7613
7984
|
try {
|
|
7614
7985
|
sig = parseSignature(signature);
|
|
7615
7986
|
} catch (e) {
|
|
7616
|
-
|
|
7617
|
-
|
|
7987
|
+
if (e instanceof Error) {
|
|
7988
|
+
const suggestion = "suggestion" in e && typeof e.suggestion === "string" ? e.suggestion : 'Please check the signature format. Example: "userInput:string -> responseText:string"';
|
|
7989
|
+
throw new AxSignatureValidationError(
|
|
7990
|
+
`Invalid Signature: ${e.message}`,
|
|
7991
|
+
void 0,
|
|
7992
|
+
suggestion
|
|
7993
|
+
);
|
|
7994
|
+
}
|
|
7995
|
+
throw new AxSignatureValidationError(
|
|
7996
|
+
`Invalid Signature: ${signature}`,
|
|
7997
|
+
void 0,
|
|
7998
|
+
'Please check the signature format. Example: "userInput:string -> responseText:string"'
|
|
7618
7999
|
);
|
|
7619
8000
|
}
|
|
7620
8001
|
this.description = sig.desc;
|
|
@@ -7632,12 +8013,20 @@ var AxSignature = class _AxSignature {
|
|
|
7632
8013
|
this.sigHash = signature.hash();
|
|
7633
8014
|
this.sigString = signature.toString();
|
|
7634
8015
|
} else {
|
|
7635
|
-
throw new
|
|
8016
|
+
throw new AxSignatureValidationError(
|
|
8017
|
+
"Invalid signature argument type",
|
|
8018
|
+
void 0,
|
|
8019
|
+
"Signature must be a string or another AxSignature instance"
|
|
8020
|
+
);
|
|
7636
8021
|
}
|
|
7637
8022
|
}
|
|
7638
8023
|
parseParsedField = (field) => {
|
|
7639
8024
|
if (!field.name || field.name.length === 0) {
|
|
7640
|
-
throw new
|
|
8025
|
+
throw new AxSignatureValidationError(
|
|
8026
|
+
"Field name is required",
|
|
8027
|
+
field.name,
|
|
8028
|
+
'Every field must have a descriptive name. Example: "userInput", "responseText"'
|
|
8029
|
+
);
|
|
7641
8030
|
}
|
|
7642
8031
|
const title = this.toTitle(field.name);
|
|
7643
8032
|
return {
|
|
@@ -7652,29 +8041,106 @@ var AxSignature = class _AxSignature {
|
|
|
7652
8041
|
parseField = (field) => {
|
|
7653
8042
|
const title = !field.title || field.title.length === 0 ? this.toTitle(field.name) : field.title;
|
|
7654
8043
|
if (field.type && (!field.type.name || field.type.name.length === 0)) {
|
|
7655
|
-
throw new
|
|
8044
|
+
throw new AxSignatureValidationError(
|
|
8045
|
+
"Field type name is required",
|
|
8046
|
+
field.name,
|
|
8047
|
+
"Specify a valid type. Available types: string, number, boolean, json, image, audio, date, datetime, class, code"
|
|
8048
|
+
);
|
|
7656
8049
|
}
|
|
7657
8050
|
return { ...field, title };
|
|
7658
8051
|
};
|
|
7659
8052
|
setDescription = (desc) => {
|
|
8053
|
+
if (typeof desc !== "string") {
|
|
8054
|
+
throw new AxSignatureValidationError(
|
|
8055
|
+
"Description must be a string",
|
|
8056
|
+
void 0,
|
|
8057
|
+
"Provide a string description for the signature"
|
|
8058
|
+
);
|
|
8059
|
+
}
|
|
7660
8060
|
this.description = desc;
|
|
7661
8061
|
this.updateHash();
|
|
7662
8062
|
};
|
|
7663
8063
|
addInputField = (field) => {
|
|
7664
|
-
|
|
7665
|
-
|
|
8064
|
+
try {
|
|
8065
|
+
const parsedField = this.parseField(field);
|
|
8066
|
+
validateField(parsedField, "input");
|
|
8067
|
+
this.inputFields.push(parsedField);
|
|
8068
|
+
this.updateHash();
|
|
8069
|
+
} catch (error) {
|
|
8070
|
+
if (error instanceof AxSignatureValidationError) {
|
|
8071
|
+
throw error;
|
|
8072
|
+
}
|
|
8073
|
+
throw new AxSignatureValidationError(
|
|
8074
|
+
`Failed to add input field "${field.name}": ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
8075
|
+
field.name
|
|
8076
|
+
);
|
|
8077
|
+
}
|
|
7666
8078
|
};
|
|
7667
8079
|
addOutputField = (field) => {
|
|
7668
|
-
|
|
7669
|
-
|
|
8080
|
+
try {
|
|
8081
|
+
const parsedField = this.parseField(field);
|
|
8082
|
+
validateField(parsedField, "output");
|
|
8083
|
+
this.outputFields.push(parsedField);
|
|
8084
|
+
this.updateHash();
|
|
8085
|
+
} catch (error) {
|
|
8086
|
+
if (error instanceof AxSignatureValidationError) {
|
|
8087
|
+
throw error;
|
|
8088
|
+
}
|
|
8089
|
+
throw new AxSignatureValidationError(
|
|
8090
|
+
`Failed to add output field "${field.name}": ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
8091
|
+
field.name
|
|
8092
|
+
);
|
|
8093
|
+
}
|
|
7670
8094
|
};
|
|
7671
8095
|
setInputFields = (fields) => {
|
|
7672
|
-
|
|
7673
|
-
|
|
8096
|
+
if (!Array.isArray(fields)) {
|
|
8097
|
+
throw new AxSignatureValidationError(
|
|
8098
|
+
"Input fields must be an array",
|
|
8099
|
+
void 0,
|
|
8100
|
+
"Provide an array of field objects"
|
|
8101
|
+
);
|
|
8102
|
+
}
|
|
8103
|
+
try {
|
|
8104
|
+
const parsedFields = fields.map((v) => {
|
|
8105
|
+
const parsed = this.parseField(v);
|
|
8106
|
+
validateField(parsed, "input");
|
|
8107
|
+
return parsed;
|
|
8108
|
+
});
|
|
8109
|
+
this.inputFields = parsedFields;
|
|
8110
|
+
this.updateHash();
|
|
8111
|
+
} catch (error) {
|
|
8112
|
+
if (error instanceof AxSignatureValidationError) {
|
|
8113
|
+
throw error;
|
|
8114
|
+
}
|
|
8115
|
+
throw new AxSignatureValidationError(
|
|
8116
|
+
`Failed to set input fields: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
8117
|
+
);
|
|
8118
|
+
}
|
|
7674
8119
|
};
|
|
7675
8120
|
setOutputFields = (fields) => {
|
|
7676
|
-
|
|
7677
|
-
|
|
8121
|
+
if (!Array.isArray(fields)) {
|
|
8122
|
+
throw new AxSignatureValidationError(
|
|
8123
|
+
"Output fields must be an array",
|
|
8124
|
+
void 0,
|
|
8125
|
+
"Provide an array of field objects"
|
|
8126
|
+
);
|
|
8127
|
+
}
|
|
8128
|
+
try {
|
|
8129
|
+
const parsedFields = fields.map((v) => {
|
|
8130
|
+
const parsed = this.parseField(v);
|
|
8131
|
+
validateField(parsed, "output");
|
|
8132
|
+
return parsed;
|
|
8133
|
+
});
|
|
8134
|
+
this.outputFields = parsedFields;
|
|
8135
|
+
this.updateHash();
|
|
8136
|
+
} catch (error) {
|
|
8137
|
+
if (error instanceof AxSignatureValidationError) {
|
|
8138
|
+
throw error;
|
|
8139
|
+
}
|
|
8140
|
+
throw new AxSignatureValidationError(
|
|
8141
|
+
`Failed to set output fields: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
8142
|
+
);
|
|
8143
|
+
}
|
|
7678
8144
|
};
|
|
7679
8145
|
getInputFields = () => this.inputFields;
|
|
7680
8146
|
getOutputFields = () => this.outputFields;
|
|
@@ -7716,23 +8182,77 @@ var AxSignature = class _AxSignature {
|
|
|
7716
8182
|
return schema;
|
|
7717
8183
|
};
|
|
7718
8184
|
updateHash = () => {
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
7723
|
-
|
|
7724
|
-
|
|
7725
|
-
|
|
8185
|
+
try {
|
|
8186
|
+
this.getInputFields().forEach((field) => {
|
|
8187
|
+
validateField(field, "input");
|
|
8188
|
+
});
|
|
8189
|
+
this.getOutputFields().forEach((field) => {
|
|
8190
|
+
validateField(field, "output");
|
|
8191
|
+
});
|
|
8192
|
+
this.validateSignatureConsistency();
|
|
8193
|
+
this.sigHash = createHash("sha256").update(this.description ?? "").update(JSON.stringify(this.inputFields)).update(JSON.stringify(this.outputFields)).digest("hex");
|
|
8194
|
+
this.sigString = renderSignature(
|
|
8195
|
+
this.description,
|
|
8196
|
+
this.inputFields,
|
|
8197
|
+
this.outputFields
|
|
8198
|
+
);
|
|
8199
|
+
return [this.sigHash, this.sigString];
|
|
8200
|
+
} catch (error) {
|
|
8201
|
+
if (error instanceof AxSignatureValidationError) {
|
|
8202
|
+
throw error;
|
|
7726
8203
|
}
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
|
|
7730
|
-
|
|
7731
|
-
this.inputFields,
|
|
7732
|
-
this.outputFields
|
|
7733
|
-
);
|
|
7734
|
-
return [this.sigHash, this.sigString];
|
|
8204
|
+
throw new AxSignatureValidationError(
|
|
8205
|
+
`Signature validation failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
8206
|
+
);
|
|
8207
|
+
}
|
|
7735
8208
|
};
|
|
8209
|
+
validateSignatureConsistency() {
|
|
8210
|
+
const inputNames = /* @__PURE__ */ new Set();
|
|
8211
|
+
for (const field of this.inputFields) {
|
|
8212
|
+
if (inputNames.has(field.name)) {
|
|
8213
|
+
throw new AxSignatureValidationError(
|
|
8214
|
+
`Duplicate input field name: "${field.name}"`,
|
|
8215
|
+
field.name,
|
|
8216
|
+
"Each field name must be unique within the signature"
|
|
8217
|
+
);
|
|
8218
|
+
}
|
|
8219
|
+
inputNames.add(field.name);
|
|
8220
|
+
}
|
|
8221
|
+
const outputNames = /* @__PURE__ */ new Set();
|
|
8222
|
+
for (const field of this.outputFields) {
|
|
8223
|
+
if (outputNames.has(field.name)) {
|
|
8224
|
+
throw new AxSignatureValidationError(
|
|
8225
|
+
`Duplicate output field name: "${field.name}"`,
|
|
8226
|
+
field.name,
|
|
8227
|
+
"Each field name must be unique within the signature"
|
|
8228
|
+
);
|
|
8229
|
+
}
|
|
8230
|
+
outputNames.add(field.name);
|
|
8231
|
+
}
|
|
8232
|
+
for (const outputField of this.outputFields) {
|
|
8233
|
+
if (inputNames.has(outputField.name)) {
|
|
8234
|
+
throw new AxSignatureValidationError(
|
|
8235
|
+
`Field name "${outputField.name}" appears in both inputs and outputs`,
|
|
8236
|
+
outputField.name,
|
|
8237
|
+
"Use different names for input and output fields to avoid confusion"
|
|
8238
|
+
);
|
|
8239
|
+
}
|
|
8240
|
+
}
|
|
8241
|
+
if (this.inputFields.length === 0) {
|
|
8242
|
+
throw new AxSignatureValidationError(
|
|
8243
|
+
"Signature must have at least one input field",
|
|
8244
|
+
void 0,
|
|
8245
|
+
'Add an input field. Example: "userInput:string -> ..."'
|
|
8246
|
+
);
|
|
8247
|
+
}
|
|
8248
|
+
if (this.outputFields.length === 0) {
|
|
8249
|
+
throw new AxSignatureValidationError(
|
|
8250
|
+
"Signature must have at least one output field",
|
|
8251
|
+
void 0,
|
|
8252
|
+
'Add an output field. Example: "... -> responseText:string"'
|
|
8253
|
+
);
|
|
8254
|
+
}
|
|
8255
|
+
}
|
|
7736
8256
|
hash = () => this.sigHash;
|
|
7737
8257
|
toString = () => this.sigString;
|
|
7738
8258
|
toJSON = () => {
|
|
@@ -7749,54 +8269,194 @@ function renderField(field) {
|
|
|
7749
8269
|
if (field.isOptional) {
|
|
7750
8270
|
result += "?";
|
|
7751
8271
|
}
|
|
8272
|
+
if (field.isInternal) {
|
|
8273
|
+
result += "!";
|
|
8274
|
+
}
|
|
7752
8275
|
if (field.type) {
|
|
7753
8276
|
result += ":" + field.type.name;
|
|
7754
8277
|
if (field.type.isArray) {
|
|
7755
8278
|
result += "[]";
|
|
7756
8279
|
}
|
|
8280
|
+
if (field.type.name === "class" && field.type.options) {
|
|
8281
|
+
result += ` "${field.type.options.join(", ")}"`;
|
|
8282
|
+
}
|
|
7757
8283
|
}
|
|
7758
|
-
if (field.description) {
|
|
8284
|
+
if (field.description && field.type?.name !== "class") {
|
|
7759
8285
|
result += ` "${field.description}"`;
|
|
7760
8286
|
}
|
|
7761
8287
|
return result;
|
|
7762
8288
|
}
|
|
7763
8289
|
function renderSignature(description, inputFields, outputFields) {
|
|
7764
|
-
const descriptionPart = description ? `"${description}"` : "";
|
|
8290
|
+
const descriptionPart = description ? `"${description}" ` : "";
|
|
7765
8291
|
const inputFieldsRendered = inputFields.map(renderField).join(", ");
|
|
7766
8292
|
const outputFieldsRendered = outputFields.map(renderField).join(", ");
|
|
7767
|
-
return `${descriptionPart}
|
|
8293
|
+
return `${descriptionPart}${inputFieldsRendered} -> ${outputFieldsRendered}`;
|
|
7768
8294
|
}
|
|
7769
8295
|
function isValidCase(inputString) {
|
|
7770
8296
|
const camelCaseRegex = /^[a-z][a-zA-Z0-9]*$/;
|
|
7771
8297
|
const snakeCaseRegex = /^[a-z]+(_[a-z0-9]+)*$/;
|
|
7772
8298
|
return camelCaseRegex.test(inputString) || snakeCaseRegex.test(inputString);
|
|
7773
8299
|
}
|
|
7774
|
-
function validateField(field) {
|
|
8300
|
+
function validateField(field, context3) {
|
|
7775
8301
|
if (!field.name || field.name.length === 0) {
|
|
7776
|
-
throw new
|
|
8302
|
+
throw new AxSignatureValidationError(
|
|
8303
|
+
"Field name cannot be blank",
|
|
8304
|
+
field.name,
|
|
8305
|
+
"Every field must have a descriptive name"
|
|
8306
|
+
);
|
|
7777
8307
|
}
|
|
7778
8308
|
if (!isValidCase(field.name)) {
|
|
7779
|
-
throw new
|
|
7780
|
-
`Invalid field name '${field.name}'
|
|
8309
|
+
throw new AxSignatureValidationError(
|
|
8310
|
+
`Invalid field name '${field.name}' - must be camelCase or snake_case`,
|
|
8311
|
+
field.name,
|
|
8312
|
+
'Use camelCase (e.g., "userInput") or snake_case (e.g., "user_input")'
|
|
7781
8313
|
);
|
|
7782
8314
|
}
|
|
7783
|
-
if (
|
|
7784
|
-
|
|
7785
|
-
|
|
7786
|
-
|
|
7787
|
-
|
|
7788
|
-
|
|
7789
|
-
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
|
|
7793
|
-
|
|
7794
|
-
|
|
7795
|
-
|
|
7796
|
-
|
|
7797
|
-
|
|
7798
|
-
|
|
7799
|
-
|
|
8315
|
+
if (axGlobals.signatureStrict) {
|
|
8316
|
+
const reservedNames = [
|
|
8317
|
+
"text",
|
|
8318
|
+
"object",
|
|
8319
|
+
"image",
|
|
8320
|
+
"string",
|
|
8321
|
+
"number",
|
|
8322
|
+
"boolean",
|
|
8323
|
+
"json",
|
|
8324
|
+
"array",
|
|
8325
|
+
"datetime",
|
|
8326
|
+
"date",
|
|
8327
|
+
"time",
|
|
8328
|
+
"type",
|
|
8329
|
+
"class",
|
|
8330
|
+
"input",
|
|
8331
|
+
"output",
|
|
8332
|
+
"data",
|
|
8333
|
+
"value",
|
|
8334
|
+
"result",
|
|
8335
|
+
"response",
|
|
8336
|
+
"request",
|
|
8337
|
+
"item",
|
|
8338
|
+
"element"
|
|
8339
|
+
];
|
|
8340
|
+
if (reservedNames.includes(field.name.toLowerCase())) {
|
|
8341
|
+
const suggestions = context3 === "input" ? [
|
|
8342
|
+
"userInput",
|
|
8343
|
+
"questionText",
|
|
8344
|
+
"documentContent",
|
|
8345
|
+
"messageText",
|
|
8346
|
+
"queryString"
|
|
8347
|
+
] : [
|
|
8348
|
+
"responseText",
|
|
8349
|
+
"analysisResult",
|
|
8350
|
+
"categoryType",
|
|
8351
|
+
"summaryText",
|
|
8352
|
+
"outputData"
|
|
8353
|
+
];
|
|
8354
|
+
throw new AxSignatureValidationError(
|
|
8355
|
+
`Field name '${field.name}' is too generic`,
|
|
8356
|
+
field.name,
|
|
8357
|
+
`Use a more descriptive name. Examples for ${context3} fields: ${suggestions.join(", ")}`
|
|
8358
|
+
);
|
|
8359
|
+
}
|
|
8360
|
+
}
|
|
8361
|
+
if (field.name.length < 2) {
|
|
8362
|
+
throw new AxSignatureValidationError(
|
|
8363
|
+
`Field name '${field.name}' is too short`,
|
|
8364
|
+
field.name,
|
|
8365
|
+
"Field names must be at least 2 characters long"
|
|
8366
|
+
);
|
|
8367
|
+
}
|
|
8368
|
+
if (field.name.length > 50) {
|
|
8369
|
+
throw new AxSignatureValidationError(
|
|
8370
|
+
`Field name '${field.name}' is too long (${field.name.length} characters)`,
|
|
8371
|
+
field.name,
|
|
8372
|
+
"Field names should be 50 characters or less"
|
|
8373
|
+
);
|
|
8374
|
+
}
|
|
8375
|
+
if (field.type) {
|
|
8376
|
+
validateFieldType(field, context3);
|
|
8377
|
+
}
|
|
8378
|
+
}
|
|
8379
|
+
function validateFieldType(field, context3) {
|
|
8380
|
+
if (!field.type) return;
|
|
8381
|
+
const { type } = field;
|
|
8382
|
+
if (type.name === "image" || type.name === "audio") {
|
|
8383
|
+
if (context3 === "output") {
|
|
8384
|
+
throw new AxSignatureValidationError(
|
|
8385
|
+
`${type.name} type is not supported in output fields`,
|
|
8386
|
+
field.name,
|
|
8387
|
+
`${type.name} types can only be used in input fields`
|
|
8388
|
+
);
|
|
8389
|
+
}
|
|
8390
|
+
if (type.isArray) {
|
|
8391
|
+
throw new AxSignatureValidationError(
|
|
8392
|
+
`Arrays of ${type.name} are not supported`,
|
|
8393
|
+
field.name,
|
|
8394
|
+
`Use a single ${type.name} type instead`
|
|
8395
|
+
);
|
|
8396
|
+
}
|
|
8397
|
+
}
|
|
8398
|
+
if (type.name === "class") {
|
|
8399
|
+
if (context3 === "input") {
|
|
8400
|
+
throw new AxSignatureValidationError(
|
|
8401
|
+
"Class type is not supported in input fields",
|
|
8402
|
+
field.name,
|
|
8403
|
+
'Class types are only allowed on output fields. Use "string" type for input classifications'
|
|
8404
|
+
);
|
|
8405
|
+
}
|
|
8406
|
+
if (!type.options || type.options.length === 0) {
|
|
8407
|
+
throw new AxSignatureValidationError(
|
|
8408
|
+
"Class type requires options",
|
|
8409
|
+
field.name,
|
|
8410
|
+
'Provide class options. Example: class "positive, negative, neutral"'
|
|
8411
|
+
);
|
|
8412
|
+
}
|
|
8413
|
+
if (type.options.length === 1) {
|
|
8414
|
+
throw new AxSignatureValidationError(
|
|
8415
|
+
"Class type needs at least 2 options",
|
|
8416
|
+
field.name,
|
|
8417
|
+
'Add more class options or use "string" type instead'
|
|
8418
|
+
);
|
|
8419
|
+
}
|
|
8420
|
+
for (const option of type.options) {
|
|
8421
|
+
if (!option || option.trim().length === 0) {
|
|
8422
|
+
throw new AxSignatureValidationError(
|
|
8423
|
+
"Empty class option found",
|
|
8424
|
+
field.name,
|
|
8425
|
+
"All class options must be non-empty strings"
|
|
8426
|
+
);
|
|
8427
|
+
}
|
|
8428
|
+
const trimmedOption = option.trim();
|
|
8429
|
+
if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(trimmedOption)) {
|
|
8430
|
+
throw new AxSignatureValidationError(
|
|
8431
|
+
`Invalid class option "${trimmedOption}"`,
|
|
8432
|
+
field.name,
|
|
8433
|
+
"Class options must start with a letter and contain only letters, numbers, underscores, or hyphens"
|
|
8434
|
+
);
|
|
8435
|
+
}
|
|
8436
|
+
}
|
|
8437
|
+
const uniqueOptions = new Set(
|
|
8438
|
+
type.options.map((opt) => opt.trim().toLowerCase())
|
|
8439
|
+
);
|
|
8440
|
+
if (uniqueOptions.size !== type.options.length) {
|
|
8441
|
+
throw new AxSignatureValidationError(
|
|
8442
|
+
"Duplicate class options found",
|
|
8443
|
+
field.name,
|
|
8444
|
+
"Each class option must be unique (case-insensitive)"
|
|
8445
|
+
);
|
|
8446
|
+
}
|
|
8447
|
+
}
|
|
8448
|
+
if (type.name === "code" && type.isArray) {
|
|
8449
|
+
throw new AxSignatureValidationError(
|
|
8450
|
+
"Arrays of code are not commonly supported",
|
|
8451
|
+
field.name,
|
|
8452
|
+
"Consider using a single code field or an array of strings instead"
|
|
8453
|
+
);
|
|
8454
|
+
}
|
|
8455
|
+
if (field.isInternal && context3 === "input") {
|
|
8456
|
+
throw new AxSignatureValidationError(
|
|
8457
|
+
"Internal marker (!) is not allowed on input fields",
|
|
8458
|
+
field.name,
|
|
8459
|
+
"Internal markers are only allowed on output fields"
|
|
7800
8460
|
);
|
|
7801
8461
|
}
|
|
7802
8462
|
}
|
|
@@ -8387,6 +9047,7 @@ Content: ${result.content}`
|
|
|
8387
9047
|
}
|
|
8388
9048
|
let prompt;
|
|
8389
9049
|
if (Array.isArray(values)) {
|
|
9050
|
+
validateAxMessageArray(values);
|
|
8390
9051
|
prompt = this.promptTemplate.render(values, {
|
|
8391
9052
|
examples: this.examples,
|
|
8392
9053
|
demos: this.demos
|
|
@@ -11529,13 +12190,18 @@ var AxMockAIService = class {
|
|
|
11529
12190
|
}
|
|
11530
12191
|
};
|
|
11531
12192
|
getLastUsedChatModel() {
|
|
11532
|
-
|
|
12193
|
+
return this.config.modelInfo?.name ?? "mock-model";
|
|
11533
12194
|
}
|
|
11534
12195
|
getLastUsedEmbedModel() {
|
|
11535
|
-
|
|
12196
|
+
return this.config.embedModelInfo?.name ?? "mock-embed-model";
|
|
11536
12197
|
}
|
|
11537
12198
|
getLastUsedModelConfig() {
|
|
11538
|
-
|
|
12199
|
+
return this.config.modelInfo ? {
|
|
12200
|
+
maxTokens: this.config.modelInfo.maxTokens,
|
|
12201
|
+
temperature: 0.7,
|
|
12202
|
+
// Default temperature
|
|
12203
|
+
stream: this.config.features?.streaming ?? false
|
|
12204
|
+
} : void 0;
|
|
11539
12205
|
}
|
|
11540
12206
|
getName() {
|
|
11541
12207
|
return this.config.name ?? "mock-ai-service";
|
|
@@ -13938,6 +14604,7 @@ export {
|
|
|
13938
14604
|
axAITogetherDefaultConfig,
|
|
13939
14605
|
axBaseAIDefaultConfig,
|
|
13940
14606
|
axBaseAIDefaultCreativeConfig,
|
|
14607
|
+
axGlobals,
|
|
13941
14608
|
axModelInfoAnthropic,
|
|
13942
14609
|
axModelInfoCohere,
|
|
13943
14610
|
axModelInfoDeepSeek,
|