@promptbook/core 0.52.0-0 → 0.52.0-10

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 (62) hide show
  1. package/README.md +10 -6
  2. package/esm/index.es.js +915 -215
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/_packages/anthropic-claude.index.d.ts +3 -0
  5. package/esm/typings/_packages/azure-openai.index.d.ts +3 -0
  6. package/esm/typings/_packages/core.index.d.ts +13 -5
  7. package/esm/typings/_packages/openai.index.d.ts +1 -1
  8. package/esm/typings/_packages/utils.index.d.ts +3 -8
  9. package/esm/typings/execution/PromptResult.d.ts +3 -3
  10. package/esm/typings/execution/plugins/llm-execution-tools/anthropic-claude/AnthropicClaudeExecutionTools.d.ts +42 -0
  11. package/esm/typings/execution/plugins/llm-execution-tools/anthropic-claude/AnthropicClaudeExecutionToolsOptions.d.ts +8 -0
  12. package/esm/typings/execution/plugins/llm-execution-tools/anthropic-claude/anthropic-claude-models.d.ts +20 -0
  13. package/esm/typings/execution/plugins/llm-execution-tools/anthropic-claude/playground/playground.d.ts +2 -0
  14. package/esm/typings/execution/plugins/llm-execution-tools/azure-openai/AzureOpenAiExecutionTools.d.ts +41 -0
  15. package/esm/typings/execution/plugins/llm-execution-tools/azure-openai/AzureOpenAiExecutionToolsOptions.d.ts +34 -0
  16. package/esm/typings/execution/plugins/llm-execution-tools/azure-openai/playground/playground.d.ts +2 -0
  17. package/esm/typings/execution/plugins/llm-execution-tools/langtail/playground/playground.d.ts +2 -0
  18. package/esm/typings/execution/plugins/llm-execution-tools/mocked/MockedEchoLlmExecutionTools.d.ts +2 -2
  19. package/esm/typings/execution/plugins/llm-execution-tools/mocked/MockedFackedLlmExecutionTools.d.ts +2 -2
  20. package/esm/typings/execution/plugins/llm-execution-tools/multiple/MultipleLlmExecutionTools.d.ts +35 -0
  21. package/esm/typings/execution/plugins/llm-execution-tools/multiple/MultipleLlmExecutionToolsOptions.d.ts +23 -0
  22. package/esm/typings/execution/plugins/llm-execution-tools/multiple/playground/playground.d.ts +2 -0
  23. package/esm/typings/execution/plugins/llm-execution-tools/openai/OpenAiExecutionTools.d.ts +3 -3
  24. package/esm/typings/execution/plugins/llm-execution-tools/openai/OpenAiExecutionToolsOptions.d.ts +3 -1
  25. package/esm/typings/execution/plugins/llm-execution-tools/openai/computeUsage.d.ts +6 -3
  26. package/esm/typings/execution/plugins/llm-execution-tools/openai/{models.d.ts → openai-models.d.ts} +2 -1
  27. package/esm/typings/execution/plugins/llm-execution-tools/openai/playground/playground.d.ts +2 -0
  28. package/esm/typings/execution/plugins/script-execution-tools/javascript/JavascriptEvalExecutionTools.d.ts +1 -1
  29. package/esm/typings/execution/plugins/script-execution-tools/javascript/JavascriptExecutionTools.d.ts +4 -17
  30. package/esm/typings/library/constructors/createPromptbookLibraryFromDirectory.d.ts +16 -1
  31. package/package.json +2 -1
  32. package/umd/index.umd.js +924 -215
  33. package/umd/index.umd.js.map +1 -1
  34. package/umd/typings/_packages/anthropic-claude.index.d.ts +3 -0
  35. package/umd/typings/_packages/azure-openai.index.d.ts +3 -0
  36. package/umd/typings/_packages/core.index.d.ts +13 -5
  37. package/umd/typings/_packages/openai.index.d.ts +1 -1
  38. package/umd/typings/_packages/utils.index.d.ts +3 -8
  39. package/umd/typings/execution/PromptResult.d.ts +3 -3
  40. package/umd/typings/execution/plugins/llm-execution-tools/anthropic-claude/AnthropicClaudeExecutionTools.d.ts +42 -0
  41. package/umd/typings/execution/plugins/llm-execution-tools/anthropic-claude/AnthropicClaudeExecutionToolsOptions.d.ts +8 -0
  42. package/umd/typings/execution/plugins/llm-execution-tools/anthropic-claude/anthropic-claude-models.d.ts +20 -0
  43. package/umd/typings/execution/plugins/llm-execution-tools/anthropic-claude/playground/playground.d.ts +2 -0
  44. package/umd/typings/execution/plugins/llm-execution-tools/azure-openai/AzureOpenAiExecutionTools.d.ts +41 -0
  45. package/umd/typings/execution/plugins/llm-execution-tools/azure-openai/AzureOpenAiExecutionToolsOptions.d.ts +34 -0
  46. package/umd/typings/execution/plugins/llm-execution-tools/azure-openai/playground/playground.d.ts +2 -0
  47. package/umd/typings/execution/plugins/llm-execution-tools/langtail/playground/playground.d.ts +2 -0
  48. package/umd/typings/execution/plugins/llm-execution-tools/mocked/MockedEchoLlmExecutionTools.d.ts +2 -2
  49. package/umd/typings/execution/plugins/llm-execution-tools/mocked/MockedFackedLlmExecutionTools.d.ts +2 -2
  50. package/umd/typings/execution/plugins/llm-execution-tools/multiple/MultipleLlmExecutionTools.d.ts +35 -0
  51. package/umd/typings/execution/plugins/llm-execution-tools/multiple/MultipleLlmExecutionToolsOptions.d.ts +23 -0
  52. package/umd/typings/execution/plugins/llm-execution-tools/multiple/playground/playground.d.ts +2 -0
  53. package/umd/typings/execution/plugins/llm-execution-tools/openai/OpenAiExecutionTools.d.ts +3 -3
  54. package/umd/typings/execution/plugins/llm-execution-tools/openai/OpenAiExecutionToolsOptions.d.ts +3 -1
  55. package/umd/typings/execution/plugins/llm-execution-tools/openai/computeUsage.d.ts +6 -3
  56. package/umd/typings/execution/plugins/llm-execution-tools/openai/{models.d.ts → openai-models.d.ts} +2 -1
  57. package/umd/typings/execution/plugins/llm-execution-tools/openai/playground/playground.d.ts +2 -0
  58. package/umd/typings/execution/plugins/script-execution-tools/javascript/JavascriptEvalExecutionTools.d.ts +1 -1
  59. package/umd/typings/execution/plugins/script-execution-tools/javascript/JavascriptExecutionTools.d.ts +4 -17
  60. package/umd/typings/library/constructors/createPromptbookLibraryFromDirectory.d.ts +16 -1
  61. package/esm/typings/_packages/wizzard.index.d.ts +0 -5
  62. package/umd/typings/_packages/wizzard.index.d.ts +0 -5
package/esm/index.es.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import spaceTrim$1, { spaceTrim } from 'spacetrim';
2
2
  import { format } from 'prettier';
3
3
  import parserHtml from 'prettier/parser-html';
4
- import 'moment';
4
+ import moment from 'moment';
5
5
 
6
6
  /*! *****************************************************************************
7
7
  Copyright (c) Microsoft Corporation.
@@ -447,7 +447,7 @@ function union() {
447
447
  /**
448
448
  * The version of the Promptbook library
449
449
  */
450
- var PROMPTBOOK_VERSION = '0.51.0';
450
+ var PROMPTBOOK_VERSION = '0.52.0-9';
451
451
 
452
452
  /**
453
453
  * Parses the template and returns the list of all parameter names
@@ -569,38 +569,6 @@ function extractParametersFromPromptTemplate(promptTemplate) {
569
569
  * TODO: [🔣] If script require contentLanguage
570
570
  */
571
571
 
