@promptbook/core 0.23.2 → 0.24.0-1.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.
Files changed (75) hide show
  1. package/esm/index.es.js +418 -97
  2. package/esm/index.es.js.map +1 -1
  3. package/esm/typings/_packages/types.index.d.ts +2 -2
  4. package/esm/typings/_packages/utils.index.d.ts +11 -1
  5. package/esm/typings/classes/PromptTemplatePipeline.d.ts +4 -1
  6. package/esm/typings/classes/PromptTemplatePipelineLibrary.d.ts +8 -2
  7. package/esm/typings/conversion/parseCommand.d.ts +2 -2
  8. package/esm/typings/execution/PromptResult.d.ts +1 -1
  9. package/esm/typings/execution/PtpExecutor.d.ts +24 -4
  10. package/esm/typings/execution/createPtpExecutor.d.ts +9 -0
  11. package/esm/typings/types/Command.d.ts +17 -4
  12. package/esm/typings/types/Prompt.d.ts +8 -2
  13. package/esm/typings/types/PromptTemplatePipelineJson/PromptTemplateJson.d.ts +21 -2
  14. package/esm/typings/types/execution-report/ExecutionReportJson.d.ts +56 -0
  15. package/esm/typings/types/execution-report/ExecutionReportString.d.ts +16 -0
  16. package/esm/typings/types/execution-report/executionReportJsonToString.d.ts +6 -0
  17. package/esm/typings/types/typeAliases.d.ts +3 -1
  18. package/esm/typings/utils/expectation-counters/countCharacters.d.ts +5 -0
  19. package/esm/typings/utils/expectation-counters/countCharacters.test.d.ts +1 -0
  20. package/esm/typings/utils/expectation-counters/countLines.d.ts +5 -0
  21. package/esm/typings/utils/expectation-counters/countLines.test.d.ts +1 -0
  22. package/esm/typings/utils/expectation-counters/countPages.d.ts +5 -0
  23. package/esm/typings/utils/expectation-counters/countPages.test.d.ts +1 -0
  24. package/esm/typings/utils/expectation-counters/countParagraphs.d.ts +5 -0
  25. package/esm/typings/utils/expectation-counters/countParagraphs.test.d.ts +1 -0
  26. package/esm/typings/utils/expectation-counters/countSentences.d.ts +5 -0
  27. package/esm/typings/utils/expectation-counters/countSentences.test.d.ts +1 -0
  28. package/esm/typings/utils/expectation-counters/countWords.d.ts +5 -0
  29. package/esm/typings/utils/expectation-counters/countWords.test.d.ts +1 -0
  30. package/esm/typings/utils/expectation-counters/index.d.ts +5 -0
  31. package/esm/typings/utils/markdown/prettifyMarkdown.d.ts +8 -0
  32. package/esm/typings/utils/markdown/prettifyMarkdown.test.d.ts +1 -0
  33. package/esm/typings/utils/parseNumber.d.ts +10 -0
  34. package/esm/typings/utils/parseNumber.test.d.ts +1 -0
  35. package/esm/typings/utils/trimCodeBlock.d.ts +8 -0
  36. package/esm/typings/utils/trimCodeBlock.test.d.ts +1 -0
  37. package/esm/typings/utils/trimEndOfCodeBlock.d.ts +2 -1
  38. package/package.json +1 -1
  39. package/umd/index.umd.js +417 -96
  40. package/umd/index.umd.js.map +1 -1
  41. package/umd/typings/_packages/types.index.d.ts +2 -2
  42. package/umd/typings/_packages/utils.index.d.ts +11 -1
  43. package/umd/typings/classes/PromptTemplatePipeline.d.ts +4 -1
  44. package/umd/typings/classes/PromptTemplatePipelineLibrary.d.ts +8 -2
  45. package/umd/typings/conversion/parseCommand.d.ts +2 -2
  46. package/umd/typings/execution/PromptResult.d.ts +1 -1
  47. package/umd/typings/execution/PtpExecutor.d.ts +24 -4
  48. package/umd/typings/execution/createPtpExecutor.d.ts +9 -0
  49. package/umd/typings/types/Command.d.ts +17 -4
  50. package/umd/typings/types/Prompt.d.ts +8 -2
  51. package/umd/typings/types/PromptTemplatePipelineJson/PromptTemplateJson.d.ts +21 -2
  52. package/umd/typings/types/execution-report/ExecutionReportJson.d.ts +56 -0
  53. package/umd/typings/types/execution-report/ExecutionReportString.d.ts +16 -0
  54. package/umd/typings/types/execution-report/executionReportJsonToString.d.ts +6 -0
  55. package/umd/typings/types/typeAliases.d.ts +3 -1
  56. package/umd/typings/utils/expectation-counters/countCharacters.d.ts +5 -0
  57. package/umd/typings/utils/expectation-counters/countCharacters.test.d.ts +1 -0
  58. package/umd/typings/utils/expectation-counters/countLines.d.ts +5 -0
  59. package/umd/typings/utils/expectation-counters/countLines.test.d.ts +1 -0
  60. package/umd/typings/utils/expectation-counters/countPages.d.ts +5 -0
  61. package/umd/typings/utils/expectation-counters/countPages.test.d.ts +1 -0
  62. package/umd/typings/utils/expectation-counters/countParagraphs.d.ts +5 -0
  63. package/umd/typings/utils/expectation-counters/countParagraphs.test.d.ts +1 -0
  64. package/umd/typings/utils/expectation-counters/countSentences.d.ts +5 -0
  65. package/umd/typings/utils/expectation-counters/countSentences.test.d.ts +1 -0
  66. package/umd/typings/utils/expectation-counters/countWords.d.ts +5 -0
  67. package/umd/typings/utils/expectation-counters/countWords.test.d.ts +1 -0
  68. package/umd/typings/utils/expectation-counters/index.d.ts +5 -0
  69. package/umd/typings/utils/markdown/prettifyMarkdown.d.ts +8 -0
  70. package/umd/typings/utils/markdown/prettifyMarkdown.test.d.ts +1 -0
  71. package/umd/typings/utils/parseNumber.d.ts +10 -0
  72. package/umd/typings/utils/parseNumber.test.d.ts +1 -0
  73. package/umd/typings/utils/trimCodeBlock.d.ts +8 -0
  74. package/umd/typings/utils/trimCodeBlock.test.d.ts +1 -0
  75. package/umd/typings/utils/trimEndOfCodeBlock.d.ts +2 -1
