@agentica/core 0.36.2 → 0.36.4

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/lib/index.mjs CHANGED
@@ -8,6 +8,8 @@ import { HttpLlm, OpenApi, McpLlm } from "@samchon/openapi";
8
8
 
9
9
  import { removeTrailingCommas, addMissingBraces, removeEmptyObjectPrefix } from "es-jsonkit";
10
10
 
11
+ import { jsonrepair } from "jsonrepair";
12
+
11
13
  import { Escaper } from "typia/lib/utils/Escaper";
12
14
 
13
15
  import * as __typia_transform__validateReport from "typia/lib/internal/_validateReport.js";
@@ -911,14 +913,164 @@ const ChatGptTokenUsageAggregator = {
911
913
  };
912
914
 
913
915
  const JsonUtil = {
914
- parse
916
+ parse,
917
+ stringifyValidateFailure
915
918
  };
916
919
 
917
920
  const pipe = (...fns) => str => fns.reduce(((acc, fn) => fn(acc)), str);
918
921
 
919
922
  function parse(str) {
920
- const corrected = pipe(removeEmptyObjectPrefix, addMissingBraces, removeTrailingCommas)(str);
921
- return JSON.parse(corrected);
923
+ str = pipe(removeEmptyObjectPrefix, addMissingBraces, removeTrailingCommas, jsonrepair)(str);
924
+ return JSON.parse(str);
925
+ }
926
+
927
+ function stringifyValidateFailure(failure) {
928
+ return stringify({
929
+ value: failure.data,
930
+ errors: failure.errors,
931
+ path: "$input",
932
+ tab: 0,
933
+ inArray: false,
934
+ inToJson: false
935
+ });
936
+ }
937
+
938
+ function stringify(props) {
939
+ const {value, errors, path, tab, inArray, inToJson} = props;
940
+ const indent = " ".repeat(tab);
941
+ const errorComment = getErrorComment(path, errors);
942
+ if (inArray && value === undefined) {
943
+ return `${indent}undefined${errorComment}`;
944
+ }
945
+ if (Array.isArray(value)) {
946
+ if (value.length === 0) {
947
+ return `${indent}[]${errorComment}`;
948
+ }
949
+ const lines = [];
950
+ lines.push(`${indent}[${errorComment}`);
951
+ value.forEach(((item, index) => {
952
+ const itemPath = `${path}[${index}]`;
953
+ let itemStr = stringify({
954
+ value: item,
955
+ errors,
956
+ path: itemPath,
957
+ tab: tab + 1,
958
+ inArray: true,
959
+ inToJson: false
960
+ });
961
+ if (index < value.length - 1) {
962
+ const itemLines = itemStr.split("\n");
963
+ const lastLine = itemLines[itemLines.length - 1];
964
+ const commentIndex = lastLine.indexOf(" //");
965
+ if (commentIndex !== -1) {
966
+ itemLines[itemLines.length - 1] = `${lastLine.slice(0, commentIndex)},${lastLine.slice(commentIndex)}`;
967
+ } else {
968
+ itemLines[itemLines.length - 1] += ",";
969
+ }
970
+ itemStr = itemLines.join("\n");
971
+ }
972
+ lines.push(itemStr);
973
+ }));
974
+ lines.push(`${indent}]`);
975
+ return lines.join("\n");
976
+ }
977
+ if (typeof value === "object" && value !== null) {
978
+ if (!inToJson && typeof value.toJSON === "function") {
979
+ const jsonValue = value.toJSON();
980
+ return stringify({
981
+ value: jsonValue,
982
+ errors,
983
+ path,
984
+ tab,
985
+ inArray,
986
+ inToJson: true
987
+ });
988
+ }
989
+ const existingEntries = Object.entries(value).filter((([_, val]) => val !== undefined));
990
+ const missingKeys = getMissingProperties(path, value, errors);
991
+ const allKeys = [ ...existingEntries.map((([key]) => key)), ...missingKeys ];
992
+ if (allKeys.length === 0) {
993
+ return `${indent}{}${errorComment}`;
994
+ }
995
+ const lines = [];
996
+ lines.push(`${indent}{${errorComment}`);
997
+ allKeys.forEach(((key, index, array) => {
998
+ const propPath = Escaper.variable(key) ? `${path}.${key}` : `${path}[${JSON.stringify(key)}]`;
999
+ const propIndent = " ".repeat(tab + 1);
1000
+ const val = missingKeys.includes(key) ? undefined : value[key];
1001
+ if (val === undefined || val === null || typeof val === "boolean" || typeof val === "number" || typeof val === "string") {
1002
+ const propErrorComment = getErrorComment(propPath, errors);
1003
+ const valueStr = val === undefined ? `${propIndent}"${key}": undefined` : `${propIndent}"${key}": ${JSON.stringify(val)}`;
1004
+ const withComma = index < array.length - 1 ? `${valueStr},` : valueStr;
1005
+ const line = withComma + propErrorComment;
1006
+ lines.push(line);
1007
+ } else {
1008
+ const keyLine = `${propIndent}"${key}": `;
1009
+ let valStr = stringify({
1010
+ value: val,
1011
+ errors,
1012
+ path: propPath,
1013
+ tab: tab + 1,
1014
+ inArray: false,
1015
+ inToJson: false
1016
+ });
1017
+ const valStrWithoutIndent = valStr.trimStart();
1018
+ if (index < array.length - 1) {
1019
+ const valLines = valStrWithoutIndent.split("\n");
1020
+ const lastLine = valLines[valLines.length - 1];
1021
+ const commentIndex = lastLine.indexOf(" //");
1022
+ if (commentIndex !== -1) {
1023
+ valLines[valLines.length - 1] = `${lastLine.slice(0, commentIndex)},${lastLine.slice(commentIndex)}`;
1024
+ } else {
1025
+ valLines[valLines.length - 1] += ",";
1026
+ }
1027
+ valStr = valLines.join("\n");
1028
+ } else {
1029
+ valStr = valStrWithoutIndent;
1030
+ }
1031
+ const combined = keyLine + valStr;
1032
+ lines.push(combined);
1033
+ }
1034
+ }));
1035
+ lines.push(`${indent}}`);
1036
+ return lines.join("\n");
1037
+ }
1038
+ const valStr = value === undefined ? "undefined" : JSON.stringify(value) ?? String(value);
1039
+ return `${indent}${valStr}${errorComment}`;
1040
+ }
1041
+
1042
+ function getErrorComment(path, errors) {
1043
+ const pathErrors = errors.filter((e => e.path === path));
1044
+ if (pathErrors.length === 0) {
1045
+ return "";
1046
+ }
1047
+ return ` // ❌ ${JSON.stringify(pathErrors.map((e => ({
1048
+ path: e.path,
1049
+ expected: e.expected,
1050
+ description: e.description
1051
+ }))))}`;
1052
+ }
1053
+
1054
+ function getMissingProperties(path, value, errors) {
1055
+ const missingKeys = new Set;
1056
+ for (const e of errors) {
1057
+ const childKey = extractDirectChildKey(path, e.path);
1058
+ if (childKey !== null) {
1059
+ if (!(childKey in value)) {
1060
+ missingKeys.add(childKey);
1061
+ }
1062
+ }
1063
+ }
1064
+ return Array.from(missingKeys);
1065
+ }
1066
+
1067
+ function extractDirectChildKey(parentPath, errorPath) {
1068
+ if (!errorPath.startsWith(parentPath)) {
1069
+ return null;
1070
+ }
1071
+ const suffix = errorPath.slice(parentPath.length);
1072
+ const match = suffix.match(/^\.([^.[\]]+)$/);
1073
+ return match !== null ? match[1] : null;
922
1074
  }