572
- /**
573
- * Prettify the html code
574
- *
575
- * @param content raw html code
576
- * @returns formatted html code
577
- */
578
- function prettifyMarkdown(content) {
579
- try {
580
- return format(content, {
581
- parser: 'markdown',
582
- plugins: [parserHtml],
583
- // TODO: DRY - make some import or auto-copy of .prettierrc
584
- endOfLine: 'lf',
585
- tabWidth: 4,
586
- singleQuote: true,
587
- trailingComma: 'all',
588
- arrowParens: 'always',
589
- printWidth: 120,
590
- htmlWhitespaceSensitivity: 'ignore',
591
- jsxBracketSameLine: false,
592
- bracketSpacing: true,
593
- });
594
- }
595
- catch (error) {
596
- console.error('There was an error with prettifying the markdown, using the original as the fallback', {
597
- error: error,
598
- html: content,
599
- });
600
- return content;
601
- }
602
- }
603
-
604
572
  /**
605
573
  * Removes emojis from a string and fix whitespaces
606
574
  *
@@ -626,6 +594,64 @@ function titleToName(value) {
626
594
  return value;
627
595
  }
628
596
 
597
+ /**
598
+ * Creates a Mermaid graph based on the promptbook
599
+ *
600
+ * Note: The result is not wrapped in a Markdown code block
601
+ */
602
+ function renderPromptbookMermaid(promptbookJson, options) {
603
+ var _a = (options || {}).linkPromptTemplate, linkPromptTemplate = _a === void 0 ? function () { return null; } : _a;
604
+ var parameterNameToTemplateName = function (parameterName) {
605
+ var parameter = promptbookJson.parameters.find(function (parameter) { return parameter.name === parameterName; });
606
+ if (!parameter) {
607
+ throw new UnexpectedError("Could not find {".concat(parameterName, "}"));
608
+ }
609
+ if (parameter.isInput) {
610
+ return 'input';
611
+ }
612
+ var template = promptbookJson.promptTemplates.find(function (template) { return template.resultingParameterName === parameterName; });
613
+ if (!template) {
614
+ throw new Error("Could not find template for {".concat(parameterName, "}"));
615
+ }
616
+ return normalizeTo_camelCase('template-' + titleToName(template.title));
617
+ };
618
+ var promptbookMermaid = spaceTrim(function (block) { return "\n\n %% \uD83D\uDD2E Tip: Open this on GitHub or in the VSCode website to see the Mermaid graph visually\n\n flowchart LR\n subgraph \"".concat(promptbookJson.title, "\"\n\n direction TB\n\n input((Input)):::input\n ").concat(block(promptbookJson.promptTemplates
619
+ .flatMap(function (_a) {
620
+ var title = _a.title, dependentParameterNames = _a.dependentParameterNames, resultingParameterName = _a.resultingParameterName;
621
+ return __spreadArray([
622
+ "".concat(parameterNameToTemplateName(resultingParameterName), "(\"").concat(title, "\")")
623
+ ], __read(dependentParameterNames.map(function (dependentParameterName) {
624
+ return "".concat(parameterNameToTemplateName(dependentParameterName), "--\"{").concat(dependentParameterName, "}\"-->").concat(parameterNameToTemplateName(resultingParameterName));
625
+ })), false);
626
+ })
627
+ .join('\n')), "\n\n ").concat(block(promptbookJson.parameters
628
+ .filter(function (_a) {
629
+ var isOutput = _a.isOutput;
630
+ return isOutput;
631
+ })
632
+ .map(function (_a) {
633
+ var name = _a.name;
634
+ return "".concat(parameterNameToTemplateName(name), "--\"{").concat(name, "}\"-->output");
635
+ })
636
+ .join('\n')), "\n output((Output)):::output\n\n ").concat(block(promptbookJson.promptTemplates
637
+ .map(function (promptTemplate) {
638
+ var link = linkPromptTemplate(promptTemplate);
639
+ if (link === null) {
640
+ return '';
641
+ }
642
+ var href = link.href, title = link.title;
643
+ var templateName = parameterNameToTemplateName(promptTemplate.resultingParameterName);
644
+ return "click ".concat(templateName, " href \"").concat(href, "\" \"").concat(title, "\";");
645
+ })
646
+ .filter(function (line) { return line !== ''; })
647
+ .join('\n')), "\n\n classDef input color: grey;\n classDef output color: grey;\n\n end;\n\n "); });
648
+ return promptbookMermaid;
649
+ }
650
+ /**
651
+ * TODO: Maybe use some Mermaid library instead of string templating
652
+ * TODO: [🕌] When more than 2 functionalities, split into separate functions
653
+ */
654
+
629
655
  /**
630
656
  * Function parseNumber will parse number from string
631
657
  *
@@ -708,35 +734,80 @@ var PromptbookLogicError = /** @class */ (function (_super) {
708
734
  }(Error));
709
735
 
710
736
  /**
711
- * This error indicates errors during the execution of the promptbook
737
+ * This error occurs during the parameter replacement in the template
738
+ *
739
+ * Note: This is a kindof subtype of PromptbookExecutionError because it occurs during the execution of the pipeline
712
740
  */