package/esm/index.es.js CHANGED
@@ -1,4 +1,4 @@
1
- import { capitalize, normalizeTo_SCREAMING_CASE, normalizeTo_PascalCase, normalizeTo_camelCase } from 'n12';
1
+ import { capitalize, normalizeTo_SCREAMING_CASE, normalizeTo_PascalCase, normalizeTo_camelCase, removeDiacritics } from 'n12';
2
2
  import spaceTrim from 'spacetrim';
3
3
 
4
4
  /*! *****************************************************************************
@@ -342,6 +342,14 @@ function removeContentComments(content) {
342
342
  */
343
343
  var ExecutionTypes = ['PROMPT_TEMPLATE', 'SIMPLE_TEMPLATE', 'SCRIPT', 'PROMPT_DIALOG'];
344
344
 
345
+ /**
346
+ * Units of text measurement
347
+ */
348
+ var EXPECTATION_UNITS = ['CHARACTERS', 'WORDS', 'SENTENCES', 'PARAGRAPHS', 'LINES', 'PAGES'];
349
+ /**
350
+ * TODO: use one helper type> (string_prompt | string_javascript | string_markdown) & string_template
351
+ */
352
+
345
353
  /**
346
354
  * Removes Markdown formatting tags from a string.
347
355
  *
@@ -358,10 +366,73 @@ function removeMarkdownFormatting(str) {
358
366
  return str;
359
367
  }
360
368
 
369
+ /**
370
+ * Function parseNumber will parse number from string
371
+ *
372
+ * Unlike Number.parseInt, Number.parseFloat it will never ever result in NaN
373
+ * Note: it also works only with decimal numbers
374
+ */
375
+ function parseNumber(value) {
376
+ var originalValue = value;
377
+ if (typeof value === 'number') {
378
+ value = value.toString(); // <- TODO: Maybe more efficient way to do this
379
+ }
380
+ if (typeof value !== 'string') {
381
+ return 0;
382
+ }
383
+ value = value.trim();
384
+ if (value.startsWith('+')) {
385
+ return parseNumber(value.substring(1));
386
+ }
387
+ if (value.startsWith('-')) {
388
+ var number = parseNumber(value.substring(1));
389
+ if (number === 0) {
390
+ return 0; // <- Note: To prevent -0
391
+ }
392
+ return -number;
393
+ }
394
+ value = value.replace(/,/g, '.');
395
+ value = value.toUpperCase();
396
+ if (value === '') {
397
+ return 0;
398
+ }
399
+ if (value === '♾' || value.startsWith('INF')) {
400
+ return Infinity;
401
+ }
402
+ if (value.includes('/')) {
403
+ var _a = __read(value.split('/'), 2), numerator_ = _a[0], denominator_ = _a[1];
404
+ var numerator = parseNumber(numerator_);
405
+ var denominator = parseNumber(denominator_);
406
+ if (denominator === 0) {
407
+ throw new Error("Unable to parse number from \"".concat(originalValue, "\" because denominator is zero"));
408
+ }
409
+ return numerator / denominator;
410
+ }
411
+ if (/^(NAN|NULL|NONE|UNDEFINED|ZERO|NO.*)$/.test(value)) {
412
+ return 0;
413
+ }
414
+ if (value.includes('E')) {
415
+ var _b = __read(value.split('E'), 2), significand = _b[0], exponent = _b[1];
416
+ return parseNumber(significand) * Math.pow(10, parseNumber(exponent));
417
+ }
418
+ if (!/^[0-9.]+$/.test(value) || value.split('.').length > 2) {
419
+ throw new Error("Unable to parse number from \"".concat(originalValue, "\""));
420
+ }
421
+ var num = parseFloat(value);
422
+ if (isNaN(num)) {
423
+ throw new Error("Unexpected NaN when parsing number from \"".concat(originalValue, "\""));
424
+ }
425
+ return num;
426
+ }
427
+ /**
428
+ * TODO: Maybe use sth. like safe-eval in fraction/calculation case @see https://www.npmjs.com/package/safe-eval
429
+ */
430
+
361
431
  /**
362
432
  * Parses one line of ul/ol to command
363
433
  */
