@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/esm/index.es.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import spaceTrim$1, { spaceTrim } from 'spacetrim';
2
2
  import { format } from 'prettier';
3
3
  import parserHtml from 'prettier/parser-html';
4
- import 'moment';
4
+ import { join } from 'path';
5
+ import moment from 'moment';
5
6
 
6
7
  /*! *****************************************************************************
7
8
  Copyright (c) Microsoft Corporation.
@@ -447,7 +448,7 @@ function union() {
447
448
  /**
448
449
  * The version of the Promptbook library
449
450
  */
450
- var PROMPTBOOK_VERSION = '0.52.0-2';
451
+ var PROMPTBOOK_VERSION = '0.52.0-29';
451
452
 
452
453
  /**
453
454
  * Parses the template and returns the list of all parameter names
@@ -569,38 +570,6 @@ function extractParametersFromPromptTemplate(promptTemplate) {
569
570
  * TODO: [🔣] If script require contentLanguage
570
571
  */
571
572
 
572
- /**
573
- * Prettify the html code
574
- *
575
- * @param content raw html code
576
- * @returns formatted html code
577
- */
578
- function prettifyMarkdown(content) {
579
- try {
580
- return format(content, {
581
- parser: 'markdown',
582
- plugins: [parserHtml],
583
- // TODO: DRY - make some import or auto-copy of .prettierrc
584
- endOfLine: 'lf',
585
- tabWidth: 4,
586
- singleQuote: true,
587
- trailingComma: 'all',
588
- arrowParens: 'always',
589
- printWidth: 120,
590
- htmlWhitespaceSensitivity: 'ignore',
591
- jsxBracketSameLine: false,
592
- bracketSpacing: true,
593
- });
594
- }
595
- catch (error) {
596
- console.error('There was an error with prettifying the markdown, using the original as the fallback', {
597
- error: error,
598
- html: content,
599
- });
600
- return content;
601
- }
602
- }
603
-
604
573
  /**
605
574
  * Removes emojis from a string and fix whitespaces
606
575
  *
@@ -626,6 +595,64 @@ function titleToName(value) {
626
595
  return value;
627
596
  }
628
597
 
598
+ /**
599
+ * Creates a Mermaid graph based on the promptbook
600
+ *
601
+ * Note: The result is not wrapped in a Markdown code block
602
+ */
603
+ function renderPromptbookMermaid(promptbookJson, options) {
604
+ var _a = (options || {}).linkPromptTemplate, linkPromptTemplate = _a === void 0 ? function () { return null; } : _a;
605
+ var parameterNameToTemplateName = function (parameterName) {
606
+ var parameter = promptbookJson.parameters.find(function (parameter) { return parameter.name === parameterName; });
607
+ if (!parameter) {
608
+ throw new UnexpectedError("Could not find {".concat(parameterName, "}"));
609
+ }
610
+ if (parameter.isInput) {
611
+ return 'input';
612
+ }
613
+ var template = promptbookJson.promptTemplates.find(function (template) { return template.resultingParameterName === parameterName; });
614
+ if (!template) {
615
+ throw new Error("Could not find template for {".concat(parameterName, "}"));
616
+ }
617
+ return normalizeTo_camelCase('template-' + titleToName(template.title));
618
+ };
619
+ var promptbookMermaid = spaceTrim(function (block) { return "\n\n %% \uD83D\uDD2E Tip: Open this on GitHub or in the VSCode website to see the Mermaid graph visually\n\n flowchart LR\n subgraph \"".concat(promptbookJson.title, "\"\n\n direction TB\n\n input((Input)):::input\n ").concat(block(promptbookJson.promptTemplates
620
+ .flatMap(function (_a) {
621
+ var title = _a.title, dependentParameterNames = _a.dependentParameterNames, resultingParameterName = _a.resultingParameterName;
622
+ return __spreadArray([
623
+ "".concat(parameterNameToTemplateName(resultingParameterName), "(\"").concat(title, "\")")
624
+ ], __read(dependentParameterNames.map(function (dependentParameterName) {
625
+ return "".concat(parameterNameToTemplateName(dependentParameterName), "--\"{").concat(dependentParameterName, "}\"-->").concat(parameterNameToTemplateName(resultingParameterName));
626
+ })), false);
627
+ })
628
+ .join('\n')), "\n\n ").concat(block(promptbookJson.parameters
629
+ .filter(function (_a) {
630
+ var isOutput = _a.isOutput;
631
+ return isOutput;
632
+ })
633
+ .map(function (_a) {
634
+ var name = _a.name;
635
+ return "".concat(parameterNameToTemplateName(name), "--\"{").concat(name, "}\"-->output");
636
+ })
637
+ .join('\n')), "\n output((Output)):::output\n\n ").concat(block(promptbookJson.promptTemplates
638
+ .map(function (promptTemplate) {
639
+ var link = linkPromptTemplate(promptTemplate);
640
+ if (link === null) {
641
+ return '';
642
+ }
643
+ var href = link.href, title = link.title;
644
+ var templateName = parameterNameToTemplateName(promptTemplate.resultingParameterName);
645
+ return "click ".concat(templateName, " href \"").concat(href, "\" \"").concat(title, "\";");
646
+ })
647
+ .filter(function (line) { return line !== ''; })
648
+ .join('\n')), "\n\n classDef input color: grey;\n classDef output color: grey;\n\n end;\n\n "); });
649
+ return promptbookMermaid;
650
+ }
651
+ /**
652
+ * TODO: Maybe use some Mermaid library instead of string templating
653
+ * TODO: [🕌] When more than 2 functionalities, split into separate functions
654
+ */
655
+
629
656
  /**
630
657
  * Function parseNumber will parse number from string
631
658
  *
@@ -708,35 +735,80 @@ var PromptbookLogicError = /** @class */ (function (_super) {
708
735
  }(Error));
709
736
 
710
737
  /**
711
- * This error indicates errors during the execution of the promptbook
738
+ * This error occurs during the parameter replacement in the template
739
+ *
740
+ * Note: This is a kindof subtype of PromptbookExecutionError because it occurs during the execution of the pipeline
712
741
  */
