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