364
434
  function parseCommand(listItem) {
435
+ var e_1, _a;
365
436
  if (listItem.includes('\n') || listItem.includes('\r')) {
366
437
  throw new Error('Command can not contain new line characters:');
367
438
  }
@@ -468,7 +539,7 @@ function parseCommand(listItem) {
468
539
  throw new Error(spaceTrim("\n Invalid parameter in command:\n\n - ".concat(listItem, "\n ")));
469
540
  }
470
541
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
471
- var _a = parametersMatch.groups, parameterName = _a.parameterName, parameterDescription = _a.parameterDescription;
542
+ var _b = parametersMatch.groups, parameterName = _b.parameterName, parameterDescription = _b.parameterDescription;
472
543
  if (parameterDescription && parameterDescription.match(/\{(?<parameterName>[a-z0-9_]+)\}/im)) {
473
544
  throw new Error(spaceTrim("\n Parameter {".concat(parameterName, "} can not contain another parameter in description:\n\n - ").concat(listItem, "\n ")));
474
545
  }
@@ -490,6 +561,74 @@ function parseCommand(listItem) {
490
561
  functionName: functionName,
491
562
  };
492
563
  }
564
+ else if (type.startsWith('EXPECT')) {
565
+ try {
566
+ listItemParts.shift();
567
+ var sign = void 0;
568
+ var signRaw = listItemParts.shift();
569
+ if (/^exact/i.test(signRaw)) {
570
+ sign = 'EXACTLY';
571
+ }
572
+ else if (/^min/i.test(signRaw)) {
573
+ sign = 'MINIMUM';
574
+ }
575
+ else if (/^max/i.test(signRaw)) {
576
+ sign = 'MAXIMUM';
577
+ }
578
+ else {
579
+ throw new Error("Invalid sign \"".concat(signRaw, "\""));
580
+ }
581
+ var amountRaw = listItemParts.shift();
582
+ var amount = parseNumber(amountRaw);
583
+ if (amount < 0) {
584
+ throw new Error('Amount must be positive number or zero');
585
+ }
586
+ if (amount !== Math.floor(amount)) {
587
+ throw new Error('Amount must be whole number');
588
+ }
589
+ var unitRaw = listItemParts.shift();
590
+ var unit = undefined;
591
+ try {
592
+ for (var EXPECTATION_UNITS_1 = __values(EXPECTATION_UNITS), EXPECTATION_UNITS_1_1 = EXPECTATION_UNITS_1.next(); !EXPECTATION_UNITS_1_1.done; EXPECTATION_UNITS_1_1 = EXPECTATION_UNITS_1.next()) {
593
+ var existingUnit = EXPECTATION_UNITS_1_1.value;
594
+ var existingUnitText = existingUnit;
595
+ existingUnitText = existingUnitText.substring(0, existingUnitText.length - 1);
596
+ if (existingUnitText === 'CHARACTER') {
597
+ existingUnitText = 'CHAR';
598
+ }
599
+ if (new RegExp("^".concat(existingUnitText.toLowerCase())).test(unitRaw.toLowerCase()) ||
600
+ new RegExp("^".concat(unitRaw.toLowerCase())).test(existingUnitText.toLowerCase())) {
601
+ if (unit !== undefined) {
602
+ throw new Error("Ambiguous unit \"".concat(unitRaw, "\""));
603
+ }
604
+ unit = existingUnit;
605
+ }
606
+ }
607
+ }
608
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
609
+ finally {
610
+ try {
611
+ if (EXPECTATION_UNITS_1_1 && !EXPECTATION_UNITS_1_1.done && (_a = EXPECTATION_UNITS_1.return)) _a.call(EXPECTATION_UNITS_1);
612
+ }
613
+ finally { if (e_1) throw e_1.error; }
614
+ }
615
+ if (unit === undefined) {
616
+ throw new Error("Invalid unit \"".concat(unitRaw, "\""));
617
+ }
618
+ return {
619
+ type: 'EXPECT',
620
+ sign: sign,
621
+ unit: unit,
622
+ amount: amount,
623
+ };
624
+ }
625
+ catch (error) {
626
+ if (!(error instanceof Error)) {
627
+ throw error;
628
+ }
629
+ throw new Error(spaceTrim("\n Invalid EXPECT command; ".concat(error.message, ":\n\n - ").concat(listItem, "\n ")));
630
+ }
631
+ }
493
632
  else {
494
633
  throw new Error(spaceTrim("\n Unknown command:\n\n - ".concat(listItem, "\n\n Supported commands are:\n - Execute\n - Model\n - Parameter\n - Input parameter\n - Output parameter\n - PTBK Version\n ")));
495
634
  }