713
- var PromptbookExecutionError = /** @class */ (function (_super) {
714
- __extends(PromptbookExecutionError, _super);
715
- function PromptbookExecutionError(message) {
742
+ var TemplateError = /** @class */ (function (_super) {
743
+ __extends(TemplateError, _super);
744
+ function TemplateError(message) {
716
745
  var _this = _super.call(this, message) || this;
717
- _this.name = 'PromptbookExecutionError';
718
- Object.setPrototypeOf(_this, PromptbookExecutionError.prototype);
746
+ _this.name = 'TemplateError';
747
+ Object.setPrototypeOf(_this, TemplateError.prototype);
719
748
  return _this;
720
749
  }
721
- return PromptbookExecutionError;
750
+ return TemplateError;
722
751
  }(Error));
723
752
 
724
753
  /**
725
- * This error occurs when some expectation is not met in the execution of the pipeline
754
+ * Replaces parameters in template with values from parameters object
726
755
  *
727
- * @private Always catched and rethrown as `PromptbookExecutionError`
728
- * Note: This is a kindof subtype of PromptbookExecutionError
756
+ * @param template the template with parameters in {curly} braces
757
+ * @param parameters the object with parameters
758
+ * @returns the template with replaced parameters
759
+ * @throws {TemplateError} if parameter is not defined, not closed, or not opened
760
+ *
761
+ * @private within the createPromptbookExecutor
729
762
  */
730
- var ExpectError = /** @class */ (function (_super) {
731
- __extends(ExpectError, _super);
732
- function ExpectError(message) {
733
- var _this = _super.call(this, message) || this;
734
- _this.name = 'ExpectError';
735
- Object.setPrototypeOf(_this, ExpectError.prototype);
736
- return _this;
763
+ function replaceParameters(template, parameters) {
764
+ var replacedTemplate = template;
765
+ var match;
766
+ var loopLimit = LOOP_LIMIT;
767
+ var _loop_1 = function () {
768
+ if (loopLimit-- < 0) {
769
+ throw new UnexpectedError('Loop limit reached during parameters replacement in `replaceParameters`');
770
+ }
771
+ var precol = match.groups.precol;
772
+ var parameterName = match.groups.parameterName;
773
+ if (parameterName === '') {
774
+ return "continue";
775
+ }
776
+ if (parameterName.indexOf('{') !== -1 || parameterName.indexOf('}') !== -1) {
777
+ throw new TemplateError('Parameter is already opened or not closed');
778
+ }
779
+ if (parameters[parameterName] === undefined) {
780
+ throw new TemplateError("Parameter {".concat(parameterName, "} is not defined"));
781
+ }
782
+ var parameterValue = parameters[parameterName];
783
+ if (parameterValue === undefined) {
784
+ throw new TemplateError("Parameter {".concat(parameterName, "} is not defined"));
785
+ }
786
+ parameterValue = parameterValue.toString();
787
+ if (parameterValue.includes('\n') && /^\s*\W{0,3}\s*$/.test(precol)) {
788
+ parameterValue = parameterValue
789
+ .split('\n')
790
+ .map(function (line, index) { return (index === 0 ? line : "".concat(precol).concat(line)); })
791
+ .join('\n');
792
+ }
793
+ replacedTemplate =
794
+ replacedTemplate.substring(0, match.index + precol.length) +
795
+ parameterValue +
796
+ replacedTemplate.substring(match.index + precol.length + parameterName.length + 2);
797
+ };
798
+ while ((match = /^(?<precol>.*){(?<parameterName>\w+)}(.*)/m /* <- Not global */
799
+ .exec(replacedTemplate))) {
800
+ _loop_1();
737
801
  }
738
- return ExpectError;
739
- }(Error));
802
+ // [💫] Check if there are parameters that are not closed properly
803
+ if (/{\w+$/.test(replacedTemplate)) {
804
+ throw new TemplateError('Parameter is not closed');
805
+ }
806
+ // [💫] Check if there are parameters that are not opened properly
807
+ if (/^\w+}/.test(replacedTemplate)) {
808
+ throw new TemplateError('Parameter is not opened');
809
+ }
810
+ return replacedTemplate;
811
+ }
740
812
 
741
813
  /**
742
814
  * Counts number of characters in the text
@@ -1064,118 +1136,6 @@ var CountUtils = {
1064
1136
  PAGES: countPages,
1065
1137
  };
1066
1138
 
1067
- /**
1068
- * Function checkExpectations will check if the expectations on given value are met
1069
- *
1070
- * Note: There are two simmilar functions:
1071
- * - `checkExpectations` which throws an error if the expectations are not met
1072
- * - `isPassingExpectations` which returns a boolean
1073
- *
1074
- * @throws {ExpectError} if the expectations are not met
1075
- * @returns {void} Nothing
1076
- */
1077
- function checkExpectations(expectations, value) {
1078
- var e_1, _a;
1079
- try {
1080
- for (var _b = __values(Object.entries(expectations)), _c = _b.next(); !_c.done; _c = _b.next()) {
1081
- var _d = __read(_c.value, 2), unit = _d[0], _e = _d[1], max = _e.max, min = _e.min;
1082
- var amount = CountUtils[unit.toUpperCase()](value);
1083
- if (min && amount < min) {
1084
- throw new ExpectError("Expected at least ".concat(min, " ").concat(unit, " but got ").concat(amount));
1085
- } /* not else */
1086
- if (max && amount > max) {
1087
- throw new ExpectError("Expected at most ".concat(max, " ").concat(unit, " but got ").concat(amount));
1088
- }
1089
- }
1090
- }
1091
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
1092
- finally {
1093
- try {
1094
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1095
- }
1096
- finally { if (e_1) throw e_1.error; }
1097
- }
1098
- }
1099
- /**
1100
- * TODO: [💝] Unite object for expecting amount and format
1101
- */
1102
-
1103
- /**
1104
- * This error occurs during the parameter replacement in the template
1105
- *
1106
- * Note: This is a kindof subtype of PromptbookExecutionError because it occurs during the execution of the pipeline
1107
- */
1108
- var TemplateError = /** @class */ (function (_super) {
1109
- __extends(TemplateError, _super);
1110
- function TemplateError(message) {
1111
- var _this = _super.call(this, message) || this;
1112
- _this.name = 'TemplateError';
1113
- Object.setPrototypeOf(_this, TemplateError.prototype);
1114
- return _this;
1115
- }
1116
- return TemplateError;
1117
- }(Error));
1118
-
1119
- /**
1120
- * Replaces parameters in template with values from parameters object
1121
- *
1122
- * @param template the template with parameters in {curly} braces
1123
- * @param parameters the object with parameters
1124
- * @returns the template with replaced parameters
1125
- * @throws {TemplateError} if parameter is not defined, not closed, or not opened
1126
- *
1127
- * @private within the createPromptbookExecutor
1128
- */
1129
- function replaceParameters(template, parameters) {
1130
- var replacedTemplate = template;
1131
- var match;
1132
- var loopLimit = LOOP_LIMIT;
1133
- var _loop_1 = function () {
1134
- if (loopLimit-- < 0) {
1135
- throw new UnexpectedError('Loop limit reached during parameters replacement in `replaceParameters`');
1136
- }
1137
- var precol = match.groups.precol;
1138
- var parameterName = match.groups.parameterName;
1139
- if (parameterName === '') {
1140
- return "continue";
1141
- }
1142
- if (parameterName.indexOf('{') !== -1 || parameterName.indexOf('}') !== -1) {
1143
- throw new TemplateError('Parameter is already opened or not closed');
1144
- }
1145
- if (parameters[parameterName] === undefined) {
1146
- throw new TemplateError("Parameter {".concat(parameterName, "} is not defined"));
1147
- }
1148
- var parameterValue = parameters[parameterName];
1149
- if (parameterValue === undefined) {
1150
- throw new TemplateError("Parameter {".concat(parameterName, "} is not defined"));
1151
- }
1152
- parameterValue = parameterValue.toString();
1153
- if (parameterValue.includes('\n') && /^\s*\W{0,3}\s*$/.test(precol)) {
1154
- parameterValue = parameterValue
1155
- .split('\n')
1156
- .map(function (line, index) { return (index === 0 ? line : "".concat(precol).concat(line)); })
1157
- .join('\n');
1158
- }
1159
- replacedTemplate =
1160
- replacedTemplate.substring(0, match.index + precol.length) +
1161
- parameterValue +
1162
- replacedTemplate.substring(match.index + precol.length + parameterName.length + 2);
1163
- };
1164
- while ((match = /^(?<precol>.*){(?<parameterName>\w+)}(.*)/m /* <- Not global */
1165
- .exec(replacedTemplate))) {
1166
- _loop_1();
1167
- }
1168
- // [💫] Check if there are parameters that are not closed properly
1169
- if (/{\w+$/.test(replacedTemplate)) {
1170
- throw new TemplateError('Parameter is not closed');
1171
- }
1172
- // [💫] Check if there are parameters that are not opened properly
1173
- if (/^\w+}/.test(replacedTemplate)) {
1174
- throw new TemplateError('Parameter is not opened');
1175
- }
1176
- return replacedTemplate;
1177
- }
1178
-
1179
1139
  /**
1180
1140
  * Function isValidJsonString will tell you if the string is valid JSON or not
1181
1141
  */
@@ -1330,16 +1290,71 @@ function normalizeToKebabCase(sentence) {
1330
1290
  return normalizedName;
1331
1291
  }
1332
1292
 
1333
- /**
1334
- * Execution type describes the way how the block is executed
1335
- *
1336
- * @see https://github.com/webgptorg/promptbook#execution-type
1337
- */
1338
- var ExecutionTypes = [
1339
- 'PROMPT_TEMPLATE',
1340
- 'SIMPLE_TEMPLATE',
1341
- 'SCRIPT',
1342
- 'PROMPT_DIALOG',
1293
+ /* tslint:disable */
1294
+ function normalizeTo_camelCase(sentence, __firstLetterCapital) {
1295
+ var e_1, _a;
1296
+ if (__firstLetterCapital === void 0) { __firstLetterCapital = false; }
1297
+ var charType;
1298
+ var lastCharType = null;
1299
+ var normalizedName = '';
1300
+ try {
1301
+ for (var sentence_1 = __values(sentence), sentence_1_1 = sentence_1.next(); !sentence_1_1.done; sentence_1_1 = sentence_1.next()) {
1302
+ var char = sentence_1_1.value;
1303
+ var normalizedChar = void 0;
1304
+ if (/^[a-z]$/.test(char)) {
1305
+ charType = 'LOWERCASE';
1306
+ normalizedChar = char;
1307
+ }
1308
+ else if (/^[A-Z]$/.test(char)) {
1309
+ charType = 'UPPERCASE';
1310
+ normalizedChar = char.toLowerCase();
1311
+ }
1312
+ else if (/^[0-9]$/.test(char)) {
1313
+ charType = 'NUMBER';
1314
+ normalizedChar = char;
1315
+ }
1316
+ else {
1317
+ charType = 'OTHER';
1318
+ normalizedChar = '';
1319
+ }
1320
+ if (!lastCharType) {
1321
+ if (__firstLetterCapital) {
1322
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: DRY
1323
+ }
1324
+ }
1325
+ else if (charType !== lastCharType &&
1326
+ !(charType === 'LOWERCASE' && lastCharType === 'UPPERCASE') &&
1327
+ !(lastCharType === 'NUMBER') &&
1328
+ !(charType === 'NUMBER')) {
1329
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: [🌺] DRY
1330
+ }
1331
+ normalizedName += normalizedChar;
1332
+ lastCharType = charType;
1333
+ }
1334
+ }
1335
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
1336
+ finally {
1337
+ try {
1338
+ if (sentence_1_1 && !sentence_1_1.done && (_a = sentence_1.return)) _a.call(sentence_1);
1339
+ }
1340
+ finally { if (e_1) throw e_1.error; }
1341
+ }
1342
+ return normalizedName;
1343
+ }
1344
+ /**
1345
+ * TODO: [🌺] Use some intermediate util splitWords
1346
+ */
1347
+
1348
+ /**
1349
+ * Execution type describes the way how the block is executed
1350
+ *
1351
+ * @see https://github.com/webgptorg/promptbook#execution-type
1352
+ */
1353
+ var ExecutionTypes = [
1354
+ 'PROMPT_TEMPLATE',
1355
+ 'SIMPLE_TEMPLATE',
1356
+ 'SCRIPT',
1357
+ 'PROMPT_DIALOG',
1343
1358
  // <- [🥻] Insert here when making new command
1344
1359
  ];
1345
1360
 
@@ -1810,6 +1825,9 @@ function promptbookStringToJson(promptbookString) {
1810
1825
  postprocessing = undefined;
1811
1826
  }
1812
1827
  dependentParameterNames = union(dependentParameterNames, extractParametersFromPromptTemplate(__assign(__assign({}, section), { description: description_1, executionType: executionType, content: content })));
1828
+ if (templateModelRequirements.modelVariant === undefined) {
1829
+ templateModelRequirements.modelVariant = 'CHAT';
1830
+ }
1813
1831
  promptbookJson.promptTemplates.push({
1814
1832
  name: titleToName(section.title),
1815
1833
  title: section.title,
@@ -1848,6 +1866,87 @@ function promptbookStringToJson(promptbookString) {
1848
1866
  * TODO: [🧠] Parameter flags - isInput, isOutput, isInternal
1849
1867
  */
1850
1868
 
1869
+ /**
1870
+ * Add or modify an auto-generated section in a markdown file
1871
+ *
1872
+ * @private within the library
1873
+ */
1874
+ function addAutoGeneratedSection(content, options) {
1875
+ var sectionName = options.sectionName, sectionContent = options.sectionContent;
1876
+ var warningLine = "<!-- \u26A0\uFE0F WARNING: This section was auto-generated -->";
1877
+ var sectionRegex = new RegExp("<!--".concat(sectionName, "-->([\\s\\S]*?)<!--/").concat(sectionName, "-->"), 'g');
1878
+ var sectionMatch = content.match(sectionRegex);
1879
+ if (sectionMatch) {
1880
+ return content.replace(sectionRegex, spaceTrim(function (block) { return "\n <!--".concat(sectionName, "-->\n ").concat(block(warningLine), "\n ").concat(block(sectionContent), "\n <!--/").concat(sectionName, "-->\n "); }));
1881
+ }
1882
+ var placeForSection = removeContentComments(content).match(/^##.*$/im);
1883
+ if (!placeForSection) {
1884
+ throw new Error("No place where to put the section <!--".concat(sectionName, "-->"));
1885
+ }
1886
+ var _a = __read(placeForSection, 1), heading = _a[0];
1887
+ return content.replace(heading, "<!--".concat(sectionName, "-->\n").concat(warningLine, "\n").concat(sectionContent, "\n<!--/").concat(sectionName, "-->\n\n").concat(heading));
1888
+ }
1889
+
1890
+ /**
1891
+ * Prettify the html code
1892
+ *
1893
+ * @param content raw html code
1894
+ * @returns formatted html code
1895
+ */
1896
+ function prettifyMarkdown(content) {
1897
+ try {
1898
+ return format(content, {
1899
+ parser: 'markdown',
1900
+ plugins: [parserHtml],
1901
+ // TODO: DRY - make some import or auto-copy of .prettierrc
1902
+ endOfLine: 'lf',
1903
+ tabWidth: 4,
1904
+ singleQuote: true,
1905
+ trailingComma: 'all',
1906
+ arrowParens: 'always',
1907
+ printWidth: 120,
1908
+ htmlWhitespaceSensitivity: 'ignore',
1909
+ jsxBracketSameLine: false,
1910
+ bracketSpacing: true,
1911
+ });
1912
+ }
1913
+ catch (error) {
1914
+ console.error('There was an error with prettifying the markdown, using the original as the fallback', {
1915
+ error: error,
1916
+ html: content,
1917
+ });
1918
+ return content;
1919
+ }
1920
+ }
1921
+
1922
+ /**
1923
+ * Prettyfies Promptbook string and adds Mermaid graph
1924
+ */
1925
+ function prettifyPromptbookString(promptbookString, options) {
1926
+ var isGraphAdded = options.isGraphAdded, isPrettifyed = options.isPrettifyed;
1927
+ if (isGraphAdded) {
1928
+ var promptbookJson = promptbookStringToJson(promptbookString);
1929
+ var promptbookMermaid_1 = renderPromptbookMermaid(promptbookJson, {
1930
+ linkPromptTemplate: function (promptTemplate) {
1931
+ return { href: "#".concat(promptTemplate.name), title: promptTemplate.title };
1932
+ },
1933
+ });
1934
+ var promptbookMermaidBlock = spaceTrim(function (block) { return "\n ```mermaid\n ".concat(block(promptbookMermaid_1), "\n ```\n "); });
1935
+ promptbookString = addAutoGeneratedSection(promptbookString, {
1936
+ sectionName: 'Graph',
1937
+ sectionContent: promptbookMermaidBlock,
1938
+ });
1939
+ }
1940
+ if (isPrettifyed) {
1941
+ promptbookString = prettifyMarkdown(promptbookString);
1942
+ }
1943
+ return promptbookString;
1944
+ }
1945
+ /**
1946
+ * TODO: Maybe use some Mermaid library instead of string templating
1947
+ * TODO: [🕌] When more than 2 functionalities, split into separate functions
1948
+ */
1949
+
1851
1950
  /**
1852
1951
  * Converts promptbook in JSON format to string format
1853
1952
  *
@@ -2074,6 +2173,7 @@ function isValidUrl(url) {
2074
2173
  * @throws {PromptbookLogicError} on logical error in the promptbook
2075
2174
  */
2076
2175
  function validatePromptbookJson(promptbook) {
2176
+ // TODO: [🧠] Maybe test if promptbook is a promise and make specific error case for that
2077
2177
  var e_1, _a, e_2, _b, e_3, _c, e_4, _d;
2078
2178
  if (promptbook.promptbookUrl !== undefined) {
2079
2179
  if (!isValidUrl(promptbook.promptbookUrl)) {
@@ -2081,6 +2181,16 @@ function validatePromptbookJson(promptbook) {
2081
2181
  throw new PromptbookLogicError("Invalid promptbook URL \"".concat(promptbook.promptbookUrl, "\""));
2082
2182
  }
2083
2183
  }
2184
+ // TODO: [🧠] Maybe do here some propper JSON-schema / ZOD checking
2185
+ if (!Array.isArray(promptbook.parameters)) {
2186
+ // TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
2187
+ throw new PromptbookSyntaxError(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 ")));
2188
+ }
2189
+ // TODO: [🧠] Maybe do here some propper JSON-schema / ZOD checking
2190
+ if (!Array.isArray(promptbook.promptTemplates)) {
2191
+ // TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
2192
+ throw new PromptbookSyntaxError(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 ")));
2193
+ }
2084
2194
  var _loop_1 = function (parameter) {
2085
2195
  if (parameter.isInput && parameter.isOutput) {
2086
2196
  throw new PromptbookLogicError("Parameter {".concat(parameter.name, "} can not be both input and output"));
@@ -2127,9 +2237,8 @@ function validatePromptbookJson(promptbook) {
2127
2237
  }
2128
2238
  definedParameters.add(template.resultingParameterName);
2129
2239
  if (template.executionType === 'PROMPT_TEMPLATE' &&
2130
- (template.modelRequirements.modelVariant === undefined ||
2131
- template.modelRequirements.modelName === undefined)) {
2132
- throw new PromptbookLogicError(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 ")));
2240
+ (template.modelRequirements.modelVariant === undefined)) {
2241
+ throw new PromptbookLogicError(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 ")));
2133
2242
  }
2134
2243
  if (template.jokers && template.jokers.length > 0) {
2135
2244
  if (!template.expectFormat &&
@@ -2236,6 +2345,119 @@ function validatePromptbookJson(promptbook) {
2236
2345
  * > ex port function validatePromptbookJson(promptbook: unknown): asserts promptbook is PromptbookJson {
2237
2346
  */
2238
2347
 
2348
+ /**
2349
+ * This error indicates errors during the execution of the promptbook
2350
+ */
2351
+ var PromptbookExecutionError = /** @class */ (function (_super) {
2352
+ __extends(PromptbookExecutionError, _super);
2353
+ function PromptbookExecutionError(message) {
2354
+ var _this = _super.call(this, message) || this;
2355
+ _this.name = 'PromptbookExecutionError';
2356
+ Object.setPrototypeOf(_this, PromptbookExecutionError.prototype);
2357
+ return _this;
2358
+ }
2359
+ return PromptbookExecutionError;
2360
+ }(Error));
2361
+
2362
+ /**
2363
+ * Asserts that the execution of a promptnook is successful
2364
+ *
2365
+ * @param executionResult - The partial result of the promptnook execution
2366
+ * @throws {PromptbookExecutionError} If the execution is not successful or if multiple errors occurred
2367
+ */
2368
+ function assertsExecutionSuccessful(executionResult) {
2369
+ var isSuccessful = executionResult.isSuccessful, errors = executionResult.errors;
2370
+ if (isSuccessful === true) {
2371
+ return;
2372
+ }
2373
+ if (errors.length === 0) {
2374
+ throw new PromptbookExecutionError("Promptnook Execution failed because of unknown reason");
2375
+ }
2376
+ else if (errors.length === 1) {
2377
+ throw errors[0];
2378
+ }
2379
+ else {
2380
+ throw new PromptbookExecutionError(spaceTrim(function (block) { return "\n Multiple errors occurred during promptnook execution\n\n ".concat(block(errors.map(function (error) { return '- ' + error.message; }).join('\n')), "\n "); }));
2381
+ }
2382
+ }
2383
+ /**
2384
+ * TODO: [🧠] Can this return type be better typed than void
2385
+ */
2386
+
2387
+ /**
2388
+ * This error occurs when some expectation is not met in the execution of the pipeline
2389
+ *
2390
+ * @private Always catched and rethrown as `PromptbookExecutionError`
2391
+ * Note: This is a kindof subtype of PromptbookExecutionError
2392
+ */
2393
+ var ExpectError = /** @class */ (function (_super) {
2394
+ __extends(ExpectError, _super);
2395
+ function ExpectError(message) {
2396
+ var _this = _super.call(this, message) || this;
2397
+ _this.name = 'ExpectError';
2398
+ Object.setPrototypeOf(_this, ExpectError.prototype);
2399
+ return _this;
2400
+ }
2401
+ return ExpectError;
2402
+ }(Error));
2403
+
2404
+ /**
2405
+ * Function checkExpectations will check if the expectations on given value are met
2406
+ *
2407
+ * Note: There are two simmilar functions:
2408
+ * - `checkExpectations` which throws an error if the expectations are not met
2409
+ * - `isPassingExpectations` which returns a boolean
2410
+ *
2411
+ * @throws {ExpectError} if the expectations are not met
2412
+ * @returns {void} Nothing
2413
+ */
2414
+ function checkExpectations(expectations, value) {
2415
+ var e_1, _a;
2416
+ try {
2417
+ for (var _b = __values(Object.entries(expectations)), _c = _b.next(); !_c.done; _c = _b.next()) {
2418
+ var _d = __read(_c.value, 2), unit = _d[0], _e = _d[1], max = _e.max, min = _e.min;
2419
+ var amount = CountUtils[unit.toUpperCase()](value);
2420
+ if (min && amount < min) {
2421
+ throw new ExpectError("Expected at least ".concat(min, " ").concat(unit, " but got ").concat(amount));
2422
+ } /* not else */
2423
+ if (max && amount > max) {
2424
+ throw new ExpectError("Expected at most ".concat(max, " ").concat(unit, " but got ").concat(amount));
2425
+ }
2426
+ }
2427
+ }
2428
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
2429
+ finally {
2430
+ try {
2431
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
2432
+ }
2433
+ finally { if (e_1) throw e_1.error; }
2434
+ }
2435
+ }
2436
+ /**
2437
+ * Function checkExpectations will check if the expectations on given value are met
2438
+ *
2439
+ * Note: There are two simmilar functions:
2440
+ * - `checkExpectations` which throws an error if the expectations are not met
2441
+ * - `isPassingExpectations` which returns a boolean
2442
+ *
2443
+ * @returns {boolean} True if the expectations are met
2444
+ */
2445
+ function isPassingExpectations(expectations, value) {
2446
+ try {
2447
+ checkExpectations(expectations, value);
2448
+ return true;
2449
+ }
2450
+ catch (error) {
2451
+ if (!(error instanceof ExpectError)) {
2452
+ throw error;
2453
+ }
2454
+ return false;
2455
+ }
2456
+ }
2457
+ /**
2458
+ * TODO: [💝] Unite object for expecting amount and format
2459
+ */
2460
+
2239
2461
  /**
2240
2462
  * Creates executor function from promptbook and execution tools.
2241
2463
  *
@@ -2317,7 +2539,7 @@ function createPromptbookExecutor(options) {
2317
2539
  title: currentTemplate.title,
2318
2540
  promptbookUrl: "".concat(promptbook.promptbookUrl
2319
2541
  ? promptbook.promptbookUrl
2320
- : 'anonymous' /* <- [🧠][🈴] How to deal with anonymous PROMPTBOOKs, do here some auto-url like SHA-256 based ad-hoc identifier? */, "#").concat(currentTemplate.name),
2542
+ : 'anonymous' /* <- TODO: [🧠] How to deal with anonymous PROMPTBOOKs, do here some auto-url like SHA-256 based ad-hoc identifier? */, "#").concat(currentTemplate.name),
2321
2543
  parameters: parametersToPass,
2322
2544
  content: replaceParameters(currentTemplate.content, parametersToPass) /* <- [2] */,
2323
2545
  modelRequirements: currentTemplate.modelRequirements,
@@ -2756,51 +2978,182 @@ function createPromptbookExecutor(options) {
2756
2978
  */
2757
2979
 
2758
2980
  /**
2759
- * Delagates the user interaction to a async callback function
2760
- * You need to provide your own implementation of this callback function and its bind to UI.
2981
+ * Multiple LLM Execution Tools is a proxy server that uses multiple execution tools internally and exposes the executor interface externally.
2982
+ *
2983
+ * @see https://github.com/webgptorg/promptbook#multiple-server
2761
2984
  */
2762
- var CallbackInterfaceTools = /** @class */ (function () {
2763
- function CallbackInterfaceTools(options) {
2764
- this.options = options;
2765
- }
2985
+ var MultipleLlmExecutionTools = /** @class */ (function () {
2766
2986
  /**
2767
- * Trigger the custom callback function
2987
+ * Gets array of execution tools in order of priority
2768
2988
  */
2769
- CallbackInterfaceTools.prototype.promptDialog = function (options) {
2770
- return __awaiter(this, void 0, void 0, function () {
2771
- var answer;
2772
- return __generator(this, function (_a) {
2773
- switch (_a.label) {
2774
- case 0: return [4 /*yield*/, this.options.callback(options)];
2775
- case 1:
2776
- answer = _a.sent();
2777
- if (this.options.isVerbose) {
2778
- console.info(spaceTrim(function (block) { return "\n \uD83D\uDCD6 ".concat(block(options.promptTitle), "\n \uD83D\uDC64 ").concat(block(answer), "\n "); }));
2779
- }
2780
- return [2 /*return*/, answer];
2781
- }
2782
- });
2783
- });
2784
- };
2785
- return CallbackInterfaceTools;
2786
- }());
2787
-
2788
- /**
2789
- * Wrapper around `window.prompt` synchronous function that interacts with the user via browser prompt
2790
- *
2791
- * Warning: It is used for testing and mocking
2792
- * **NOT intended to use in the production** due to its synchronous nature.
2793
- */
2794
- var SimplePromptInterfaceTools = /** @class */ (function () {
2795
- function SimplePromptInterfaceTools(options) {
2796
- this.options = options;
2989
+ function MultipleLlmExecutionTools() {
2990
+ var llmExecutionTools = [];
2991
+ for (var _i = 0; _i < arguments.length; _i++) {
2992
+ llmExecutionTools[_i] = arguments[_i];
2993
+ }
2994
+ this.llmExecutionTools = llmExecutionTools;
2797
2995
  }
2798
2996
  /**
2799
- * Trigger window.PROMPT DIALOG
2997
+ * Calls the best available chat model
2800
2998
  */
2801
- SimplePromptInterfaceTools.prototype.promptDialog = function (options) {
2802
- return __awaiter(this, void 0, void 0, function () {
2803
- var answer;
2999
+ MultipleLlmExecutionTools.prototype.gptChat = function (prompt) {
3000
+ return this.gptCommon(prompt);
3001
+ };
3002
+ /**
3003
+ * Calls the best available completion model
3004
+ */
3005
+ MultipleLlmExecutionTools.prototype.gptComplete = function (prompt) {
3006
+ return this.gptCommon(prompt);
3007
+ };
3008
+ /**
3009
+ * Calls the best available model
3010
+ */
3011
+ MultipleLlmExecutionTools.prototype.gptCommon = function (prompt) {
3012
+ return __awaiter(this, void 0, void 0, function () {
3013
+ var errors, _a, _b, llmExecutionTools, error_1, e_1_1;
3014
+ var e_1, _c;
3015
+ return __generator(this, function (_d) {
3016
+ switch (_d.label) {
3017
+ case 0:
3018
+ errors = [];
3019
+ _d.label = 1;
3020
+ case 1:
3021
+ _d.trys.push([1, 11, 12, 13]);
3022
+ _a = __values(this.llmExecutionTools), _b = _a.next();
3023
+ _d.label = 2;
3024
+ case 2:
3025
+ if (!!_b.done) return [3 /*break*/, 10];
3026
+ llmExecutionTools = _b.value;
3027
+ _d.label = 3;
3028
+ case 3:
3029
+ _d.trys.push([3, 8, , 9]);
3030
+ if (!(prompt.modelRequirements.modelVariant === 'CHAT')) return [3 /*break*/, 5];
3031
+ return [4 /*yield*/, llmExecutionTools.gptChat(prompt)];
3032
+ case 4: return [2 /*return*/, _d.sent()];
3033
+ case 5:
3034
+ if (!(prompt.modelRequirements.modelVariant === 'COMPLETION')) return [3 /*break*/, 7];
3035
+ return [4 /*yield*/, llmExecutionTools.gptComplete(prompt)];
3036
+ case 6: return [2 /*return*/, _d.sent()];
3037
+ case 7: return [3 /*break*/, 9];
3038
+ case 8:
3039
+ error_1 = _d.sent();
3040
+ if (!(error_1 instanceof Error)) {
3041
+ throw error_1;
3042
+ }
3043
+ errors.push(error_1);
3044
+ return [3 /*break*/, 9];
3045
+ case 9:
3046
+ _b = _a.next();
3047
+ return [3 /*break*/, 2];
3048
+ case 10: return [3 /*break*/, 13];
3049
+ case 11:
3050
+ e_1_1 = _d.sent();
3051
+ e_1 = { error: e_1_1 };
3052
+ return [3 /*break*/, 13];
3053
+ case 12:
3054
+ try {
3055
+ if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
3056
+ }
3057
+ finally { if (e_1) throw e_1.error; }
3058
+ return [7 /*endfinally*/];
3059
+ case 13: throw new Error(spaceTrim$1(function (block) { return "\n All execution tools failed:\n \n ".concat(block(errors.map(function (error) { return "- ".concat(error.name || 'Error', ": ").concat(error.message); }).join('\n')), "\n \n "); }));
3060
+ }
3061
+ });
3062
+ });
3063
+ };
3064
+ /**
3065
+ * List all available models that can be used
3066
+ * This liost is a combination of all available models from all execution tools
3067
+ */
3068
+ MultipleLlmExecutionTools.prototype.listModels = function () {
3069
+ return __awaiter(this, void 0, void 0, function () {
3070
+ var availableModels, _a, _b, llmExecutionTools, models, e_2_1;
3071
+ var e_2, _c;
3072
+ return __generator(this, function (_d) {
3073
+ switch (_d.label) {
3074
+ case 0:
3075
+ availableModels = [];
3076
+ _d.label = 1;
3077
+ case 1:
3078
+ _d.trys.push([1, 6, 7, 8]);
3079
+ _a = __values(this.llmExecutionTools), _b = _a.next();
3080
+ _d.label = 2;
3081
+ case 2:
3082
+ if (!!_b.done) return [3 /*break*/, 5];
3083
+ llmExecutionTools = _b.value;
3084
+ return [4 /*yield*/, llmExecutionTools.listModels()];
3085
+ case 3:
3086
+ models = _d.sent();
3087
+ availableModels.push.apply(availableModels, __spreadArray([], __read(models), false));
3088
+ _d.label = 4;
3089
+ case 4:
3090
+ _b = _a.next();
3091
+ return [3 /*break*/, 2];
3092
+ case 5: return [3 /*break*/, 8];
3093
+ case 6:
3094
+ e_2_1 = _d.sent();
3095
+ e_2 = { error: e_2_1 };
3096
+ return [3 /*break*/, 8];
3097
+ case 7:
3098
+ try {
3099
+ if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
3100
+ }
3101
+ finally { if (e_2) throw e_2.error; }
3102
+ return [7 /*endfinally*/];
3103
+ case 8: return [2 /*return*/, availableModels];
3104
+ }
3105
+ });
3106
+ });
3107
+ };
3108
+ return MultipleLlmExecutionTools;
3109
+ }());
3110
+
3111
+ /**
3112
+ * Delagates the user interaction to a async callback function
3113
+ * You need to provide your own implementation of this callback function and its bind to UI.
3114
+ */
3115
+ var CallbackInterfaceTools = /** @class */ (function () {
3116
+ function CallbackInterfaceTools(options) {
3117
+ this.options = options;
3118
+ }
3119
+ /**
3120
+ * Trigger the custom callback function
3121
+ */
3122
+ CallbackInterfaceTools.prototype.promptDialog = function (options) {
3123
+ return __awaiter(this, void 0, void 0, function () {
3124
+ var answer;
3125
+ return __generator(this, function (_a) {
3126
+ switch (_a.label) {
3127
+ case 0: return [4 /*yield*/, this.options.callback(options)];
3128
+ case 1:
3129
+ answer = _a.sent();
3130
+ if (this.options.isVerbose) {
3131
+ console.info(spaceTrim(function (block) { return "\n \uD83D\uDCD6 ".concat(block(options.promptTitle), "\n \uD83D\uDC64 ").concat(block(answer), "\n "); }));
3132
+ }
3133
+ return [2 /*return*/, answer];
3134
+ }
3135
+ });
3136
+ });
3137
+ };
3138
+ return CallbackInterfaceTools;
3139
+ }());
3140
+
3141
+ /**
3142
+ * Wrapper around `window.prompt` synchronous function that interacts with the user via browser prompt
3143
+ *
3144
+ * Warning: It is used for testing and mocking
3145
+ * **NOT intended to use in the production** due to its synchronous nature.
3146
+ */
3147
+ var SimplePromptInterfaceTools = /** @class */ (function () {
3148
+ function SimplePromptInterfaceTools(options) {
3149
+ this.options = options;
3150
+ }
3151
+ /**
3152
+ * Trigger window.PROMPT DIALOG
3153
+ */
3154
+ SimplePromptInterfaceTools.prototype.promptDialog = function (options) {
3155
+ return __awaiter(this, void 0, void 0, function () {
3156
+ var answer;
2804
3157
  return __generator(this, function (_a) {
2805
3158
  answer = window.prompt(spaceTrim(function (block) { return "\n ".concat(block(options.promptTitle), "\n\n ").concat(block(options.promptMessage), "\n "); }));
2806
3159
  if (this.options.isVerbose) {
@@ -2816,6 +3169,36 @@ var SimplePromptInterfaceTools = /** @class */ (function () {
2816
3169
  return SimplePromptInterfaceTools;
2817
3170
  }());
2818
3171
 
3172
+ /**
3173
+ * Detects if the code is running in a browser environment in main thread (Not in a web worker)
3174
+ */
3175
+ new Function("\n try {\n return this === window;\n } catch (e) {\n return false;\n }\n");
3176
+ /**
3177
+ * Detects if the code is running in a Node.js environment
3178
+ */
3179
+ var isRunningInNode = new Function("\n try {\n return this === global;\n } catch (e) {\n return false;\n }\n");
3180
+ /**
3181
+ * Detects if the code is running in a web worker
3182
+ */
3183
+ 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");
3184
+
3185
+ /**
3186
+ * Returns the same value that is passed as argument.
3187
+ * No side effects.
3188
+ *
3189
+ * Note: It can be usefull for leveling indentation
3190
+ *
3191
+ * @param value any values
3192
+ * @returns the same values
3193
+ */
3194
+ function just(value) {
3195
+ if (value === undefined) {
3196
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3197
+ return undefined;
3198
+ }
3199
+ return value;
3200
+ }
3201
+
2819
3202
  /**
2820
3203
  * This error indicates that promptbook not found in the library
2821
3204
  */
@@ -2873,6 +3256,12 @@ var SimplePromptbookLibrary = /** @class */ (function () {
2873
3256
  throw new PromptbookReferenceError(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 ")));
2874
3257
  }
2875
3258
  validatePromptbookJson(promptbook);
3259
+ // Note: [🦄]
3260
+ if (this.library.has(promptbook.promptbookUrl) &&
3261
+ promptbookJsonToString(promptbook) !==
3262
+ promptbookJsonToString(this.library.get(promptbook.promptbookUrl))) {
3263
+ throw new PromptbookReferenceError(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 ")));
3264
+ }
2876
3265
  this.library.set(promptbook.promptbookUrl, promptbook);
2877
3266
  }
2878
3267
  }
@@ -2899,6 +3288,9 @@ var SimplePromptbookLibrary = /** @class */ (function () {
2899
3288
  var _this = this;
2900
3289
  var promptbook = this.library.get(url);
2901
3290
  if (!promptbook) {
3291
+ if (this.listPromptbooks().length === 0) {
3292
+ throw new PromptbookNotFoundError(spaceTrim("\n Promptbook with url \"".concat(url, "\" not found\n\n No promptbooks available\n ")));
3293
+ }
2902
3294
  throw new PromptbookNotFoundError(spaceTrim(function (block) { return "\n Promptbook with url \"".concat(url, "\" not found\n\n Available promptbooks:\n ").concat(block(_this.listPromptbooks()
2903
3295
  .map(function (promptbookUrl) { return "- ".concat(promptbookUrl); })
2904
3296
  .join('\n')), "\n\n "); }));
@@ -2971,11 +3363,11 @@ function createPromptbookLibraryFromSources() {
2971
3363
  * Note: The function does NOT return promise it returns the library directly which waits for the sources to be resolved
2972
3364
  * when error occurs in given promise or factory function, it is thrown during `listPromptbooks` or `getPromptbookByUrl` call
2973
3365
  *
3366
+ * Note: Consider using `createPromptbookLibraryFromDirectory` or `createPromptbookLibraryFromUrl`
2974
3367
  *
2975
3368
  * @param promptbookSourcesPromiseOrFactory
2976
3369
  * @returns PromptbookLibrary
2977
- *
2978
- * @deprecated Consider using `createPromptbookLibraryFromUrl` or `createPromptbookLibraryFromDirectory`
3370
+ * @private Just internal tool for other constructor functions
2979
3371
  */
2980
3372
  function createPromptbookLibraryFromPromise(promptbookSourcesPromiseOrFactory) {
2981
3373
  var library;
@@ -3044,6 +3436,228 @@ function createPromptbookLibraryFromPromise(promptbookSourcesPromiseOrFactory) {
3044
3436
  * TODO: [🍓][🚯] !!! Add to README and samples + maybe make `@promptbook/library` package
3045
3437
  */
3046
3438
 
3439
+ /**
3440
+ * Constructs Promptbook from given directory
3441
+ *
3442
+ * Note: Works only in Node.js environment because it reads the file system
3443
+ *
3444
+ * @param path - path to the directory with promptbooks
3445
+ * @param options - Misc options for the library
3446
+ * @returns PromptbookLibrary
3447
+ */
3448
+ function createPromptbookLibraryFromDirectory(path, options) {
3449
+ return __awaiter(this, void 0, void 0, function () {
3450
+ var _a, _b, isRecursive, _c, isVerbose, _d, isLazyLoaded, library;
3451
+ var _this = this;
3452
+ return __generator(this, function (_e) {
3453
+ switch (_e.label) {
3454
+ case 0:
3455
+ if (!isRunningInNode()) {
3456
+ throw new Error('Function `createPromptbookLibraryFromDirectory` can only be run in Node.js environment because it reads the file system.');
3457
+ }
3458
+ _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;
3459
+ library = createPromptbookLibraryFromPromise(function () { return __awaiter(_this, void 0, void 0, function () {
3460
+ var fsPromises, readFile, fileNames, promptbooks, fileNames_1, fileNames_1_1, fileName, promptbook, promptbookString, _a, _b, e_1_1;
3461
+ var e_1, _c;
3462
+ return __generator(this, function (_d) {
3463
+ switch (_d.label) {
3464
+ case 0:
3465
+ if (isVerbose) {
3466
+ console.info("Creating promptbook library from path ".concat(path));
3467
+ }
3468
+ fsPromises = require(just('fs/promises') /* <- Note: [1] */);
3469
+ readFile = fsPromises.readFile;
3470
+ return [4 /*yield*/, listAllFiles(path, isRecursive)];
3471
+ case 1:
3472
+ fileNames = _d.sent();
3473
+ if (isVerbose) {
3474
+ console.info('createPromptbookLibraryFromDirectory', { path: path, isRecursive: isRecursive, fileNames: fileNames });
3475
+ }
3476
+ promptbooks = [];
3477
+ _d.label = 2;
3478
+ case 2:
3479
+ _d.trys.push([2, 11, 12, 13]);
3480
+ fileNames_1 = __values(fileNames), fileNames_1_1 = fileNames_1.next();
3481
+ _d.label = 3;
3482
+ case 3:
3483
+ if (!!fileNames_1_1.done) return [3 /*break*/, 10];
3484
+ fileName = fileNames_1_1.value;
3485
+ promptbook = null;
3486
+ if (!fileName.endsWith('.ptbk.md')) return [3 /*break*/, 5];
3487
+ return [4 /*yield*/, readFile(fileName, 'utf8')];
3488
+ case 4:
3489
+ promptbookString = (_d.sent());
3490
+ promptbook = promptbookStringToJson(promptbookString);
3491
+ return [3 /*break*/, 8];
3492
+ case 5:
3493
+ if (!fileName.endsWith('.ptbk.json')) return [3 /*break*/, 7];
3494
+ if (isVerbose) {
3495
+ console.info("Loading ".concat(fileName));
3496
+ }
3497
+ _b = (_a = JSON).parse;
3498
+ return [4 /*yield*/, readFile(fileName, 'utf8')];
3499
+ case 6:
3500
+ // TODO: Handle non-valid JSON files
3501
+ promptbook = _b.apply(_a, [_d.sent()]);
3502
+ return [3 /*break*/, 8];
3503
+ case 7:
3504
+ if (isVerbose) {
3505
+ console.info("Skipping file ".concat(fileName));
3506
+ }
3507
+ _d.label = 8;
3508
+ case 8:
3509
+ // ---
3510
+ if (promptbook !== null) {
3511
+ if (!promptbook.promptbookUrl) {
3512
+ if (isVerbose) {
3513
+ console.info("Not loading ".concat(fileName, " - missing URL"));
3514
+ }
3515
+ }
3516
+ else {
3517
+ if (isVerbose) {
3518
+ console.info("Loading ".concat(fileName));
3519
+ }
3520
+ // Note: [🦄] Promptbook with same url uniqueness will be checked automatically in SimplePromptbookLibrary
3521
+ promptbooks.push(promptbook);
3522
+ }
3523
+ }
3524
+ _d.label = 9;
3525
+ case 9:
3526
+ fileNames_1_1 = fileNames_1.next();
3527
+ return [3 /*break*/, 3];
3528
+ case 10: return [3 /*break*/, 13];
3529
+ case 11:
3530
+ e_1_1 = _d.sent();
3531
+ e_1 = { error: e_1_1 };
3532
+ return [3 /*break*/, 13];
3533
+ case 12:
3534
+ try {
3535
+ if (fileNames_1_1 && !fileNames_1_1.done && (_c = fileNames_1.return)) _c.call(fileNames_1);
3536
+ }
3537
+ finally { if (e_1) throw e_1.error; }
3538
+ return [7 /*endfinally*/];
3539
+ case 13: return [2 /*return*/, promptbooks];
3540
+ }
3541
+ });
3542
+ }); });
3543
+ if (!(isLazyLoaded === false)) return [3 /*break*/, 2];
3544
+ return [4 /*yield*/, library.listPromptbooks()];
3545
+ case 1:
3546
+ _e.sent();
3547
+ _e.label = 2;
3548
+ case 2: return [2 /*return*/, library];
3549
+ }
3550
+ });
3551
+ });
3552
+ }
3553
+ /**
3554
+ * Reads all files in the directory
3555
+ *
3556
+ * @param path
3557
+ * @param isRecursive
3558
+ * @returns List of all files in the directory
3559
+ * @private internal function for `createPromptbookLibraryFromDirectory`
3560
+ */
3561
+ function listAllFiles(path, isRecursive) {
3562
+ return __awaiter(this, void 0, void 0, function () {
3563
+ var fsPromises, readdir, dirents, fileNames, _a, _b, dirent, subPath, _c, _d, _e, _f, e_2_1;
3564
+ var e_2, _g;
3565
+ return __generator(this, function (_h) {
3566
+ switch (_h.label) {
3567
+ case 0:
3568
+ fsPromises = require(just('fs/promises') /* <- Note: [1] */);
3569
+ readdir = fsPromises.readdir;
3570
+ return [4 /*yield*/, readdir(path, {
3571
+ withFileTypes: true /* Note: This is not working: recursive: isRecursive */,
3572
+ })];
3573
+ case 1:
3574
+ dirents = _h.sent();
3575
+ fileNames = dirents.filter(function (dirent) { return dirent.isFile(); }).map(function (_a) {
3576
+ var name = _a.name;
3577
+ return join(path, name);
3578
+ });
3579
+ if (!isRecursive) return [3 /*break*/, 9];
3580
+ _h.label = 2;
3581
+ case 2:
3582
+ _h.trys.push([2, 7, 8, 9]);
3583
+ _a = __values(dirents.filter(function (dirent) { return dirent.isDirectory(); })), _b = _a.next();
3584
+ _h.label = 3;
3585
+ case 3:
3586
+ if (!!_b.done) return [3 /*break*/, 6];
3587
+ dirent = _b.value;
3588
+ subPath = join(path, dirent.name);
3589
+ _d = (_c = fileNames.push).apply;
3590
+ _e = [fileNames];
3591
+ _f = [[]];
3592
+ return [4 /*yield*/, listAllFiles(subPath, isRecursive)];
3593
+ case 4:
3594
+ _d.apply(_c, _e.concat([__spreadArray.apply(void 0, _f.concat([__read.apply(void 0, [(_h.sent())]), false]))]));
3595
+ _h.label = 5;
3596
+ case 5:
3597
+ _b = _a.next();
3598
+ return [3 /*break*/, 3];
3599
+ case 6: return [3 /*break*/, 9];
3600
+ case 7:
3601
+ e_2_1 = _h.sent();
3602
+ e_2 = { error: e_2_1 };
3603
+ return [3 /*break*/, 9];
3604
+ case 8:
3605
+ try {
3606
+ if (_b && !_b.done && (_g = _a.return)) _g.call(_a);
3607
+ }
3608
+ finally { if (e_2) throw e_2.error; }
3609
+ return [7 /*endfinally*/];
3610
+ case 9: return [2 /*return*/, fileNames];
3611
+ }
3612
+ });
3613
+ });
3614
+ }
3615
+ /***
3616
+ * TODO: [🧠] Maybe do not do hacks like [1] and just create package @promptbook/node
3617
+ * [🍓][🚯] maybe make `@promptbook/library` package
3618
+ * TODO: Fix the dynamic import issue in Webpack (! Not working !)
3619
+ * > ./node_modules/@promptbook/core/esm/index.es.js
3620
+ * > Critical dependency: the request of a dependency is an expression
3621
+ *
3622
+ * Note: [1] Using require(just('fs/promises')) to allow
3623
+ * the `@promptbook/core` work for both Node.js and browser environments
3624
+ */
3625
+
3626
+ /**
3627
+ * Constructs Promptbook from remote Promptbase URL
3628
+
3629
+ * @returns PromptbookLibrary
3630
+ */
3631
+ function createPromptbookLibraryFromUrl(url, options) {
3632
+ return __awaiter(this, void 0, void 0, function () {
3633
+ var _a, _b, isVerbose, _c, isLazyLoaded, library;
3634
+ var _this = this;
3635
+ return __generator(this, function (_d) {
3636
+ switch (_d.label) {
3637
+ case 0:
3638
+ _a = options || {}, _b = _a.isVerbose, isVerbose = _b === void 0 ? false : _b, _c = _a.isLazyLoaded, isLazyLoaded = _c === void 0 ? false : _c;
3639
+ library = createPromptbookLibraryFromPromise(function () { return __awaiter(_this, void 0, void 0, function () {
3640
+ return __generator(this, function (_a) {
3641
+ if (isVerbose) {
3642
+ console.info("Creating promptbook library from url ".concat(url.toString()));
3643
+ }
3644
+ throw new Error('Not implemented yet');
3645
+ });
3646
+ }); });
3647
+ if (!(isLazyLoaded === false)) return [3 /*break*/, 2];
3648
+ return [4 /*yield*/, library.listPromptbooks()];
3649
+ case 1:
3650
+ _d.sent();
3651
+ _d.label = 2;
3652
+ case 2: return [2 /*return*/, library];
3653
+ }
3654
+ });
3655
+ });
3656
+ }
3657
+ /***
3658
+ * TODO: [🍓][🚯] !!! Add to README and samples + maybe make `@promptbook/library` package
3659
+ */
3660
+
3047
3661
  /**
3048
3662
  * Creates PromptbookLibrary as a subset of another PromptbookLibrary
3049
3663
  *
@@ -3127,135 +3741,329 @@ function createPromptbookSublibrary(library, predicate) {
3127
3741
  */
3128
3742
 
3129
3743
  /**
3130
- * Multiple LLM Execution Tools is a proxy server that uses multiple execution tools internally and exposes the executor interface externally.
3744
+ * Just testing imports and compatibility
3745
+ */
3746
+ function justTestFsImport() {
3747
+ return __awaiter(this, void 0, void 0, function () {
3748
+ var files;
3749
+ return __generator(this, function (_a) {
3750
+ switch (_a.label) {
3751
+ case 0:
3752
+ if (!isRunningInNode()) {
3753
+ throw new Error('Function `testFiles` can only be run in Node.js environment because it reads the file system.');
3754
+ }
3755
+ return [4 /*yield*/, require(just('glob-promise'))('/**/*')];
3756
+ case 1:
3757
+ files = _a.sent();
3758
+ console.info('testFiles', { files: files });
3759
+ return [2 /*return*/];
3760
+ }
3761
+ });
3762
+ });
3763
+ }
3764
+ /**
3765
+ * TODO: !!! Remove this file
3766
+ */
3767
+
3768
+ /**
3769
+ * Format either small or big number
3131
3770
  *
3132
- * @see https://github.com/webgptorg/promptbook#multiple-server
3771
+ * @private within the library
3133
3772
  */
3134
- var MultipleLlmExecutionTools = /** @class */ (function () {
3135
- /**
3136
- * Gets array of execution tools in order of priority
3137
- */
3138
- function MultipleLlmExecutionTools() {
3139
- var llmExecutionTools = [];
3140
- for (var _i = 0; _i < arguments.length; _i++) {
3141
- llmExecutionTools[_i] = arguments[_i];
3773
+ function formatNumber(value) {
3774
+ if (value === 0) {
3775
+ return '0';
3776
+ }
3777
+ for (var exponent = 0; exponent < 15; exponent++) {
3778
+ var factor = Math.pow(10, exponent);
3779
+ var valueRounded = Math.round(value * factor) / factor;
3780
+ if (Math.abs(value - valueRounded) / value <
3781
+ 0.001 /* <- TODO: Pass as option, pass to executionReportJsonToString as option */) {
3782
+ return valueRounded.toFixed(exponent);
3142
3783
  }
3143
- this.llmExecutionTools = llmExecutionTools;
3144
3784
  }
3145
- /**
3146
- * Calls the best available chat model
3147
- */
3148
- MultipleLlmExecutionTools.prototype.gptChat = function (prompt) {
3149
- return this.gptCommon(prompt);
3150
- };
3151
- /**
3152
- * Calls the best available completion model
3153
- */
3154
- MultipleLlmExecutionTools.prototype.gptComplete = function (prompt) {
3155
- return this.gptCommon(prompt);
3785
+ return value.toString();
3786
+ }
3787
+
3788
+ /**
3789
+ * Create a markdown table from a 2D array of strings
3790
+ *
3791
+ * @private within the library
3792
+ */
3793
+ function createMarkdownTable(table) {
3794
+ var columnWidths = table.reduce(function (widths, row) {
3795
+ row.forEach(function (cell, columnIndex) {
3796
+ var cellLength = cell.length;
3797
+ if (!widths[columnIndex] || cellLength > widths[columnIndex]) {
3798
+ widths[columnIndex] = cellLength;
3799
+ }
3800
+ });
3801
+ return widths;
3802
+ }, []);
3803
+ var header = "| ".concat(table[0]
3804
+ .map(function (cell, columnIndex) { return cell.padEnd(columnWidths[columnIndex]); })
3805
+ .join(' | '), " |");
3806
+ var separator = "|".concat(columnWidths.map(function (width) { return '-'.repeat(width + 2); }).join('|'), "|");
3807
+ var rows = table.slice(1).map(function (row) {
3808
+ var paddedRow = row.map(function (cell, columnIndex) {
3809
+ return cell.padEnd(columnWidths[columnIndex]);
3810
+ });
3811
+ return "| ".concat(paddedRow.join(' | '), " |");
3812
+ });
3813
+ return __spreadArray([header, separator], __read(rows), false).join('\n');
3814
+ }
3815
+
3816
+ /**
3817
+ * Function createMarkdownChart will draw a chart in markdown from ⬛+🟦 tiles
3818
+ *
3819
+ * @private within the library
3820
+ */
3821
+ function createMarkdownChart(options) {
3822
+ var e_1, _a;
3823
+ var nameHeader = options.nameHeader, valueHeader = options.valueHeader, items = options.items, width = options.width, unitName = options.unitName;
3824
+ var from = Math.min.apply(Math, __spreadArray([], __read(items.map(function (item) { return item.from; })), false));
3825
+ var to = Math.max.apply(Math, __spreadArray([], __read(items.map(function (item) { return item.to; })), false));
3826
+ var scale = width / (to - from);
3827
+ var table = [[nameHeader, valueHeader]];
3828
+ try {
3829
+ for (var items_1 = __values(items), items_1_1 = items_1.next(); !items_1_1.done; items_1_1 = items_1.next()) {
3830
+ var item = items_1_1.value;
3831
+ var before = Math.round((item.from - from) * scale);
3832
+ var during = Math.round((item.to - item.from) * scale);
3833
+ var after = width - before - during;
3834
+ table.push([removeEmojis(item.title).trim(), '░'.repeat(before) + '█'.repeat(during) + '░'.repeat(after)]);
3835
+ }
3836
+ }
3837
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
3838
+ finally {
3839
+ try {
3840
+ if (items_1_1 && !items_1_1.done && (_a = items_1.return)) _a.call(items_1);
3841
+ }
3842
+ finally { if (e_1) throw e_1.error; }
3843
+ }
3844
+ 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_");
3845
+ return createMarkdownTable(table) + '\n\n' + legend;
3846
+ }
3847
+ /**
3848
+ * TODO: Maybe use Mermain Gant Diagrams
3849
+ * @see https://jojozhuang.github.io/tutorial/mermaid-cheat-sheet/
3850
+ */
3851
+
3852
+ /**
3853
+ * Function escapeMarkdownBlock will escape markdown block if needed
3854
+ * It is useful when you want have block in block
3855
+ */
3856
+ function escapeMarkdownBlock(value) {
3857
+ return value.replace(/```/g, '\\`\\`\\`');
3858
+ }
3859
+
3860
+ /**
3861
+ * Default options for generating an execution report string
3862
+ */
3863
+ var ExecutionReportStringOptionsDefaults = {
3864
+ taxRate: 0,
3865
+ chartsWidth: 36,
3866
+ };
3867
+
3868
+ /**
3869
+ * The thresholds for the relative time in the `moment` library.
3870
+ *
3871
+ * @see https://momentjscom.readthedocs.io/en/latest/moment/07-customization/13-relative-time-threshold/
3872
+ */
3873
+ var MOMENT_ARG_THRESHOLDS = {
3874
+ 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.
3875
+ };
3876
+
3877
+ /**
3878
+ * Count the duration of working time
3879
+ *
3880
+ * @private within the library
3881
+ */
3882
+ function countWorkingDuration(items) {
3883
+ var e_1, _a;
3884
+ var steps = Array.from(new Set(items.flatMap(function (item) { return [item.from, item.to]; })));
3885
+ steps.sort(function (a, b) { return a - b; });
3886
+ var intervals = steps.map(function (step, index) { return [step, steps[index + 1] || 0]; }).slice(0, -1);
3887
+ var duration = 0;
3888
+ var _loop_1 = function (interval) {
3889
+ var _b = __read(interval, 2), from = _b[0], to = _b[1];
3890
+ if (items.some(function (item) { return item.from < to && item.to > from; })) {
3891
+ duration += to - from;
3892
+ }
3156
3893
  };
3157
- /**
3158
- * Calls the best available model
3159
- */
3160
- MultipleLlmExecutionTools.prototype.gptCommon = function (prompt) {
3161
- return __awaiter(this, void 0, void 0, function () {
3162
- var errors, _a, _b, llmExecutionTools, error_1, e_1_1;
3163
- var e_1, _c;
3164
- return __generator(this, function (_d) {
3165
- switch (_d.label) {
3166
- case 0:
3167
- errors = [];
3168
- _d.label = 1;
3169
- case 1:
3170
- _d.trys.push([1, 11, 12, 13]);
3171
- _a = __values(this.llmExecutionTools), _b = _a.next();
3172
- _d.label = 2;
3173
- case 2:
3174
- if (!!_b.done) return [3 /*break*/, 10];
3175
- llmExecutionTools = _b.value;
3176
- _d.label = 3;
3177
- case 3:
3178
- _d.trys.push([3, 8, , 9]);
3179
- if (!(prompt.modelRequirements.modelVariant === 'CHAT')) return [3 /*break*/, 5];
3180
- return [4 /*yield*/, llmExecutionTools.gptChat(prompt)];
3181
- case 4: return [2 /*return*/, _d.sent()];
3182
- case 5:
3183
- if (!(prompt.modelRequirements.modelVariant === 'COMPLETION')) return [3 /*break*/, 7];
3184
- return [4 /*yield*/, llmExecutionTools.gptComplete(prompt)];
3185
- case 6: return [2 /*return*/, _d.sent()];
3186
- case 7: return [3 /*break*/, 9];
3187
- case 8:
3188
- error_1 = _d.sent();
3189
- if (!(error_1 instanceof Error)) {
3190
- throw error_1;
3191
- }
3192
- errors.push(error_1);
3193
- return [3 /*break*/, 9];
3194
- case 9:
3195
- _b = _a.next();
3196
- return [3 /*break*/, 2];
3197
- case 10: return [3 /*break*/, 13];
3198
- case 11:
3199
- e_1_1 = _d.sent();
3200
- e_1 = { error: e_1_1 };
3201
- return [3 /*break*/, 13];
3202
- case 12:
3203
- try {
3204
- if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
3205
- }
3206
- finally { if (e_1) throw e_1.error; }
3207
- return [7 /*endfinally*/];
3208
- case 13: throw new Error(spaceTrim$1(function (block) { return "\n All execution tools failed:\n \n ".concat(block(errors.map(function (error) { return "- ".concat(error.name || 'Error', ": ").concat(error.message); }).join('\n')), "\n \n "); }));
3209
- }
3894
+ try {
3895
+ for (var intervals_1 = __values(intervals), intervals_1_1 = intervals_1.next(); !intervals_1_1.done; intervals_1_1 = intervals_1.next()) {
3896
+ var interval = intervals_1_1.value;
3897
+ _loop_1(interval);
3898
+ }
3899
+ }
3900
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
3901
+ finally {
3902
+ try {
3903
+ if (intervals_1_1 && !intervals_1_1.done && (_a = intervals_1.return)) _a.call(intervals_1);
3904
+ }
3905
+ finally { if (e_1) throw e_1.error; }
3906
+ }
3907
+ return duration;
3908
+ }
3909
+
3910
+ /**
3911
+ * Converts execution report from JSON to string format
3912
+ */
3913
+ function executionReportJsonToString(executionReportJson, options) {
3914
+ var e_1, _a;
3915
+ var _b, _c, _d, _e, _f, _g;
3916
+ var _h = __assign(__assign({}, ExecutionReportStringOptionsDefaults), (options || {})), taxRate = _h.taxRate, chartsWidth = _h.chartsWidth;
3917
+ var executionReportString = spaceTrim(function (block) { return "\n # ".concat(executionReportJson.title || 'Execution report', "\n\n ").concat(block(executionReportJson.description || ''), "\n "); });
3918
+ var headerList = [];
3919
+ if (executionReportJson.promptbookUrl) {
3920
+ headerList.push("PROMPTBOOK URL ".concat(executionReportJson.promptbookUrl));
3921
+ }
3922
+ headerList.push("PROMPTBOOK VERSION ".concat(executionReportJson.promptbookUsedVersion) +
3923
+ (!executionReportJson.promptbookRequestedVersion
3924
+ ? ''
3925
+ : " *(requested ".concat(executionReportJson.promptbookRequestedVersion, ")*")));
3926
+ if (executionReportJson.promptExecutions.length !== 0) {
3927
+ // TODO: What if startedAt OR/AND completedAt is not defined?
3928
+ var startedAt = moment(Math.min.apply(Math, __spreadArray([], __read(executionReportJson.promptExecutions
3929
+ .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; })
3930
+ .map(function (promptExecution) { return moment(promptExecution.result.timing.start).valueOf(); })), false)));
3931
+ var completedAt = moment(Math.max.apply(Math, __spreadArray([], __read(executionReportJson.promptExecutions
3932
+ .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; })
3933
+ .map(function (promptExecution) { return moment(promptExecution.result.timing.complete).valueOf(); })), false)));
3934
+ var timingItems = executionReportJson.promptExecutions.map(function (promptExecution) {
3935
+ var _a, _b, _c, _d;
3936
+ return ({
3937
+ title: promptExecution.prompt.title,
3938
+ from: moment((_b = (_a = promptExecution.result) === null || _a === void 0 ? void 0 : _a.timing) === null || _b === void 0 ? void 0 : _b.start).valueOf() / 1000,
3939
+ to: moment((_d = (_c = promptExecution.result) === null || _c === void 0 ? void 0 : _c.timing) === null || _d === void 0 ? void 0 : _d.complete).valueOf() / 1000,
3210
3940
  });
3211
3941
  });
3212
- };
3213
- /**
3214
- * List all available models that can be used
3215
- * This liost is a combination of all available models from all execution tools
3216
- */
3217
- MultipleLlmExecutionTools.prototype.listModels = function () {
3218
- return __awaiter(this, void 0, void 0, function () {
3219
- var availableModels, _a, _b, llmExecutionTools, models, e_2_1;
3220
- var e_2, _c;
3221
- return __generator(this, function (_d) {
3222
- switch (_d.label) {
3223
- case 0:
3224
- availableModels = [];
3225
- _d.label = 1;
3226
- case 1:
3227
- _d.trys.push([1, 6, 7, 8]);
3228
- _a = __values(this.llmExecutionTools), _b = _a.next();
3229
- _d.label = 2;
3230
- case 2:
3231
- if (!!_b.done) return [3 /*break*/, 5];
3232
- llmExecutionTools = _b.value;
3233
- return [4 /*yield*/, llmExecutionTools.listModels()];
3234
- case 3:
3235
- models = _d.sent();
3236
- availableModels.push.apply(availableModels, __spreadArray([], __read(models), false));
3237
- _d.label = 4;
3238
- case 4:
3239
- _b = _a.next();
3240
- return [3 /*break*/, 2];
3241
- case 5: return [3 /*break*/, 8];
3242
- case 6:
3243
- e_2_1 = _d.sent();
3244
- e_2 = { error: e_2_1 };
3245
- return [3 /*break*/, 8];
3246
- case 7:
3247
- try {
3248
- if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
3249
- }
3250
- finally { if (e_2) throw e_2.error; }
3251
- return [7 /*endfinally*/];
3252
- case 8: return [2 /*return*/, availableModels];
3253
- }
3942
+ var costItems = executionReportJson.promptExecutions
3943
+ .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'; })
3944
+ .map(function (promptExecution) {
3945
+ var _a, _b;
3946
+ return ({
3947
+ title: promptExecution.prompt.title,
3948
+ from: 0,
3949
+ to: ((_b = (_a = promptExecution.result) === null || _a === void 0 ? void 0 : _a.usage) === null || _b === void 0 ? void 0 : _b.price) * (1 + taxRate),
3254
3950
  });
3255
3951
  });
3952
+ var duration = moment.duration(completedAt.diff(startedAt));
3953
+ var llmDuration = moment.duration(countWorkingDuration(timingItems) * 1000);
3954
+ 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'; });
3955
+ var cost = executionsWithKnownCost.reduce(function (cost, promptExecution) { return cost + (promptExecution.result.usage.price || 0); }, 0);
3956
+ headerList.push("STARTED AT ".concat(moment(startedAt).format("YYYY-MM-DD HH:mm:ss")));
3957
+ headerList.push("COMPLETED AT ".concat(moment(completedAt).format("YYYY-MM-DD HH:mm:ss")));
3958
+ headerList.push("TOTAL DURATION ".concat(duration.humanize(MOMENT_ARG_THRESHOLDS)));
3959
+ headerList.push("TOTAL LLM DURATION ".concat(llmDuration.humanize(MOMENT_ARG_THRESHOLDS)));
3960
+ headerList.push("TOTAL COST $".concat(formatNumber(cost * (1 + taxRate))) +
3961
+ (executionsWithKnownCost.length === executionReportJson.promptExecutions.length
3962
+ ? ''
3963
+ : " *(Some cost is unknown)*") +
3964
+ (taxRate !== 0 ? " *(with tax ".concat(taxRate * 100, "%)*") : ''));
3965
+ executionReportString += '\n\n' + headerList.map(function (header) { return "- ".concat(header); }).join('\n');
3966
+ executionReportString +=
3967
+ '\n\n' +
3968
+ '## 🗃 Index' +
3969
+ '\n\n' +
3970
+ executionReportJson.promptExecutions
3971
+ .map(function (promptExecution) {
3972
+ // TODO: Make some better system to convert hedings to links
3973
+ var hash = normalizeToKebabCase(promptExecution.prompt.title);
3974
+ if (/^\s*\p{Extended_Pictographic}/u.test(promptExecution.prompt.title)) {
3975
+ hash = '-' + hash;
3976
+ }
3977
+ // TODO: Make working hash link for the template in md + pdf
3978
+ return "- [".concat(promptExecution.prompt.title, "](#").concat(hash, ")");
3979
+ })
3980
+ .join('\n');
3981
+ executionReportString +=
3982
+ '\n\n' +
3983
+ '## ⌚ Time chart' +
3984
+ '\n\n' +
3985
+ createMarkdownChart({
3986
+ nameHeader: 'Template',
3987
+ valueHeader: 'Timeline',
3988
+ items: timingItems,
3989
+ width: chartsWidth,
3990
+ unitName: 'seconds',
3991
+ });
3992
+ executionReportString +=
3993
+ '\n\n' +
3994
+ '## 💸 Cost chart' +
3995
+ '\n\n' +
3996
+ createMarkdownChart({
3997
+ nameHeader: 'Template',
3998
+ valueHeader: 'Cost',
3999
+ items: costItems,
4000
+ width: chartsWidth,
4001
+ unitName: 'USD',
4002
+ });
4003
+ }
4004
+ else {
4005
+ headerList.push("TOTAL COST $0 *(Nothing executed)*");
4006
+ }
4007
+ var _loop_1 = function (promptExecution) {
4008
+ executionReportString += '\n\n\n\n' + "## ".concat(promptExecution.prompt.title);
4009
+ var templateList = [];
4010
+ // TODO: What if startedAt OR/AND completedAt is not defined?
4011
+ var startedAt = moment((_c = (_b = promptExecution.result) === null || _b === void 0 ? void 0 : _b.timing) === null || _c === void 0 ? void 0 : _c.start);
4012
+ var completedAt = moment((_e = (_d = promptExecution.result) === null || _d === void 0 ? void 0 : _d.timing) === null || _e === void 0 ? void 0 : _e.complete);
4013
+ var duration = moment.duration(completedAt.diff(startedAt));
4014
+ // Not need here:
4015
+ // > templateList.push(`STARTED AT ${moment(startedAt).calendar()}`);
4016
+ templateList.push("DURATION ".concat(duration.humanize(MOMENT_ARG_THRESHOLDS)));
4017
+ if (typeof ((_g = (_f = promptExecution.result) === null || _f === void 0 ? void 0 : _f.usage) === null || _g === void 0 ? void 0 : _g.price) === 'number') {
4018
+ templateList.push("COST $".concat(formatNumber(promptExecution.result.usage.price * (1 + taxRate))) +
4019
+ (taxRate !== 0 ? " *(with tax ".concat(taxRate * 100, "%)*") : ''));
4020
+ }
4021
+ else {
4022
+ templateList.push("COST UNKNOWN");
4023
+ }
4024
+ executionReportString += '\n\n' + templateList.map(function (header) { return "- ".concat(header); }).join('\n');
4025
+ /*
4026
+ - MODEL VARIANT ${promptExecution.prompt.modelRequirements.modelVariant}
4027
+ - MODEL NAME \`${promptExecution.result?.model}\` (requested \`${
4028
+ promptExecution.prompt.modelRequirements.modelName
4029
+
4030
+ */
4031
+ if (just(true)) {
4032
+ executionReportString +=
4033
+ '\n\n\n\n' +
4034
+ spaceTrim(function (block) { return "\n\n ### Prompt\n\n ```\n ".concat(block(escapeMarkdownBlock(promptExecution.prompt.content)), "\n ```\n\n "); });
4035
+ }
4036
+ if (promptExecution.result && promptExecution.result.content) {
4037
+ executionReportString +=
4038
+ '\n\n\n\n' +
4039
+ spaceTrim(function (block) { return "\n\n ### Result\n\n ```\n ".concat(block(escapeMarkdownBlock(promptExecution.result.content)), "\n ```\n "); });
4040
+ }
4041
+ if (promptExecution.error && promptExecution.error.message) {
4042
+ executionReportString +=
4043
+ '\n\n\n\n' +
4044
+ spaceTrim(function (block) { return "\n\n ### Error\n\n ```\n ".concat(block(escapeMarkdownBlock(promptExecution.error.message)), "\n ```\n\n "); });
4045
+ }
3256
4046
  };
3257
- return MultipleLlmExecutionTools;
3258
- }());
4047
+ try {
4048
+ for (var _j = __values(executionReportJson.promptExecutions), _k = _j.next(); !_k.done; _k = _j.next()) {
4049
+ var promptExecution = _k.value;
4050
+ _loop_1(promptExecution);
4051
+ }
4052
+ }
4053
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
4054
+ finally {
4055
+ try {
4056
+ if (_k && !_k.done && (_a = _j.return)) _a.call(_j);
4057
+ }
4058
+ finally { if (e_1) throw e_1.error; }
4059
+ }
4060
+ executionReportString = prettifyMarkdown(executionReportString);
4061
+ return executionReportString;
4062
+ }
4063
+ /**
4064
+ * TODO: Add mermaid chart for every report
4065
+ * TODO: [🧠] Allow to filter out some parts of the report by options
4066
+ */
3259
4067
 
3260
- export { CallbackInterfaceTools, ExecutionTypes, MultipleLlmExecutionTools, PROMPTBOOK_VERSION, SimplePromptInterfaceTools, SimplePromptbookLibrary, createPromptbookExecutor, createPromptbookLibraryFromPromise, createPromptbookLibraryFromSources, createPromptbookSublibrary, promptbookJsonToString, promptbookStringToJson, validatePromptbookJson };
4068
+ export { CallbackInterfaceTools, ExecutionReportStringOptionsDefaults, ExecutionTypes, MultipleLlmExecutionTools, PROMPTBOOK_VERSION, SimplePromptInterfaceTools, SimplePromptbookLibrary, assertsExecutionSuccessful, checkExpectations, createPromptbookExecutor, createPromptbookLibraryFromDirectory, createPromptbookLibraryFromSources, createPromptbookLibraryFromUrl, createPromptbookSublibrary, executionReportJsonToString, isPassingExpectations, justTestFsImport, prettifyPromptbookString, promptbookJsonToString, promptbookStringToJson, validatePromptbookJson };
3261
4069
  //# sourceMappingURL=index.es.js.map