713
- var PromptbookExecutionError = /** @class */ (function (_super) {
714
- __extends(PromptbookExecutionError, _super);
715
- function PromptbookExecutionError(message) {
741
+ var TemplateError = /** @class */ (function (_super) {
742
+ __extends(TemplateError, _super);
743
+ function TemplateError(message) {
716
744
  var _this = _super.call(this, message) || this;
717
- _this.name = 'PromptbookExecutionError';
718
- Object.setPrototypeOf(_this, PromptbookExecutionError.prototype);
745
+ _this.name = 'TemplateError';
746
+ Object.setPrototypeOf(_this, TemplateError.prototype);
719
747
  return _this;
720
748
  }
721
- return PromptbookExecutionError;
749
+ return TemplateError;
722
750
  }(Error));
723
751
 
724
752
  /**
725
- * This error occurs when some expectation is not met in the execution of the pipeline
753
+ * Replaces parameters in template with values from parameters object
726
754
  *
727
- * @private Always catched and rethrown as `PromptbookExecutionError`
728
- * Note: This is a kindof subtype of PromptbookExecutionError
755
+ * @param template the template with parameters in {curly} braces
756
+ * @param parameters the object with parameters
757
+ * @returns the template with replaced parameters
758
+ * @throws {TemplateError} if parameter is not defined, not closed, or not opened
759
+ *
760
+ * @private within the createPromptbookExecutor
729
761
  */
730
- var ExpectError = /** @class */ (function (_super) {
731
- __extends(ExpectError, _super);
732
- function ExpectError(message) {
733
- var _this = _super.call(this, message) || this;
734
- _this.name = 'ExpectError';
735
- Object.setPrototypeOf(_this, ExpectError.prototype);
736
- return _this;
762
+ function replaceParameters(template, parameters) {
763
+ var replacedTemplate = template;
764
+ var match;
765
+ var loopLimit = LOOP_LIMIT;
766
+ var _loop_1 = function () {
767
+ if (loopLimit-- < 0) {
768
+ throw new UnexpectedError('Loop limit reached during parameters replacement in `replaceParameters`');
769
+ }
770
+ var precol = match.groups.precol;
771
+ var parameterName = match.groups.parameterName;
772
+ if (parameterName === '') {
773
+ return "continue";
774
+ }
775
+ if (parameterName.indexOf('{') !== -1 || parameterName.indexOf('}') !== -1) {
776
+ throw new TemplateError('Parameter is already opened or not closed');
777
+ }
778
+ if (parameters[parameterName] === undefined) {
779
+ throw new TemplateError("Parameter {".concat(parameterName, "} is not defined"));
780
+ }
781
+ var parameterValue = parameters[parameterName];
782
+ if (parameterValue === undefined) {
783
+ throw new TemplateError("Parameter {".concat(parameterName, "} is not defined"));
784
+ }
785
+ parameterValue = parameterValue.toString();
786
+ if (parameterValue.includes('\n') && /^\s*\W{0,3}\s*$/.test(precol)) {
787
+ parameterValue = parameterValue
788
+ .split('\n')
789
+ .map(function (line, index) { return (index === 0 ? line : "".concat(precol).concat(line)); })
790
+ .join('\n');
791
+ }
792
+ replacedTemplate =
793
+ replacedTemplate.substring(0, match.index + precol.length) +
794
+ parameterValue +
795
+ replacedTemplate.substring(match.index + precol.length + parameterName.length + 2);
796
+ };
797
+ while ((match = /^(?<precol>.*){(?<parameterName>\w+)}(.*)/m /* <- Not global */
798
+ .exec(replacedTemplate))) {
799
+ _loop_1();
737
800
  }
738
- return ExpectError;
739
- }(Error));
801
+ // [💫] Check if there are parameters that are not closed properly
802
+ if (/{\w+$/.test(replacedTemplate)) {
803
+ throw new TemplateError('Parameter is not closed');
804
+ }
805
+ // [💫] Check if there are parameters that are not opened properly
806
+ if (/^\w+}/.test(replacedTemplate)) {
807
+ throw new TemplateError('Parameter is not opened');
808
+ }
809
+ return replacedTemplate;
810
+ }
740
811
 
741
812
  /**
742
813
  * Counts number of characters in the text
@@ -1064,118 +1135,6 @@ var CountUtils = {
1064
1135
  PAGES: countPages,
1065
1136
  };
1066
1137
 
1067
- /**
1068
- * Function checkExpectations will check if the expectations on given value are met
1069
- *
1070
- * Note: There are two simmilar functions:
1071
- * - `checkExpectations` which throws an error if the expectations are not met
1072
- * - `isPassingExpectations` which returns a boolean
1073
- *
1074
- * @throws {ExpectError} if the expectations are not met
1075
- * @returns {void} Nothing
1076
- */
1077
- function checkExpectations(expectations, value) {
1078
- var e_1, _a;
1079
- try {
1080
- for (var _b = __values(Object.entries(expectations)), _c = _b.next(); !_c.done; _c = _b.next()) {
1081
- var _d = __read(_c.value, 2), unit = _d[0], _e = _d[1], max = _e.max, min = _e.min;
1082
- var amount = CountUtils[unit.toUpperCase()](value);
1083
- if (min && amount < min) {
1084
- throw new ExpectError("Expected at least ".concat(min, " ").concat(unit, " but got ").concat(amount));
1085
- } /* not else */
1086
- if (max && amount > max) {
1087
- throw new ExpectError("Expected at most ".concat(max, " ").concat(unit, " but got ").concat(amount));
1088
- }
1089
- }
1090
- }
1091
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
1092
- finally {
1093
- try {
1094
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1095
- }
1096
- finally { if (e_1) throw e_1.error; }
1097
- }
1098
- }
1099
- /**
1100
- * TODO: [💝] Unite object for expecting amount and format
1101
- */
1102
-
1103
- /**
1104
- * This error occurs during the parameter replacement in the template
1105
- *
1106
- * Note: This is a kindof subtype of PromptbookExecutionError because it occurs during the execution of the pipeline
1107
- */
1108
- var TemplateError = /** @class */ (function (_super) {
1109
- __extends(TemplateError, _super);
1110
- function TemplateError(message) {
1111
- var _this = _super.call(this, message) || this;
1112
- _this.name = 'TemplateError';
1113
- Object.setPrototypeOf(_this, TemplateError.prototype);
1114
- return _this;
1115
- }
1116
- return TemplateError;
1117
- }(Error));
1118
-
1119
- /**
1120
- * Replaces parameters in template with values from parameters object
1121
- *
1122
- * @param template the template with parameters in {curly} braces
1123
- * @param parameters the object with parameters
1124
- * @returns the template with replaced parameters
1125
- * @throws {TemplateError} if parameter is not defined, not closed, or not opened
1126
- *
1127
- * @private within the createPromptbookExecutor
1128
- */
1129
- function replaceParameters(template, parameters) {
1130
- var replacedTemplate = template;
1131
- var match;
1132
- var loopLimit = LOOP_LIMIT;
1133
- var _loop_1 = function () {
1134
- if (loopLimit-- < 0) {
1135
- throw new UnexpectedError('Loop limit reached during parameters replacement in `replaceParameters`');
1136
- }
1137
- var precol = match.groups.precol;
1138
- var parameterName = match.groups.parameterName;
1139
- if (parameterName === '') {
1140
- return "continue";
1141
- }
1142
- if (parameterName.indexOf('{') !== -1 || parameterName.indexOf('}') !== -1) {
1143
- throw new TemplateError('Parameter is already opened or not closed');
1144
- }
1145
- if (parameters[parameterName] === undefined) {
1146
- throw new TemplateError("Parameter {".concat(parameterName, "} is not defined"));
1147
- }
1148
- var parameterValue = parameters[parameterName];
1149
- if (parameterValue === undefined) {
1150
- throw new TemplateError("Parameter {".concat(parameterName, "} is not defined"));
1151
- }
1152
- parameterValue = parameterValue.toString();
1153
- if (parameterValue.includes('\n') && /^\s*\W{0,3}\s*$/.test(precol)) {
1154
- parameterValue = parameterValue
1155
- .split('\n')
1156
- .map(function (line, index) { return (index === 0 ? line : "".concat(precol).concat(line)); })
1157
- .join('\n');
1158
- }
1159
- replacedTemplate =
1160
- replacedTemplate.substring(0, match.index + precol.length) +
1161
- parameterValue +
1162
- replacedTemplate.substring(match.index + precol.length + parameterName.length + 2);
1163
- };
1164
- while ((match = /^(?<precol>.*){(?<parameterName>\w+)}(.*)/m /* <- Not global */
1165
- .exec(replacedTemplate))) {
1166
- _loop_1();
1167
- }
1168
- // [💫] Check if there are parameters that are not closed properly
1169
- if (/{\w+$/.test(replacedTemplate)) {
1170
- throw new TemplateError('Parameter is not closed');
1171
- }
1172
- // [💫] Check if there are parameters that are not opened properly
1173
- if (/^\w+}/.test(replacedTemplate)) {
1174
- throw new TemplateError('Parameter is not opened');
1175
- }
1176
- return replacedTemplate;
1177
- }
1178
-
1179
1138
  /**
1180
1139
  * Function isValidJsonString will tell you if the string is valid JSON or not
1181
1140
  */
@@ -1330,6 +1289,61 @@ function normalizeToKebabCase(sentence) {
1330
1289
  return normalizedName;
1331
1290
  }
1332
1291
 
1292
+ /* tslint:disable */
1293
+ function normalizeTo_camelCase(sentence, __firstLetterCapital) {
1294
+ var e_1, _a;
1295
+ if (__firstLetterCapital === void 0) { __firstLetterCapital = false; }
1296
+ var charType;
1297
+ var lastCharType = null;
1298
+ var normalizedName = '';
1299
+ try {
1300
+ for (var sentence_1 = __values(sentence), sentence_1_1 = sentence_1.next(); !sentence_1_1.done; sentence_1_1 = sentence_1.next()) {
1301
+ var char = sentence_1_1.value;
1302
+ var normalizedChar = void 0;
1303
+ if (/^[a-z]$/.test(char)) {
1304
+ charType = 'LOWERCASE';
1305
+ normalizedChar = char;
1306
+ }
1307
+ else if (/^[A-Z]$/.test(char)) {
1308
+ charType = 'UPPERCASE';
1309
+ normalizedChar = char.toLowerCase();
1310
+ }
1311
+ else if (/^[0-9]$/.test(char)) {
1312
+ charType = 'NUMBER';
1313
+ normalizedChar = char;
1314
+ }
1315
+ else {
1316
+ charType = 'OTHER';
1317
+ normalizedChar = '';
1318
+ }
1319
+ if (!lastCharType) {
1320
+ if (__firstLetterCapital) {
1321
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: DRY
1322
+ }
1323
+ }
1324
+ else if (charType !== lastCharType &&
1325
+ !(charType === 'LOWERCASE' && lastCharType === 'UPPERCASE') &&
1326
+ !(lastCharType === 'NUMBER') &&
1327
+ !(charType === 'NUMBER')) {
1328
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: [🌺] DRY
1329
+ }
1330
+ normalizedName += normalizedChar;
1331
+ lastCharType = charType;
1332
+ }
1333
+ }
1334
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
1335
+ finally {
1336
+ try {
1337
+ if (sentence_1_1 && !sentence_1_1.done && (_a = sentence_1.return)) _a.call(sentence_1);
1338
+ }
1339
+ finally { if (e_1) throw e_1.error; }
1340
+ }
1341
+ return normalizedName;
1342
+ }
1343
+ /**
1344
+ * TODO: [🌺] Use some intermediate util splitWords
1345
+ */
1346
+
1333
1347
  /**
1334
1348
  * Execution type describes the way how the block is executed
1335
1349
  *
@@ -1848,6 +1862,87 @@ function promptbookStringToJson(promptbookString) {
1848
1862
  * TODO: [🧠] Parameter flags - isInput, isOutput, isInternal
1849
1863
  */
1850
1864
 
1865
+ /**
1866
+ * Add or modify an auto-generated section in a markdown file
1867
+ *
1868
+ * @private within the library
1869
+ */
1870
+ function addAutoGeneratedSection(content, options) {
1871
+ var sectionName = options.sectionName, sectionContent = options.sectionContent;
1872
+ var warningLine = "<!-- \u26A0\uFE0F WARNING: This section was auto-generated -->";
1873
+ var sectionRegex = new RegExp("<!--".concat(sectionName, "-->([\\s\\S]*?)<!--/").concat(sectionName, "-->"), 'g');
1874
+ var sectionMatch = content.match(sectionRegex);
1875
+ if (sectionMatch) {
1876
+ return content.replace(sectionRegex, spaceTrim(function (block) { return "\n <!--".concat(sectionName, "-->\n ").concat(block(warningLine), "\n ").concat(block(sectionContent), "\n <!--/").concat(sectionName, "-->\n "); }));
1877
+ }
1878
+ var placeForSection = removeContentComments(content).match(/^##.*$/im);
1879
+ if (!placeForSection) {
1880
+ throw new Error("No place where to put the section <!--".concat(sectionName, "-->"));
1881
+ }
1882
+ var _a = __read(placeForSection, 1), heading = _a[0];
1883
+ return content.replace(heading, "<!--".concat(sectionName, "-->\n").concat(warningLine, "\n").concat(sectionContent, "\n<!--/").concat(sectionName, "-->\n\n").concat(heading));
1884
+ }
1885
+
1886
+ /**
1887
+ * Prettify the html code
1888
+ *
1889
+ * @param content raw html code
1890
+ * @returns formatted html code
1891
+ */
1892
+ function prettifyMarkdown(content) {
1893
+ try {
1894
+ return format(content, {
1895
+ parser: 'markdown',
1896
+ plugins: [parserHtml],
1897
+ // TODO: DRY - make some import or auto-copy of .prettierrc
1898
+ endOfLine: 'lf',
1899
+ tabWidth: 4,
1900
+ singleQuote: true,
1901
+ trailingComma: 'all',
1902
+ arrowParens: 'always',
1903
+ printWidth: 120,
1904
+ htmlWhitespaceSensitivity: 'ignore',
1905
+ jsxBracketSameLine: false,
1906
+ bracketSpacing: true,
1907
+ });
1908
+ }
1909
+ catch (error) {
1910
+ console.error('There was an error with prettifying the markdown, using the original as the fallback', {
1911
+ error: error,
1912
+ html: content,
1913
+ });
1914
+ return content;
1915
+ }
1916
+ }
1917
+
1918
+ /**
1919
+ * Prettyfies Promptbook string and adds Mermaid graph
1920
+ */
1921
+ function prettifyPromptbookString(promptbookString, options) {
1922
+ var isGraphAdded = options.isGraphAdded, isPrettifyed = options.isPrettifyed;
1923
+ if (isGraphAdded) {
1924
+ var promptbookJson = promptbookStringToJson(promptbookString);
1925
+ var promptbookMermaid_1 = renderPromptbookMermaid(promptbookJson, {
1926
+ linkPromptTemplate: function (promptTemplate) {
1927
+ return { href: "#".concat(promptTemplate.name), title: promptTemplate.title };
1928
+ },
1929
+ });
1930
+ var promptbookMermaidBlock = spaceTrim(function (block) { return "\n ```mermaid\n ".concat(block(promptbookMermaid_1), "\n ```\n "); });
1931
+ promptbookString = addAutoGeneratedSection(promptbookString, {
1932
+ sectionName: 'Graph',
1933
+ sectionContent: promptbookMermaidBlock,
1934
+ });
1935
+ }
1936
+ if (isPrettifyed) {
1937
+ promptbookString = prettifyMarkdown(promptbookString);
1938
+ }
1939
+ return promptbookString;
1940
+ }
1941
+ /**
1942
+ * TODO: Maybe use some Mermaid library instead of string templating
1943
+ * TODO: [🕌] When more than 2 functionalities, split into separate functions
1944
+ */
1945
+
1851
1946
  /**
1852
1947
  * Converts promptbook in JSON format to string format
1853
1948
  *
@@ -2177,63 +2272,176 @@ function validatePromptbookJson(promptbook) {
2177
2272
  }
2178
2273
  }
2179
2274
  }
2180
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
2275
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
2276
+ finally {
2277
+ try {
2278
+ if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
2279
+ }
2280
+ finally { if (e_2) throw e_2.error; }
2281
+ }
2282
+ // Note: Detect circular dependencies
2283
+ var resovedParameters = promptbook.parameters
2284
+ .filter(function (_a) {
2285
+ var isInput = _a.isInput;
2286
+ return isInput;
2287
+ })
2288
+ .map(function (_a) {
2289
+ var name = _a.name;
2290
+ return name;
2291
+ });
2292
+ var unresovedTemplates = __spreadArray([], __read(promptbook.promptTemplates), false);
2293
+ var loopLimit = LOOP_LIMIT;
2294
+ var _loop_2 = function () {
2295
+ if (loopLimit-- < 0) {
2296
+ throw new UnexpectedError('Loop limit reached during detection of circular dependencies in `validatePromptbookJson`');
2297
+ }
2298
+ var currentlyResovedTemplates = unresovedTemplates.filter(function (template) {
2299
+ return template.dependentParameterNames.every(function (name) { return resovedParameters.includes(name); });
2300
+ });
2301
+ if (currentlyResovedTemplates.length === 0) {
2302
+ throw new PromptbookLogicError(spaceTrim(function (block) { return "\n\n Can not resolve some parameters\n It may be circular dependencies\n\n Can not resolve:\n ".concat(block(unresovedTemplates
2303
+ .map(function (_a) {
2304
+ var resultingParameterName = _a.resultingParameterName, dependentParameterNames = _a.dependentParameterNames;
2305
+ return "- {".concat(resultingParameterName, "} depends on ").concat(dependentParameterNames
2306
+ .map(function (dependentParameterName) { return "{".concat(dependentParameterName, "}"); })
2307
+ .join(', '));
2308
+ })
2309
+ .join('\n')), "\n\n Resolved:\n ").concat(block(resovedParameters.map(function (name) { return "- {".concat(name, "}"); }).join('\n')), "\n "); }));
2310
+ }
2311
+ resovedParameters = __spreadArray(__spreadArray([], __read(resovedParameters), false), __read(currentlyResovedTemplates.map(function (_a) {
2312
+ var resultingParameterName = _a.resultingParameterName;
2313
+ return resultingParameterName;
2314
+ })), false);
2315
+ unresovedTemplates = unresovedTemplates.filter(function (template) { return !currentlyResovedTemplates.includes(template); });
2316
+ };
2317
+ while (unresovedTemplates.length > 0) {
2318
+ _loop_2();
2319
+ }
2320
+ return promptbook;
2321
+ }
2322
+ /**
2323
+ * TODO: [🧠] Work with promptbookVersion
2324
+ * TODO: Use here some json-schema, Zod or something similar and change it to:
2325
+ * > /**
2326
+ * > * Validates PromptbookJson if it is logically valid.
2327
+ * > *
2328
+ * > * It checks:
2329
+ * > * - it has a valid structure
2330
+ * > * - ...
2331
+ * > ex port function validatePromptbookJson(promptbook: unknown): asserts promptbook is PromptbookJson {
2332
+ */
2333
+
2334
+ /**
2335
+ * This error indicates errors during the execution of the promptbook
2336
+ */
2337
+ var PromptbookExecutionError = /** @class */ (function (_super) {
2338
+ __extends(PromptbookExecutionError, _super);
2339
+ function PromptbookExecutionError(message) {
2340
+ var _this = _super.call(this, message) || this;
2341
+ _this.name = 'PromptbookExecutionError';
2342
+ Object.setPrototypeOf(_this, PromptbookExecutionError.prototype);
2343
+ return _this;
2344
+ }
2345
+ return PromptbookExecutionError;
2346
+ }(Error));
2347
+
2348
+ /**
2349
+ * Asserts that the execution of a promptnook is successful
2350
+ *
2351
+ * @param executionResult - The partial result of the promptnook execution
2352
+ * @throws {PromptbookExecutionError} If the execution is not successful or if multiple errors occurred
2353
+ */
2354
+ function assertsExecutionSuccessful(executionResult) {
2355
+ var isSuccessful = executionResult.isSuccessful, errors = executionResult.errors;
2356
+ if (isSuccessful === true) {
2357
+ return;
2358
+ }
2359
+ if (errors.length === 0) {
2360
+ throw new PromptbookExecutionError("Promptnook Execution failed because of unknown reason");
2361
+ }
2362
+ else if (errors.length === 1) {
2363
+ throw errors[0];
2364
+ }
2365
+ else {
2366
+ throw new PromptbookExecutionError(spaceTrim(function (block) { return "\n Multiple errors occurred during promptnook execution\n\n ".concat(block(errors.map(function (error) { return '- ' + error.message; }).join('\n')), "\n "); }));
2367
+ }
2368
+ }
2369
+ /**
2370
+ * TODO: [🧠] Can this return type be better typed than void
2371
+ */
2372
+
2373
+ /**
2374
+ * This error occurs when some expectation is not met in the execution of the pipeline
2375
+ *
2376
+ * @private Always catched and rethrown as `PromptbookExecutionError`
2377
+ * Note: This is a kindof subtype of PromptbookExecutionError
2378
+ */
2379
+ var ExpectError = /** @class */ (function (_super) {
2380
+ __extends(ExpectError, _super);
2381
+ function ExpectError(message) {
2382
+ var _this = _super.call(this, message) || this;
2383
+ _this.name = 'ExpectError';
2384
+ Object.setPrototypeOf(_this, ExpectError.prototype);
2385
+ return _this;
2386
+ }
2387
+ return ExpectError;
2388
+ }(Error));
2389
+
2390
+ /**
2391
+ * Function checkExpectations will check if the expectations on given value are met
2392
+ *
2393
+ * Note: There are two simmilar functions:
2394
+ * - `checkExpectations` which throws an error if the expectations are not met
2395
+ * - `isPassingExpectations` which returns a boolean
2396
+ *
2397
+ * @throws {ExpectError} if the expectations are not met
2398
+ * @returns {void} Nothing
2399
+ */
2400
+ function checkExpectations(expectations, value) {
2401
+ var e_1, _a;
2402
+ try {
2403
+ for (var _b = __values(Object.entries(expectations)), _c = _b.next(); !_c.done; _c = _b.next()) {
2404
+ var _d = __read(_c.value, 2), unit = _d[0], _e = _d[1], max = _e.max, min = _e.min;
2405
+ var amount = CountUtils[unit.toUpperCase()](value);
2406
+ if (min && amount < min) {
2407
+ throw new ExpectError("Expected at least ".concat(min, " ").concat(unit, " but got ").concat(amount));
2408
+ } /* not else */
2409
+ if (max && amount > max) {
2410
+ throw new ExpectError("Expected at most ".concat(max, " ").concat(unit, " but got ").concat(amount));
2411
+ }
2412
+ }
2413
+ }
2414
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
2181
2415
  finally {
2182
2416
  try {
2183
- if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
2417
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
2184
2418
  }
2185
- finally { if (e_2) throw e_2.error; }
2419
+ finally { if (e_1) throw e_1.error; }
2186
2420
  }
2187
- // Note: Detect circular dependencies
2188
- var resovedParameters = promptbook.parameters
2189
- .filter(function (_a) {
2190
- var isInput = _a.isInput;
2191
- return isInput;
2192
- })
2193
- .map(function (_a) {
2194
- var name = _a.name;
2195
- return name;
2196
- });
2197
- var unresovedTemplates = __spreadArray([], __read(promptbook.promptTemplates), false);
2198
- var loopLimit = LOOP_LIMIT;
2199
- var _loop_2 = function () {
2200
- if (loopLimit-- < 0) {
2201
- throw new UnexpectedError('Loop limit reached during detection of circular dependencies in `validatePromptbookJson`');
2202
- }
2203
- var currentlyResovedTemplates = unresovedTemplates.filter(function (template) {
2204
- return template.dependentParameterNames.every(function (name) { return resovedParameters.includes(name); });
2205
- });
2206
- if (currentlyResovedTemplates.length === 0) {
2207
- throw new PromptbookLogicError(spaceTrim(function (block) { return "\n\n Can not resolve some parameters\n It may be circular dependencies\n\n Can not resolve:\n ".concat(block(unresovedTemplates
2208
- .map(function (_a) {
2209
- var resultingParameterName = _a.resultingParameterName, dependentParameterNames = _a.dependentParameterNames;
2210
- return "- {".concat(resultingParameterName, "} depends on ").concat(dependentParameterNames
2211
- .map(function (dependentParameterName) { return "{".concat(dependentParameterName, "}"); })
2212
- .join(', '));
2213
- })
2214
- .join('\n')), "\n\n Resolved:\n ").concat(block(resovedParameters.map(function (name) { return "- {".concat(name, "}"); }).join('\n')), "\n "); }));
2421
+ }
2422
+ /**
2423
+ * Function checkExpectations will check if the expectations on given value are met
2424
+ *
2425
+ * Note: There are two simmilar functions:
2426
+ * - `checkExpectations` which throws an error if the expectations are not met
2427
+ * - `isPassingExpectations` which returns a boolean
2428
+ *
2429
+ * @returns {boolean} True if the expectations are met
2430
+ */
2431
+ function isPassingExpectations(expectations, value) {
2432
+ try {
2433
+ checkExpectations(expectations, value);
2434
+ return true;
2435
+ }
2436
+ catch (error) {
2437
+ if (!(error instanceof ExpectError)) {
2438
+ throw error;
2215
2439
  }
2216
- resovedParameters = __spreadArray(__spreadArray([], __read(resovedParameters), false), __read(currentlyResovedTemplates.map(function (_a) {
2217
- var resultingParameterName = _a.resultingParameterName;
2218
- return resultingParameterName;
2219
- })), false);
2220
- unresovedTemplates = unresovedTemplates.filter(function (template) { return !currentlyResovedTemplates.includes(template); });
2221
- };
2222
- while (unresovedTemplates.length > 0) {
2223
- _loop_2();
2440
+ return false;
2224
2441
  }
2225
- return promptbook;
2226
2442
  }
2227
2443
  /**
2228
- * TODO: [🧠] Work with promptbookVersion
2229
- * TODO: Use here some json-schema, Zod or something similar and change it to:
2230
- * > /**
2231
- * > * Validates PromptbookJson if it is logically valid.
2232
- * > *
2233
- * > * It checks:
2234
- * > * - it has a valid structure
2235
- * > * - ...
2236
- * > ex port function validatePromptbookJson(promptbook: unknown): asserts promptbook is PromptbookJson {
2444
+ * TODO: [💝] Unite object for expecting amount and format
2237
2445
  */
2238
2446
 
2239
2447
  /**
@@ -2755,6 +2963,137 @@ function createPromptbookExecutor(options) {
2755
2963
  * TODO: [🧠][3] transparent = (report intermediate parameters) / opaque execution = (report only output parameters) progress reporting mode
2756
2964
  */
2757
2965
 
2966
+ /**
2967
+ * Multiple LLM Execution Tools is a proxy server that uses multiple execution tools internally and exposes the executor interface externally.
2968
+ *
2969
+ * @see https://github.com/webgptorg/promptbook#multiple-server
2970
+ */
2971
+ var MultipleLlmExecutionTools = /** @class */ (function () {
2972
+ /**
2973
+ * Gets array of execution tools in order of priority
2974
+ */
2975
+ function MultipleLlmExecutionTools() {
2976
+ var llmExecutionTools = [];
2977
+ for (var _i = 0; _i < arguments.length; _i++) {
2978
+ llmExecutionTools[_i] = arguments[_i];
2979
+ }
2980
+ this.llmExecutionTools = llmExecutionTools;
2981
+ }
2982
+ /**
2983
+ * Calls the best available chat model
2984
+ */
2985
+ MultipleLlmExecutionTools.prototype.gptChat = function (prompt) {
2986
+ return this.gptCommon(prompt);
2987
+ };
2988
+ /**
2989
+ * Calls the best available completion model
2990
+ */
2991
+ MultipleLlmExecutionTools.prototype.gptComplete = function (prompt) {
2992
+ return this.gptCommon(prompt);
2993
+ };
2994
+ /**
2995
+ * Calls the best available model
2996
+ */
2997
+ MultipleLlmExecutionTools.prototype.gptCommon = function (prompt) {
2998
+ return __awaiter(this, void 0, void 0, function () {
2999
+ var errors, _a, _b, llmExecutionTools, error_1, e_1_1;
3000
+ var e_1, _c;
3001
+ return __generator(this, function (_d) {
3002
+ switch (_d.label) {
3003
+ case 0:
3004
+ errors = [];
3005
+ _d.label = 1;
3006
+ case 1:
3007
+ _d.trys.push([1, 11, 12, 13]);
3008
+ _a = __values(this.llmExecutionTools), _b = _a.next();
3009
+ _d.label = 2;
3010
+ case 2:
3011
+ if (!!_b.done) return [3 /*break*/, 10];
3012
+ llmExecutionTools = _b.value;
3013
+ _d.label = 3;
3014
+ case 3:
3015
+ _d.trys.push([3, 8, , 9]);
3016
+ if (!(prompt.modelRequirements.modelVariant === 'CHAT')) return [3 /*break*/, 5];
3017
+ return [4 /*yield*/, llmExecutionTools.gptChat(prompt)];
3018
+ case 4: return [2 /*return*/, _d.sent()];
3019
+ case 5:
3020
+ if (!(prompt.modelRequirements.modelVariant === 'COMPLETION')) return [3 /*break*/, 7];
3021
+ return [4 /*yield*/, llmExecutionTools.gptComplete(prompt)];
3022
+ case 6: return [2 /*return*/, _d.sent()];
3023
+ case 7: return [3 /*break*/, 9];
3024
+ case 8:
3025
+ error_1 = _d.sent();
3026
+ if (!(error_1 instanceof Error)) {
3027
+ throw error_1;
3028
+ }
3029
+ errors.push(error_1);
3030
+ return [3 /*break*/, 9];
3031
+ case 9:
3032
+ _b = _a.next();
3033
+ return [3 /*break*/, 2];
3034
+ case 10: return [3 /*break*/, 13];
3035
+ case 11:
3036
+ e_1_1 = _d.sent();
3037
+ e_1 = { error: e_1_1 };
3038
+ return [3 /*break*/, 13];
3039
+ case 12:
3040
+ try {
3041
+ if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
3042
+ }
3043
+ finally { if (e_1) throw e_1.error; }
3044
+ return [7 /*endfinally*/];
3045
+ case 13: throw new Error(spaceTrim$1(function (block) { return "\n All execution tools failed:\n \n ".concat(block(errors.map(function (error) { return "- ".concat(error.name || 'Error', ": ").concat(error.message); }).join('\n')), "\n \n "); }));
3046
+ }
3047
+ });
3048
+ });
3049
+ };
3050
+ /**
3051
+ * List all available models that can be used
3052
+ * This liost is a combination of all available models from all execution tools
3053
+ */
3054
+ MultipleLlmExecutionTools.prototype.listModels = function () {
3055
+ return __awaiter(this, void 0, void 0, function () {
3056
+ var availableModels, _a, _b, llmExecutionTools, models, e_2_1;
3057
+ var e_2, _c;
3058
+ return __generator(this, function (_d) {
3059
+ switch (_d.label) {
3060
+ case 0:
3061
+ availableModels = [];
3062
+ _d.label = 1;
3063
+ case 1:
3064
+ _d.trys.push([1, 6, 7, 8]);
3065
+ _a = __values(this.llmExecutionTools), _b = _a.next();
3066
+ _d.label = 2;
3067
+ case 2:
3068
+ if (!!_b.done) return [3 /*break*/, 5];
3069
+ llmExecutionTools = _b.value;
3070
+ return [4 /*yield*/, llmExecutionTools.listModels()];
3071
+ case 3:
3072
+ models = _d.sent();
3073
+ availableModels.push.apply(availableModels, __spreadArray([], __read(models), false));
3074
+ _d.label = 4;
3075
+ case 4:
3076
+ _b = _a.next();
3077
+ return [3 /*break*/, 2];
3078
+ case 5: return [3 /*break*/, 8];
3079
+ case 6:
3080
+ e_2_1 = _d.sent();
3081
+ e_2 = { error: e_2_1 };
3082
+ return [3 /*break*/, 8];
3083
+ case 7:
3084
+ try {
3085
+ if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
3086
+ }
3087
+ finally { if (e_2) throw e_2.error; }
3088
+ return [7 /*endfinally*/];
3089
+ case 8: return [2 /*return*/, availableModels];
3090
+ }
3091
+ });
3092
+ });
3093
+ };
3094
+ return MultipleLlmExecutionTools;
3095
+ }());
3096
+
2758
3097
  /**
2759
3098
  * Delagates the user interaction to a async callback function
2760
3099
  * You need to provide your own implementation of this callback function and its bind to UI.
@@ -2816,6 +3155,19 @@ var SimplePromptInterfaceTools = /** @class */ (function () {
2816
3155
  return SimplePromptInterfaceTools;
2817
3156
  }());
2818
3157
 
3158
+ /**
3159
+ * Detects if the code is running in a browser environment in main thread (Not in a web worker)
3160
+ */
3161
+ new Function("\n try {\n return this === window;\n } catch (e) {\n return false;\n }\n");
3162
+ /**
3163
+ * Detects if the code is running in a Node.js environment
3164
+ */
3165
+ var isRunningInNode = new Function("\n try {\n return this === global;\n } catch (e) {\n return false;\n }\n");
3166
+ /**
3167
+ * Detects if the code is running in a web worker
3168
+ */
3169
+ new Function("\n try {\n if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {\n return true;\n } else {\n return false;\n }\n } catch (e) {\n return false;\n }\n");
3170
+
2819
3171
  /**
2820
3172
  * This error indicates that promptbook not found in the library
2821
3173
  */
@@ -3044,6 +3396,37 @@ function createPromptbookLibraryFromPromise(promptbookSourcesPromiseOrFactory) {
3044
3396
  * TODO: [🍓][🚯] !!! Add to README and samples + maybe make `@promptbook/library` package
3045
3397
  */
3046
3398
 
3399
+ /**
3400
+ * Constructs Promptbook from given directory
3401
+ *
3402
+ * Note: Works only in Node.js environment because it reads the file system
3403
+ * Note: The function does NOT return promise it returns the library directly which dynamically loads promptbooks when needed
3404
+ * SO during the construction syntax and logic sources IS NOT validated
3405
+ *
3406
+ * @param path - path to the directory with promptbooks
3407
+ * @param options - Misc options for the library
3408
+ * @returns PromptbookLibrary
3409
+ */
3410
+ function createPromptbookLibraryFromDirectory(path, options) {
3411
+ var _this = this;
3412
+ if (!isRunningInNode()) {
3413
+ throw new Error('Function `createPromptbookLibraryFromDirectory` can only be run in Node.js environment because it reads the file system.');
3414
+ }
3415
+ var _a = (options || {}).isRecursive, isRecursive = _a === void 0 ? true : _a;
3416
+ return createPromptbookLibraryFromPromise(function () { return __awaiter(_this, void 0, void 0, function () {
3417
+ return __generator(this, function (_a) {
3418
+ //const { readdir } = await import('fs/promises');
3419
+ //const readdirResult = await readdir(path);
3420
+ // TODO: !!! Implement
3421
+ console.info('createPromptbookLibraryFromDirectory', { path: path, isRecursive: isRecursive /*, readdirResult/*/ });
3422
+ throw new Error('Not implemented yet');
3423
+ });
3424
+ }); });
3425
+ }
3426
+ /***
3427
+ * TODO: [🍓][🚯] !!! Add to README and samples + maybe make `@promptbook/library` package
3428
+ */
3429
+
3047
3430
  /**
3048
3431
  * Creates PromptbookLibrary as a subset of another PromptbookLibrary
3049
3432
  *
@@ -3126,5 +3509,322 @@ function createPromptbookSublibrary(library, predicate) {
3126
3509
  * TODO: [🍓][🚯] !!! Add to README and samples + maybe make `@promptbook/library` package
3127
3510
  */
3128
3511
 
3129
- export { CallbackInterfaceTools, ExecutionTypes, PROMPTBOOK_VERSION, SimplePromptInterfaceTools, SimplePromptbookLibrary, createPromptbookExecutor, createPromptbookLibraryFromPromise, createPromptbookLibraryFromSources, createPromptbookSublibrary, promptbookJsonToString, promptbookStringToJson, validatePromptbookJson };
3512
+ /**
3513
+ * Format either small or big number
3514
+ *
3515
+ * @private within the library
3516
+ */
3517
+ function formatNumber(value) {
3518
+ if (value === 0) {
3519
+ return '0';
3520
+ }
3521
+ for (var exponent = 0; exponent < 15; exponent++) {
3522
+ var factor = Math.pow(10, exponent);
3523
+ var valueRounded = Math.round(value * factor) / factor;
3524
+ if (Math.abs(value - valueRounded) / value <
3525
+ 0.001 /* <- TODO: Pass as option, pass to executionReportJsonToString as option */) {
3526
+ return valueRounded.toFixed(exponent);
3527
+ }
3528
+ }
3529
+ return value.toString();
3530
+ }
3531
+
3532
+ /**
3533
+ * Returns the same value that is passed as argument.
3534
+ * No side effects.
3535
+ *
3536
+ * Note: It can be usefull for leveling indentation
3537
+ *
3538
+ * @param value any values
3539
+ * @returns the same values
3540
+ */
3541
+ function just(value) {
3542
+ if (value === undefined) {
3543
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3544
+ return undefined;
3545
+ }
3546
+ return value;
3547
+ }
3548
+
3549
+ /**
3550
+ * Create a markdown table from a 2D array of strings
3551
+ *
3552
+ * @private within the library
3553
+ */
3554
+ function createMarkdownTable(table) {
3555
+ var columnWidths = table.reduce(function (widths, row) {
3556
+ row.forEach(function (cell, columnIndex) {
3557
+ var cellLength = cell.length;
3558
+ if (!widths[columnIndex] || cellLength > widths[columnIndex]) {
3559
+ widths[columnIndex] = cellLength;
3560
+ }
3561
+ });
3562
+ return widths;
3563
+ }, []);
3564
+ var header = "| ".concat(table[0]
3565
+ .map(function (cell, columnIndex) { return cell.padEnd(columnWidths[columnIndex]); })
3566
+ .join(' | '), " |");
3567
+ var separator = "|".concat(columnWidths.map(function (width) { return '-'.repeat(width + 2); }).join('|'), "|");
3568
+ var rows = table.slice(1).map(function (row) {
3569
+ var paddedRow = row.map(function (cell, columnIndex) {
3570
+ return cell.padEnd(columnWidths[columnIndex]);
3571
+ });
3572
+ return "| ".concat(paddedRow.join(' | '), " |");
3573
+ });
3574
+ return __spreadArray([header, separator], __read(rows), false).join('\n');
3575
+ }
3576
+
3577
+ /**
3578
+ * Function createMarkdownChart will draw a chart in markdown from ⬛+🟦 tiles
3579
+ *
3580
+ * @private within the library
3581
+ */
3582
+ function createMarkdownChart(options) {
3583
+ var e_1, _a;
3584
+ var nameHeader = options.nameHeader, valueHeader = options.valueHeader, items = options.items, width = options.width, unitName = options.unitName;
3585
+ var from = Math.min.apply(Math, __spreadArray([], __read(items.map(function (item) { return item.from; })), false));
3586
+ var to = Math.max.apply(Math, __spreadArray([], __read(items.map(function (item) { return item.to; })), false));
3587
+ var scale = width / (to - from);
3588
+ var table = [[nameHeader, valueHeader]];
3589
+ try {
3590
+ for (var items_1 = __values(items), items_1_1 = items_1.next(); !items_1_1.done; items_1_1 = items_1.next()) {
3591
+ var item = items_1_1.value;
3592
+ var before = Math.round((item.from - from) * scale);
3593
+ var during = Math.round((item.to - item.from) * scale);
3594
+ var after = width - before - during;
3595
+ table.push([removeEmojis(item.title).trim(), '░'.repeat(before) + '█'.repeat(during) + '░'.repeat(after)]);
3596
+ }
3597
+ }
3598
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
3599
+ finally {
3600
+ try {
3601
+ if (items_1_1 && !items_1_1.done && (_a = items_1.return)) _a.call(items_1);
3602
+ }
3603
+ finally { if (e_1) throw e_1.error; }
3604
+ }
3605
+ var legend = "_Note: Each \u2588 represents ".concat(formatNumber(1 / scale), " ").concat(unitName, ", width of ").concat(valueHeader.toLowerCase(), " is ").concat(formatNumber(to - from), " ").concat(unitName, " = ").concat(width, " squares_");
3606
+ return createMarkdownTable(table) + '\n\n' + legend;
3607
+ }
3608
+ /**
3609
+ * TODO: Maybe use Mermain Gant Diagrams
3610
+ * @see https://jojozhuang.github.io/tutorial/mermaid-cheat-sheet/
3611
+ */
3612
+
3613
+ /**
3614
+ * Function escapeMarkdownBlock will escape markdown block if needed
3615
+ * It is useful when you want have block in block
3616
+ */
3617
+ function escapeMarkdownBlock(value) {
3618
+ return value.replace(/```/g, '\\`\\`\\`');
3619
+ }
3620
+
3621
+ /**
3622
+ * Default options for generating an execution report string
3623
+ */
3624
+ var ExecutionReportStringOptionsDefaults = {
3625
+ taxRate: 0,
3626
+ chartsWidth: 36,
3627
+ };
3628
+
3629
+ /**
3630
+ * The thresholds for the relative time in the `moment` library.
3631
+ *
3632
+ * @see https://momentjscom.readthedocs.io/en/latest/moment/07-customization/13-relative-time-threshold/
3633
+ */
3634
+ var MOMENT_ARG_THRESHOLDS = {
3635
+ ss: 3, // <- least number of seconds to be counted in seconds, minus 1. Must be set after setting the `s` unit or without setting the `s` unit.
3636
+ };
3637
+
3638
+ /**
3639
+ * Count the duration of working time
3640
+ *
3641
+ * @private within the library
3642
+ */
3643
+ function countWorkingDuration(items) {
3644
+ var e_1, _a;
3645
+ var steps = Array.from(new Set(items.flatMap(function (item) { return [item.from, item.to]; })));
3646
+ steps.sort(function (a, b) { return a - b; });
3647
+ var intervals = steps.map(function (step, index) { return [step, steps[index + 1] || 0]; }).slice(0, -1);
3648
+ var duration = 0;
3649
+ var _loop_1 = function (interval) {
3650
+ var _b = __read(interval, 2), from = _b[0], to = _b[1];
3651
+ if (items.some(function (item) { return item.from < to && item.to > from; })) {
3652
+ duration += to - from;
3653
+ }
3654
+ };
3655
+ try {
3656
+ for (var intervals_1 = __values(intervals), intervals_1_1 = intervals_1.next(); !intervals_1_1.done; intervals_1_1 = intervals_1.next()) {
3657
+ var interval = intervals_1_1.value;
3658
+ _loop_1(interval);
3659
+ }
3660
+ }
3661
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
3662
+ finally {
3663
+ try {
3664
+ if (intervals_1_1 && !intervals_1_1.done && (_a = intervals_1.return)) _a.call(intervals_1);
3665
+ }
3666
+ finally { if (e_1) throw e_1.error; }
3667
+ }
3668
+ return duration;
3669
+ }
3670
+
3671
+ /**
3672
+ * Converts execution report from JSON to string format
3673
+ */
3674
+ function executionReportJsonToString(executionReportJson, options) {
3675
+ var e_1, _a;
3676
+ var _b, _c, _d, _e, _f, _g;
3677
+ var _h = __assign(__assign({}, ExecutionReportStringOptionsDefaults), (options || {})), taxRate = _h.taxRate, chartsWidth = _h.chartsWidth;
3678
+ var executionReportString = spaceTrim(function (block) { return "\n # ".concat(executionReportJson.title || 'Execution report', "\n\n ").concat(block(executionReportJson.description || ''), "\n "); });
3679
+ var headerList = [];
3680
+ if (executionReportJson.promptbookUrl) {
3681
+ headerList.push("PROMPTBOOK URL ".concat(executionReportJson.promptbookUrl));
3682
+ }
3683
+ headerList.push("PROMPTBOOK VERSION ".concat(executionReportJson.promptbookUsedVersion) +
3684
+ (!executionReportJson.promptbookRequestedVersion
3685
+ ? ''
3686
+ : " *(requested ".concat(executionReportJson.promptbookRequestedVersion, ")*")));
3687
+ if (executionReportJson.promptExecutions.length !== 0) {
3688
+ // TODO: What if startedAt OR/AND completedAt is not defined?
3689
+ var startedAt = moment(Math.min.apply(Math, __spreadArray([], __read(executionReportJson.promptExecutions
3690
+ .filter(function (promptExecution) { var _a, _b; return (_b = (_a = promptExecution.result) === null || _a === void 0 ? void 0 : _a.timing) === null || _b === void 0 ? void 0 : _b.start; })
3691
+ .map(function (promptExecution) { return moment(promptExecution.result.timing.start).valueOf(); })), false)));
3692
+ var completedAt = moment(Math.max.apply(Math, __spreadArray([], __read(executionReportJson.promptExecutions
3693
+ .filter(function (promptExecution) { var _a, _b; return (_b = (_a = promptExecution.result) === null || _a === void 0 ? void 0 : _a.timing) === null || _b === void 0 ? void 0 : _b.complete; })
3694
+ .map(function (promptExecution) { return moment(promptExecution.result.timing.complete).valueOf(); })), false)));
3695
+ var timingItems = executionReportJson.promptExecutions.map(function (promptExecution) {
3696
+ var _a, _b, _c, _d;
3697
+ return ({
3698
+ title: promptExecution.prompt.title,
3699
+ from: moment((_b = (_a = promptExecution.result) === null || _a === void 0 ? void 0 : _a.timing) === null || _b === void 0 ? void 0 : _b.start).valueOf() / 1000,
3700
+ to: moment((_d = (_c = promptExecution.result) === null || _c === void 0 ? void 0 : _c.timing) === null || _d === void 0 ? void 0 : _d.complete).valueOf() / 1000,
3701
+ });
3702
+ });
3703
+ var costItems = executionReportJson.promptExecutions
3704
+ .filter(function (promptExecution) { var _a, _b; return typeof ((_b = (_a = promptExecution.result) === null || _a === void 0 ? void 0 : _a.usage) === null || _b === void 0 ? void 0 : _b.price) === 'number'; })
3705
+ .map(function (promptExecution) {
3706
+ var _a, _b;
3707
+ return ({
3708
+ title: promptExecution.prompt.title,
3709
+ from: 0,
3710
+ to: ((_b = (_a = promptExecution.result) === null || _a === void 0 ? void 0 : _a.usage) === null || _b === void 0 ? void 0 : _b.price) * (1 + taxRate),
3711
+ });
3712
+ });
3713
+ var duration = moment.duration(completedAt.diff(startedAt));
3714
+ var llmDuration = moment.duration(countWorkingDuration(timingItems) * 1000);
3715
+ var executionsWithKnownCost = executionReportJson.promptExecutions.filter(function (promptExecution) { var _a, _b; return (((_b = (_a = promptExecution.result) === null || _a === void 0 ? void 0 : _a.usage) === null || _b === void 0 ? void 0 : _b.price) || 'UNKNOWN') !== 'UNKNOWN'; });
3716
+ var cost = executionsWithKnownCost.reduce(function (cost, promptExecution) { return cost + (promptExecution.result.usage.price || 0); }, 0);
3717
+ headerList.push("STARTED AT ".concat(moment(startedAt).format("YYYY-MM-DD HH:mm:ss")));
3718
+ headerList.push("COMPLETED AT ".concat(moment(completedAt).format("YYYY-MM-DD HH:mm:ss")));
3719
+ headerList.push("TOTAL DURATION ".concat(duration.humanize(MOMENT_ARG_THRESHOLDS)));
3720
+ headerList.push("TOTAL LLM DURATION ".concat(llmDuration.humanize(MOMENT_ARG_THRESHOLDS)));
3721
+ headerList.push("TOTAL COST $".concat(formatNumber(cost * (1 + taxRate))) +
3722
+ (executionsWithKnownCost.length === executionReportJson.promptExecutions.length
3723
+ ? ''
3724
+ : " *(Some cost is unknown)*") +
3725
+ (taxRate !== 0 ? " *(with tax ".concat(taxRate * 100, "%)*") : ''));
3726
+ executionReportString += '\n\n' + headerList.map(function (header) { return "- ".concat(header); }).join('\n');
3727
+ executionReportString +=
3728
+ '\n\n' +
3729
+ '## 🗃 Index' +
3730
+ '\n\n' +
3731
+ executionReportJson.promptExecutions
3732
+ .map(function (promptExecution) {
3733
+ // TODO: Make some better system to convert hedings to links
3734
+ var hash = normalizeToKebabCase(promptExecution.prompt.title);
3735
+ if (/^\s*\p{Extended_Pictographic}/u.test(promptExecution.prompt.title)) {
3736
+ hash = '-' + hash;
3737
+ }
3738
+ // TODO: Make working hash link for the template in md + pdf
3739
+ return "- [".concat(promptExecution.prompt.title, "](#").concat(hash, ")");
3740
+ })
3741
+ .join('\n');
3742
+ executionReportString +=
3743
+ '\n\n' +
3744
+ '## ⌚ Time chart' +
3745
+ '\n\n' +
3746
+ createMarkdownChart({
3747
+ nameHeader: 'Template',
3748
+ valueHeader: 'Timeline',
3749
+ items: timingItems,
3750
+ width: chartsWidth,
3751
+ unitName: 'seconds',
3752
+ });
3753
+ executionReportString +=
3754
+ '\n\n' +
3755
+ '## 💸 Cost chart' +
3756
+ '\n\n' +
3757
+ createMarkdownChart({
3758
+ nameHeader: 'Template',
3759
+ valueHeader: 'Cost',
3760
+ items: costItems,
3761
+ width: chartsWidth,
3762
+ unitName: 'USD',
3763
+ });
3764
+ }
3765
+ else {
3766
+ headerList.push("TOTAL COST $0 *(Nothing executed)*");
3767
+ }
3768
+ var _loop_1 = function (promptExecution) {
3769
+ executionReportString += '\n\n\n\n' + "## ".concat(promptExecution.prompt.title);
3770
+ var templateList = [];
3771
+ // TODO: What if startedAt OR/AND completedAt is not defined?
3772
+ var startedAt = moment((_c = (_b = promptExecution.result) === null || _b === void 0 ? void 0 : _b.timing) === null || _c === void 0 ? void 0 : _c.start);
3773
+ var completedAt = moment((_e = (_d = promptExecution.result) === null || _d === void 0 ? void 0 : _d.timing) === null || _e === void 0 ? void 0 : _e.complete);
3774
+ var duration = moment.duration(completedAt.diff(startedAt));
3775
+ // Not need here:
3776
+ // > templateList.push(`STARTED AT ${moment(startedAt).calendar()}`);
3777
+ templateList.push("DURATION ".concat(duration.humanize(MOMENT_ARG_THRESHOLDS)));
3778
+ if (typeof ((_g = (_f = promptExecution.result) === null || _f === void 0 ? void 0 : _f.usage) === null || _g === void 0 ? void 0 : _g.price) === 'number') {
3779
+ templateList.push("COST $".concat(formatNumber(promptExecution.result.usage.price * (1 + taxRate))) +
3780
+ (taxRate !== 0 ? " *(with tax ".concat(taxRate * 100, "%)*") : ''));
3781
+ }
3782
+ else {
3783
+ templateList.push("COST UNKNOWN");
3784
+ }
3785
+ executionReportString += '\n\n' + templateList.map(function (header) { return "- ".concat(header); }).join('\n');
3786
+ /*
3787
+ - MODEL VARIANT ${promptExecution.prompt.modelRequirements.modelVariant}
3788
+ - MODEL NAME \`${promptExecution.result?.model}\` (requested \`${
3789
+ promptExecution.prompt.modelRequirements.modelName
3790
+
3791
+ */
3792
+ if (just(true)) {
3793
+ executionReportString +=
3794
+ '\n\n\n\n' +
3795
+ spaceTrim(function (block) { return "\n\n ### Prompt\n\n ```\n ".concat(block(escapeMarkdownBlock(promptExecution.prompt.content)), "\n ```\n\n "); });
3796
+ }
3797
+ if (promptExecution.result && promptExecution.result.content) {
3798
+ executionReportString +=
3799
+ '\n\n\n\n' +
3800
+ spaceTrim(function (block) { return "\n\n ### Result\n\n ```\n ".concat(block(escapeMarkdownBlock(promptExecution.result.content)), "\n ```\n "); });
3801
+ }
3802
+ if (promptExecution.error && promptExecution.error.message) {
3803
+ executionReportString +=
3804
+ '\n\n\n\n' +
3805
+ spaceTrim(function (block) { return "\n\n ### Error\n\n ```\n ".concat(block(escapeMarkdownBlock(promptExecution.error.message)), "\n ```\n\n "); });
3806
+ }
3807
+ };
3808
+ try {
3809
+ for (var _j = __values(executionReportJson.promptExecutions), _k = _j.next(); !_k.done; _k = _j.next()) {
3810
+ var promptExecution = _k.value;
3811
+ _loop_1(promptExecution);
3812
+ }
3813
+ }
3814
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
3815
+ finally {
3816
+ try {
3817
+ if (_k && !_k.done && (_a = _j.return)) _a.call(_j);
3818
+ }
3819
+ finally { if (e_1) throw e_1.error; }
3820
+ }
3821
+ executionReportString = prettifyMarkdown(executionReportString);
3822
+ return executionReportString;
3823
+ }
3824
+ /**
3825
+ * TODO: Add mermaid chart for every report
3826
+ * TODO: [🧠] Allow to filter out some parts of the report by options
3827
+ */
3828
+
3829
+ export { CallbackInterfaceTools, ExecutionReportStringOptionsDefaults, ExecutionTypes, MultipleLlmExecutionTools, PROMPTBOOK_VERSION, SimplePromptInterfaceTools, SimplePromptbookLibrary, assertsExecutionSuccessful, checkExpectations, createPromptbookExecutor, createPromptbookLibraryFromDirectory, createPromptbookLibraryFromPromise, createPromptbookLibraryFromSources, createPromptbookSublibrary, executionReportJsonToString, isPassingExpectations, prettifyPromptbookString, promptbookJsonToString, promptbookStringToJson, validatePromptbookJson };
3130
3830
  //# sourceMappingURL=index.es.js.map