@@ -598,6 +737,7 @@ function promptTemplatePipelineStringToJson(promptTemplatePipelineString) {
598
737
  var postprocessingCommands = [];
599
738
  var listItems_3 = extractAllListItemsFromMarkdown(section.content);
600
739
  var executionType = 'PROMPT_TEMPLATE';
740
+ var expectations = {};
601
741
  var isExecutionTypeChanged = false;
602
742
  try {
603
743
  for (var listItems_2 = (e_3 = void 0, __values(listItems_3)), listItems_2_1 = listItems_2.next(); !listItems_2_1.done; listItems_2_1 = listItems_2.next()) {
@@ -621,6 +761,23 @@ function promptTemplatePipelineStringToJson(promptTemplatePipelineString) {
621
761
  case 'POSTPROCESS':
622
762
  postprocessingCommands.push(command);
623
763
  break;
764
+ case 'EXPECT':
765
+ // eslint-disable-next-line no-case-declarations
766
+ var unit = command.unit.toLowerCase();
767
+ expectations[unit] = expectations[unit] || {};
768
+ if (command.sign === 'MINIMUM' || command.sign === 'EXACTLY') {
769
+ if (expectations[unit].min !== undefined) {
770
+ throw new Error("Already defined minumum ".concat(expectations[unit].min, " ").concat(command.unit.toLowerCase(), ", now trying to redefine it to ").concat(command.amount));
771
+ }
772
+ expectations[unit].min = command.amount;
773
+ } /* not else */
774
+ if (command.sign === 'MAXIMUM' || command.sign === 'EXACTLY') {
775
+ if (expectations[unit].max !== undefined) {
776
+ throw new Error("Already defined maximum ".concat(expectations[unit].max, " ").concat(command.unit.toLowerCase(), ", now trying to redefine it to ").concat(command.amount));
777
+ }
778
+ expectations[unit].max = command.amount;
779
+ }
780
+ break;
624
781
  default:
625
782
  throw new Error("Command ".concat(command.type, " is not allowed in the block of the prompt template ONLY at the head of the prompt template pipeline"));
626
783
  }
@@ -684,6 +841,7 @@ function promptTemplatePipelineStringToJson(promptTemplatePipelineString) {
684
841
  title: section.title,
685
842
  description: description_1,
686
843
  executionType: executionType,
844
+ expectations: expectations,
687
845
  modelRequirements: templateModelRequirements,
688
846
  contentLanguage: executionType === 'SCRIPT' ? language : undefined,
689
847
  content: content,
@@ -817,8 +975,11 @@ function validatePromptTemplatePipelineJson(ptp) {
817
975
  * @see https://github.com/webgptorg/promptbook#prompt-template-pipeline
818
976
  */
819
977
  var PromptTemplatePipeline = /** @class */ (function () {
820
- function PromptTemplatePipeline(ptbkUrl, parameters, promptTemplates) {
978
+ function PromptTemplatePipeline(ptbkUrl, title, ptbkVersion, description, parameters, promptTemplates) {
821
979
  this.ptbkUrl = ptbkUrl;
980
+ this.title = title;
981
+ this.ptbkVersion = ptbkVersion;
982
+ this.description = description;
822
983
  this.parameters = parameters;
823
984
  this.promptTemplates = promptTemplates;
824
985
  if (promptTemplates.length === 0) {
@@ -863,7 +1024,7 @@ var PromptTemplatePipeline = /** @class */ (function () {
863
1024
  */
864
1025
  PromptTemplatePipeline.fromJson = function (ptbkjson) {
865
1026
  validatePromptTemplatePipelineJson(ptbkjson);
866
- return new PromptTemplatePipeline(ptbkjson.ptbkUrl ? new URL(ptbkjson.ptbkUrl) : null, Object.fromEntries(ptbkjson.parameters.map(function (parameter) { return [parameter.name, parameter]; })), ptbkjson.promptTemplates);
1027
+ return new PromptTemplatePipeline(ptbkjson.ptbkUrl ? new URL(ptbkjson.ptbkUrl) : null, ptbkjson.title, ptbkjson.ptbkVersion, ptbkjson.ptbkVersion, Object.fromEntries(ptbkjson.parameters.map(function (parameter) { return [parameter.name, parameter]; })), ptbkjson.promptTemplates);
867
1028
  };
868
1029
  Object.defineProperty(PromptTemplatePipeline.prototype, "entryPromptTemplate", {
869
1030
  /**
@@ -920,6 +1081,74 @@ var PromptTemplatePipeline = /** @class */ (function () {
920
1081
  * TODO: [🧠] Each PromptTemplatePipeline should have its unique hash to be able to compare them and execute on server ONLY the desired ones
921
1082
  */
922
1083
 
1084
+ /**
1085
+ * Counts number of characters in the text
1086
+ */
1087
+ function countCharacters(text) {
1088
+ // Remove null characters
1089
+ text = text.replace(/\0/g, '');
1090
+ // Replace emojis (and also ZWJ sequence) with hyphens
1091
+ text = text.replace(/(\p{Emoji})\p{Modifier_Symbol}/gu, '$1');
1092
+ text = text.replace(/(\p{Emoji})[\u{FE00}-\u{FE0F}]/gu, '$1');
1093
+ text = text.replace(/\p{Emoji}(\u{200D}\p{Emoji})*/gu, '-');
1094
+ return text.length;
1095
+ }
1096
+
1097
+ /**
1098
+ * Counts number of lines in the text
1099
+ */
1100
+ function countLines(text) {
1101
+ if (text === '') {
1102
+ return 0;
1103
+ }
1104
+ return text.split('\n').length;
1105
+ }
1106
+
1107
+ /**
1108
+ * Counts number of pages in the text
1109
+ */
1110
+ function countPages(text) {
1111
+ var sentencesPerPage = 5; // Assuming each page has 5 sentences
1112
+ var sentences = text.split(/[.!?]+/).filter(function (sentence) { return sentence.trim() !== ''; });
1113
+ var pageCount = Math.ceil(sentences.length / sentencesPerPage);
1114
+ return pageCount;
1115
+ }
1116
+
1117
+ /**
1118
+ * Counts number of paragraphs in the text
1119
+ */
1120
+ function countParagraphs(text) {
1121
+ return text.split(/\n\s*\n/).filter(function (paragraph) { return paragraph.trim() !== ''; }).length;
1122
+ }
1123
+
1124
+ /**
1125
+ * Counts number of sentences in the text
1126
+ */
1127
+ function countSentences(text) {
1128
+ return text.split(/[.!?]+/).filter(function (sentence) { return sentence.trim() !== ''; }).length;
1129
+ }
1130
+
1131
+ /**
1132
+ * Counts number of words in the text
1133
+ */
1134
+ function countWords(text) {
1135
+ text = text.replace(/[\p{Emoji}]/gu, 'a');
1136
+ text = removeDiacritics(text);
1137
+ return text.split(/[^a-zа-я0-9]+/i).filter(function (word) { return word.length > 0; }).length;
1138
+ }
1139
+
1140
+ /**
1141
+ * Index of all counter functions
1142
+ */
1143
+ var CountUtils = {
1144
+ CHARACTERS: countCharacters,
1145
+ WORDS: countWords,
1146
+ SENTENCES: countSentences,
1147
+ PARAGRAPHS: countParagraphs,
1148
+ LINES: countLines,
1149
+ PAGES: countPages,
1150
+ };
1151
+
923
1152
  /**
924
1153
  * All possible emoji chars like "🍆", "🍡", "🍤"...
925
1154
  * Note: this will be needed to update annually - now updated at 2022-01-19
@@ -1043,19 +1272,31 @@ function replaceParameters(template, parameters) {
1043
1272
  */
1044
1273
  function createPtpExecutor(options) {
1045
1274
  var _this = this;
1046
- var ptp = options.ptp, tools = options.tools;
1275
+ var ptp = options.ptp, tools = options.tools, settings = options.settings;
1047
1276
  var ptpExecutor = function (inputParameters, onProgress) { return __awaiter(_this, void 0, void 0, function () {
1048
- var parametersToPass, currentTemplate, _loop_1;
1049
- return __generator(this, function (_a) {
1050
- switch (_a.label) {
1277
+ var parametersToPass, currentTemplate, executionReport, _loop_1, error_1;
1278
+ var _a;
1279
+ return __generator(this, function (_b) {
1280
+ switch (_b.label) {
1051
1281
  case 0:
1052
1282
  parametersToPass = inputParameters;
1053
1283
  currentTemplate = ptp.entryPromptTemplate;
1284
+ executionReport = {
1285
+ ptbkUrl: ((_a = ptp.ptbkUrl) === null || _a === void 0 ? void 0 : _a.href) || undefined,
1286
+ title: ptp.title || undefined,
1287
+ ptbkUsedVersion: PTBK_VERSION,
1288
+ ptbkRequestedVersion: ptp.ptbkVersion || undefined,
1289
+ description: ptp.description || undefined,
1290
+ promptExecutions: [],
1291
+ };
1292
+ _b.label = 1;
1293
+ case 1:
1294
+ _b.trys.push([1, 5, , 6]);
1054
1295
  _loop_1 = function () {
1055
- var resultingParameter, name_1, title, prompt_1, chatThread, completionResult, promptResult, scriptExecutionErrors, isScriptExecutionSuccessful, _b, _c, _d, _e, scriptTools, error_1, e_1_1;
1056
- var e_1, _f, _g;
1057
- return __generator(this, function (_h) {
1058
- switch (_h.label) {
1296
+ var resultingParameter, name_1, title, prompt_1, chatThread, completionResult, result, resultString, naturalExecutionError, scriptExecutionErrors, isScriptExecutionSuccessful, _c, attempt, _d, _e, _f, _g, unit, _h, max, min, amount, error_2, _j, _k, scriptTools, error_3, e_1_1;
1297
+ var e_2, _l, e_1, _m, _o;
1298
+ return __generator(this, function (_p) {
1299
+ switch (_p.label) {
1059
1300
  case 0:
1060
1301
  resultingParameter = ptp.getResultingParameter(currentTemplate.name);
1061
1302
  name_1 = "ptp-executor-frame-".concat(currentTemplate.name);
@@ -1071,27 +1312,30 @@ function createPtpExecutor(options) {
1071
1312
  parameterValue: null,
1072
1313
  })];
1073
1314
  case 1:
1074
- _h.sent();
1075
- _h.label = 2;
1315
+ _p.sent();
1316
+ _p.label = 2;
1076
1317
  case 2:
1077
1318
  prompt_1 = void 0;
1078
1319
  chatThread = void 0;
1079
1320
  completionResult = void 0;
1080
- promptResult = null;
1321
+ result = null;
1322
+ resultString = null;
1323
+ naturalExecutionError = null;
1081
1324
  isScriptExecutionSuccessful = void 0;
1082
- _b = currentTemplate.executionType;
1083
- switch (_b) {
1325
+ _c = currentTemplate.executionType;
1326
+ switch (_c) {
1084
1327
  case 'SIMPLE_TEMPLATE': return [3 /*break*/, 3];
1085
1328
  case 'PROMPT_TEMPLATE': return [3 /*break*/, 4];
1086
- case 'SCRIPT': return [3 /*break*/, 11];
1087
- case 'PROMPT_DIALOG': return [3 /*break*/, 22];
1329
+ case 'SCRIPT': return [3 /*break*/, 18];
1330
+ case 'PROMPT_DIALOG': return [3 /*break*/, 29];
1088
1331
  }
1089
- return [3 /*break*/, 24];
1332
+ return [3 /*break*/, 31];
1090
1333
  case 3:
1091
- promptResult = replaceParameters(currentTemplate.content, parametersToPass);
1092
- return [3 /*break*/, 25];
1334
+ resultString = replaceParameters(currentTemplate.content, parametersToPass);
1335
+ return [3 /*break*/, 32];
1093
1336
  case 4:
1094
1337
  prompt_1 = {
1338
+ title: currentTemplate.title,
1095
1339
  ptbkUrl: "".concat(ptp.ptbkUrl
1096
1340
  ? ptp.ptbkUrl.href
1097
1341
  : 'anonymous' /* <- [🧠] !!!! How to deal with anonymous PTPs, do here some auto-url like SHA-256 based ad-hoc identifier? */, "#").concat(currentTemplate.name),
@@ -1099,28 +1343,88 @@ function createPtpExecutor(options) {
1099
1343
  content: replaceParameters(currentTemplate.content, parametersToPass),
1100
1344
  modelRequirements: currentTemplate.modelRequirements,
1101
1345
  };
1102
- _c = currentTemplate.modelRequirements.modelVariant;
1103
- switch (_c) {
1104
- case 'CHAT': return [3 /*break*/, 5];
1105
- case 'COMPLETION': return [3 /*break*/, 7];
1106
- }
1107
- return [3 /*break*/, 9];
1108
- case 5: return [4 /*yield*/, tools.natural.gptChat(prompt_1)];
1346
+ attempt = 0;
1347
+ _p.label = 5;
1348
+ case 5:
1349
+ if (!(attempt < settings.maxNaturalExecutionAttempts)) return [3 /*break*/, 17];
1350
+ result = null;
1351
+ resultString = null;
1352
+ naturalExecutionError = null;
1353
+ _p.label = 6;
1109
1354
  case 6:
1110
- chatThread = _h.sent();
1111
- // TODO: Use all information from chatThread like "model"
1112
- // TODO: [🍬] Destroy chatThread
1113
- promptResult = chatThread.content;
1114
- return [3 /*break*/, 10];
1115
- case 7: return [4 /*yield*/, tools.natural.gptComplete(prompt_1)];
1355
+ _p.trys.push([6, 13, 14, 15]);
1356
+ _d = currentTemplate.modelRequirements.modelVariant;
1357
+ switch (_d) {
1358
+ case 'CHAT': return [3 /*break*/, 7];
1359
+ case 'COMPLETION': return [3 /*break*/, 9];
1360
+ }
1361
+ return [3 /*break*/, 11];
1362
+ case 7: return [4 /*yield*/, tools.natural.gptChat(prompt_1)];
1116
1363
  case 8:
1117
- completionResult = _h.sent();
1118
- // TODO: Use all information from chatThread like "model"
1119
- promptResult = completionResult.content;
1120
- return [3 /*break*/, 10];
1121
- case 9: throw new Error("Unknown model variant \"".concat(currentTemplate.modelRequirements.modelVariant, "\""));
1122
- case 10: return [3 /*break*/, 25];
1123
- case 11:
1364
+ chatThread = _p.sent();
1365
+ // TODO: [🍬] Destroy chatThread
1366
+ result = chatThread;
1367
+ resultString = chatThread.content;
1368
+ return [3 /*break*/, 12];
1369
+ case 9: return [4 /*yield*/, tools.natural.gptComplete(prompt_1)];
1370
+ case 10:
1371
+ completionResult = _p.sent();
1372
+ result = completionResult;
1373
+ resultString = completionResult.content;
1374
+ return [3 /*break*/, 12];
1375
+ case 11: throw new Error("Unknown model variant \"".concat(currentTemplate.modelRequirements.modelVariant, "\""));
1376
+ case 12:
1377
+ try {
1378
+ // TODO: !!!!!! Here should postprocessing happen
1379
+ for (_e = (e_2 = void 0, __values(Object.entries(currentTemplate.expectations))), _f = _e.next(); !_f.done; _f = _e.next()) {
1380
+ _g = __read(_f.value, 2), unit = _g[0], _h = _g[1], max = _h.max, min = _h.min;
1381
+ amount = CountUtils[unit.toUpperCase()](resultString);
1382
+ if (min && amount < min) {
1383
+ throw new Error("Expected at least ".concat(min, " ").concat(unit, " but got ").concat(amount));
1384
+ } /* not else */
1385
+ if (max && amount > max) {
1386
+ throw new Error("Expected at most ".concat(max, " ").concat(unit, " but got ").concat(amount));
1387
+ }
1388
+ }
1389
+ }
1390
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
1391
+ finally {
1392
+ try {
1393
+ if (_f && !_f.done && (_l = _e.return)) _l.call(_e);
1394
+ }
1395
+ finally { if (e_2) throw e_2.error; }
1396
+ }
1397
+ return [3 /*break*/, 15];
1398
+ case 13:
1399
+ error_2 = _p.sent();
1400
+ if (!(error_2 instanceof Error)) {
1401
+ throw error_2;
1402
+ }
1403
+ naturalExecutionError = error_2;
1404
+ return [3 /*break*/, 15];
1405
+ case 14:
1406
+ executionReport.promptExecutions.push({
1407
+ prompt: {
1408
+ title: prompt_1.title,
1409
+ content: prompt_1.content,
1410
+ modelRequirements: prompt_1.modelRequirements,
1411
+ // <- Note: Do want to pass ONLY wanted information to the report
1412
+ },
1413
+ result: result /* <- !!!!! Look what is exposed here and probbably also filter out */ ||
1414
+ undefined,
1415
+ error: naturalExecutionError || undefined,
1416
+ });
1417
+ return [7 /*endfinally*/];
1418
+ case 15:
1419
+ if (result !== null && naturalExecutionError === null) {
1420
+ return [3 /*break*/, 32];
1421
+ }
1422
+ _p.label = 16;
1423
+ case 16:
1424
+ attempt++;
1425
+ return [3 /*break*/, 5];
1426
+ case 17: throw new Error(spaceTrim(function (block) { return "\n Natural execution failed ".concat(settings.maxNaturalExecutionAttempts, "x\n\n ").concat(block((naturalExecutionError === null || naturalExecutionError === void 0 ? void 0 : naturalExecutionError.message) || ''), "\n "); }));
1427
+ case 18:
1124
1428
  if (tools.script.length === 0) {
1125
1429
  throw new Error('No script execution tools are available');
1126
1430
  }
@@ -1129,50 +1433,50 @@ function createPtpExecutor(options) {
1129
1433
  }
1130
1434
  scriptExecutionErrors = [];
1131
1435
  isScriptExecutionSuccessful = false;
1132
- _h.label = 12;
1133
- case 12:
1134
- _h.trys.push([12, 19, 20, 21]);
1135
- _d = (e_1 = void 0, __values(tools.script)), _e = _d.next();
1136
- _h.label = 13;
1137
- case 13:
1138
- if (!!_e.done) return [3 /*break*/, 18];
1139
- scriptTools = _e.value;
1140
- _h.label = 14;
1141
- case 14:
1142
- _h.trys.push([14, 16, , 17]);
1436
+ _p.label = 19;
1437
+ case 19:
1438
+ _p.trys.push([19, 26, 27, 28]);
1439
+ _j = (e_1 = void 0, __values(tools.script)), _k = _j.next();
1440
+ _p.label = 20;
1441
+ case 20:
1442
+ if (!!_k.done) return [3 /*break*/, 25];
1443
+ scriptTools = _k.value;
1444
+ _p.label = 21;
1445
+ case 21:
1446
+ _p.trys.push([21, 23, , 24]);
1143
1447
  return [4 /*yield*/, scriptTools.execute({
1144
1448
  scriptLanguage: currentTemplate.contentLanguage,
1145
1449
  script: currentTemplate.content,
1146
1450
  parameters: parametersToPass,
1147
1451
  })];
1148
- case 15:
1149
- promptResult = _h.sent();
1452
+ case 22:
1453
+ resultString = _p.sent();
1150
1454
  isScriptExecutionSuccessful = true;
1151
- return [3 /*break*/, 18];
1152
- case 16:
1153
- error_1 = _h.sent();
1154
- if (!(error_1 instanceof Error)) {
1155
- throw error_1;
1455
+ return [3 /*break*/, 25];
1456
+ case 23:
1457
+ error_3 = _p.sent();
1458
+ if (!(error_3 instanceof Error)) {
1459
+ throw error_3;
1156
1460
  }
1157
- scriptExecutionErrors.push(error_1);
1158
- return [3 /*break*/, 17];
1159
- case 17:
1160
- _e = _d.next();
1161
- return [3 /*break*/, 13];
1162
- case 18: return [3 /*break*/, 21];
1163
- case 19:
1164
- e_1_1 = _h.sent();
1461
+ scriptExecutionErrors.push(error_3);
1462
+ return [3 /*break*/, 24];
1463
+ case 24:
1464
+ _k = _j.next();
1465
+ return [3 /*break*/, 20];
1466
+ case 25: return [3 /*break*/, 28];
1467
+ case 26:
1468
+ e_1_1 = _p.sent();
1165
1469
  e_1 = { error: e_1_1 };
1166
- return [3 /*break*/, 21];
1167
- case 20:
1470
+ return [3 /*break*/, 28];
1471
+ case 27:
1168
1472
  try {
1169
- if (_e && !_e.done && (_f = _d.return)) _f.call(_d);
1473
+ if (_k && !_k.done && (_m = _j.return)) _m.call(_j);
1170
1474
  }
1171
1475
  finally { if (e_1) throw e_1.error; }
1172
1476
  return [7 /*endfinally*/];
1173
- case 21:
1477
+ case 28:
1174
1478
  if (isScriptExecutionSuccessful) {
1175
- return [3 /*break*/, 25];
1479
+ return [3 /*break*/, 32];
1176
1480
  }
1177
1481
  if (scriptExecutionErrors.length === 1) {
1178
1482
  throw scriptExecutionErrors[0];
@@ -1180,20 +1484,20 @@ function createPtpExecutor(options) {
1180
1484
  else {
1181
1485
  throw new Error(spaceTrim(function (block) { return "\n Script execution failed ".concat(scriptExecutionErrors.length, " times\n\n ").concat(block(scriptExecutionErrors.map(function (error) { return '- ' + error.message; }).join('\n\n')), "\n "); }));
1182
1486
  }
1183
- case 22: return [4 /*yield*/, tools.userInterface.promptDialog({
1487
+ case 29: return [4 /*yield*/, tools.userInterface.promptDialog({
1184
1488
  prompt: replaceParameters(currentTemplate.description || '', parametersToPass),
1185
1489
  defaultValue: replaceParameters(currentTemplate.content, parametersToPass),
1186
1490
  // TODO: [🧠] !! Figure out how to define placeholder in .ptbk.md file
1187
1491
  placeholder: undefined,
1188
1492
  })];
1189
- case 23:
1190
- promptResult = _h.sent();
1191
- return [3 /*break*/, 25];
1192
- case 24:
1493
+ case 30:
1494
+ resultString = _p.sent();
1495
+ return [3 /*break*/, 32];
1496
+ case 31:
1193
1497
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1194
1498
  throw new Error("Unknown execution type \"".concat(currentTemplate.executionType, "\""));
1195
- case 25:
1196
- if (promptResult === null) {
1499
+ case 32:
1500
+ if (resultString === null) {
1197
1501
  // <- TODO: [🥨] Make some NeverShouldHappenError
1198
1502
  throw new Error('Something went wrong and prompt result is null');
1199
1503
  }
@@ -1205,23 +1509,40 @@ function createPtpExecutor(options) {
1205
1509
  isDone: true,
1206
1510
  executionType: currentTemplate.executionType,
1207
1511
  parameterName: resultingParameter.name,
1208
- parameterValue: promptResult,
1512
+ parameterValue: resultString,
1209
1513
  });
1210
1514
  }
1211
- parametersToPass = __assign(__assign({}, parametersToPass), (_g = {}, _g[resultingParameter.name] = promptResult /* <- Note: Not need to detect parameter collision here because PromptTemplatePipeline checks logic consistency during construction */, _g));
1515
+ parametersToPass = __assign(__assign({}, parametersToPass), (_o = {}, _o[resultingParameter.name] = resultString /* <- Note: Not need to detect parameter collision here because PromptTemplatePipeline checks logic consistency during construction */, _o));
1212
1516
  currentTemplate = ptp.getFollowingPromptTemplate(currentTemplate.name);
1213
1517
  return [2 /*return*/];
1214
1518
  }
1215
1519
  });
1216
1520
  };
1217
- _a.label = 1;
1218
- case 1:
1219
- if (!(currentTemplate !== null)) return [3 /*break*/, 3];
1220
- return [5 /*yield**/, _loop_1()];
1521
+ _b.label = 2;
1221
1522
  case 2:
1222
- _a.sent();
1223
- return [3 /*break*/, 1];
1224
- case 3: return [2 /*return*/, parametersToPass];
1523
+ if (!(currentTemplate !== null)) return [3 /*break*/, 4];
1524
+ return [5 /*yield**/, _loop_1()];
1525
+ case 3:
1526
+ _b.sent();
1527
+ return [3 /*break*/, 2];
1528
+ case 4: return [3 /*break*/, 6];
1529
+ case 5:
1530
+ error_1 = _b.sent();
1531
+ if (!(error_1 instanceof Error)) {
1532
+ throw error_1;
1533
+ }
1534
+ return [2 /*return*/, {
1535
+ isSuccessful: false,
1536
+ errors: [error_1],
1537
+ executionReport: executionReport,
1538
+ outputParameters: parametersToPass,
1539
+ }];
1540
+ case 6: return [2 /*return*/, {
1541
+ isSuccessful: true,
1542
+ errors: [],
1543
+ executionReport: executionReport,
1544
+ outputParameters: parametersToPass,
1545
+ }];
1225
1546
  }
1226
1547
  });
1227
1548
  }); };
@@ -1242,8 +1563,8 @@ function createPtpExecutor(options) {
1242
1563
  * @see https://github.com/webgptorg/promptbook#prompt-template-pipeline-library
1243
1564
  */
1244
1565
  var PromptTemplatePipelineLibrary = /** @class */ (function () {
1245
- function PromptTemplatePipelineLibrary(promptTemplatePipelines) {
1246
- this.promptTemplatePipelines = promptTemplatePipelines;
1566
+ function PromptTemplatePipelineLibrary(options) {
1567
+ this.options = options;
1247
1568
  }
1248
1569
  /**
1249
1570
  * Constructs PromptTemplatePipeline from any sources
@@ -1254,13 +1575,13 @@ var PromptTemplatePipelineLibrary = /** @class */ (function () {
1254
1575
  * @param ptbkSources contents of .ptbk.md or .ptbk.json files
1255
1576
  * @returns PromptTemplatePipelineLibrary
1256
1577
  */
1257
- PromptTemplatePipelineLibrary.fromSources = function (ptbkSources) {
1578
+ PromptTemplatePipelineLibrary.fromSources = function (ptbkSources, settings) {
1258
1579
  var e_1, _a;
1259
- var promptTemplatePipelines = {};
1580
+ var library = {};
1260
1581
  try {
1261
1582
  for (var _b = __values(Object.entries(ptbkSources)), _c = _b.next(); !_c.done; _c = _b.next()) {
1262
1583
  var _d = __read(_c.value, 2), name_1 = _d[0], source = _d[1];
1263
- promptTemplatePipelines[name_1] = PromptTemplatePipeline.fromSource(source);
1584
+ library[name_1] = PromptTemplatePipeline.fromSource(source);
1264
1585
  }
1265
1586
  }
1266
1587
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
@@ -1270,13 +1591,13 @@ var PromptTemplatePipelineLibrary = /** @class */ (function () {
1270
1591
  }
1271
1592
  finally { if (e_1) throw e_1.error; }
1272
1593
  }
1273
- return new PromptTemplatePipelineLibrary(promptTemplatePipelines);
1594
+ return new PromptTemplatePipelineLibrary({ library: library, settings: settings });
1274
1595
  };
1275
1596
  /**
1276
1597
  * Gets prompt template pipeline by name
1277
1598
  */
1278
1599
  PromptTemplatePipelineLibrary.prototype.getPtp = function (name) {
1279
- var promptTemplatePipeline = this.promptTemplatePipelines[name];
1600
+ var promptTemplatePipeline = this.options.library[name];
1280
1601
  if (!promptTemplatePipeline) {
1281
1602
  throw new Error("Prompt template pipeline with name \"".concat(name, "\" not found"));
1282
1603
  }
@@ -1293,7 +1614,7 @@ var PromptTemplatePipelineLibrary = /** @class */ (function () {
1293
1614
  */
1294
1615
  PromptTemplatePipelineLibrary.prototype.createExecutor = function (name, tools) {
1295
1616
  var ptp = this.getPtp(name);
1296
- return createPtpExecutor({ ptp: ptp, tools: tools });
1617
+ return createPtpExecutor({ ptp: ptp, tools: tools, settings: this.options.settings });
1297
1618
  };
1298
1619
  return PromptTemplatePipelineLibrary;
1299
1620
  }());