923
1075
 
924
1076
  function transformCompletionChunk(source) {
@@ -1344,155 +1496,6 @@ async function reduceStreamingWithDispatch(stream, eventProcessor, abortSignal)
1344
1496
  return nullableCompletion;
1345
1497
  }
1346
1498
 
1347
- function stringifyValidateFailure(failure) {
1348
- return stringify({
1349
- value: failure.data,
1350
- errors: failure.errors,
1351
- path: "$input",
1352
- tab: 0,
1353
- inArray: false,
1354
- inToJson: false
1355
- });
1356
- }
1357
-
1358
- function stringify(props) {
1359
- const {value, errors, path, tab, inArray, inToJson} = props;
1360
- const indent = " ".repeat(tab);
1361
- const errorComment = getErrorComment(path, errors);
1362
- if (inArray && value === undefined) {
1363
- return `${indent}undefined${errorComment}`;
1364
- }
1365
- if (Array.isArray(value)) {
1366
- if (value.length === 0) {
1367
- return `${indent}[]${errorComment}`;
1368
- }
1369
- const lines = [];
1370
- lines.push(`${indent}[${errorComment}`);
1371
- value.forEach(((item, index) => {
1372
- const itemPath = `${path}[${index}]`;
1373
- let itemStr = stringify({
1374
- value: item,
1375
- errors,
1376
- path: itemPath,
1377
- tab: tab + 1,
1378
- inArray: true,
1379
- inToJson: false
1380
- });
1381
- if (index < value.length - 1) {
1382
- const itemLines = itemStr.split("\n");
1383
- const lastLine = itemLines[itemLines.length - 1];
1384
- const commentIndex = lastLine.indexOf(" //");
1385
- if (commentIndex !== -1) {
1386
- itemLines[itemLines.length - 1] = `${lastLine.slice(0, commentIndex)},${lastLine.slice(commentIndex)}`;
1387
- } else {
1388
- itemLines[itemLines.length - 1] += ",";
1389
- }
1390
- itemStr = itemLines.join("\n");
1391
- }
1392
- lines.push(itemStr);
1393
- }));
1394
- lines.push(`${indent}]`);
1395
- return lines.join("\n");
1396
- }
1397
- if (typeof value === "object" && value !== null) {
1398
- if (!inToJson && typeof value.toJSON === "function") {
1399
- const jsonValue = value.toJSON();
1400
- return stringify({
1401
- value: jsonValue,
1402
- errors,
1403
- path,
1404
- tab,
1405
- inArray,
1406
- inToJson: true
1407
- });
1408
- }
1409
- const existingEntries = Object.entries(value).filter((([_, val]) => val !== undefined));
1410
- const missingKeys = getMissingProperties(path, value, errors);
1411
- const allKeys = [ ...existingEntries.map((([key]) => key)), ...missingKeys ];
1412
- if (allKeys.length === 0) {
1413
- return `${indent}{}${errorComment}`;
1414
- }
1415
- const lines = [];
1416
- lines.push(`${indent}{${errorComment}`);
1417
- allKeys.forEach(((key, index, array) => {
1418
- const propPath = Escaper.variable(key) ? `${path}.${key}` : `${path}[${JSON.stringify(key)}]`;
1419
- const propIndent = " ".repeat(tab + 1);
1420
- const val = missingKeys.includes(key) ? undefined : value[key];
1421
- if (val === undefined || val === null || typeof val === "boolean" || typeof val === "number" || typeof val === "string") {
1422
- const propErrorComment = getErrorComment(propPath, errors);
1423
- const valueStr = val === undefined ? `${propIndent}"${key}": undefined` : `${propIndent}"${key}": ${JSON.stringify(val)}`;
1424
- const withComma = index < array.length - 1 ? `${valueStr},` : valueStr;
1425
- const line = withComma + propErrorComment;
1426
- lines.push(line);
1427
- } else {
1428
- const keyLine = `${propIndent}"${key}": `;
1429
- let valStr = stringify({
1430
- value: val,
1431
- errors,
1432
- path: propPath,
1433
- tab: tab + 1,
1434
- inArray: false,
1435
- inToJson: false
1436
- });
1437
- const valStrWithoutIndent = valStr.trimStart();
1438
- if (index < array.length - 1) {
1439
- const valLines = valStrWithoutIndent.split("\n");
1440
- const lastLine = valLines[valLines.length - 1];
1441
- const commentIndex = lastLine.indexOf(" //");
1442
- if (commentIndex !== -1) {
1443
- valLines[valLines.length - 1] = `${lastLine.slice(0, commentIndex)},${lastLine.slice(commentIndex)}`;
1444
- } else {
1445
- valLines[valLines.length - 1] += ",";
1446
- }
1447
- valStr = valLines.join("\n");
1448
- } else {
1449
- valStr = valStrWithoutIndent;
1450
- }
1451
- const combined = keyLine + valStr;
1452
- lines.push(combined);
1453
- }
1454
- }));
1455
- lines.push(`${indent}}`);
1456
- return lines.join("\n");
1457
- }
1458
- const valStr = value === undefined ? "undefined" : JSON.stringify(value) ?? String(value);
1459
- return `${indent}${valStr}${errorComment}`;
1460
- }
1461
-
1462
- function getErrorComment(path, errors) {
1463
- const pathErrors = errors.filter((e => e.path === path));
1464
- if (pathErrors.length === 0) {
1465
- return "";
1466
- }
1467
- return ` // ❌ ${JSON.stringify(pathErrors.map((e => ({
1468
- path: e.path,
1469
- expected: e.expected,
1470
- description: e.description
1471
- }))))}`;
1472
- }
1473
-
1474
- function getMissingProperties(path, value, errors) {
1475
- const missingKeys = new Set;
1476
- for (const e of errors) {
1477
- const childKey = extractDirectChildKey(path, e.path);
1478
- if (childKey !== null) {
1479
- if (!(childKey in value)) {
1480
- missingKeys.add(childKey);
1481
- }
1482
- }
1483
- }
1484
- return Array.from(missingKeys);
1485
- }
1486
-
1487
- function extractDirectChildKey(parentPath, errorPath) {
1488
- if (!errorPath.startsWith(parentPath)) {
1489
- return null;
1490
- }
1491
- const suffix = errorPath.slice(parentPath.length);
1492
- const match = suffix.match(/^\.([^.[\]]+)$/);
1493
- return match !== null ? match[1] : null;
1494
- }
1495
-
1496
1499
  function createOperationSelection(props) {
1497
1500
  return {
1498
1501
  operation: props.operation,
@@ -1644,9 +1647,9 @@ async function correctTypeError(ctx, callEvent, validateEvent, previousValidatio
1644
1647
  toolCall: {
1645
1648
  id: callEvent.id,
1646
1649
  arguments: JSON.stringify(callEvent.arguments),
1647
- result: [ "🚨 VALIDATION FAILURE: Your function arguments do not conform to the required schema.", "", "The validation errors below represent computed absolute truth from rigorous type validation.", "Each error is marked with ❌ comments showing the exact location, expected type, and actual value.", "", "You must fix ALL errors to achieve 100% schema compliance.", "", "```json", stringifyValidateFailure(validateEvent.result), "```" ].join("\n")
1650
+ result: [ "🚨 VALIDATION FAILURE: Your function arguments do not conform to the required schema.", "", "The validation errors below represent computed absolute truth from rigorous type validation.", "Each error is marked with ❌ comments showing the exact location, expected type, and actual value.", "", "You must fix ALL errors to achieve 100% schema compliance.", "", "```json", JsonUtil.stringifyValidateFailure(validateEvent.result), "```" ].join("\n")
1648
1651
  },
1649
- systemPrompt: ctx.config?.systemPrompt?.validate?.(previousValidationErrors.slice(0, -1)) ?? [ AgenticaSystemPrompt.VALIDATE, ...previousValidationErrors.length > 1 ? [ "", AgenticaSystemPrompt.VALIDATE_REPEATED.replace("${{HISTORICAL_ERRORS}}", previousValidationErrors.slice(0, -1).map(((ve, i) => [ `### ${i + 1}. Previous Validation Error`, "", "```json", stringifyValidateFailure(ve.result), "```" ].join("\n"))).join("\n\n")) ] : [] ].join("\n"),
1652
+ systemPrompt: ctx.config?.systemPrompt?.validate?.(previousValidationErrors.slice(0, -1)) ?? [ AgenticaSystemPrompt.VALIDATE, ...previousValidationErrors.length > 1 ? [ "", AgenticaSystemPrompt.VALIDATE_REPEATED.replace("${{HISTORICAL_ERRORS}}", previousValidationErrors.slice(0, -1).map(((ve, i) => [ `### ${i + 1}. Previous Validation Error`, "", "```json", JsonUtil.stringifyValidateFailure(ve.result), "```" ].join("\n"))).join("\n\n")) ] : [] ].join("\n"),
1650
1653
  life,
1651
1654
  previousValidationErrors
1652
1655
  });