@promptbook/core 0.52.0-3 → 0.52.0-30

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 (52) hide show
  1. package/README.md +1 -3
  2. package/esm/index.es.js +1148 -340
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/_packages/core.index.d.ts +15 -6
  5. package/esm/typings/_packages/utils.index.d.ts +5 -8
  6. package/esm/typings/execution/ExecutionTools.d.ts +5 -3
  7. package/esm/typings/execution/plugins/llm-execution-tools/anthropic-claude/AnthropicClaudeExecutionTools.d.ts +0 -1
  8. package/esm/typings/execution/plugins/llm-execution-tools/azure-openai/AzureOpenAiExecutionTools.d.ts +0 -1
  9. package/esm/typings/execution/plugins/llm-execution-tools/langtail/LangtailExecutionTools.d.ts +0 -3
  10. package/esm/typings/execution/plugins/llm-execution-tools/openai/OpenAiExecutionTools.d.ts +1 -1
  11. package/esm/typings/execution/plugins/llm-execution-tools/remote/RemoteLlmExecutionTools.d.ts +1 -1
  12. package/esm/typings/execution/plugins/script-execution-tools/javascript/JavascriptEvalExecutionTools.d.ts +1 -1
  13. package/esm/typings/execution/plugins/script-execution-tools/javascript/JavascriptExecutionTools.d.ts +4 -17
  14. package/esm/typings/execution/utils/forEachAsync.d.ts +18 -0
  15. package/esm/typings/library/constructors/createPromptbookLibraryFromDirectory.d.ts +36 -4
  16. package/esm/typings/library/constructors/createPromptbookLibraryFromDirectory.test.d.ts +1 -0
  17. package/esm/typings/library/constructors/createPromptbookLibraryFromPromise.d.ts +2 -2
  18. package/esm/typings/library/constructors/createPromptbookLibraryFromPromise.test.d.ts +1 -0
  19. package/esm/typings/library/constructors/createPromptbookLibraryFromSources.test.d.ts +1 -0
  20. package/esm/typings/library/constructors/createPromptbookLibraryFromUrl.d.ts +21 -5
  21. package/esm/typings/library/constructors/justTestFsImport.d.ts +7 -0
  22. package/esm/typings/types/Prompt.d.ts +1 -1
  23. package/esm/typings/types/typeAliases.d.ts +2 -2
  24. package/package.json +3 -2
  25. package/umd/index.umd.js +1154 -338
  26. package/umd/index.umd.js.map +1 -1
  27. package/umd/typings/_packages/core.index.d.ts +15 -6
  28. package/umd/typings/_packages/utils.index.d.ts +5 -8
  29. package/umd/typings/execution/ExecutionTools.d.ts +5 -3
  30. package/umd/typings/execution/plugins/llm-execution-tools/anthropic-claude/AnthropicClaudeExecutionTools.d.ts +0 -1
  31. package/umd/typings/execution/plugins/llm-execution-tools/azure-openai/AzureOpenAiExecutionTools.d.ts +0 -1
  32. package/umd/typings/execution/plugins/llm-execution-tools/langtail/LangtailExecutionTools.d.ts +0 -3
  33. package/umd/typings/execution/plugins/llm-execution-tools/openai/OpenAiExecutionTools.d.ts +1 -1
  34. package/umd/typings/execution/plugins/llm-execution-tools/remote/RemoteLlmExecutionTools.d.ts +1 -1
  35. package/umd/typings/execution/plugins/script-execution-tools/javascript/JavascriptEvalExecutionTools.d.ts +1 -1
  36. package/umd/typings/execution/plugins/script-execution-tools/javascript/JavascriptExecutionTools.d.ts +4 -17
  37. package/umd/typings/execution/utils/forEachAsync.d.ts +18 -0
  38. package/umd/typings/library/constructors/createPromptbookLibraryFromDirectory.d.ts +36 -4
  39. package/umd/typings/library/constructors/createPromptbookLibraryFromDirectory.test.d.ts +1 -0
  40. package/umd/typings/library/constructors/createPromptbookLibraryFromPromise.d.ts +2 -2
  41. package/umd/typings/library/constructors/createPromptbookLibraryFromPromise.test.d.ts +1 -0
  42. package/umd/typings/library/constructors/createPromptbookLibraryFromSources.test.d.ts +1 -0
  43. package/umd/typings/library/constructors/createPromptbookLibraryFromUrl.d.ts +21 -5
  44. package/umd/typings/library/constructors/justTestFsImport.d.ts +7 -0
  45. package/umd/typings/types/Prompt.d.ts +1 -1
  46. package/umd/typings/types/typeAliases.d.ts +2 -2
  47. package/esm/typings/_packages/wizzard.index.d.ts +0 -5
  48. package/esm/typings/wizzard/Wizzard.d.ts +0 -4
  49. package/esm/typings/wizzard/sample.d.ts +0 -6
  50. package/umd/typings/_packages/wizzard.index.d.ts +0 -5
  51. package/umd/typings/wizzard/Wizzard.d.ts +0 -4
  52. package/umd/typings/wizzard/sample.d.ts +0 -6
package/umd/index.umd.js CHANGED
@@ -1,13 +1,14 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('spacetrim'), require('prettier'), require('prettier/parser-html'), require('moment')) :
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';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('spacetrim'), require('prettier'), require('prettier/parser-html'), require('path'), require('moment')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'spacetrim', 'prettier', 'prettier/parser-html', 'path', 'moment'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-core"] = {}, global.spaceTrim, global.prettier, global.parserHtml, global.path, global.moment));
5
+ })(this, (function (exports, spaceTrim, prettier, parserHtml, path, 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.52.0-2';
457
+ var PROMPTBOOK_VERSION = '0.52.0-29';
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,15 +1296,70 @@
1336
1296
  return normalizedName;
1337
1297
  }
1338
1298
 
1339
- /**
1340
- * Execution type describes the way how the block is executed
1341
- *
1342
- * @see https://github.com/webgptorg/promptbook#execution-type
1343
- */
1344
- var ExecutionTypes = [
1345
- 'PROMPT_TEMPLATE',
1346
- 'SIMPLE_TEMPLATE',
1347
- 'SCRIPT',
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
+
1354
+ /**
1355
+ * Execution type describes the way how the block is executed
1356
+ *
1357
+ * @see https://github.com/webgptorg/promptbook#execution-type
1358
+ */
1359
+ var ExecutionTypes = [
1360
+ 'PROMPT_TEMPLATE',
1361
+ 'SIMPLE_TEMPLATE',
1362
+ 'SCRIPT',
1348
1363
  'PROMPT_DIALOG',
1349
1364
  // <- [🥻] Insert here when making new command
1350
1365
  ];
@@ -1816,6 +1831,9 @@
1816
1831
  postprocessing = undefined;
1817
1832
  }
1818
1833
  dependentParameterNames = union(dependentParameterNames, extractParametersFromPromptTemplate(__assign(__assign({}, section), { description: description_1, executionType: executionType, content: content })));
1834
+ if (templateModelRequirements.modelVariant === undefined) {
1835
+ templateModelRequirements.modelVariant = 'CHAT';
1836
+ }
1819
1837
  promptbookJson.promptTemplates.push({
1820
1838
  name: titleToName(section.title),
1821
1839
  title: section.title,
@@ -1854,6 +1872,87 @@
1854
1872
  * TODO: [🧠] Parameter flags - isInput, isOutput, isInternal
1855
1873
  */
1856
1874
 
1875
+ /**
1876
+ * Add or modify an auto-generated section in a markdown file
1877
+ *
1878
+ * @private within the library
1879
+ */
1880
+ function addAutoGeneratedSection(content, options) {
1881
+ var sectionName = options.sectionName, sectionContent = options.sectionContent;
1882
+ var warningLine = "<!-- \u26A0\uFE0F WARNING: This section was auto-generated -->";
1883
+ var sectionRegex = new RegExp("<!--".concat(sectionName, "-->([\\s\\S]*?)<!--/").concat(sectionName, "-->"), 'g');
1884
+ var sectionMatch = content.match(sectionRegex);
1885
+ if (sectionMatch) {
1886
+ return content.replace(sectionRegex, spaceTrim.spaceTrim(function (block) { return "\n <!--".concat(sectionName, "-->\n ").concat(block(warningLine), "\n ").concat(block(sectionContent), "\n <!--/").concat(sectionName, "-->\n "); }));
1887
+ }
1888
+ var placeForSection = removeContentComments(content).match(/^##.*$/im);
1889
+ if (!placeForSection) {
1890
+ throw new Error("No place where to put the section <!--".concat(sectionName, "-->"));
1891
+ }
1892
+ var _a = __read(placeForSection, 1), heading = _a[0];
1893
+ return content.replace(heading, "<!--".concat(sectionName, "-->\n").concat(warningLine, "\n").concat(sectionContent, "\n<!--/").concat(sectionName, "-->\n\n").concat(heading));
1894
+ }
1895
+
1896
+ /**
1897
+ * Prettify the html code
1898
+ *
1899
+ * @param content raw html code
1900
+ * @returns formatted html code
1901
+ */
1902
+ function prettifyMarkdown(content) {
1903
+ try {
1904
+ return prettier.format(content, {
1905
+ parser: 'markdown',
1906
+ plugins: [parserHtml__default["default"]],
1907
+ // TODO: DRY - make some import or auto-copy of .prettierrc
1908
+ endOfLine: 'lf',
1909
+ tabWidth: 4,
1910
+ singleQuote: true,
1911
+ trailingComma: 'all',
1912
+ arrowParens: 'always',
1913
+ printWidth: 120,
1914
+ htmlWhitespaceSensitivity: 'ignore',
1915
+ jsxBracketSameLine: false,
1916
+ bracketSpacing: true,
1917
+ });
1918
+ }
1919
+ catch (error) {
1920
+ console.error('There was an error with prettifying the markdown, using the original as the fallback', {
1921
+ error: error,
1922
+ html: content,
1923
+ });
1924
+ return content;
1925
+ }
1926
+ }
1927
+
1928
+ /**
1929
+ * Prettyfies Promptbook string and adds Mermaid graph
1930
+ */
1931
+ function prettifyPromptbookString(promptbookString, options) {
1932
+ var isGraphAdded = options.isGraphAdded, isPrettifyed = options.isPrettifyed;
1933
+ if (isGraphAdded) {
1934
+ var promptbookJson = promptbookStringToJson(promptbookString);
1935
+ var promptbookMermaid_1 = renderPromptbookMermaid(promptbookJson, {
1936
+ linkPromptTemplate: function (promptTemplate) {
1937
+ return { href: "#".concat(promptTemplate.name), title: promptTemplate.title };
1938
+ },
1939
+ });
1940
+ var promptbookMermaidBlock = spaceTrim.spaceTrim(function (block) { return "\n ```mermaid\n ".concat(block(promptbookMermaid_1), "\n ```\n "); });
1941
+ promptbookString = addAutoGeneratedSection(promptbookString, {
1942
+ sectionName: 'Graph',
1943
+ sectionContent: promptbookMermaidBlock,
1944
+ });
1945
+ }
1946
+ if (isPrettifyed) {
1947
+ promptbookString = prettifyMarkdown(promptbookString);
1948
+ }
1949
+ return promptbookString;
1950
+ }
1951
+ /**
1952
+ * TODO: Maybe use some Mermaid library instead of string templating
1953
+ * TODO: [🕌] When more than 2 functionalities, split into separate functions
1954
+ */
1955
+
1857
1956
  /**
1858
1957
  * Converts promptbook in JSON format to string format
1859
1958
  *
@@ -2080,6 +2179,7 @@
2080
2179
  * @throws {PromptbookLogicError} on logical error in the promptbook
2081
2180
  */
2082
2181
  function validatePromptbookJson(promptbook) {
2182
+ // TODO: [🧠] Maybe test if promptbook is a promise and make specific error case for that
2083
2183
  var e_1, _a, e_2, _b, e_3, _c, e_4, _d;
2084
2184
  if (promptbook.promptbookUrl !== undefined) {
2085
2185
  if (!isValidUrl(promptbook.promptbookUrl)) {
@@ -2087,6 +2187,16 @@
2087
2187
  throw new PromptbookLogicError("Invalid promptbook URL \"".concat(promptbook.promptbookUrl, "\""));
2088
2188
  }
2089
2189
  }
2190
+ // TODO: [🧠] Maybe do here some propper JSON-schema / ZOD checking
2191
+ if (!Array.isArray(promptbook.parameters)) {
2192
+ // TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
2193
+ throw new PromptbookSyntaxError(spaceTrim.spaceTrim("\n Promptbook is valid JSON but with wrong structure\n\n promptbook.parameters expected to be an array, but got ".concat(typeof promptbook.parameters, "\n ")));
2194
+ }
2195
+ // TODO: [🧠] Maybe do here some propper JSON-schema / ZOD checking
2196
+ if (!Array.isArray(promptbook.promptTemplates)) {
2197
+ // TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
2198
+ throw new PromptbookSyntaxError(spaceTrim.spaceTrim("\n Promptbook is valid JSON but with wrong structure\n\n promptbook.promptTemplates expected to be an array, but got ".concat(typeof promptbook.promptTemplates, "\n ")));
2199
+ }
2090
2200
  var _loop_1 = function (parameter) {
2091
2201
  if (parameter.isInput && parameter.isOutput) {
2092
2202
  throw new PromptbookLogicError("Parameter {".concat(parameter.name, "} can not be both input and output"));
@@ -2133,9 +2243,8 @@
2133
2243
  }
2134
2244
  definedParameters.add(template.resultingParameterName);
2135
2245
  if (template.executionType === 'PROMPT_TEMPLATE' &&
2136
- (template.modelRequirements.modelVariant === undefined ||
2137
- template.modelRequirements.modelName === undefined)) {
2138
- throw new PromptbookLogicError(spaceTrim.spaceTrim("\n\n You must specify MODEL VARIANT and MODEL NAME in the prompt template \"".concat(template.title, "\"\n\n For example:\n - MODEL VARIANT Chat\n - MODEL NAME `gpt-4-1106-preview`\n\n ")));
2246
+ (template.modelRequirements.modelVariant === undefined)) {
2247
+ throw new PromptbookLogicError(spaceTrim.spaceTrim("\n\n You must specify MODEL VARIANT in the prompt template \"".concat(template.title, "\"\n\n For example:\n - MODEL VARIANT Chat\n - MODEL NAME `gpt-4-1106-preview`\n\n ")));
2139
2248
  }
2140
2249
  if (template.jokers && template.jokers.length > 0) {
2141
2250
  if (!template.expectFormat &&
@@ -2242,6 +2351,119 @@
2242
2351
  * > ex port function validatePromptbookJson(promptbook: unknown): asserts promptbook is PromptbookJson {
2243
2352
  */
2244
2353
 
2354
+ /**
2355
+ * This error indicates errors during the execution of the promptbook
2356
+ */
2357
+ var PromptbookExecutionError = /** @class */ (function (_super) {
2358
+ __extends(PromptbookExecutionError, _super);
2359
+ function PromptbookExecutionError(message) {
2360
+ var _this = _super.call(this, message) || this;
2361
+ _this.name = 'PromptbookExecutionError';
2362
+ Object.setPrototypeOf(_this, PromptbookExecutionError.prototype);
2363
+ return _this;
2364
+ }
2365
+ return PromptbookExecutionError;
2366
+ }(Error));
2367
+
2368
+ /**
2369
+ * Asserts that the execution of a promptnook is successful
2370
+ *
2371
+ * @param executionResult - The partial result of the promptnook execution
2372
+ * @throws {PromptbookExecutionError} If the execution is not successful or if multiple errors occurred
2373
+ */
2374
+ function assertsExecutionSuccessful(executionResult) {
2375
+ var isSuccessful = executionResult.isSuccessful, errors = executionResult.errors;
2376
+ if (isSuccessful === true) {
2377
+ return;
2378
+ }
2379
+ if (errors.length === 0) {
2380
+ throw new PromptbookExecutionError("Promptnook Execution failed because of unknown reason");
2381
+ }
2382
+ else if (errors.length === 1) {
2383
+ throw errors[0];
2384
+ }
2385
+ else {
2386
+ 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 "); }));
2387
+ }
2388
+ }
2389
+ /**
2390
+ * TODO: [🧠] Can this return type be better typed than void
2391
+ */
2392
+
2393
+ /**
2394
+ * This error occurs when some expectation is not met in the execution of the pipeline
2395
+ *
2396
+ * @private Always catched and rethrown as `PromptbookExecutionError`
2397
+ * Note: This is a kindof subtype of PromptbookExecutionError
2398
+ */
2399
+ var ExpectError = /** @class */ (function (_super) {
2400
+ __extends(ExpectError, _super);
2401
+ function ExpectError(message) {
2402
+ var _this = _super.call(this, message) || this;
2403
+ _this.name = 'ExpectError';
2404
+ Object.setPrototypeOf(_this, ExpectError.prototype);
2405
+ return _this;
2406
+ }
2407
+ return ExpectError;
2408
+ }(Error));
2409
+
2410
+ /**
2411
+ * Function checkExpectations will check if the expectations on given value are met
2412
+ *
2413
+ * Note: There are two simmilar functions:
2414
+ * - `checkExpectations` which throws an error if the expectations are not met
2415
+ * - `isPassingExpectations` which returns a boolean
2416
+ *
2417
+ * @throws {ExpectError} if the expectations are not met
2418
+ * @returns {void} Nothing
2419
+ */
2420
+ function checkExpectations(expectations, value) {
2421
+ var e_1, _a;
2422
+ try {
2423
+ for (var _b = __values(Object.entries(expectations)), _c = _b.next(); !_c.done; _c = _b.next()) {
2424
+ var _d = __read(_c.value, 2), unit = _d[0], _e = _d[1], max = _e.max, min = _e.min;
2425
+ var amount = CountUtils[unit.toUpperCase()](value);
2426
+ if (min && amount < min) {
2427
+ throw new ExpectError("Expected at least ".concat(min, " ").concat(unit, " but got ").concat(amount));
2428
+ } /* not else */
2429
+ if (max && amount > max) {
2430
+ throw new ExpectError("Expected at most ".concat(max, " ").concat(unit, " but got ").concat(amount));
2431
+ }
2432
+ }
2433
+ }
2434
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
2435
+ finally {
2436
+ try {
2437
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
2438
+ }
2439
+ finally { if (e_1) throw e_1.error; }
2440
+ }
2441
+ }
2442
+ /**
2443
+ * Function checkExpectations will check if the expectations on given value are met
2444
+ *
2445
+ * Note: There are two simmilar functions:
2446
+ * - `checkExpectations` which throws an error if the expectations are not met
2447
+ * - `isPassingExpectations` which returns a boolean
2448
+ *
2449
+ * @returns {boolean} True if the expectations are met
2450
+ */
2451
+ function isPassingExpectations(expectations, value) {
2452
+ try {
2453
+ checkExpectations(expectations, value);
2454
+ return true;
2455
+ }
2456
+ catch (error) {
2457
+ if (!(error instanceof ExpectError)) {
2458
+ throw error;
2459
+ }
2460
+ return false;
2461
+ }
2462
+ }
2463
+ /**
2464
+ * TODO: [💝] Unite object for expecting amount and format
2465
+ */
2466
+
2245
2467
  /**
2246
2468
  * Creates executor function from promptbook and execution tools.
2247
2469
  *
@@ -2323,7 +2545,7 @@
2323
2545
  title: currentTemplate.title,
2324
2546
  promptbookUrl: "".concat(promptbook.promptbookUrl
2325
2547
  ? promptbook.promptbookUrl
2326
- : 'anonymous' /* <- [🧠][🈴] How to deal with anonymous PROMPTBOOKs, do here some auto-url like SHA-256 based ad-hoc identifier? */, "#").concat(currentTemplate.name),
2548
+ : 'anonymous' /* <- TODO: [🧠] How to deal with anonymous PROMPTBOOKs, do here some auto-url like SHA-256 based ad-hoc identifier? */, "#").concat(currentTemplate.name),
2327
2549
  parameters: parametersToPass,
2328
2550
  content: replaceParameters(currentTemplate.content, parametersToPass) /* <- [2] */,
2329
2551
  modelRequirements: currentTemplate.modelRequirements,
@@ -2762,47 +2984,178 @@
2762
2984
  */
2763
2985
 
2764
2986
  /**
2765
- * Delagates the user interaction to a async callback function
2766
- * You need to provide your own implementation of this callback function and its bind to UI.
2987
+ * Multiple LLM Execution Tools is a proxy server that uses multiple execution tools internally and exposes the executor interface externally.
2988
+ *
2989
+ * @see https://github.com/webgptorg/promptbook#multiple-server
2767
2990
  */
2768
- var CallbackInterfaceTools = /** @class */ (function () {
2769
- function CallbackInterfaceTools(options) {
2770
- this.options = options;
2991
+ var MultipleLlmExecutionTools = /** @class */ (function () {
2992
+ /**
2993
+ * Gets array of execution tools in order of priority
2994
+ */
2995
+ function MultipleLlmExecutionTools() {
2996
+ var llmExecutionTools = [];
2997
+ for (var _i = 0; _i < arguments.length; _i++) {
2998
+ llmExecutionTools[_i] = arguments[_i];
2999
+ }
3000
+ this.llmExecutionTools = llmExecutionTools;
2771
3001
  }
2772
3002
  /**
2773
- * Trigger the custom callback function
3003
+ * Calls the best available chat model
2774
3004
  */
2775
- CallbackInterfaceTools.prototype.promptDialog = function (options) {
2776
- return __awaiter(this, void 0, void 0, function () {
2777
- var answer;
2778
- return __generator(this, function (_a) {
2779
- switch (_a.label) {
2780
- case 0: return [4 /*yield*/, this.options.callback(options)];
2781
- case 1:
2782
- answer = _a.sent();
2783
- if (this.options.isVerbose) {
2784
- console.info(spaceTrim.spaceTrim(function (block) { return "\n \uD83D\uDCD6 ".concat(block(options.promptTitle), "\n \uD83D\uDC64 ").concat(block(answer), "\n "); }));
2785
- }
2786
- return [2 /*return*/, answer];
2787
- }
2788
- });
2789
- });
3005
+ MultipleLlmExecutionTools.prototype.gptChat = function (prompt) {
3006
+ return this.gptCommon(prompt);
2790
3007
  };
2791
- return CallbackInterfaceTools;
2792
- }());
2793
-
2794
- /**
2795
- * Wrapper around `window.prompt` synchronous function that interacts with the user via browser prompt
2796
- *
2797
- * Warning: It is used for testing and mocking
2798
- * **NOT intended to use in the production** due to its synchronous nature.
2799
- */
2800
- var SimplePromptInterfaceTools = /** @class */ (function () {
2801
- function SimplePromptInterfaceTools(options) {
2802
- this.options = options;
2803
- }
2804
3008
  /**
2805
- * Trigger window.PROMPT DIALOG
3009
+ * Calls the best available completion model
3010
+ */
3011
+ MultipleLlmExecutionTools.prototype.gptComplete = function (prompt) {
3012
+ return this.gptCommon(prompt);
3013
+ };
3014
+ /**
3015
+ * Calls the best available model
3016
+ */
3017
+ MultipleLlmExecutionTools.prototype.gptCommon = function (prompt) {
3018
+ return __awaiter(this, void 0, void 0, function () {
3019
+ var errors, _a, _b, llmExecutionTools, error_1, e_1_1;
3020
+ var e_1, _c;
3021
+ return __generator(this, function (_d) {
3022
+ switch (_d.label) {
3023
+ case 0:
3024
+ errors = [];
3025
+ _d.label = 1;
3026
+ case 1:
3027
+ _d.trys.push([1, 11, 12, 13]);
3028
+ _a = __values(this.llmExecutionTools), _b = _a.next();
3029
+ _d.label = 2;
3030
+ case 2:
3031
+ if (!!_b.done) return [3 /*break*/, 10];
3032
+ llmExecutionTools = _b.value;
3033
+ _d.label = 3;
3034
+ case 3:
3035
+ _d.trys.push([3, 8, , 9]);
3036
+ if (!(prompt.modelRequirements.modelVariant === 'CHAT')) return [3 /*break*/, 5];
3037
+ return [4 /*yield*/, llmExecutionTools.gptChat(prompt)];
3038
+ case 4: return [2 /*return*/, _d.sent()];
3039
+ case 5:
3040
+ if (!(prompt.modelRequirements.modelVariant === 'COMPLETION')) return [3 /*break*/, 7];
3041
+ return [4 /*yield*/, llmExecutionTools.gptComplete(prompt)];
3042
+ case 6: return [2 /*return*/, _d.sent()];
3043
+ case 7: return [3 /*break*/, 9];
3044
+ case 8:
3045
+ error_1 = _d.sent();
3046
+ if (!(error_1 instanceof Error)) {
3047
+ throw error_1;
3048
+ }
3049
+ errors.push(error_1);
3050
+ return [3 /*break*/, 9];
3051
+ case 9:
3052
+ _b = _a.next();
3053
+ return [3 /*break*/, 2];
3054
+ case 10: return [3 /*break*/, 13];
3055
+ case 11:
3056
+ e_1_1 = _d.sent();
3057
+ e_1 = { error: e_1_1 };
3058
+ return [3 /*break*/, 13];
3059
+ case 12:
3060
+ try {
3061
+ if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
3062
+ }
3063
+ finally { if (e_1) throw e_1.error; }
3064
+ return [7 /*endfinally*/];
3065
+ 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 "); }));
3066
+ }
3067
+ });
3068
+ });
3069
+ };
3070
+ /**
3071
+ * List all available models that can be used
3072
+ * This liost is a combination of all available models from all execution tools
3073
+ */
3074
+ MultipleLlmExecutionTools.prototype.listModels = function () {
3075
+ return __awaiter(this, void 0, void 0, function () {
3076
+ var availableModels, _a, _b, llmExecutionTools, models, e_2_1;
3077
+ var e_2, _c;
3078
+ return __generator(this, function (_d) {
3079
+ switch (_d.label) {
3080
+ case 0:
3081
+ availableModels = [];
3082
+ _d.label = 1;
3083
+ case 1:
3084
+ _d.trys.push([1, 6, 7, 8]);
3085
+ _a = __values(this.llmExecutionTools), _b = _a.next();
3086
+ _d.label = 2;
3087
+ case 2:
3088
+ if (!!_b.done) return [3 /*break*/, 5];
3089
+ llmExecutionTools = _b.value;
3090
+ return [4 /*yield*/, llmExecutionTools.listModels()];
3091
+ case 3:
3092
+ models = _d.sent();
3093
+ availableModels.push.apply(availableModels, __spreadArray([], __read(models), false));
3094
+ _d.label = 4;
3095
+ case 4:
3096
+ _b = _a.next();
3097
+ return [3 /*break*/, 2];
3098
+ case 5: return [3 /*break*/, 8];
3099
+ case 6:
3100
+ e_2_1 = _d.sent();
3101
+ e_2 = { error: e_2_1 };
3102
+ return [3 /*break*/, 8];
3103
+ case 7:
3104
+ try {
3105
+ if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
3106
+ }
3107
+ finally { if (e_2) throw e_2.error; }
3108
+ return [7 /*endfinally*/];
3109
+ case 8: return [2 /*return*/, availableModels];
3110
+ }
3111
+ });
3112
+ });
3113
+ };
3114
+ return MultipleLlmExecutionTools;
3115
+ }());
3116
+
3117
+ /**
3118
+ * Delagates the user interaction to a async callback function
3119
+ * You need to provide your own implementation of this callback function and its bind to UI.
3120
+ */
3121
+ var CallbackInterfaceTools = /** @class */ (function () {
3122
+ function CallbackInterfaceTools(options) {
3123
+ this.options = options;
3124
+ }
3125
+ /**
3126
+ * Trigger the custom callback function
3127
+ */
3128
+ CallbackInterfaceTools.prototype.promptDialog = function (options) {
3129
+ return __awaiter(this, void 0, void 0, function () {
3130
+ var answer;
3131
+ return __generator(this, function (_a) {
3132
+ switch (_a.label) {
3133
+ case 0: return [4 /*yield*/, this.options.callback(options)];
3134
+ case 1:
3135
+ answer = _a.sent();
3136
+ if (this.options.isVerbose) {
3137
+ console.info(spaceTrim.spaceTrim(function (block) { return "\n \uD83D\uDCD6 ".concat(block(options.promptTitle), "\n \uD83D\uDC64 ").concat(block(answer), "\n "); }));
3138
+ }
3139
+ return [2 /*return*/, answer];
3140
+ }
3141
+ });
3142
+ });
3143
+ };
3144
+ return CallbackInterfaceTools;
3145
+ }());
3146
+
3147
+ /**
3148
+ * Wrapper around `window.prompt` synchronous function that interacts with the user via browser prompt
3149
+ *
3150
+ * Warning: It is used for testing and mocking
3151
+ * **NOT intended to use in the production** due to its synchronous nature.
3152
+ */
3153
+ var SimplePromptInterfaceTools = /** @class */ (function () {
3154
+ function SimplePromptInterfaceTools(options) {
3155
+ this.options = options;
3156
+ }
3157
+ /**
3158
+ * Trigger window.PROMPT DIALOG
2806
3159
  */
2807
3160
  SimplePromptInterfaceTools.prototype.promptDialog = function (options) {
2808
3161
  return __awaiter(this, void 0, void 0, function () {
@@ -2822,6 +3175,36 @@
2822
3175
  return SimplePromptInterfaceTools;
2823
3176
  }());
2824
3177
 
3178
+ /**
3179
+ * Detects if the code is running in a browser environment in main thread (Not in a web worker)
3180
+ */
3181
+ new Function("\n try {\n return this === window;\n } catch (e) {\n return false;\n }\n");
3182
+ /**
3183
+ * Detects if the code is running in a Node.js environment
3184
+ */
3185
+ var isRunningInNode = new Function("\n try {\n return this === global;\n } catch (e) {\n return false;\n }\n");
3186
+ /**
3187
+ * Detects if the code is running in a web worker
3188
+ */
3189
+ 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");
3190
+
3191
+ /**
3192
+ * Returns the same value that is passed as argument.
3193
+ * No side effects.
3194
+ *
3195
+ * Note: It can be usefull for leveling indentation
3196
+ *
3197
+ * @param value any values
3198
+ * @returns the same values
3199
+ */
3200
+ function just(value) {
3201
+ if (value === undefined) {
3202
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3203
+ return undefined;
3204
+ }
3205
+ return value;
3206
+ }
3207
+
2825
3208
  /**
2826
3209
  * This error indicates that promptbook not found in the library
2827
3210
  */
@@ -2879,6 +3262,12 @@
2879
3262
  throw new PromptbookReferenceError(spaceTrim.spaceTrim("\n Promptbook with name \"".concat(promptbook.title, "\" does not have defined URL\n\n Note: Promptbooks without URLs are called anonymous promptbooks\n They can be used as standalone promptbooks, but they cannot be referenced by other promptbooks\n And also they cannot be used in the promptbook library\n\n ")));
2880
3263
  }
2881
3264
  validatePromptbookJson(promptbook);
3265
+ // Note: [🦄]
3266
+ if (this.library.has(promptbook.promptbookUrl) &&
3267
+ promptbookJsonToString(promptbook) !==
3268
+ promptbookJsonToString(this.library.get(promptbook.promptbookUrl))) {
3269
+ throw new PromptbookReferenceError(spaceTrim.spaceTrim("\n Promptbook with URL \"".concat(promptbook.promptbookUrl, "\" is already in the library\n\n Note: Promptbooks with the same URL are not allowed\n Note: Automatically check whether the promptbooks are the same BUT they are DIFFERENT\n\n ")));
3270
+ }
2882
3271
  this.library.set(promptbook.promptbookUrl, promptbook);
2883
3272
  }
2884
3273
  }
@@ -2905,6 +3294,9 @@
2905
3294
  var _this = this;
2906
3295
  var promptbook = this.library.get(url);
2907
3296
  if (!promptbook) {
3297
+ if (this.listPromptbooks().length === 0) {
3298
+ throw new PromptbookNotFoundError(spaceTrim.spaceTrim("\n Promptbook with url \"".concat(url, "\" not found\n\n No promptbooks available\n ")));
3299
+ }
2908
3300
  throw new PromptbookNotFoundError(spaceTrim.spaceTrim(function (block) { return "\n Promptbook with url \"".concat(url, "\" not found\n\n Available promptbooks:\n ").concat(block(_this.listPromptbooks()
2909
3301
  .map(function (promptbookUrl) { return "- ".concat(promptbookUrl); })
2910
3302
  .join('\n')), "\n\n "); }));
@@ -2977,11 +3369,11 @@
2977
3369
  * Note: The function does NOT return promise it returns the library directly which waits for the sources to be resolved
2978
3370
  * when error occurs in given promise or factory function, it is thrown during `listPromptbooks` or `getPromptbookByUrl` call
2979
3371
  *
3372
+ * Note: Consider using `createPromptbookLibraryFromDirectory` or `createPromptbookLibraryFromUrl`
2980
3373
  *
2981
3374
  * @param promptbookSourcesPromiseOrFactory
2982
3375
  * @returns PromptbookLibrary
2983
- *
2984
- * @deprecated Consider using `createPromptbookLibraryFromUrl` or `createPromptbookLibraryFromDirectory`
3376
+ * @private Just internal tool for other constructor functions
2985
3377
  */
2986
3378
  function createPromptbookLibraryFromPromise(promptbookSourcesPromiseOrFactory) {
2987
3379
  var library;
@@ -3050,6 +3442,228 @@
3050
3442
  * TODO: [🍓][🚯] !!! Add to README and samples + maybe make `@promptbook/library` package
3051
3443
  */
3052
3444
 
3445
+ /**
3446
+ * Constructs Promptbook from given directory
3447
+ *
3448
+ * Note: Works only in Node.js environment because it reads the file system
3449
+ *
3450
+ * @param path - path to the directory with promptbooks
3451
+ * @param options - Misc options for the library
3452
+ * @returns PromptbookLibrary
3453
+ */
3454
+ function createPromptbookLibraryFromDirectory(path, options) {
3455
+ return __awaiter(this, void 0, void 0, function () {
3456
+ var _a, _b, isRecursive, _c, isVerbose, _d, isLazyLoaded, library;
3457
+ var _this = this;
3458
+ return __generator(this, function (_e) {
3459
+ switch (_e.label) {
3460
+ case 0:
3461
+ if (!isRunningInNode()) {
3462
+ throw new Error('Function `createPromptbookLibraryFromDirectory` can only be run in Node.js environment because it reads the file system.');
3463
+ }
3464
+ _a = options || {}, _b = _a.isRecursive, isRecursive = _b === void 0 ? true : _b, _c = _a.isVerbose, isVerbose = _c === void 0 ? false : _c, _d = _a.isLazyLoaded, isLazyLoaded = _d === void 0 ? false : _d;
3465
+ library = createPromptbookLibraryFromPromise(function () { return __awaiter(_this, void 0, void 0, function () {
3466
+ var fsPromises, readFile, fileNames, promptbooks, fileNames_1, fileNames_1_1, fileName, promptbook, promptbookString, _a, _b, e_1_1;
3467
+ var e_1, _c;
3468
+ return __generator(this, function (_d) {
3469
+ switch (_d.label) {
3470
+ case 0:
3471
+ if (isVerbose) {
3472
+ console.info("Creating promptbook library from path ".concat(path));
3473
+ }
3474
+ fsPromises = require(just('fs/promises') /* <- Note: [1] */);
3475
+ readFile = fsPromises.readFile;
3476
+ return [4 /*yield*/, listAllFiles(path, isRecursive)];
3477
+ case 1:
3478
+ fileNames = _d.sent();
3479
+ if (isVerbose) {
3480
+ console.info('createPromptbookLibraryFromDirectory', { path: path, isRecursive: isRecursive, fileNames: fileNames });
3481
+ }
3482
+ promptbooks = [];
3483
+ _d.label = 2;
3484
+ case 2:
3485
+ _d.trys.push([2, 11, 12, 13]);
3486
+ fileNames_1 = __values(fileNames), fileNames_1_1 = fileNames_1.next();
3487
+ _d.label = 3;
3488
+ case 3:
3489
+ if (!!fileNames_1_1.done) return [3 /*break*/, 10];
3490
+ fileName = fileNames_1_1.value;
3491
+ promptbook = null;
3492
+ if (!fileName.endsWith('.ptbk.md')) return [3 /*break*/, 5];
3493
+ return [4 /*yield*/, readFile(fileName, 'utf8')];
3494
+ case 4:
3495
+ promptbookString = (_d.sent());
3496
+ promptbook = promptbookStringToJson(promptbookString);
3497
+ return [3 /*break*/, 8];
3498
+ case 5:
3499
+ if (!fileName.endsWith('.ptbk.json')) return [3 /*break*/, 7];
3500
+ if (isVerbose) {
3501
+ console.info("Loading ".concat(fileName));
3502
+ }
3503
+ _b = (_a = JSON).parse;
3504
+ return [4 /*yield*/, readFile(fileName, 'utf8')];
3505
+ case 6:
3506
+ // TODO: Handle non-valid JSON files
3507
+ promptbook = _b.apply(_a, [_d.sent()]);
3508
+ return [3 /*break*/, 8];
3509
+ case 7:
3510
+ if (isVerbose) {
3511
+ console.info("Skipping file ".concat(fileName));
3512
+ }
3513
+ _d.label = 8;
3514
+ case 8:
3515
+ // ---
3516
+ if (promptbook !== null) {
3517
+ if (!promptbook.promptbookUrl) {
3518
+ if (isVerbose) {
3519
+ console.info("Not loading ".concat(fileName, " - missing URL"));
3520
+ }
3521
+ }
3522
+ else {
3523
+ if (isVerbose) {
3524
+ console.info("Loading ".concat(fileName));
3525
+ }
3526
+ // Note: [🦄] Promptbook with same url uniqueness will be checked automatically in SimplePromptbookLibrary
3527
+ promptbooks.push(promptbook);
3528
+ }
3529
+ }
3530
+ _d.label = 9;
3531
+ case 9:
3532
+ fileNames_1_1 = fileNames_1.next();
3533
+ return [3 /*break*/, 3];
3534
+ case 10: return [3 /*break*/, 13];
3535
+ case 11:
3536
+ e_1_1 = _d.sent();
3537
+ e_1 = { error: e_1_1 };
3538
+ return [3 /*break*/, 13];
3539
+ case 12:
3540
+ try {
3541
+ if (fileNames_1_1 && !fileNames_1_1.done && (_c = fileNames_1.return)) _c.call(fileNames_1);
3542
+ }
3543
+ finally { if (e_1) throw e_1.error; }
3544
+ return [7 /*endfinally*/];
3545
+ case 13: return [2 /*return*/, promptbooks];
3546
+ }
3547
+ });
3548
+ }); });
3549
+ if (!(isLazyLoaded === false)) return [3 /*break*/, 2];
3550
+ return [4 /*yield*/, library.listPromptbooks()];
3551
+ case 1:
3552
+ _e.sent();
3553
+ _e.label = 2;
3554
+ case 2: return [2 /*return*/, library];
3555
+ }
3556
+ });
3557
+ });
3558
+ }
3559
+ /**
3560
+ * Reads all files in the directory
3561
+ *
3562
+ * @param path
3563
+ * @param isRecursive
3564
+ * @returns List of all files in the directory
3565
+ * @private internal function for `createPromptbookLibraryFromDirectory`
3566
+ */
3567
+ function listAllFiles(path$1, isRecursive) {
3568
+ return __awaiter(this, void 0, void 0, function () {
3569
+ var fsPromises, readdir, dirents, fileNames, _a, _b, dirent, subPath, _c, _d, _e, _f, e_2_1;
3570
+ var e_2, _g;
3571
+ return __generator(this, function (_h) {
3572
+ switch (_h.label) {
3573
+ case 0:
3574
+ fsPromises = require(just('fs/promises') /* <- Note: [1] */);
3575
+ readdir = fsPromises.readdir;
3576
+ return [4 /*yield*/, readdir(path$1, {
3577
+ withFileTypes: true /* Note: This is not working: recursive: isRecursive */,
3578
+ })];
3579
+ case 1:
3580
+ dirents = _h.sent();
3581
+ fileNames = dirents.filter(function (dirent) { return dirent.isFile(); }).map(function (_a) {
3582
+ var name = _a.name;
3583
+ return path.join(path$1, name);
3584
+ });
3585
+ if (!isRecursive) return [3 /*break*/, 9];
3586
+ _h.label = 2;
3587
+ case 2:
3588
+ _h.trys.push([2, 7, 8, 9]);
3589
+ _a = __values(dirents.filter(function (dirent) { return dirent.isDirectory(); })), _b = _a.next();
3590
+ _h.label = 3;
3591
+ case 3:
3592
+ if (!!_b.done) return [3 /*break*/, 6];
3593
+ dirent = _b.value;
3594
+ subPath = path.join(path$1, dirent.name);
3595
+ _d = (_c = fileNames.push).apply;
3596
+ _e = [fileNames];
3597
+ _f = [[]];
3598
+ return [4 /*yield*/, listAllFiles(subPath, isRecursive)];
3599
+ case 4:
3600
+ _d.apply(_c, _e.concat([__spreadArray.apply(void 0, _f.concat([__read.apply(void 0, [(_h.sent())]), false]))]));
3601
+ _h.label = 5;
3602
+ case 5:
3603
+ _b = _a.next();
3604
+ return [3 /*break*/, 3];
3605
+ case 6: return [3 /*break*/, 9];
3606
+ case 7:
3607
+ e_2_1 = _h.sent();
3608
+ e_2 = { error: e_2_1 };
3609
+ return [3 /*break*/, 9];
3610
+ case 8:
3611
+ try {
3612
+ if (_b && !_b.done && (_g = _a.return)) _g.call(_a);
3613
+ }
3614
+ finally { if (e_2) throw e_2.error; }
3615
+ return [7 /*endfinally*/];
3616
+ case 9: return [2 /*return*/, fileNames];
3617
+ }
3618
+ });
3619
+ });
3620
+ }
3621
+ /***
3622
+ * TODO: [🧠] Maybe do not do hacks like [1] and just create package @promptbook/node
3623
+ * [🍓][🚯] maybe make `@promptbook/library` package
3624
+ * TODO: Fix the dynamic import issue in Webpack (! Not working !)
3625
+ * > ./node_modules/@promptbook/core/esm/index.es.js
3626
+ * > Critical dependency: the request of a dependency is an expression
3627
+ *
3628
+ * Note: [1] Using require(just('fs/promises')) to allow
3629
+ * the `@promptbook/core` work for both Node.js and browser environments
3630
+ */
3631
+
3632
+ /**
3633
+ * Constructs Promptbook from remote Promptbase URL
3634
+
3635
+ * @returns PromptbookLibrary
3636
+ */
3637
+ function createPromptbookLibraryFromUrl(url, options) {
3638
+ return __awaiter(this, void 0, void 0, function () {
3639
+ var _a, _b, isVerbose, _c, isLazyLoaded, library;
3640
+ var _this = this;
3641
+ return __generator(this, function (_d) {
3642
+ switch (_d.label) {
3643
+ case 0:
3644
+ _a = options || {}, _b = _a.isVerbose, isVerbose = _b === void 0 ? false : _b, _c = _a.isLazyLoaded, isLazyLoaded = _c === void 0 ? false : _c;
3645
+ library = createPromptbookLibraryFromPromise(function () { return __awaiter(_this, void 0, void 0, function () {
3646
+ return __generator(this, function (_a) {
3647
+ if (isVerbose) {
3648
+ console.info("Creating promptbook library from url ".concat(url.toString()));
3649
+ }
3650
+ throw new Error('Not implemented yet');
3651
+ });
3652
+ }); });
3653
+ if (!(isLazyLoaded === false)) return [3 /*break*/, 2];
3654
+ return [4 /*yield*/, library.listPromptbooks()];
3655
+ case 1:
3656
+ _d.sent();
3657
+ _d.label = 2;
3658
+ case 2: return [2 /*return*/, library];
3659
+ }
3660
+ });
3661
+ });
3662
+ }
3663
+ /***
3664
+ * TODO: [🍓][🚯] !!! Add to README and samples + maybe make `@promptbook/library` package
3665
+ */
3666
+
3053
3667
  /**
3054
3668
  * Creates PromptbookLibrary as a subset of another PromptbookLibrary
3055
3669
  *
@@ -3133,146 +3747,348 @@
3133
3747
  */
3134
3748
 
3135
3749
  /**
3136
- * Multiple LLM Execution Tools is a proxy server that uses multiple execution tools internally and exposes the executor interface externally.
3750
+ * Just testing imports and compatibility
3751
+ */
3752
+ function justTestFsImport() {
3753
+ return __awaiter(this, void 0, void 0, function () {
3754
+ var files;
3755
+ return __generator(this, function (_a) {
3756
+ switch (_a.label) {
3757
+ case 0:
3758
+ if (!isRunningInNode()) {
3759
+ throw new Error('Function `testFiles` can only be run in Node.js environment because it reads the file system.');
3760
+ }
3761
+ return [4 /*yield*/, require(just('glob-promise'))('/**/*')];
3762
+ case 1:
3763
+ files = _a.sent();
3764
+ console.info('testFiles', { files: files });
3765
+ return [2 /*return*/];
3766
+ }
3767
+ });
3768
+ });
3769
+ }
3770
+ /**
3771
+ * TODO: !!! Remove this file
3772
+ */
3773
+
3774
+ /**
3775
+ * Format either small or big number
3137
3776
  *
3138
- * @see https://github.com/webgptorg/promptbook#multiple-server
3777
+ * @private within the library
3139
3778
  */
3140
- var MultipleLlmExecutionTools = /** @class */ (function () {
3141
- /**
3142
- * Gets array of execution tools in order of priority
3143
- */
3144
- function MultipleLlmExecutionTools() {
3145
- var llmExecutionTools = [];
3146
- for (var _i = 0; _i < arguments.length; _i++) {
3147
- llmExecutionTools[_i] = arguments[_i];
3779
+ function formatNumber(value) {
3780
+ if (value === 0) {
3781
+ return '0';
3782
+ }
3783
+ for (var exponent = 0; exponent < 15; exponent++) {
3784
+ var factor = Math.pow(10, exponent);
3785
+ var valueRounded = Math.round(value * factor) / factor;
3786
+ if (Math.abs(value - valueRounded) / value <
3787
+ 0.001 /* <- TODO: Pass as option, pass to executionReportJsonToString as option */) {
3788
+ return valueRounded.toFixed(exponent);
3148
3789
  }
3149
- this.llmExecutionTools = llmExecutionTools;
3150
3790
  }
3151
- /**
3152
- * Calls the best available chat model
3153
- */
3154
- MultipleLlmExecutionTools.prototype.gptChat = function (prompt) {
3155
- return this.gptCommon(prompt);
3156
- };
3157
- /**
3158
- * Calls the best available completion model
3159
- */
3160
- MultipleLlmExecutionTools.prototype.gptComplete = function (prompt) {
3161
- return this.gptCommon(prompt);
3791
+ return value.toString();
3792
+ }
3793
+
3794
+ /**
3795
+ * Create a markdown table from a 2D array of strings
3796
+ *
3797
+ * @private within the library
3798
+ */
3799
+ function createMarkdownTable(table) {
3800
+ var columnWidths = table.reduce(function (widths, row) {
3801
+ row.forEach(function (cell, columnIndex) {
3802
+ var cellLength = cell.length;
3803
+ if (!widths[columnIndex] || cellLength > widths[columnIndex]) {
3804
+ widths[columnIndex] = cellLength;
3805
+ }
3806
+ });
3807
+ return widths;
3808
+ }, []);
3809
+ var header = "| ".concat(table[0]
3810
+ .map(function (cell, columnIndex) { return cell.padEnd(columnWidths[columnIndex]); })
3811
+ .join(' | '), " |");
3812
+ var separator = "|".concat(columnWidths.map(function (width) { return '-'.repeat(width + 2); }).join('|'), "|");
3813
+ var rows = table.slice(1).map(function (row) {
3814
+ var paddedRow = row.map(function (cell, columnIndex) {
3815
+ return cell.padEnd(columnWidths[columnIndex]);
3816
+ });
3817
+ return "| ".concat(paddedRow.join(' | '), " |");
3818
+ });
3819
+ return __spreadArray([header, separator], __read(rows), false).join('\n');
3820
+ }
3821
+
3822
+ /**
3823
+ * Function createMarkdownChart will draw a chart in markdown from ⬛+🟦 tiles
3824
+ *
3825
+ * @private within the library
3826
+ */
3827
+ function createMarkdownChart(options) {
3828
+ var e_1, _a;
3829
+ var nameHeader = options.nameHeader, valueHeader = options.valueHeader, items = options.items, width = options.width, unitName = options.unitName;
3830
+ var from = Math.min.apply(Math, __spreadArray([], __read(items.map(function (item) { return item.from; })), false));
3831
+ var to = Math.max.apply(Math, __spreadArray([], __read(items.map(function (item) { return item.to; })), false));
3832
+ var scale = width / (to - from);
3833
+ var table = [[nameHeader, valueHeader]];
3834
+ try {
3835
+ for (var items_1 = __values(items), items_1_1 = items_1.next(); !items_1_1.done; items_1_1 = items_1.next()) {
3836
+ var item = items_1_1.value;
3837
+ var before = Math.round((item.from - from) * scale);
3838
+ var during = Math.round((item.to - item.from) * scale);
3839
+ var after = width - before - during;
3840
+ table.push([removeEmojis(item.title).trim(), '░'.repeat(before) + '█'.repeat(during) + '░'.repeat(after)]);
3841
+ }
3842
+ }
3843
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
3844
+ finally {
3845
+ try {
3846
+ if (items_1_1 && !items_1_1.done && (_a = items_1.return)) _a.call(items_1);
3847
+ }
3848
+ finally { if (e_1) throw e_1.error; }
3849
+ }
3850
+ 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_");
3851
+ return createMarkdownTable(table) + '\n\n' + legend;
3852
+ }
3853
+ /**
3854
+ * TODO: Maybe use Mermain Gant Diagrams
3855
+ * @see https://jojozhuang.github.io/tutorial/mermaid-cheat-sheet/
3856
+ */
3857
+
3858
+ /**
3859
+ * Function escapeMarkdownBlock will escape markdown block if needed
3860
+ * It is useful when you want have block in block
3861
+ */
3862
+ function escapeMarkdownBlock(value) {
3863
+ return value.replace(/```/g, '\\`\\`\\`');
3864
+ }
3865
+
3866
+ /**
3867
+ * Default options for generating an execution report string
3868
+ */
3869
+ var ExecutionReportStringOptionsDefaults = {
3870
+ taxRate: 0,
3871
+ chartsWidth: 36,
3872
+ };
3873
+
3874
+ /**
3875
+ * The thresholds for the relative time in the `moment` library.
3876
+ *
3877
+ * @see https://momentjscom.readthedocs.io/en/latest/moment/07-customization/13-relative-time-threshold/
3878
+ */
3879
+ var MOMENT_ARG_THRESHOLDS = {
3880
+ 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.
3881
+ };
3882
+
3883
+ /**
3884
+ * Count the duration of working time
3885
+ *
3886
+ * @private within the library
3887
+ */
3888
+ function countWorkingDuration(items) {
3889
+ var e_1, _a;
3890
+ var steps = Array.from(new Set(items.flatMap(function (item) { return [item.from, item.to]; })));
3891
+ steps.sort(function (a, b) { return a - b; });
3892
+ var intervals = steps.map(function (step, index) { return [step, steps[index + 1] || 0]; }).slice(0, -1);
3893
+ var duration = 0;
3894
+ var _loop_1 = function (interval) {
3895
+ var _b = __read(interval, 2), from = _b[0], to = _b[1];
3896
+ if (items.some(function (item) { return item.from < to && item.to > from; })) {
3897
+ duration += to - from;
3898
+ }
3162
3899
  };
3163
- /**
3164
- * Calls the best available model
3165
- */
3166
- MultipleLlmExecutionTools.prototype.gptCommon = function (prompt) {
3167
- return __awaiter(this, void 0, void 0, function () {
3168
- var errors, _a, _b, llmExecutionTools, error_1, e_1_1;
3169
- var e_1, _c;
3170
- return __generator(this, function (_d) {
3171
- switch (_d.label) {
3172
- case 0:
3173
- errors = [];
3174
- _d.label = 1;
3175
- case 1:
3176
- _d.trys.push([1, 11, 12, 13]);
3177
- _a = __values(this.llmExecutionTools), _b = _a.next();
3178
- _d.label = 2;
3179
- case 2:
3180
- if (!!_b.done) return [3 /*break*/, 10];
3181
- llmExecutionTools = _b.value;
3182
- _d.label = 3;
3183
- case 3:
3184
- _d.trys.push([3, 8, , 9]);
3185
- if (!(prompt.modelRequirements.modelVariant === 'CHAT')) return [3 /*break*/, 5];
3186
- return [4 /*yield*/, llmExecutionTools.gptChat(prompt)];
3187
- case 4: return [2 /*return*/, _d.sent()];
3188
- case 5:
3189
- if (!(prompt.modelRequirements.modelVariant === 'COMPLETION')) return [3 /*break*/, 7];
3190
- return [4 /*yield*/, llmExecutionTools.gptComplete(prompt)];
3191
- case 6: return [2 /*return*/, _d.sent()];
3192
- case 7: return [3 /*break*/, 9];
3193
- case 8:
3194
- error_1 = _d.sent();
3195
- if (!(error_1 instanceof Error)) {
3196
- throw error_1;
3197
- }
3198
- errors.push(error_1);
3199
- return [3 /*break*/, 9];
3200
- case 9:
3201
- _b = _a.next();
3202
- return [3 /*break*/, 2];
3203
- case 10: return [3 /*break*/, 13];
3204
- case 11:
3205
- e_1_1 = _d.sent();
3206
- e_1 = { error: e_1_1 };
3207
- return [3 /*break*/, 13];
3208
- case 12:
3209
- try {
3210
- if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
3211
- }
3212
- finally { if (e_1) throw e_1.error; }
3213
- return [7 /*endfinally*/];
3214
- 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 "); }));
3215
- }
3900
+ try {
3901
+ for (var intervals_1 = __values(intervals), intervals_1_1 = intervals_1.next(); !intervals_1_1.done; intervals_1_1 = intervals_1.next()) {
3902
+ var interval = intervals_1_1.value;
3903
+ _loop_1(interval);
3904
+ }
3905
+ }
3906
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
3907
+ finally {
3908
+ try {
3909
+ if (intervals_1_1 && !intervals_1_1.done && (_a = intervals_1.return)) _a.call(intervals_1);
3910
+ }
3911
+ finally { if (e_1) throw e_1.error; }
3912
+ }
3913
+ return duration;
3914
+ }
3915
+
3916
+ /**
3917
+ * Converts execution report from JSON to string format
3918
+ */
3919
+ function executionReportJsonToString(executionReportJson, options) {
3920
+ var e_1, _a;
3921
+ var _b, _c, _d, _e, _f, _g;
3922
+ var _h = __assign(__assign({}, ExecutionReportStringOptionsDefaults), (options || {})), taxRate = _h.taxRate, chartsWidth = _h.chartsWidth;
3923
+ var executionReportString = spaceTrim.spaceTrim(function (block) { return "\n # ".concat(executionReportJson.title || 'Execution report', "\n\n ").concat(block(executionReportJson.description || ''), "\n "); });
3924
+ var headerList = [];
3925
+ if (executionReportJson.promptbookUrl) {
3926
+ headerList.push("PROMPTBOOK URL ".concat(executionReportJson.promptbookUrl));
3927
+ }
3928
+ headerList.push("PROMPTBOOK VERSION ".concat(executionReportJson.promptbookUsedVersion) +
3929
+ (!executionReportJson.promptbookRequestedVersion
3930
+ ? ''
3931
+ : " *(requested ".concat(executionReportJson.promptbookRequestedVersion, ")*")));
3932
+ if (executionReportJson.promptExecutions.length !== 0) {
3933
+ // TODO: What if startedAt OR/AND completedAt is not defined?
3934
+ var startedAt = moment__default["default"](Math.min.apply(Math, __spreadArray([], __read(executionReportJson.promptExecutions
3935
+ .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; })
3936
+ .map(function (promptExecution) { return moment__default["default"](promptExecution.result.timing.start).valueOf(); })), false)));
3937
+ var completedAt = moment__default["default"](Math.max.apply(Math, __spreadArray([], __read(executionReportJson.promptExecutions
3938
+ .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; })
3939
+ .map(function (promptExecution) { return moment__default["default"](promptExecution.result.timing.complete).valueOf(); })), false)));
3940
+ var timingItems = executionReportJson.promptExecutions.map(function (promptExecution) {
3941
+ var _a, _b, _c, _d;
3942
+ return ({
3943
+ title: promptExecution.prompt.title,
3944
+ 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,
3945
+ 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,
3216
3946
  });
3217
3947
  });
3218
- };
3219
- /**
3220
- * List all available models that can be used
3221
- * This liost is a combination of all available models from all execution tools
3222
- */
3223
- MultipleLlmExecutionTools.prototype.listModels = function () {
3224
- return __awaiter(this, void 0, void 0, function () {
3225
- var availableModels, _a, _b, llmExecutionTools, models, e_2_1;
3226
- var e_2, _c;
3227
- return __generator(this, function (_d) {
3228
- switch (_d.label) {
3229
- case 0:
3230
- availableModels = [];
3231
- _d.label = 1;
3232
- case 1:
3233
- _d.trys.push([1, 6, 7, 8]);
3234
- _a = __values(this.llmExecutionTools), _b = _a.next();
3235
- _d.label = 2;
3236
- case 2:
3237
- if (!!_b.done) return [3 /*break*/, 5];
3238
- llmExecutionTools = _b.value;
3239
- return [4 /*yield*/, llmExecutionTools.listModels()];
3240
- case 3:
3241
- models = _d.sent();
3242
- availableModels.push.apply(availableModels, __spreadArray([], __read(models), false));
3243
- _d.label = 4;
3244
- case 4:
3245
- _b = _a.next();
3246
- return [3 /*break*/, 2];
3247
- case 5: return [3 /*break*/, 8];
3248
- case 6:
3249
- e_2_1 = _d.sent();
3250
- e_2 = { error: e_2_1 };
3251
- return [3 /*break*/, 8];
3252
- case 7:
3253
- try {
3254
- if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
3255
- }
3256
- finally { if (e_2) throw e_2.error; }
3257
- return [7 /*endfinally*/];
3258
- case 8: return [2 /*return*/, availableModels];
3259
- }
3948
+ var costItems = executionReportJson.promptExecutions
3949
+ .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'; })
3950
+ .map(function (promptExecution) {
3951
+ var _a, _b;
3952
+ return ({
3953
+ title: promptExecution.prompt.title,
3954
+ from: 0,
3955
+ to: ((_b = (_a = promptExecution.result) === null || _a === void 0 ? void 0 : _a.usage) === null || _b === void 0 ? void 0 : _b.price) * (1 + taxRate),
3260
3956
  });
3261
3957
  });
3958
+ var duration = moment__default["default"].duration(completedAt.diff(startedAt));
3959
+ var llmDuration = moment__default["default"].duration(countWorkingDuration(timingItems) * 1000);
3960
+ 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'; });
3961
+ var cost = executionsWithKnownCost.reduce(function (cost, promptExecution) { return cost + (promptExecution.result.usage.price || 0); }, 0);
3962
+ headerList.push("STARTED AT ".concat(moment__default["default"](startedAt).format("YYYY-MM-DD HH:mm:ss")));
3963
+ headerList.push("COMPLETED AT ".concat(moment__default["default"](completedAt).format("YYYY-MM-DD HH:mm:ss")));
3964
+ headerList.push("TOTAL DURATION ".concat(duration.humanize(MOMENT_ARG_THRESHOLDS)));
3965
+ headerList.push("TOTAL LLM DURATION ".concat(llmDuration.humanize(MOMENT_ARG_THRESHOLDS)));
3966
+ headerList.push("TOTAL COST $".concat(formatNumber(cost * (1 + taxRate))) +
3967
+ (executionsWithKnownCost.length === executionReportJson.promptExecutions.length
3968
+ ? ''
3969
+ : " *(Some cost is unknown)*") +
3970
+ (taxRate !== 0 ? " *(with tax ".concat(taxRate * 100, "%)*") : ''));
3971
+ executionReportString += '\n\n' + headerList.map(function (header) { return "- ".concat(header); }).join('\n');
3972
+ executionReportString +=
3973
+ '\n\n' +
3974
+ '## 🗃 Index' +
3975
+ '\n\n' +
3976
+ executionReportJson.promptExecutions
3977
+ .map(function (promptExecution) {
3978
+ // TODO: Make some better system to convert hedings to links
3979
+ var hash = normalizeToKebabCase(promptExecution.prompt.title);
3980
+ if (/^\s*\p{Extended_Pictographic}/u.test(promptExecution.prompt.title)) {
3981
+ hash = '-' + hash;
3982
+ }
3983
+ // TODO: Make working hash link for the template in md + pdf
3984
+ return "- [".concat(promptExecution.prompt.title, "](#").concat(hash, ")");
3985
+ })
3986
+ .join('\n');
3987
+ executionReportString +=
3988
+ '\n\n' +
3989
+ '## ⌚ Time chart' +
3990
+ '\n\n' +
3991
+ createMarkdownChart({
3992
+ nameHeader: 'Template',
3993
+ valueHeader: 'Timeline',
3994
+ items: timingItems,
3995
+ width: chartsWidth,
3996
+ unitName: 'seconds',
3997
+ });
3998
+ executionReportString +=
3999
+ '\n\n' +
4000
+ '## 💸 Cost chart' +
4001
+ '\n\n' +
4002
+ createMarkdownChart({
4003
+ nameHeader: 'Template',
4004
+ valueHeader: 'Cost',
4005
+ items: costItems,
4006
+ width: chartsWidth,
4007
+ unitName: 'USD',
4008
+ });
4009
+ }
4010
+ else {
4011
+ headerList.push("TOTAL COST $0 *(Nothing executed)*");
4012
+ }
4013
+ var _loop_1 = function (promptExecution) {
4014
+ executionReportString += '\n\n\n\n' + "## ".concat(promptExecution.prompt.title);
4015
+ var templateList = [];
4016
+ // TODO: What if startedAt OR/AND completedAt is not defined?
4017
+ 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);
4018
+ 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);
4019
+ var duration = moment__default["default"].duration(completedAt.diff(startedAt));
4020
+ // Not need here:
4021
+ // > templateList.push(`STARTED AT ${moment(startedAt).calendar()}`);
4022
+ templateList.push("DURATION ".concat(duration.humanize(MOMENT_ARG_THRESHOLDS)));
4023
+ if (typeof ((_g = (_f = promptExecution.result) === null || _f === void 0 ? void 0 : _f.usage) === null || _g === void 0 ? void 0 : _g.price) === 'number') {
4024
+ templateList.push("COST $".concat(formatNumber(promptExecution.result.usage.price * (1 + taxRate))) +
4025
+ (taxRate !== 0 ? " *(with tax ".concat(taxRate * 100, "%)*") : ''));
4026
+ }
4027
+ else {
4028
+ templateList.push("COST UNKNOWN");
4029
+ }
4030
+ executionReportString += '\n\n' + templateList.map(function (header) { return "- ".concat(header); }).join('\n');
4031
+ /*
4032
+ - MODEL VARIANT ${promptExecution.prompt.modelRequirements.modelVariant}
4033
+ - MODEL NAME \`${promptExecution.result?.model}\` (requested \`${
4034
+ promptExecution.prompt.modelRequirements.modelName
4035
+
4036
+ */
4037
+ if (just(true)) {
4038
+ executionReportString +=
4039
+ '\n\n\n\n' +
4040
+ spaceTrim.spaceTrim(function (block) { return "\n\n ### Prompt\n\n ```\n ".concat(block(escapeMarkdownBlock(promptExecution.prompt.content)), "\n ```\n\n "); });
4041
+ }
4042
+ if (promptExecution.result && promptExecution.result.content) {
4043
+ executionReportString +=
4044
+ '\n\n\n\n' +
4045
+ spaceTrim.spaceTrim(function (block) { return "\n\n ### Result\n\n ```\n ".concat(block(escapeMarkdownBlock(promptExecution.result.content)), "\n ```\n "); });
4046
+ }
4047
+ if (promptExecution.error && promptExecution.error.message) {
4048
+ executionReportString +=
4049
+ '\n\n\n\n' +
4050
+ spaceTrim.spaceTrim(function (block) { return "\n\n ### Error\n\n ```\n ".concat(block(escapeMarkdownBlock(promptExecution.error.message)), "\n ```\n\n "); });
4051
+ }
3262
4052
  };
3263
- return MultipleLlmExecutionTools;
3264
- }());
4053
+ try {
4054
+ for (var _j = __values(executionReportJson.promptExecutions), _k = _j.next(); !_k.done; _k = _j.next()) {
4055
+ var promptExecution = _k.value;
4056
+ _loop_1(promptExecution);
4057
+ }
4058
+ }
4059
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
4060
+ finally {
4061
+ try {
4062
+ if (_k && !_k.done && (_a = _j.return)) _a.call(_j);
4063
+ }
4064
+ finally { if (e_1) throw e_1.error; }
4065
+ }
4066
+ executionReportString = prettifyMarkdown(executionReportString);
4067
+ return executionReportString;
4068
+ }
4069
+ /**
4070
+ * TODO: Add mermaid chart for every report
4071
+ * TODO: [🧠] Allow to filter out some parts of the report by options
4072
+ */
3265
4073
 
3266
4074
  exports.CallbackInterfaceTools = CallbackInterfaceTools;
4075
+ exports.ExecutionReportStringOptionsDefaults = ExecutionReportStringOptionsDefaults;
3267
4076
  exports.ExecutionTypes = ExecutionTypes;
3268
4077
  exports.MultipleLlmExecutionTools = MultipleLlmExecutionTools;
3269
4078
  exports.PROMPTBOOK_VERSION = PROMPTBOOK_VERSION;
3270
4079
  exports.SimplePromptInterfaceTools = SimplePromptInterfaceTools;
3271
4080
  exports.SimplePromptbookLibrary = SimplePromptbookLibrary;
4081
+ exports.assertsExecutionSuccessful = assertsExecutionSuccessful;
4082
+ exports.checkExpectations = checkExpectations;
3272
4083
  exports.createPromptbookExecutor = createPromptbookExecutor;
3273
- exports.createPromptbookLibraryFromPromise = createPromptbookLibraryFromPromise;
4084
+ exports.createPromptbookLibraryFromDirectory = createPromptbookLibraryFromDirectory;
3274
4085
  exports.createPromptbookLibraryFromSources = createPromptbookLibraryFromSources;
4086
+ exports.createPromptbookLibraryFromUrl = createPromptbookLibraryFromUrl;
3275
4087
  exports.createPromptbookSublibrary = createPromptbookSublibrary;
4088
+ exports.executionReportJsonToString = executionReportJsonToString;
4089
+ exports.isPassingExpectations = isPassingExpectations;
4090
+ exports.justTestFsImport = justTestFsImport;
4091
+ exports.prettifyPromptbookString = prettifyPromptbookString;
3276
4092
  exports.promptbookJsonToString = promptbookJsonToString;
3277
4093
  exports.promptbookStringToJson = promptbookStringToJson;
3278
4094
  exports.validatePromptbookJson = validatePromptbookJson;