@promptbook/core 0.81.0-8 → 0.82.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +25 -4
  2. package/esm/index.es.js +1147 -932
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/books/index.d.ts +38 -0
  5. package/esm/typings/src/_packages/core.index.d.ts +12 -4
  6. package/esm/typings/src/_packages/markdown-utils.index.d.ts +2 -2
  7. package/esm/typings/src/_packages/node.index.d.ts +0 -2
  8. package/esm/typings/src/_packages/remote-client.index.d.ts +7 -3
  9. package/esm/typings/src/_packages/remote-server.index.d.ts +2 -2
  10. package/esm/typings/src/_packages/templates.index.d.ts +2 -2
  11. package/esm/typings/src/_packages/types.index.d.ts +34 -30
  12. package/esm/typings/src/_packages/utils.index.d.ts +2 -0
  13. package/esm/typings/src/_packages/wizzard.index.d.ts +44 -0
  14. package/esm/typings/src/cli/cli-commands/make.d.ts +1 -1
  15. package/esm/typings/src/cli/cli-commands/run.d.ts +2 -2
  16. package/esm/typings/src/collection/constructors/createCollectionFromDirectory.d.ts +11 -0
  17. package/esm/typings/src/collection/constructors/createCollectionFromUrl.d.ts +1 -1
  18. package/esm/typings/src/commands/index.d.ts +1 -1
  19. package/esm/typings/src/config.d.ts +3 -3
  20. package/esm/typings/src/conversion/compilePipeline.d.ts +1 -4
  21. package/esm/typings/src/conversion/compilePipelineOnRemoteServer.d.ts +18 -0
  22. package/esm/typings/src/conversion/{precompilePipeline.d.ts → parsePipeline.d.ts} +3 -3
  23. package/esm/typings/src/conversion/prettify/renderPipelineMermaidOptions.d.ts +3 -3
  24. package/esm/typings/src/conversion/validation/validatePipeline.d.ts +7 -7
  25. package/esm/typings/src/errors/utils/getErrorReportUrl.d.ts +1 -1
  26. package/esm/typings/src/execution/PipelineExecutor.d.ts +2 -2
  27. package/esm/typings/src/execution/createPipelineExecutor/10-executePipeline.d.ts +2 -2
  28. package/esm/typings/src/formfactors/generator/GeneratorFormfactorDefinition.d.ts +9 -4
  29. package/esm/typings/src/formfactors/image-generator/ImageGeneratorFormfactorDefinition.d.ts +24 -0
  30. package/esm/typings/src/formfactors/index.d.ts +31 -9
  31. package/esm/typings/src/high-level-abstractions/_common/HighLevelAbstraction.d.ts +1 -1
  32. package/esm/typings/src/high-level-abstractions/index.d.ts +3 -3
  33. package/esm/typings/src/high-level-abstractions/quick-chatbot/QuickChatbotHla.d.ts +3 -0
  34. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsConfigurationFromEnv.d.ts +1 -1
  35. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForTestingAndScriptsAndPlayground.d.ts +1 -1
  36. package/esm/typings/src/llm-providers/_common/register/{$provideLlmToolsForCli.d.ts → $provideLlmToolsForWizzardOrCli.d.ts} +2 -2
  37. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsFromEnv.d.ts +1 -1
  38. package/esm/typings/src/llm-providers/anthropic-claude/AnthropicClaudeExecutionToolsOptions.d.ts +1 -1
  39. package/esm/typings/src/llm-providers/anthropic-claude/anthropic-claude-models.d.ts +1 -1
  40. package/esm/typings/src/llm-providers/anthropic-claude/createAnthropicClaudeExecutionTools.d.ts +2 -2
  41. package/esm/typings/src/llm-providers/anthropic-claude/playground/playground.d.ts +2 -2
  42. package/esm/typings/src/llm-providers/anthropic-claude/register-configuration.d.ts +1 -0
  43. package/esm/typings/src/llm-providers/anthropic-claude/register-constructor.d.ts +2 -0
  44. package/esm/typings/src/llm-providers/azure-openai/register-configuration.d.ts +1 -0
  45. package/esm/typings/src/llm-providers/azure-openai/register-constructor.d.ts +1 -0
  46. package/esm/typings/src/llm-providers/google/register-configuration.d.ts +1 -0
  47. package/esm/typings/src/llm-providers/google/register-constructor.d.ts +1 -0
  48. package/esm/typings/src/llm-providers/openai/playground/playground.d.ts +1 -1
  49. package/esm/typings/src/llm-providers/openai/register-configuration.d.ts +2 -0
  50. package/esm/typings/src/llm-providers/openai/register-constructor.d.ts +2 -0
  51. package/esm/typings/src/llm-providers/remote/RemoteLlmExecutionTools.d.ts +1 -1
  52. package/esm/typings/src/llm-providers/vercel/playground/playground.d.ts +1 -1
  53. package/esm/typings/src/other/templates/getBookTemplates.d.ts +22 -0
  54. package/esm/typings/src/personas/preparePersona.d.ts +4 -4
  55. package/esm/typings/src/pipeline/PipelineString.d.ts +0 -3
  56. package/esm/typings/src/pipeline/book-notation.d.ts +14 -0
  57. package/esm/typings/src/pipeline/isValidPipelineString.d.ts +13 -0
  58. package/esm/typings/src/pipeline/isValidPipelineString.test.d.ts +4 -0
  59. package/esm/typings/src/pipeline/validatePipelineString.d.ts +14 -0
  60. package/esm/typings/src/prepare/isPipelinePrepared.d.ts +3 -1
  61. package/esm/typings/src/prepare/preparePipeline.d.ts +4 -2
  62. package/esm/typings/src/prepare/preparePipelineOnRemoteServer.d.ts +14 -0
  63. package/esm/typings/src/prepare/prepareTasks.d.ts +1 -1
  64. package/esm/typings/src/{llm-providers/remote → remote-server}/interfaces/PromptbookServer_Error.d.ts +1 -1
  65. package/esm/typings/src/{llm-providers/remote → remote-server}/interfaces/PromptbookServer_ListModels_Request.d.ts +4 -4
  66. package/esm/typings/src/{llm-providers/remote → remote-server}/interfaces/PromptbookServer_ListModels_Response.d.ts +1 -1
  67. package/esm/typings/src/{llm-providers/remote → remote-server}/interfaces/PromptbookServer_Prompt_Progress.d.ts +1 -1
  68. package/esm/typings/src/{llm-providers/remote → remote-server}/interfaces/PromptbookServer_Prompt_Request.d.ts +5 -5
  69. package/esm/typings/src/{llm-providers/remote → remote-server}/interfaces/PromptbookServer_Prompt_Response.d.ts +1 -1
  70. package/esm/typings/src/{llm-providers/remote → remote-server}/interfaces/RemoteLlmExecutionToolsOptions.d.ts +7 -7
  71. package/esm/typings/src/{llm-providers/remote → remote-server}/interfaces/RemoteServerOptions.d.ts +10 -10
  72. package/esm/typings/src/scrapers/_common/Converter.d.ts +1 -0
  73. package/esm/typings/src/scrapers/_common/Scraper.d.ts +1 -1
  74. package/esm/typings/src/scrapers/_common/ScraperIntermediateSource.d.ts +3 -0
  75. package/esm/typings/src/scrapers/_common/register/ScraperAndConverterMetadata.d.ts +2 -0
  76. package/esm/typings/src/scrapers/_common/utils/scraperFetch.d.ts +3 -0
  77. package/esm/typings/src/scrapers/document/register-constructor.d.ts +1 -0
  78. package/esm/typings/src/scrapers/document/register-metadata.d.ts +1 -0
  79. package/esm/typings/src/scrapers/document-legacy/register-constructor.d.ts +1 -0
  80. package/esm/typings/src/scrapers/document-legacy/register-metadata.d.ts +1 -0
  81. package/esm/typings/src/scrapers/markdown/register-constructor.d.ts +1 -0
  82. package/esm/typings/src/scrapers/markdown/register-metadata.d.ts +1 -0
  83. package/esm/typings/src/scrapers/pdf/PdfScraper.d.ts +1 -0
  84. package/esm/typings/src/scrapers/pdf/createPdfScraper.d.ts +1 -1
  85. package/esm/typings/src/scrapers/pdf/register-constructor.d.ts +1 -0
  86. package/esm/typings/src/scrapers/pdf/register-metadata.d.ts +2 -1
  87. package/esm/typings/src/scrapers/website/createWebsiteScraper.d.ts +3 -1
  88. package/esm/typings/src/scrapers/website/register-constructor.d.ts +1 -0
  89. package/esm/typings/src/scrapers/website/register-metadata.d.ts +1 -0
  90. package/esm/typings/src/scripting/javascript/JavascriptEvalExecutionTools.test.d.ts +1 -1
  91. package/esm/typings/src/scripting/javascript/utils/preserve.d.ts +2 -1
  92. package/esm/typings/src/types/typeAliases.d.ts +16 -2
  93. package/esm/typings/src/utils/markdown/flattenMarkdown.d.ts +1 -1
  94. package/esm/typings/src/utils/markdown/{removeContentComments.d.ts → removeMarkdownComments.d.ts} +2 -2
  95. package/esm/typings/src/utils/organization/$sideEffect.d.ts +9 -0
  96. package/esm/typings/src/utils/serialization/checkSerializableAsJson.d.ts +1 -1
  97. package/esm/typings/src/utils/serialization/isSerializableAsJson.d.ts +2 -2
  98. package/esm/typings/src/utils/validators/filePath/isRootPath.d.ts +12 -0
  99. package/esm/typings/src/utils/validators/filePath/isRootPath.test.d.ts +4 -0
  100. package/esm/typings/src/utils/validators/filePath/isValidFilePath.d.ts +3 -0
  101. package/esm/typings/src/wizzard/$getCompiledBook.d.ts +16 -0
  102. package/esm/typings/src/wizzard/wizzard.d.ts +52 -8
  103. package/package.json +1 -1
  104. package/umd/index.umd.js +1152 -933
  105. package/umd/index.umd.js.map +1 -1
  106. package/esm/typings/src/other/templates/getBookTemplate.d.ts +0 -21
  107. package/esm/typings/src/scripting/javascript/utils/unknownToString.d.ts +0 -8
  108. /package/esm/typings/src/conversion/{precompilePipeline.test.d.ts → parsePipeline.test.d.ts} +0 -0
  109. /package/esm/typings/src/{llm-providers/remote → remote-server}/startRemoteServer.d.ts +0 -0
  110. /package/esm/typings/src/utils/markdown/{removeContentComments.test.d.ts → removeMarkdownComments.test.d.ts} +0 -0
package/umd/index.umd.js CHANGED
@@ -27,7 +27,7 @@
27
27
  * @generated
28
28
  * @see https://github.com/webgptorg/promptbook
29
29
  */
30
- var PROMPTBOOK_ENGINE_VERSION = '0.81.0-7';
30
+ var PROMPTBOOK_ENGINE_VERSION = '0.81.0-23';
31
31
  /**
32
32
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
33
33
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -179,6 +179,66 @@
179
179
  * TODO: [🧠] Maybe clear `sourceFile` or clear when exposing through API or remote server
180
180
  */
181
181
 
182
+ /**
183
+ * Function isValidJsonString will tell you if the string is valid JSON or not
184
+ *
185
+ * @public exported from `@promptbook/utils`
186
+ */
187
+ function isValidJsonString(value /* <- [👨‍⚖️] */) {
188
+ try {
189
+ JSON.parse(value);
190
+ return true;
191
+ }
192
+ catch (error) {
193
+ if (!(error instanceof Error)) {
194
+ throw error;
195
+ }
196
+ if (error.message.includes('Unexpected token')) {
197
+ return false;
198
+ }
199
+ return false;
200
+ }
201
+ }
202
+
203
+ /**
204
+ * This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
205
+ *
206
+ * @public exported from `@promptbook/core`
207
+ */
208
+ var ParseError = /** @class */ (function (_super) {
209
+ __extends(ParseError, _super);
210
+ function ParseError(message) {
211
+ var _this = _super.call(this, message) || this;
212
+ _this.name = 'ParseError';
213
+ Object.setPrototypeOf(_this, ParseError.prototype);
214
+ return _this;
215
+ }
216
+ return ParseError;
217
+ }(Error));
218
+ /**
219
+ * TODO: Maybe split `ParseError` and `ApplyError`
220
+ */
221
+
222
+ /**
223
+ * Function `validatePipelineString` will validate the if the string is a valid pipeline string
224
+ * It does not check if the string is fully logically correct, but if it is a string that can be a pipeline string or the string looks completely different.
225
+ *
226
+ * @param {string} pipelineString the candidate for a pipeline string
227
+ * @returns {PipelineString} the same string as input, but validated as valid
228
+ * @throws {ParseError} if the string is not a valid pipeline string
229
+ * @public exported from `@promptbook/core`
230
+ */
231
+ function validatePipelineString(pipelineString) {
232
+ if (isValidJsonString(pipelineString)) {
233
+ throw new ParseError('Expected a book, but got a JSON string');
234
+ }
235
+ // <- TODO: Implement the validation + add tests when the pipeline logic considered as invalid
236
+ return pipelineString;
237
+ }
238
+ /**
239
+ * TODO: [🧠][🈴] Where is the best location for this file
240
+ */
241
+
182
242
  /**
183
243
  * Prettify the html code
184
244
  *
@@ -245,7 +305,7 @@
245
305
  if (bookVersion !== "undefined") {
246
306
  commands.push("BOOK VERSION ".concat(bookVersion));
247
307
  }
248
- // TODO: [main] !!!!! This increases size of the bundle and is probbably not necessary
308
+ // TODO: [main] !!5 This increases size of the bundle and is probbably not necessary
249
309
  pipelineString = prettifyMarkdown(pipelineString);
250
310
  try {
251
311
  for (var _g = __values(parameters.filter(function (_a) {
@@ -393,12 +453,12 @@
393
453
  pipelineString += '```' + contentLanguage;
394
454
  pipelineString += '\n';
395
455
  pipelineString += spaceTrim__default["default"](content);
396
- // <- TODO: [main] !!! Escape
456
+ // <- TODO: [main] !!3 Escape
397
457
  // <- TODO: [🧠] Some clear strategy how to spaceTrim the blocks
398
458
  pipelineString += '\n';
399
459
  pipelineString += '```';
400
460
  pipelineString += '\n\n';
401
- pipelineString += "`-> {".concat(resultingParameterName, "}`"); // <- TODO: [main] !!! If the parameter here has description, add it and use taskParameterJsonToString
461
+ pipelineString += "`-> {".concat(resultingParameterName, "}`"); // <- TODO: [main] !!3 If the parameter here has description, add it and use taskParameterJsonToString
402
462
  }
403
463
  }
404
464
  catch (e_3_1) { e_3 = { error: e_3_1 }; }
@@ -408,7 +468,7 @@
408
468
  }
409
469
  finally { if (e_3) throw e_3.error; }
410
470
  }
411
- return pipelineString;
471
+ return validatePipelineString(pipelineString);
412
472
  }
413
473
  /**
414
474
  * @private internal utility of `pipelineJsonToString`
@@ -505,7 +565,7 @@
505
565
  *
506
566
  * @public exported from `@promptbook/core`
507
567
  */
508
- var DEFAULT_TITLE = "Untitled";
568
+ var DEFAULT_BOOK_TITLE = "\u2728 Untitled Book";
509
569
  // <- TODO: [🧠] Better system for generator warnings - not always "code" and "by `@promptbook/cli`"
510
570
  /**
511
571
  * The maximum number of iterations for a loops
@@ -566,14 +626,14 @@
566
626
  var DEFAULT_MAX_EXECUTION_ATTEMPTS = 3; // <- TODO: [🤹‍♂️]
567
627
  /**
568
628
  * @@@
569
- * TODO: [🐝][main] !!! Use
629
+ * TODO: [🐝][main] !!3 Use
570
630
  *
571
631
  * @public exported from `@promptbook/core`
572
632
  */
573
633
  var DEFAULT_MAX_KNOWLEDGE_SOURCES_SCRAPING_DEPTH = 3;
574
634
  /**
575
635
  * @@@
576
- * TODO: [🐝][main] !!! Use
636
+ * TODO: [🐝][main] !!3 Use
577
637
  *
578
638
  * @public exported from `@promptbook/core`
579
639
  */
@@ -585,6 +645,7 @@
585
645
  * @public exported from `@promptbook/core`
586
646
  */
587
647
  var DEFAULT_BOOKS_DIRNAME = './books';
648
+ // <- TODO: [🕝] Make also `BOOKS_DIRNAME_ALTERNATIVES`
588
649
  /**
589
650
  * Where to store the cache of executions for promptbook CLI
590
651
  *
@@ -735,7 +796,7 @@
735
796
  /**
736
797
  * Make error report URL for the given error
737
798
  *
738
- * @private !!!!!!
799
+ * @private private within the repository
739
800
  */
740
801
  function getErrorReportUrl(error) {
741
802
  var report = {
@@ -856,7 +917,7 @@
856
917
  if (!(error instanceof Error)) {
857
918
  throw error;
858
919
  }
859
- throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is not serializable\n\n ").concat(block(error.toString()), "\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
920
+ throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is not serializable\n\n ").concat(block(error.stack || error.message), "\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
860
921
  }
861
922
  /*
862
923
  TODO: [0] Is there some more elegant way to check circular references?
@@ -886,7 +947,7 @@
886
947
  }
887
948
  /**
888
949
  * TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
889
- * TODO: [🧠][main] !!! In-memory cache of same values to prevent multiple checks
950
+ * TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
890
951
  * Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
891
952
  */
892
953
 
@@ -898,7 +959,6 @@
898
959
  function deepClone(objectValue) {
899
960
  return JSON.parse(JSON.stringify(objectValue));
900
961
  /*
901
- !!!!!!!!
902
962
  TODO: [🧠] Is there a better implementation?
903
963
  > const propertyNames = Object.getOwnPropertyNames(objectValue);
904
964
  > for (const propertyName of propertyNames) {
@@ -1010,25 +1070,6 @@
1010
1070
  * Note: [💞] Ignore a discrepancy between file name and entity name
1011
1071
  */
1012
1072
 
1013
- /**
1014
- * This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
1015
- *
1016
- * @public exported from `@promptbook/core`
1017
- */
1018
- var ParseError = /** @class */ (function (_super) {
1019
- __extends(ParseError, _super);
1020
- function ParseError(message) {
1021
- var _this = _super.call(this, message) || this;
1022
- _this.name = 'ParseError';
1023
- Object.setPrototypeOf(_this, ParseError.prototype);
1024
- return _this;
1025
- }
1026
- return ParseError;
1027
- }(Error));
1028
- /**
1029
- * TODO: Maybe split `ParseError` and `ApplyError`
1030
- */
1031
-
1032
1073
  /**
1033
1074
  * This error indicates that the promptbook object has valid syntax (=can be parsed) but contains logical errors (like circular dependencies)
1034
1075
  *
@@ -1083,7 +1124,7 @@
1083
1124
  if ( /* version === '1.0.0' || */version === '2.0.0' || version === '3.0.0') {
1084
1125
  return false;
1085
1126
  }
1086
- // <- TODO: [main] !!! Check isValidPromptbookVersion against PROMPTBOOK_ENGINE_VERSIONS
1127
+ // <- TODO: [main] !!3 Check isValidPromptbookVersion against PROMPTBOOK_ENGINE_VERSIONS
1087
1128
  return true;
1088
1129
  }
1089
1130
 
@@ -1183,9 +1224,6 @@
1183
1224
  if (!url.startsWith('https://')) {
1184
1225
  return false;
1185
1226
  }
1186
- if (!(url.endsWith('.book.md') || url.endsWith('.book') || url.endsWith('.book.md') || url.endsWith('.ptbk'))) {
1187
- return false;
1188
- }
1189
1227
  if (url.includes('#')) {
1190
1228
  // TODO: [🐠]
1191
1229
  return false;
@@ -1216,11 +1254,11 @@
1216
1254
  */
1217
1255
  function validatePipeline(pipeline) {
1218
1256
  if (IS_PIPELINE_LOGIC_VALIDATED) {
1219
- validatePipelineCore(pipeline);
1257
+ validatePipeline_InnerFunction(pipeline);
1220
1258
  }
1221
1259
  else {
1222
1260
  try {
1223
- validatePipelineCore(pipeline);
1261
+ validatePipeline_InnerFunction(pipeline);
1224
1262
  }
1225
1263
  catch (error) {
1226
1264
  if (!(error instanceof PipelineLogicError)) {
@@ -1234,7 +1272,7 @@
1234
1272
  /**
1235
1273
  * @private internal function for `validatePipeline`
1236
1274
  */
1237
- function validatePipelineCore(pipeline) {
1275
+ function validatePipeline_InnerFunction(pipeline) {
1238
1276
  // TODO: [🧠] Maybe test if promptbook is a promise and make specific error case for that
1239
1277
  var e_1, _a, e_2, _b, e_3, _c;
1240
1278
  var pipelineIdentification = (function () {
@@ -1458,11 +1496,11 @@
1458
1496
  _loop_3();
1459
1497
  }
1460
1498
  // Note: Check that formfactor is corresponding to the pipeline interface
1461
- // TODO: !!!!!! Implement this
1499
+ // TODO: !!6 Implement this
1462
1500
  // pipeline.formfactorName
1463
1501
  }
1464
1502
  /**
1465
- * TODO: !! [🧞‍♀️] Do not allow joker + foreach
1503
+ * TODO: [🧞‍♀️] Do not allow joker + foreach
1466
1504
  * TODO: [🧠] Work with promptbookVersion
1467
1505
  * TODO: Use here some json-schema, Zod or something similar and change it to:
1468
1506
  * > /**
@@ -1474,11 +1512,11 @@
1474
1512
  * > ex port function validatePipeline(promptbook: really_unknown): asserts promptbook is PipelineJson {
1475
1513
  */
1476
1514
  /**
1477
- * TODO: [🧳][main] !!!! Validate that all examples match expectations
1478
- * TODO: [🧳][🐝][main] !!!! Validate that knowledge is valid (non-void)
1479
- * TODO: [🧳][main] !!!! Validate that persona can be used only with CHAT variant
1480
- * TODO: [🧳][main] !!!! Validate that parameter with reserved name not used RESERVED_PARAMETER_NAMES
1481
- * TODO: [🧳][main] !!!! Validate that reserved parameter is not used as joker
1515
+ * TODO: [🧳][main] !!4 Validate that all examples match expectations
1516
+ * TODO: [🧳][🐝][main] !!4 Validate that knowledge is valid (non-void)
1517
+ * TODO: [🧳][main] !!4 Validate that persona can be used only with CHAT variant
1518
+ * TODO: [🧳][main] !!4 Validate that parameter with reserved name not used RESERVED_PARAMETER_NAMES
1519
+ * TODO: [🧳][main] !!4 Validate that reserved parameter is not used as joker
1482
1520
  * TODO: [🧠] Validation not only logic itself but imports around - files and websites and rerefenced pipelines exists
1483
1521
  * TODO: [🛠] Actions, instruments (and maybe knowledge) => Functions and tools
1484
1522
  */
@@ -1614,7 +1652,7 @@
1614
1652
  pipelineJsonToString(unpreparePipeline(pipeline)) !==
1615
1653
  pipelineJsonToString(unpreparePipeline(this.collection.get(pipeline.pipelineUrl)))) {
1616
1654
  var existing = this.collection.get(pipeline.pipelineUrl);
1617
- throw new PipelineUrlError(spaceTrim.spaceTrim("\n Pipeline with URL \"".concat(pipeline.pipelineUrl, "\" is already in the collection \uD83C\uDF4E\n\n Conflicting files:\n ").concat(existing.sourceFile || 'Unknown', "\n ").concat(pipeline.sourceFile || 'Unknown', "\n\n Note: You have probably forgotten to run \"ptbk make\" to update the collection\n Note: Pipelines with the same URL are not allowed\n Only exepction is when the pipelines are identical\n\n ")));
1655
+ throw new PipelineUrlError(spaceTrim.spaceTrim("\n Pipeline with URL ".concat(pipeline.pipelineUrl, " is already in the collection \uD83C\uDF4E\n\n Conflicting files:\n ").concat(existing.sourceFile || 'Unknown', "\n ").concat(pipeline.sourceFile || 'Unknown', "\n\n Note: You have probably forgotten to run \"ptbk make\" to update the collection\n Note: Pipelines with the same URL are not allowed\n Only exepction is when the pipelines are identical\n\n ")));
1618
1656
  }
1619
1657
  // Note: [🧠] Overwrite existing pipeline with the same URL
1620
1658
  this.collection.set(pipeline.pipelineUrl, pipeline);
@@ -1798,7 +1836,7 @@
1798
1836
  });
1799
1837
  }
1800
1838
  /**
1801
- * TODO: [main] !!!! [🧠] Library precompilation and do not mix markdown and json promptbooks
1839
+ * TODO: [main] !!4 [🧠] Library precompilation and do not mix markdown and json promptbooks
1802
1840
  */
1803
1841
 
1804
1842
  /**
@@ -1868,7 +1906,7 @@
1868
1906
  case 0: return [4 /*yield*/, collection.isResponsibleForPrompt(prompt)];
1869
1907
  case 1:
1870
1908
  isResponsible = _a.sent();
1871
- // TODO: !! Only if responsible, check if predicate is true
1909
+ // TODO: Only if responsible, check if predicate is true
1872
1910
  return [2 /*return*/, isResponsible];
1873
1911
  }
1874
1912
  });
@@ -1881,6 +1919,8 @@
1881
1919
  };
1882
1920
  }
1883
1921
 
1922
+ var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book.md",formfactorName:"GENERIC",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}",resultingParameterName:"knowledgePieces",dependentParameterNames:["knowledgeContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge from Markdown\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book.md`\n- INPUT PARAMETER `{knowledgeContent}` Markdown document content\n- OUTPUT PARAMETER `{knowledgePieces}` The knowledge JSON object\n\n## Knowledge\n\n<!-- TODO: [🍆] -FORMAT JSON -->\n\n```markdown\nYou are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}\n```\n\n`-> {knowledgePieces}`\n"}],sourceFile:"./books/prepare-knowledge-from-markdown.book.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.book.md",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}",resultingParameterName:"keywords",dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Keywords\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-keywords.book.md`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{keywords}` Keywords separated by comma\n\n## Knowledge\n\n<!-- TODO: [🍆] -FORMAT JSON -->\n\n```markdown\nYou are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}\n```\n\n`-> {keywords}`\n"}],sourceFile:"./books/prepare-knowledge-keywords.book.md"},{title:"Prepare Knowledge-piece Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.book.md",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}",resultingParameterName:"title",expectations:{words:{min:1,max:8}},dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge-piece Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-title.book.md`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{title}` The title of the document\n\n## Knowledge\n\n- EXPECT MIN 1 WORD\n- EXPECT MAX 8 WORDS\n\n```markdown\nYou are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-knowledge-title.book.md"},{title:"Prepare Persona",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.book.md",formfactorName:"GENERIC",parameters:[{name:"availableModelNames",description:"List of available model names separated by comma (,)",isInput:true,isOutput:false},{name:"personaDescription",description:"Description of the persona",isInput:true,isOutput:false},{name:"modelRequirements",description:"Specific requirements for the model",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-model-requirements",title:"Make modelRequirements",content:"You are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Example\n\n```json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n```\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}",resultingParameterName:"modelRequirements",format:"JSON",dependentParameterNames:["availableModelNames","personaDescription"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Persona\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-persona.book.md`\n- INPUT PARAMETER `{availableModelNames}` List of available model names separated by comma (,)\n- INPUT PARAMETER `{personaDescription}` Description of the persona\n- OUTPUT PARAMETER `{modelRequirements}` Specific requirements for the model\n\n## Make modelRequirements\n\n- FORMAT JSON\n\n```markdown\nYou are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Example\n\n\\`\\`\\`json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n\\`\\`\\`\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}\n```\n\n`-> {modelRequirements}`\n"}],sourceFile:"./books/prepare-persona.book.md"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-title.book.md",formfactorName:"GENERIC",parameters:[{name:"book",description:"The book to prepare the title for",isInput:true,isOutput:false},{name:"title",description:"Best title for the book",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-title",title:"Make title",content:"Make best title for given text which describes the task:\n\n> {book}\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear\n- Title starts with emoticon",resultingParameterName:"title",expectations:{words:{min:1,max:8},lines:{min:1,max:1}},dependentParameterNames:["book"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-title.book.md`\n- INPUT PARAMETER `{book}` The book to prepare the title for\n- OUTPUT PARAMETER `{title}` Best title for the book\n\n## Make title\n\n- EXPECT MIN 1 Word\n- EXPECT MAX 8 Words\n- EXPECT EXACTLY 1 Line\n\n```markdown\nMake best title for given text which describes the task:\n\n> {book}\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear\n- Title starts with emoticon\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-title.book.md"}];
1923
+
1884
1924
  /**
1885
1925
  * This error type indicates that some tools are missing for pipeline execution or preparation
1886
1926
  *
@@ -1898,660 +1938,75 @@
1898
1938
  }(Error));
1899
1939
 
1900
1940
  /**
1901
- * Async version of Array.forEach
1941
+ * This error indicates errors during the execution of the pipeline
1902
1942
  *
1903
- * @param array - Array to iterate over
1904
- * @param options - Options for the function
1905
- * @param callbackfunction - Function to call for each item
1906
- * @public exported from `@promptbook/utils`
1907
- * @deprecated [🪂] Use queues instead
1943
+ * @public exported from `@promptbook/core`
1908
1944
  */
1909
- function forEachAsync(array, options, callbackfunction) {
1910
- return __awaiter(this, void 0, void 0, function () {
1911
- var _a, maxParallelCount, index, runningTasks, tasks, _loop_1, _b, _c, item, e_1_1;
1912
- var e_1, _d;
1913
- return __generator(this, function (_e) {
1914
- switch (_e.label) {
1915
- case 0:
1916
- _a = options.maxParallelCount, maxParallelCount = _a === void 0 ? Infinity : _a;
1917
- index = 0;
1918
- runningTasks = [];
1919
- tasks = [];
1920
- _loop_1 = function (item) {
1921
- var currentIndex, task;
1922
- return __generator(this, function (_f) {
1923
- switch (_f.label) {
1924
- case 0:
1925
- currentIndex = index++;
1926
- task = callbackfunction(item, currentIndex, array);
1927
- tasks.push(task);
1928
- runningTasks.push(task);
1929
- /* not await */ Promise.resolve(task).then(function () {
1930
- runningTasks = runningTasks.filter(function (t) { return t !== task; });
1931
- });
1932
- if (!(maxParallelCount < runningTasks.length)) return [3 /*break*/, 2];
1933
- return [4 /*yield*/, Promise.race(runningTasks)];
1934
- case 1:
1935
- _f.sent();
1936
- _f.label = 2;
1937
- case 2: return [2 /*return*/];
1938
- }
1939
- });
1940
- };
1941
- _e.label = 1;
1942
- case 1:
1943
- _e.trys.push([1, 6, 7, 8]);
1944
- _b = __values(array), _c = _b.next();
1945
- _e.label = 2;
1946
- case 2:
1947
- if (!!_c.done) return [3 /*break*/, 5];
1948
- item = _c.value;
1949
- return [5 /*yield**/, _loop_1(item)];
1950
- case 3:
1951
- _e.sent();
1952
- _e.label = 4;
1953
- case 4:
1954
- _c = _b.next();
1955
- return [3 /*break*/, 2];
1956
- case 5: return [3 /*break*/, 8];
1957
- case 6:
1958
- e_1_1 = _e.sent();
1959
- e_1 = { error: e_1_1 };
1960
- return [3 /*break*/, 8];
1961
- case 7:
1962
- try {
1963
- if (_c && !_c.done && (_d = _b.return)) _d.call(_b);
1964
- }
1965
- finally { if (e_1) throw e_1.error; }
1966
- return [7 /*endfinally*/];
1967
- case 8: return [4 /*yield*/, Promise.all(tasks)];
1968
- case 9:
1969
- _e.sent();
1970
- return [2 /*return*/];
1971
- }
1972
- });
1973
- });
1974
- }
1945
+ var PipelineExecutionError = /** @class */ (function (_super) {
1946
+ __extends(PipelineExecutionError, _super);
1947
+ function PipelineExecutionError(message) {
1948
+ var _this = _super.call(this, message) || this;
1949
+ _this.name = 'PipelineExecutionError';
1950
+ Object.setPrototypeOf(_this, PipelineExecutionError.prototype);
1951
+ return _this;
1952
+ }
1953
+ return PipelineExecutionError;
1954
+ }(Error));
1975
1955
 
1976
1956
  /**
1977
- * Represents the usage with no resources consumed
1957
+ * This error indicates problems parsing the format value
1958
+ *
1959
+ * For example, when the format value is not a valid JSON or CSV
1960
+ * This is not thrown directly but in extended classes
1978
1961
  *
1979
1962
  * @public exported from `@promptbook/core`
1980
1963
  */
1981
- var ZERO_USAGE = $deepFreeze({
1982
- price: { value: 0 },
1983
- input: {
1984
- tokensCount: { value: 0 },
1985
- charactersCount: { value: 0 },
1986
- wordsCount: { value: 0 },
1987
- sentencesCount: { value: 0 },
1988
- linesCount: { value: 0 },
1989
- paragraphsCount: { value: 0 },
1990
- pagesCount: { value: 0 },
1991
- },
1992
- output: {
1993
- tokensCount: { value: 0 },
1994
- charactersCount: { value: 0 },
1995
- wordsCount: { value: 0 },
1996
- sentencesCount: { value: 0 },
1997
- linesCount: { value: 0 },
1998
- paragraphsCount: { value: 0 },
1999
- pagesCount: { value: 0 },
2000
- },
2001
- });
1964
+ var AbstractFormatError = /** @class */ (function (_super) {
1965
+ __extends(AbstractFormatError, _super);
1966
+ // Note: To allow instanceof do not put here error `name`
1967
+ // public readonly name = 'AbstractFormatError';
1968
+ function AbstractFormatError(message) {
1969
+ var _this = _super.call(this, message) || this;
1970
+ Object.setPrototypeOf(_this, AbstractFormatError.prototype);
1971
+ return _this;
1972
+ }
1973
+ return AbstractFormatError;
1974
+ }(Error));
1975
+
2002
1976
  /**
2003
- * Represents the usage with unknown resources consumed
1977
+ * This error indicates problem with parsing of CSV
2004
1978
  *
2005
1979
  * @public exported from `@promptbook/core`
2006
1980
  */
2007
- var UNCERTAIN_USAGE = $deepFreeze({
2008
- price: { value: 0, isUncertain: true },
2009
- input: {
2010
- tokensCount: { value: 0, isUncertain: true },
2011
- charactersCount: { value: 0, isUncertain: true },
2012
- wordsCount: { value: 0, isUncertain: true },
2013
- sentencesCount: { value: 0, isUncertain: true },
2014
- linesCount: { value: 0, isUncertain: true },
2015
- paragraphsCount: { value: 0, isUncertain: true },
2016
- pagesCount: { value: 0, isUncertain: true },
2017
- },
2018
- output: {
2019
- tokensCount: { value: 0, isUncertain: true },
2020
- charactersCount: { value: 0, isUncertain: true },
2021
- wordsCount: { value: 0, isUncertain: true },
2022
- sentencesCount: { value: 0, isUncertain: true },
2023
- linesCount: { value: 0, isUncertain: true },
2024
- paragraphsCount: { value: 0, isUncertain: true },
2025
- pagesCount: { value: 0, isUncertain: true },
2026
- },
2027
- });
1981
+ var CsvFormatError = /** @class */ (function (_super) {
1982
+ __extends(CsvFormatError, _super);
1983
+ function CsvFormatError(message) {
1984
+ var _this = _super.call(this, message) || this;
1985
+ _this.name = 'CsvFormatError';
1986
+ Object.setPrototypeOf(_this, CsvFormatError.prototype);
1987
+ return _this;
1988
+ }
1989
+ return CsvFormatError;
1990
+ }(AbstractFormatError));
1991
+
2028
1992
  /**
2029
- * Note: [💞] Ignore a discrepancy between file name and entity name
1993
+ * This error indicates that the pipeline collection cannot be propperly loaded
1994
+ *
1995
+ * @public exported from `@promptbook/core`
2030
1996
  */
1997
+ var CollectionError = /** @class */ (function (_super) {
1998
+ __extends(CollectionError, _super);
1999
+ function CollectionError(message) {
2000
+ var _this = _super.call(this, message) || this;
2001
+ _this.name = 'CollectionError';
2002
+ Object.setPrototypeOf(_this, CollectionError.prototype);
2003
+ return _this;
2004
+ }
2005
+ return CollectionError;
2006
+ }(Error));
2031
2007
 
2032
2008
  /**
2033
- * Function `addUsage` will add multiple usages into one
2034
- *
2035
- * Note: If you provide 0 values, it returns ZERO_USAGE
2036
- *
2037
- * @public exported from `@promptbook/core`
2038
- */
2039
- function addUsage() {
2040
- var usageItems = [];
2041
- for (var _i = 0; _i < arguments.length; _i++) {
2042
- usageItems[_i] = arguments[_i];
2043
- }
2044
- return usageItems.reduce(function (acc, item) {
2045
- var e_1, _a, e_2, _b;
2046
- var _c;
2047
- acc.price.value += ((_c = item.price) === null || _c === void 0 ? void 0 : _c.value) || 0;
2048
- try {
2049
- for (var _d = __values(Object.keys(acc.input)), _e = _d.next(); !_e.done; _e = _d.next()) {
2050
- var key = _e.value;
2051
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2052
- //@ts-ignore
2053
- if (item.input[key]) {
2054
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2055
- //@ts-ignore
2056
- acc.input[key].value += item.input[key].value || 0;
2057
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2058
- //@ts-ignore
2059
- if (item.input[key].isUncertain) {
2060
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2061
- //@ts-ignore
2062
- acc.input[key].isUncertain = true;
2063
- }
2064
- }
2065
- }
2066
- }
2067
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
2068
- finally {
2069
- try {
2070
- if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
2071
- }
2072
- finally { if (e_1) throw e_1.error; }
2073
- }
2074
- try {
2075
- for (var _f = __values(Object.keys(acc.output)), _g = _f.next(); !_g.done; _g = _f.next()) {
2076
- var key = _g.value;
2077
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2078
- //@ts-ignore
2079
- if (item.output[key]) {
2080
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2081
- //@ts-ignore
2082
- acc.output[key].value += item.output[key].value || 0;
2083
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2084
- //@ts-ignore
2085
- if (item.output[key].isUncertain) {
2086
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2087
- //@ts-ignore
2088
- acc.output[key].isUncertain = true;
2089
- }
2090
- }
2091
- }
2092
- }
2093
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
2094
- finally {
2095
- try {
2096
- if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
2097
- }
2098
- finally { if (e_2) throw e_2.error; }
2099
- }
2100
- return acc;
2101
- }, deepClone(ZERO_USAGE));
2102
- }
2103
-
2104
- /**
2105
- * Intercepts LLM tools and counts total usage of the tools
2106
- *
2107
- * @param llmTools LLM tools to be intercepted with usage counting
2108
- * @returns LLM tools with same functionality with added total cost counting
2109
- * @public exported from `@promptbook/core`
2110
- */
2111
- function countTotalUsage(llmTools) {
2112
- var _this = this;
2113
- var totalUsage = ZERO_USAGE;
2114
- var proxyTools = {
2115
- get title() {
2116
- // TODO: [🧠] Maybe put here some suffix
2117
- return llmTools.title;
2118
- },
2119
- get description() {
2120
- // TODO: [🧠] Maybe put here some suffix
2121
- return llmTools.description;
2122
- },
2123
- checkConfiguration: function () {
2124
- return __awaiter(this, void 0, void 0, function () {
2125
- return __generator(this, function (_a) {
2126
- return [2 /*return*/, /* not await */ llmTools.checkConfiguration()];
2127
- });
2128
- });
2129
- },
2130
- listModels: function () {
2131
- return /* not await */ llmTools.listModels();
2132
- },
2133
- getTotalUsage: function () {
2134
- // <- Note: [🥫] Not using getter `get totalUsage` but `getTotalUsage` to allow this object to be proxied
2135
- return totalUsage;
2136
- },
2137
- };
2138
- if (llmTools.callChatModel !== undefined) {
2139
- proxyTools.callChatModel = function (prompt) { return __awaiter(_this, void 0, void 0, function () {
2140
- var promptResult;
2141
- return __generator(this, function (_a) {
2142
- switch (_a.label) {
2143
- case 0: return [4 /*yield*/, llmTools.callChatModel(prompt)];
2144
- case 1:
2145
- promptResult = _a.sent();
2146
- totalUsage = addUsage(totalUsage, promptResult.usage);
2147
- return [2 /*return*/, promptResult];
2148
- }
2149
- });
2150
- }); };
2151
- }
2152
- if (llmTools.callCompletionModel !== undefined) {
2153
- proxyTools.callCompletionModel = function (prompt) { return __awaiter(_this, void 0, void 0, function () {
2154
- var promptResult;
2155
- return __generator(this, function (_a) {
2156
- switch (_a.label) {
2157
- case 0: return [4 /*yield*/, llmTools.callCompletionModel(prompt)];
2158
- case 1:
2159
- promptResult = _a.sent();
2160
- totalUsage = addUsage(totalUsage, promptResult.usage);
2161
- return [2 /*return*/, promptResult];
2162
- }
2163
- });
2164
- }); };
2165
- }
2166
- if (llmTools.callEmbeddingModel !== undefined) {
2167
- proxyTools.callEmbeddingModel = function (prompt) { return __awaiter(_this, void 0, void 0, function () {
2168
- var promptResult;
2169
- return __generator(this, function (_a) {
2170
- switch (_a.label) {
2171
- case 0: return [4 /*yield*/, llmTools.callEmbeddingModel(prompt)];
2172
- case 1:
2173
- promptResult = _a.sent();
2174
- totalUsage = addUsage(totalUsage, promptResult.usage);
2175
- return [2 /*return*/, promptResult];
2176
- }
2177
- });
2178
- }); };
2179
- }
2180
- // <- Note: [🤖]
2181
- return proxyTools;
2182
- }
2183
- /**
2184
- * TODO: [🧠][💸] Maybe make some common abstraction `interceptLlmTools` and use here (or use javascript Proxy?)
2185
- * TODO: [🧠] Is there some meaningfull way how to test this util
2186
- * TODO: [🧠][🌯] Maybe a way how to hide ability to `get totalUsage`
2187
- * > const [llmToolsWithUsage,getUsage] = countTotalUsage(llmTools);
2188
- * TODO: [👷‍♂️] @@@ Manual about construction of llmTools
2189
- */
2190
-
2191
- /**
2192
- * This error indicates errors during the execution of the pipeline
2193
- *
2194
- * @public exported from `@promptbook/core`
2195
- */
2196
- var PipelineExecutionError = /** @class */ (function (_super) {
2197
- __extends(PipelineExecutionError, _super);
2198
- function PipelineExecutionError(message) {
2199
- var _this = _super.call(this, message) || this;
2200
- _this.name = 'PipelineExecutionError';
2201
- Object.setPrototypeOf(_this, PipelineExecutionError.prototype);
2202
- return _this;
2203
- }
2204
- return PipelineExecutionError;
2205
- }(Error));
2206
-
2207
- /**
2208
- * Multiple LLM Execution Tools is a proxy server that uses multiple execution tools internally and exposes the executor interface externally.
2209
- *
2210
- * Note: Internal utility of `joinLlmExecutionTools` but exposed type
2211
- * @public exported from `@promptbook/core`
2212
- */
2213
- var MultipleLlmExecutionTools = /** @class */ (function () {
2214
- /**
2215
- * Gets array of execution tools in order of priority
2216
- */
2217
- function MultipleLlmExecutionTools() {
2218
- var llmExecutionTools = [];
2219
- for (var _i = 0; _i < arguments.length; _i++) {
2220
- llmExecutionTools[_i] = arguments[_i];
2221
- }
2222
- this.llmExecutionTools = llmExecutionTools;
2223
- }
2224
- Object.defineProperty(MultipleLlmExecutionTools.prototype, "title", {
2225
- get: function () {
2226
- return 'Multiple LLM Providers';
2227
- },
2228
- enumerable: false,
2229
- configurable: true
2230
- });
2231
- Object.defineProperty(MultipleLlmExecutionTools.prototype, "description", {
2232
- get: function () {
2233
- return this.llmExecutionTools.map(function (_a, index) {
2234
- var title = _a.title;
2235
- return "".concat(index + 1, ") `").concat(title, "`");
2236
- }).join('\n');
2237
- },
2238
- enumerable: false,
2239
- configurable: true
2240
- });
2241
- /**
2242
- * Check the configuration of all execution tools
2243
- */
2244
- MultipleLlmExecutionTools.prototype.checkConfiguration = function () {
2245
- return __awaiter(this, void 0, void 0, function () {
2246
- var _a, _b, llmExecutionTools, e_1_1;
2247
- var e_1, _c;
2248
- return __generator(this, function (_d) {
2249
- switch (_d.label) {
2250
- case 0:
2251
- _d.trys.push([0, 5, 6, 7]);
2252
- _a = __values(this.llmExecutionTools), _b = _a.next();
2253
- _d.label = 1;
2254
- case 1:
2255
- if (!!_b.done) return [3 /*break*/, 4];
2256
- llmExecutionTools = _b.value;
2257
- return [4 /*yield*/, llmExecutionTools.checkConfiguration()];
2258
- case 2:
2259
- _d.sent();
2260
- _d.label = 3;
2261
- case 3:
2262
- _b = _a.next();
2263
- return [3 /*break*/, 1];
2264
- case 4: return [3 /*break*/, 7];
2265
- case 5:
2266
- e_1_1 = _d.sent();
2267
- e_1 = { error: e_1_1 };
2268
- return [3 /*break*/, 7];
2269
- case 6:
2270
- try {
2271
- if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
2272
- }
2273
- finally { if (e_1) throw e_1.error; }
2274
- return [7 /*endfinally*/];
2275
- case 7: return [2 /*return*/];
2276
- }
2277
- });
2278
- });
2279
- };
2280
- /**
2281
- * List all available models that can be used
2282
- * This lists is a combination of all available models from all execution tools
2283
- */
2284
- MultipleLlmExecutionTools.prototype.listModels = function () {
2285
- return __awaiter(this, void 0, void 0, function () {
2286
- var availableModels, _a, _b, llmExecutionTools, models, e_2_1;
2287
- var e_2, _c;
2288
- return __generator(this, function (_d) {
2289
- switch (_d.label) {
2290
- case 0:
2291
- availableModels = [];
2292
- _d.label = 1;
2293
- case 1:
2294
- _d.trys.push([1, 6, 7, 8]);
2295
- _a = __values(this.llmExecutionTools), _b = _a.next();
2296
- _d.label = 2;
2297
- case 2:
2298
- if (!!_b.done) return [3 /*break*/, 5];
2299
- llmExecutionTools = _b.value;
2300
- return [4 /*yield*/, llmExecutionTools.listModels()];
2301
- case 3:
2302
- models = _d.sent();
2303
- availableModels.push.apply(availableModels, __spreadArray([], __read(models), false));
2304
- _d.label = 4;
2305
- case 4:
2306
- _b = _a.next();
2307
- return [3 /*break*/, 2];
2308
- case 5: return [3 /*break*/, 8];
2309
- case 6:
2310
- e_2_1 = _d.sent();
2311
- e_2 = { error: e_2_1 };
2312
- return [3 /*break*/, 8];
2313
- case 7:
2314
- try {
2315
- if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
2316
- }
2317
- finally { if (e_2) throw e_2.error; }
2318
- return [7 /*endfinally*/];
2319
- case 8: return [2 /*return*/, availableModels];
2320
- }
2321
- });
2322
- });
2323
- };
2324
- /**
2325
- * Calls the best available chat model
2326
- */
2327
- MultipleLlmExecutionTools.prototype.callChatModel = function (prompt) {
2328
- return this.callCommonModel(prompt);
2329
- };
2330
- /**
2331
- * Calls the best available completion model
2332
- */
2333
- MultipleLlmExecutionTools.prototype.callCompletionModel = function (prompt) {
2334
- return this.callCommonModel(prompt);
2335
- };
2336
- /**
2337
- * Calls the best available embedding model
2338
- */
2339
- MultipleLlmExecutionTools.prototype.callEmbeddingModel = function (prompt) {
2340
- return this.callCommonModel(prompt);
2341
- };
2342
- // <- Note: [🤖]
2343
- /**
2344
- * Calls the best available model
2345
- *
2346
- * Note: This should be private or protected but is public to be usable with duck typing
2347
- */
2348
- MultipleLlmExecutionTools.prototype.callCommonModel = function (prompt) {
2349
- return __awaiter(this, void 0, void 0, function () {
2350
- var errors, _a, _b, llmExecutionTools, _c, error_1, e_3_1;
2351
- var e_3, _d;
2352
- var _this = this;
2353
- return __generator(this, function (_e) {
2354
- switch (_e.label) {
2355
- case 0:
2356
- errors = [];
2357
- _e.label = 1;
2358
- case 1:
2359
- _e.trys.push([1, 15, 16, 17]);
2360
- _a = __values(this.llmExecutionTools), _b = _a.next();
2361
- _e.label = 2;
2362
- case 2:
2363
- if (!!_b.done) return [3 /*break*/, 14];
2364
- llmExecutionTools = _b.value;
2365
- _e.label = 3;
2366
- case 3:
2367
- _e.trys.push([3, 12, , 13]);
2368
- _c = prompt.modelRequirements.modelVariant;
2369
- switch (_c) {
2370
- case 'CHAT': return [3 /*break*/, 4];
2371
- case 'COMPLETION': return [3 /*break*/, 6];
2372
- case 'EMBEDDING': return [3 /*break*/, 8];
2373
- }
2374
- return [3 /*break*/, 10];
2375
- case 4:
2376
- if (llmExecutionTools.callChatModel === undefined) {
2377
- return [3 /*break*/, 13];
2378
- }
2379
- return [4 /*yield*/, llmExecutionTools.callChatModel(prompt)];
2380
- case 5: return [2 /*return*/, _e.sent()];
2381
- case 6:
2382
- if (llmExecutionTools.callCompletionModel === undefined) {
2383
- return [3 /*break*/, 13];
2384
- }
2385
- return [4 /*yield*/, llmExecutionTools.callCompletionModel(prompt)];
2386
- case 7: return [2 /*return*/, _e.sent()];
2387
- case 8:
2388
- if (llmExecutionTools.callEmbeddingModel === undefined) {
2389
- return [3 /*break*/, 13];
2390
- }
2391
- return [4 /*yield*/, llmExecutionTools.callEmbeddingModel(prompt)];
2392
- case 9: return [2 /*return*/, _e.sent()];
2393
- case 10: throw new UnexpectedError("Unknown model variant \"".concat(prompt.modelRequirements.modelVariant, "\""));
2394
- case 11: return [3 /*break*/, 13];
2395
- case 12:
2396
- error_1 = _e.sent();
2397
- if (!(error_1 instanceof Error) || error_1 instanceof UnexpectedError) {
2398
- throw error_1;
2399
- }
2400
- errors.push(error_1);
2401
- return [3 /*break*/, 13];
2402
- case 13:
2403
- _b = _a.next();
2404
- return [3 /*break*/, 2];
2405
- case 14: return [3 /*break*/, 17];
2406
- case 15:
2407
- e_3_1 = _e.sent();
2408
- e_3 = { error: e_3_1 };
2409
- return [3 /*break*/, 17];
2410
- case 16:
2411
- try {
2412
- if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
2413
- }
2414
- finally { if (e_3) throw e_3.error; }
2415
- return [7 /*endfinally*/];
2416
- case 17:
2417
- if (errors.length === 1) {
2418
- throw errors[0];
2419
- }
2420
- else if (errors.length > 1) {
2421
- throw new PipelineExecutionError(
2422
- // TODO: Tell which execution tools failed like
2423
- // 1) OpenAI throw PipelineExecutionError: Parameter `{knowledge}` is not defined
2424
- // 2) AnthropicClaude throw PipelineExecutionError: Parameter `{knowledge}` is not defined
2425
- // 3) ...
2426
- spaceTrim__default["default"](function (block) { return "\n All execution tools failed:\n\n ".concat(block(errors
2427
- .map(function (error, i) { return "".concat(i + 1, ") **").concat(error.name || 'Error', ":** ").concat(error.message); })
2428
- .join('\n')), "\n\n "); }));
2429
- }
2430
- else if (this.llmExecutionTools.length === 0) {
2431
- throw new PipelineExecutionError("You have not provided any `LlmExecutionTools`");
2432
- }
2433
- else {
2434
- throw new PipelineExecutionError(spaceTrim__default["default"](function (block) { return "\n You have not provided any `LlmExecutionTools` that support model variant \"".concat(prompt.modelRequirements.modelVariant, "\"\n\n Available `LlmExecutionTools`:\n ").concat(block(_this.description), "\n\n "); }));
2435
- }
2436
- }
2437
- });
2438
- });
2439
- };
2440
- return MultipleLlmExecutionTools;
2441
- }());
2442
- /**
2443
- * TODO: [🧠][🎛] Aggregating multiple models - have result not only from one first aviable model BUT all of them
2444
- * TODO: [🏖] If no llmTools have for example not defined `callCompletionModel` this will still return object with defined `callCompletionModel` which just throws `PipelineExecutionError`, make it undefined instead
2445
- * Look how `countTotalUsage` (and `cacheLlmTools`) implements it
2446
- */
2447
-
2448
- /**
2449
- * Joins multiple LLM Execution Tools into one
2450
- *
2451
- * @returns {LlmExecutionTools} Single wrapper for multiple LlmExecutionTools
2452
- *
2453
- * 0) If there is no LlmExecutionTools, it warns and returns valid but empty LlmExecutionTools
2454
- * 1) If there is only one LlmExecutionTools, it returns it wrapped in a proxy object
2455
- * 2) If there are multiple LlmExecutionTools, first will be used first, second will be used if the first hasn`t defined model variant or fails, etc.
2456
- * 3) When all LlmExecutionTools fail, it throws an error with a list of all errors merged into one
2457
- *
2458
- *
2459
- * Tip: You don't have to use this function directly, just pass an array of LlmExecutionTools to the `ExecutionTools`
2460
- *
2461
- * @public exported from `@promptbook/core`
2462
- */
2463
- function joinLlmExecutionTools() {
2464
- var llmExecutionTools = [];
2465
- for (var _i = 0; _i < arguments.length; _i++) {
2466
- llmExecutionTools[_i] = arguments[_i];
2467
- }
2468
- if (llmExecutionTools.length === 0) {
2469
- var warningMessage = spaceTrim__default["default"]("\n You have not provided any `LlmExecutionTools`\n This means that you won't be able to execute any prompts that require large language models like GPT-4 or Anthropic's Claude.\n\n Technically, it's not an error, but it's probably not what you want because it does not make sense to use Promptbook without language models.\n ");
2470
- // TODO: [🟥] Detect browser / node and make it colorfull
2471
- console.warn(warningMessage);
2472
- /*
2473
- return {
2474
- async listModels() {
2475
- // TODO: [🟥] Detect browser / node and make it colorfull
2476
- console.warn(
2477
- spaceTrim(
2478
- (block) => `
2479
-
2480
- You can't list models because you have no LLM Execution Tools defined:
2481
-
2482
- tl;dr
2483
-
2484
- ${block(warningMessage)}
2485
- `,
2486
- ),
2487
- );
2488
- return [];
2489
- },
2490
- };
2491
- */
2492
- }
2493
- return new (MultipleLlmExecutionTools.bind.apply(MultipleLlmExecutionTools, __spreadArray([void 0], __read(llmExecutionTools), false)))();
2494
- }
2495
- /**
2496
- * TODO: [👷‍♂️] @@@ Manual about construction of llmTools
2497
- */
2498
-
2499
- var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book.md",formfactorName:"GENERIC",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}",resultingParameterName:"knowledgePieces",dependentParameterNames:["knowledgeContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge from Markdown\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book.md`\n- INPUT PARAMETER `{knowledgeContent}` Markdown document content\n- OUTPUT PARAMETER `{knowledgePieces}` The knowledge JSON object\n\n## Knowledge\n\n<!-- TODO: [🍆] -FORMAT JSON -->\n\n```markdown\nYou are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}\n```\n\n`-> {knowledgePieces}`\n"}],sourceFile:"./books/prepare-knowledge-from-markdown.book.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.book.md",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}",resultingParameterName:"keywords",dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Keywords\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-keywords.book.md`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{keywords}` Keywords separated by comma\n\n## Knowledge\n\n<!-- TODO: [🍆] -FORMAT JSON -->\n\n```markdown\nYou are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}\n```\n\n`-> {keywords}`\n"}],sourceFile:"./books/prepare-knowledge-keywords.book.md"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.book.md",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Title should be concise and clear\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}",resultingParameterName:"title",expectations:{words:{min:1,max:8}},dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-title.book.md`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{title}` The title of the document\n\n## Knowledge\n\n- EXPECT MIN 1 WORD\n- EXPECT MAX 8 WORDS\n\n```markdown\nYou are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Title should be concise and clear\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-knowledge-title.book.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.book.md",formfactorName:"GENERIC",parameters:[{name:"availableModelNames",description:"List of available model names separated by comma (,)",isInput:true,isOutput:false},{name:"personaDescription",description:"Description of the persona",isInput:true,isOutput:false},{name:"modelRequirements",description:"Specific requirements for the model",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-model-requirements",title:"Make modelRequirements",content:"You are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Example\n\n```json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n```\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}",resultingParameterName:"modelRequirements",format:"JSON",dependentParameterNames:["availableModelNames","personaDescription"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Keywords\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-persona.book.md`\n- INPUT PARAMETER `{availableModelNames}` List of available model names separated by comma (,)\n- INPUT PARAMETER `{personaDescription}` Description of the persona\n- OUTPUT PARAMETER `{modelRequirements}` Specific requirements for the model\n\n## Make modelRequirements\n\n- FORMAT JSON\n\n```markdown\nYou are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Example\n\n\\`\\`\\`json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n\\`\\`\\`\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}\n```\n\n`-> {modelRequirements}`\n"}],sourceFile:"./books/prepare-persona.book.md"}];
2500
-
2501
- /**
2502
- * This error indicates problems parsing the format value
2503
- *
2504
- * For example, when the format value is not a valid JSON or CSV
2505
- * This is not thrown directly but in extended classes
2506
- *
2507
- * @public exported from `@promptbook/core`
2508
- */
2509
- var AbstractFormatError = /** @class */ (function (_super) {
2510
- __extends(AbstractFormatError, _super);
2511
- // Note: To allow instanceof do not put here error `name`
2512
- // public readonly name = 'AbstractFormatError';
2513
- function AbstractFormatError(message) {
2514
- var _this = _super.call(this, message) || this;
2515
- Object.setPrototypeOf(_this, AbstractFormatError.prototype);
2516
- return _this;
2517
- }
2518
- return AbstractFormatError;
2519
- }(Error));
2520
-
2521
- /**
2522
- * This error indicates problem with parsing of CSV
2523
- *
2524
- * @public exported from `@promptbook/core`
2525
- */
2526
- var CsvFormatError = /** @class */ (function (_super) {
2527
- __extends(CsvFormatError, _super);
2528
- function CsvFormatError(message) {
2529
- var _this = _super.call(this, message) || this;
2530
- _this.name = 'CsvFormatError';
2531
- Object.setPrototypeOf(_this, CsvFormatError.prototype);
2532
- return _this;
2533
- }
2534
- return CsvFormatError;
2535
- }(AbstractFormatError));
2536
-
2537
- /**
2538
- * This error indicates that the pipeline collection cannot be propperly loaded
2539
- *
2540
- * @public exported from `@promptbook/core`
2541
- */
2542
- var CollectionError = /** @class */ (function (_super) {
2543
- __extends(CollectionError, _super);
2544
- function CollectionError(message) {
2545
- var _this = _super.call(this, message) || this;
2546
- _this.name = 'CollectionError';
2547
- Object.setPrototypeOf(_this, CollectionError.prototype);
2548
- return _this;
2549
- }
2550
- return CollectionError;
2551
- }(Error));
2552
-
2553
- /**
2554
- * This error type indicates that you try to use a feature that is not available in the current environment
2009
+ * This error type indicates that you try to use a feature that is not available in the current environment
2555
2010
  *
2556
2011
  * @public exported from `@promptbook/core`
2557
2012
  */
@@ -2737,11 +2192,16 @@
2737
2192
  /**
2738
2193
  * Determine if the pipeline is fully prepared
2739
2194
  *
2195
+ * @see https://github.com/webgptorg/promptbook/discussions/196
2196
+ *
2740
2197
  * @public exported from `@promptbook/core`
2741
2198
  */
2742
2199
  function isPipelinePrepared(pipeline) {
2743
2200
  // Note: Ignoring `pipeline.preparations` @@@
2744
2201
  // Note: Ignoring `pipeline.knowledgePieces` @@@
2202
+ if (pipeline.title === undefined || pipeline.title === '' || pipeline.title === DEFAULT_BOOK_TITLE) {
2203
+ return false;
2204
+ }
2745
2205
  if (!pipeline.personas.every(function (persona) { return persona.modelRequirements !== undefined; })) {
2746
2206
  return false;
2747
2207
  }
@@ -2757,7 +2217,7 @@
2757
2217
  return true;
2758
2218
  }
2759
2219
  /**
2760
- * TODO: [🔃][main] !! If the pipeline was prepared with different version or different set of models, prepare it once again
2220
+ * TODO: [🔃][main] If the pipeline was prepared with different version or different set of models, prepare it once again
2761
2221
  * TODO: [🐠] Maybe base this on `makeValidator`
2762
2222
  * TODO: [🧊] Pipeline can be partially prepared, this should return true ONLY if fully prepared
2763
2223
  * TODO: [🧿] Maybe do same process with same granularity and subfinctions as `preparePipeline`
@@ -2766,6 +2226,81 @@
2766
2226
  * - [♨] Are tasks prepared
2767
2227
  */
2768
2228
 
2229
+ /**
2230
+ * Format either small or big number
2231
+ *
2232
+ * @public exported from `@promptbook/utils`
2233
+ */
2234
+ function numberToString(value) {
2235
+ if (value === 0) {
2236
+ return '0';
2237
+ }
2238
+ else if (Number.isNaN(value)) {
2239
+ return VALUE_STRINGS.nan;
2240
+ }
2241
+ else if (value === Infinity) {
2242
+ return VALUE_STRINGS.infinity;
2243
+ }
2244
+ else if (value === -Infinity) {
2245
+ return VALUE_STRINGS.negativeInfinity;
2246
+ }
2247
+ for (var exponent = 0; exponent < 15; exponent++) {
2248
+ var factor = Math.pow(10, exponent);
2249
+ var valueRounded = Math.round(value * factor) / factor;
2250
+ if (Math.abs(value - valueRounded) / value < SMALL_NUMBER) {
2251
+ return valueRounded.toFixed(exponent);
2252
+ }
2253
+ }
2254
+ return value.toString();
2255
+ }
2256
+
2257
+ /**
2258
+ * Function `valueToString` will convert the given value to string
2259
+ * This is useful and used in the `templateParameters` function
2260
+ *
2261
+ * Note: This function is not just calling `toString` method
2262
+ * It's more complex and can handle this conversion specifically for LLM models
2263
+ * See `VALUE_STRINGS`
2264
+ *
2265
+ * Note: There are 2 similar functions
2266
+ * - `valueToString` converts value to string for LLM models as human-readable string
2267
+ * - `asSerializable` converts value to string to preserve full information to be able to convert it back
2268
+ *
2269
+ * @public exported from `@promptbook/utils`
2270
+ */
2271
+ function valueToString(value) {
2272
+ try {
2273
+ if (value === '') {
2274
+ return VALUE_STRINGS.empty;
2275
+ }
2276
+ else if (value === null) {
2277
+ return VALUE_STRINGS.null;
2278
+ }
2279
+ else if (value === undefined) {
2280
+ return VALUE_STRINGS.undefined;
2281
+ }
2282
+ else if (typeof value === 'string') {
2283
+ return value;
2284
+ }
2285
+ else if (typeof value === 'number') {
2286
+ return numberToString(value);
2287
+ }
2288
+ else if (value instanceof Date) {
2289
+ return value.toISOString();
2290
+ }
2291
+ else {
2292
+ return JSON.stringify(value);
2293
+ }
2294
+ }
2295
+ catch (error) {
2296
+ if (!(error instanceof Error)) {
2297
+ throw error;
2298
+ }
2299
+ console.error(error);
2300
+ return VALUE_STRINGS.unserializable;
2301
+ }
2302
+ }
2303
+
2769
2304
  /**
2770
2305
  * Serializes an error into a [🚉] JSON-serializable object
2771
2306
  *
@@ -2783,6 +2318,134 @@
2783
2318
  };
2784
2319
  }
2785
2320
 
2321
+ /**
2322
+ * Represents the usage with no resources consumed
2323
+ *
2324
+ * @public exported from `@promptbook/core`
2325
+ */
2326
+ var ZERO_USAGE = $deepFreeze({
2327
+ price: { value: 0 },
2328
+ input: {
2329
+ tokensCount: { value: 0 },
2330
+ charactersCount: { value: 0 },
2331
+ wordsCount: { value: 0 },
2332
+ sentencesCount: { value: 0 },
2333
+ linesCount: { value: 0 },
2334
+ paragraphsCount: { value: 0 },
2335
+ pagesCount: { value: 0 },
2336
+ },
2337
+ output: {
2338
+ tokensCount: { value: 0 },
2339
+ charactersCount: { value: 0 },
2340
+ wordsCount: { value: 0 },
2341
+ sentencesCount: { value: 0 },
2342
+ linesCount: { value: 0 },
2343
+ paragraphsCount: { value: 0 },
2344
+ pagesCount: { value: 0 },
2345
+ },
2346
+ });
2347
+ /**
2348
+ * Represents the usage with unknown resources consumed
2349
+ *
2350
+ * @public exported from `@promptbook/core`
2351
+ */
2352
+ var UNCERTAIN_USAGE = $deepFreeze({
2353
+ price: { value: 0, isUncertain: true },
2354
+ input: {
2355
+ tokensCount: { value: 0, isUncertain: true },
2356
+ charactersCount: { value: 0, isUncertain: true },
2357
+ wordsCount: { value: 0, isUncertain: true },
2358
+ sentencesCount: { value: 0, isUncertain: true },
2359
+ linesCount: { value: 0, isUncertain: true },
2360
+ paragraphsCount: { value: 0, isUncertain: true },
2361
+ pagesCount: { value: 0, isUncertain: true },
2362
+ },
2363
+ output: {
2364
+ tokensCount: { value: 0, isUncertain: true },
2365
+ charactersCount: { value: 0, isUncertain: true },
2366
+ wordsCount: { value: 0, isUncertain: true },
2367
+ sentencesCount: { value: 0, isUncertain: true },
2368
+ linesCount: { value: 0, isUncertain: true },
2369
+ paragraphsCount: { value: 0, isUncertain: true },
2370
+ pagesCount: { value: 0, isUncertain: true },
2371
+ },
2372
+ });
2373
+ /**
2374
+ * Note: [💞] Ignore a discrepancy between file name and entity name
2375
+ */
2376
+
2377
+ /**
2378
+ * Function `addUsage` will add multiple usages into one
2379
+ *
2380
+ * Note: If you provide 0 values, it returns ZERO_USAGE
2381
+ *
2382
+ * @public exported from `@promptbook/core`
2383
+ */
2384
+ function addUsage() {
2385
+ var usageItems = [];
2386
+ for (var _i = 0; _i < arguments.length; _i++) {
2387
+ usageItems[_i] = arguments[_i];
2388
+ }
2389
+ return usageItems.reduce(function (acc, item) {
2390
+ var e_1, _a, e_2, _b;
2391
+ var _c;
2392
+ acc.price.value += ((_c = item.price) === null || _c === void 0 ? void 0 : _c.value) || 0;
2393
+ try {
2394
+ for (var _d = __values(Object.keys(acc.input)), _e = _d.next(); !_e.done; _e = _d.next()) {
2395
+ var key = _e.value;
2396
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2397
+ //@ts-ignore
2398
+ if (item.input[key]) {
2399
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2400
+ //@ts-ignore
2401
+ acc.input[key].value += item.input[key].value || 0;
2402
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2403
+ //@ts-ignore
2404
+ if (item.input[key].isUncertain) {
2405
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2406
+ //@ts-ignore
2407
+ acc.input[key].isUncertain = true;
2408
+ }
2409
+ }
2410
+ }
2411
+ }
2412
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
2413
+ finally {
2414
+ try {
2415
+ if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
2416
+ }
2417
+ finally { if (e_1) throw e_1.error; }
2418
+ }
2419
+ try {
2420
+ for (var _f = __values(Object.keys(acc.output)), _g = _f.next(); !_g.done; _g = _f.next()) {
2421
+ var key = _g.value;
2422
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2423
+ //@ts-ignore
2424
+ if (item.output[key]) {
2425
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2426
+ //@ts-ignore
2427
+ acc.output[key].value += item.output[key].value || 0;
2428
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2429
+ //@ts-ignore
2430
+ if (item.output[key].isUncertain) {
2431
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2432
+ //@ts-ignore
2433
+ acc.output[key].isUncertain = true;
2434
+ }
2435
+ }
2436
+ }
2437
+ }
2438
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
2439
+ finally {
2440
+ try {
2441
+ if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
2442
+ }
2443
+ finally { if (e_2) throw e_2.error; }
2444
+ }
2445
+ return acc;
2446
+ }, deepClone(ZERO_USAGE));
2447
+ }
2448
+
2786
2449
  /**
2787
2450
  * Parses the given script and returns the list of all used variables that are not defined in the script
2788
2451
  *
@@ -2837,7 +2500,7 @@
2837
2500
  if (!(error instanceof Error)) {
2838
2501
  throw error;
2839
2502
  }
2840
- throw new ParseError(spaceTrim.spaceTrim(function (block) { return "\n Can not extract variables from the script\n\n ".concat(block(error.toString()), "}\n\n\n Found variables:\n\n ").concat(Array.from(variables)
2503
+ throw new ParseError(spaceTrim.spaceTrim(function (block) { return "\n Can not extract variables from the script\n ".concat(block(error.stack || error.message), "\n\n Found variables:\n ").concat(Array.from(variables)
2841
2504
  .map(function (variableName, i) { return "".concat(i + 1, ") ").concat(variableName); })
2842
2505
  .join('\n'), "\n\n\n The script:\n\n ```javascript\n ").concat(block(originalScript), "\n ```\n "); }));
2843
2506
  }
@@ -3102,41 +2765,20 @@
3102
2765
  case 1:
3103
2766
  mappedData = _a.sent();
3104
2767
  return [2 /*return*/, papaparse.unparse(mappedData, __assign(__assign({}, settings), MANDATORY_CSV_SETTINGS))];
3105
- }
3106
- });
3107
- });
3108
- },
3109
- },
3110
- ],
3111
- };
3112
- /**
3113
- * TODO: [🍓] In `CsvFormatDefinition` implement simple `isValid`
3114
- * TODO: [🍓] In `CsvFormatDefinition` implement partial `canBeValid`
3115
- * TODO: [🍓] In `CsvFormatDefinition` implement `heal
3116
- * TODO: [🍓] In `CsvFormatDefinition` implement `subvalueDefinitions`
3117
- * TODO: [🏢] Allow to expect something inside CSV objects and other formats
3118
- */
3119
-
3120
- /**
3121
- * Function isValidJsonString will tell you if the string is valid JSON or not
3122
- *
3123
- * @public exported from `@promptbook/utils`
3124
- */
3125
- function isValidJsonString(value /* <- [👨‍⚖️] */) {
3126
- try {
3127
- JSON.parse(value);
3128
- return true;
3129
- }
3130
- catch (error) {
3131
- if (!(error instanceof Error)) {
3132
- throw error;
3133
- }
3134
- if (error.message.includes('Unexpected token')) {
3135
- return false;
3136
- }
3137
- return false;
3138
- }
3139
- }
2768
+ }
2769
+ });
2770
+ });
2771
+ },
2772
+ },
2773
+ ],
2774
+ };
2775
+ /**
2776
+ * TODO: [🍓] In `CsvFormatDefinition` implement simple `isValid`
2777
+ * TODO: [🍓] In `CsvFormatDefinition` implement partial `canBeValid`
2778
+ * TODO: [🍓] In `CsvFormatDefinition` implement `heal
2779
+ * TODO: [🍓] In `CsvFormatDefinition` implement `subvalueDefinitions`
2780
+ * TODO: [🏢] Allow to expect something inside CSV objects and other formats
2781
+ */
3140
2782
 
3141
2783
  /**
3142
2784
  * Definition for JSON format
@@ -3330,15 +2972,307 @@
3330
2972
  .map(function (parameterName) { return "- {".concat(parameterName, "}"); })
3331
2973
  .join('\n')), "\n\n "); }));
3332
2974
  }
3333
- var expectedParameterNamesArray = Array.from(expectedParameterNames);
3334
- var availableParametersNamesArray = Array.from(availableParametersNames);
3335
- for (var i = 0; i < expectedParameterNames.size; i++) {
3336
- mappedParameters[expectedParameterNamesArray[i]] = availableParameters[availableParametersNamesArray[i]];
2975
+ var expectedParameterNamesArray = Array.from(expectedParameterNames);
2976
+ var availableParametersNamesArray = Array.from(availableParametersNames);
2977
+ for (var i = 0; i < expectedParameterNames.size; i++) {
2978
+ mappedParameters[expectedParameterNamesArray[i]] = availableParameters[availableParametersNamesArray[i]];
2979
+ }
2980
+ // Note: [👨‍👨‍👧] Now we can freeze `mappedParameters` to prevent @@@
2981
+ Object.freeze(mappedParameters);
2982
+ return mappedParameters;
2983
+ }
2984
+
2985
+ /**
2986
+ * Multiple LLM Execution Tools is a proxy server that uses multiple execution tools internally and exposes the executor interface externally.
2987
+ *
2988
+ * Note: Internal utility of `joinLlmExecutionTools` but exposed type
2989
+ * @public exported from `@promptbook/core`
2990
+ */
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;
3001
+ }
3002
+ Object.defineProperty(MultipleLlmExecutionTools.prototype, "title", {
3003
+ get: function () {
3004
+ return 'Multiple LLM Providers';
3005
+ },
3006
+ enumerable: false,
3007
+ configurable: true
3008
+ });
3009
+ Object.defineProperty(MultipleLlmExecutionTools.prototype, "description", {
3010
+ get: function () {
3011
+ return this.llmExecutionTools.map(function (_a, index) {
3012
+ var title = _a.title;
3013
+ return "".concat(index + 1, ") `").concat(title, "`");
3014
+ }).join('\n');
3015
+ },
3016
+ enumerable: false,
3017
+ configurable: true
3018
+ });
3019
+ /**
3020
+ * Check the configuration of all execution tools
3021
+ */
3022
+ MultipleLlmExecutionTools.prototype.checkConfiguration = function () {
3023
+ return __awaiter(this, void 0, void 0, function () {
3024
+ var _a, _b, llmExecutionTools, e_1_1;
3025
+ var e_1, _c;
3026
+ return __generator(this, function (_d) {
3027
+ switch (_d.label) {
3028
+ case 0:
3029
+ _d.trys.push([0, 5, 6, 7]);
3030
+ _a = __values(this.llmExecutionTools), _b = _a.next();
3031
+ _d.label = 1;
3032
+ case 1:
3033
+ if (!!_b.done) return [3 /*break*/, 4];
3034
+ llmExecutionTools = _b.value;
3035
+ return [4 /*yield*/, llmExecutionTools.checkConfiguration()];
3036
+ case 2:
3037
+ _d.sent();
3038
+ _d.label = 3;
3039
+ case 3:
3040
+ _b = _a.next();
3041
+ return [3 /*break*/, 1];
3042
+ case 4: return [3 /*break*/, 7];
3043
+ case 5:
3044
+ e_1_1 = _d.sent();
3045
+ e_1 = { error: e_1_1 };
3046
+ return [3 /*break*/, 7];
3047
+ case 6:
3048
+ try {
3049
+ if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
3050
+ }
3051
+ finally { if (e_1) throw e_1.error; }
3052
+ return [7 /*endfinally*/];
3053
+ case 7: return [2 /*return*/];
3054
+ }
3055
+ });
3056
+ });
3057
+ };
3058
+ /**
3059
+ * List all available models that can be used
3060
+ * This lists is a combination of all available models from all execution tools
3061
+ */
3062
+ MultipleLlmExecutionTools.prototype.listModels = function () {
3063
+ return __awaiter(this, void 0, void 0, function () {
3064
+ var availableModels, _a, _b, llmExecutionTools, models, e_2_1;
3065
+ var e_2, _c;
3066
+ return __generator(this, function (_d) {
3067
+ switch (_d.label) {
3068
+ case 0:
3069
+ availableModels = [];
3070
+ _d.label = 1;
3071
+ case 1:
3072
+ _d.trys.push([1, 6, 7, 8]);
3073
+ _a = __values(this.llmExecutionTools), _b = _a.next();
3074
+ _d.label = 2;
3075
+ case 2:
3076
+ if (!!_b.done) return [3 /*break*/, 5];
3077
+ llmExecutionTools = _b.value;
3078
+ return [4 /*yield*/, llmExecutionTools.listModels()];
3079
+ case 3:
3080
+ models = _d.sent();
3081
+ availableModels.push.apply(availableModels, __spreadArray([], __read(models), false));
3082
+ _d.label = 4;
3083
+ case 4:
3084
+ _b = _a.next();
3085
+ return [3 /*break*/, 2];
3086
+ case 5: return [3 /*break*/, 8];
3087
+ case 6:
3088
+ e_2_1 = _d.sent();
3089
+ e_2 = { error: e_2_1 };
3090
+ return [3 /*break*/, 8];
3091
+ case 7:
3092
+ try {
3093
+ if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
3094
+ }
3095
+ finally { if (e_2) throw e_2.error; }
3096
+ return [7 /*endfinally*/];
3097
+ case 8: return [2 /*return*/, availableModels];
3098
+ }
3099
+ });
3100
+ });
3101
+ };
3102
+ /**
3103
+ * Calls the best available chat model
3104
+ */
3105
+ MultipleLlmExecutionTools.prototype.callChatModel = function (prompt) {
3106
+ return this.callCommonModel(prompt);
3107
+ };
3108
+ /**
3109
+ * Calls the best available completion model
3110
+ */
3111
+ MultipleLlmExecutionTools.prototype.callCompletionModel = function (prompt) {
3112
+ return this.callCommonModel(prompt);
3113
+ };
3114
+ /**
3115
+ * Calls the best available embedding model
3116
+ */
3117
+ MultipleLlmExecutionTools.prototype.callEmbeddingModel = function (prompt) {
3118
+ return this.callCommonModel(prompt);
3119
+ };
3120
+ // <- Note: [🤖]
3121
+ /**
3122
+ * Calls the best available model
3123
+ *
3124
+ * Note: This should be private or protected but is public to be usable with duck typing
3125
+ */
3126
+ MultipleLlmExecutionTools.prototype.callCommonModel = function (prompt) {
3127
+ return __awaiter(this, void 0, void 0, function () {
3128
+ var errors, _a, _b, llmExecutionTools, _c, error_1, e_3_1;
3129
+ var e_3, _d;
3130
+ var _this = this;
3131
+ return __generator(this, function (_e) {
3132
+ switch (_e.label) {
3133
+ case 0:
3134
+ errors = [];
3135
+ _e.label = 1;
3136
+ case 1:
3137
+ _e.trys.push([1, 15, 16, 17]);
3138
+ _a = __values(this.llmExecutionTools), _b = _a.next();
3139
+ _e.label = 2;
3140
+ case 2:
3141
+ if (!!_b.done) return [3 /*break*/, 14];
3142
+ llmExecutionTools = _b.value;
3143
+ _e.label = 3;
3144
+ case 3:
3145
+ _e.trys.push([3, 12, , 13]);
3146
+ _c = prompt.modelRequirements.modelVariant;
3147
+ switch (_c) {
3148
+ case 'CHAT': return [3 /*break*/, 4];
3149
+ case 'COMPLETION': return [3 /*break*/, 6];
3150
+ case 'EMBEDDING': return [3 /*break*/, 8];
3151
+ }
3152
+ return [3 /*break*/, 10];
3153
+ case 4:
3154
+ if (llmExecutionTools.callChatModel === undefined) {
3155
+ return [3 /*break*/, 13];
3156
+ }
3157
+ return [4 /*yield*/, llmExecutionTools.callChatModel(prompt)];
3158
+ case 5: return [2 /*return*/, _e.sent()];
3159
+ case 6:
3160
+ if (llmExecutionTools.callCompletionModel === undefined) {
3161
+ return [3 /*break*/, 13];
3162
+ }
3163
+ return [4 /*yield*/, llmExecutionTools.callCompletionModel(prompt)];
3164
+ case 7: return [2 /*return*/, _e.sent()];
3165
+ case 8:
3166
+ if (llmExecutionTools.callEmbeddingModel === undefined) {
3167
+ return [3 /*break*/, 13];
3168
+ }
3169
+ return [4 /*yield*/, llmExecutionTools.callEmbeddingModel(prompt)];
3170
+ case 9: return [2 /*return*/, _e.sent()];
3171
+ case 10: throw new UnexpectedError("Unknown model variant \"".concat(prompt.modelRequirements.modelVariant, "\""));
3172
+ case 11: return [3 /*break*/, 13];
3173
+ case 12:
3174
+ error_1 = _e.sent();
3175
+ if (!(error_1 instanceof Error) || error_1 instanceof UnexpectedError) {
3176
+ throw error_1;
3177
+ }
3178
+ errors.push(error_1);
3179
+ return [3 /*break*/, 13];
3180
+ case 13:
3181
+ _b = _a.next();
3182
+ return [3 /*break*/, 2];
3183
+ case 14: return [3 /*break*/, 17];
3184
+ case 15:
3185
+ e_3_1 = _e.sent();
3186
+ e_3 = { error: e_3_1 };
3187
+ return [3 /*break*/, 17];
3188
+ case 16:
3189
+ try {
3190
+ if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
3191
+ }
3192
+ finally { if (e_3) throw e_3.error; }
3193
+ return [7 /*endfinally*/];
3194
+ case 17:
3195
+ if (errors.length === 1) {
3196
+ throw errors[0];
3197
+ }
3198
+ else if (errors.length > 1) {
3199
+ throw new PipelineExecutionError(
3200
+ // TODO: Tell which execution tools failed like
3201
+ // 1) OpenAI throw PipelineExecutionError: Parameter `{knowledge}` is not defined
3202
+ // 2) AnthropicClaude throw PipelineExecutionError: Parameter `{knowledge}` is not defined
3203
+ // 3) ...
3204
+ spaceTrim__default["default"](function (block) { return "\n All execution tools failed:\n\n ".concat(block(errors
3205
+ .map(function (error, i) { return "".concat(i + 1, ") **").concat(error.name || 'Error', ":** ").concat(error.message); })
3206
+ .join('\n')), "\n\n "); }));
3207
+ }
3208
+ else if (this.llmExecutionTools.length === 0) {
3209
+ throw new PipelineExecutionError("You have not provided any `LlmExecutionTools`");
3210
+ }
3211
+ else {
3212
+ throw new PipelineExecutionError(spaceTrim__default["default"](function (block) { return "\n You have not provided any `LlmExecutionTools` that support model variant \"".concat(prompt.modelRequirements.modelVariant, "\"\n\n Available `LlmExecutionTools`:\n ").concat(block(_this.description), "\n\n "); }));
3213
+ }
3214
+ }
3215
+ });
3216
+ });
3217
+ };
3218
+ return MultipleLlmExecutionTools;
3219
+ }());
3220
+ /**
3221
+ * TODO: [🧠][🎛] Aggregating multiple models - have result not only from one first aviable model BUT all of them
3222
+ * TODO: [🏖] If no llmTools have for example not defined `callCompletionModel` this will still return object with defined `callCompletionModel` which just throws `PipelineExecutionError`, make it undefined instead
3223
+ * Look how `countTotalUsage` (and `cacheLlmTools`) implements it
3224
+ */
3225
+
3226
+ /**
3227
+ * Joins multiple LLM Execution Tools into one
3228
+ *
3229
+ * @returns {LlmExecutionTools} Single wrapper for multiple LlmExecutionTools
3230
+ *
3231
+ * 0) If there is no LlmExecutionTools, it warns and returns valid but empty LlmExecutionTools
3232
+ * 1) If there is only one LlmExecutionTools, it returns it wrapped in a proxy object
3233
+ * 2) If there are multiple LlmExecutionTools, first will be used first, second will be used if the first hasn`t defined model variant or fails, etc.
3234
+ * 3) When all LlmExecutionTools fail, it throws an error with a list of all errors merged into one
3235
+ *
3236
+ *
3237
+ * Tip: You don't have to use this function directly, just pass an array of LlmExecutionTools to the `ExecutionTools`
3238
+ *
3239
+ * @public exported from `@promptbook/core`
3240
+ */
3241
+ function joinLlmExecutionTools() {
3242
+ var llmExecutionTools = [];
3243
+ for (var _i = 0; _i < arguments.length; _i++) {
3244
+ llmExecutionTools[_i] = arguments[_i];
3245
+ }
3246
+ if (llmExecutionTools.length === 0) {
3247
+ var warningMessage = spaceTrim__default["default"]("\n You have not provided any `LlmExecutionTools`\n This means that you won't be able to execute any prompts that require large language models like GPT-4 or Anthropic's Claude.\n\n Technically, it's not an error, but it's probably not what you want because it does not make sense to use Promptbook without language models.\n ");
3248
+ // TODO: [🟥] Detect browser / node and make it colorfull
3249
+ console.warn(warningMessage);
3250
+ /*
3251
+ return {
3252
+ async listModels() {
3253
+ // TODO: [🟥] Detect browser / node and make it colorfull
3254
+ console.warn(
3255
+ spaceTrim(
3256
+ (block) => `
3257
+
3258
+ You can't list models because you have no LLM Execution Tools defined:
3259
+
3260
+ tl;dr
3261
+
3262
+ ${block(warningMessage)}
3263
+ `,
3264
+ ),
3265
+ );
3266
+ return [];
3267
+ },
3268
+ };
3269
+ */
3337
3270
  }
3338
- // Note: [👨‍👨‍👧] Now we can freeze `mappedParameters` to prevent @@@
3339
- Object.freeze(mappedParameters);
3340
- return mappedParameters;
3271
+ return new (MultipleLlmExecutionTools.bind.apply(MultipleLlmExecutionTools, __spreadArray([void 0], __read(llmExecutionTools), false)))();
3341
3272
  }
3273
+ /**
3274
+ * TODO: [👷‍♂️] @@@ Manual about construction of llmTools
3275
+ */
3342
3276
 
3343
3277
  /**
3344
3278
  * Extracts all code blocks from markdown.
@@ -3475,81 +3409,6 @@
3475
3409
  return [input];
3476
3410
  }
3477
3411
 
3478
- /**
3479
- * Format either small or big number
3480
- *
3481
- * @public exported from `@promptbook/utils`
3482
- */
3483
- function numberToString(value) {
3484
- if (value === 0) {
3485
- return '0';
3486
- }
3487
- else if (Number.isNaN(value)) {
3488
- return VALUE_STRINGS.nan;
3489
- }
3490
- else if (value === Infinity) {
3491
- return VALUE_STRINGS.infinity;
3492
- }
3493
- else if (value === -Infinity) {
3494
- return VALUE_STRINGS.negativeInfinity;
3495
- }
3496
- for (var exponent = 0; exponent < 15; exponent++) {
3497
- var factor = Math.pow(10, exponent);
3498
- var valueRounded = Math.round(value * factor) / factor;
3499
- if (Math.abs(value - valueRounded) / value < SMALL_NUMBER) {
3500
- return valueRounded.toFixed(exponent);
3501
- }
3502
- }
3503
- return value.toString();
3504
- }
3505
-
3506
- /**
3507
- * Function `valueToString` will convert the given value to string
3508
- * This is useful and used in the `templateParameters` function
3509
- *
3510
- * Note: This function is not just calling `toString` method
3511
- * It's more complex and can handle this conversion specifically for LLM models
3512
- * See `VALUE_STRINGS`
3513
- *
3514
- * Note: There are 2 similar functions
3515
- * - `valueToString` converts value to string for LLM models as human-readable string
3516
- * - `asSerializable` converts value to string to preserve full information to be able to convert it back
3517
- *
3518
- * @public exported from `@promptbook/utils`
3519
- */
3520
- function valueToString(value) {
3521
- try {
3522
- if (value === '') {
3523
- return VALUE_STRINGS.empty;
3524
- }
3525
- else if (value === null) {
3526
- return VALUE_STRINGS.null;
3527
- }
3528
- else if (value === undefined) {
3529
- return VALUE_STRINGS.undefined;
3530
- }
3531
- else if (typeof value === 'string') {
3532
- return value;
3533
- }
3534
- else if (typeof value === 'number') {
3535
- return numberToString(value);
3536
- }
3537
- else if (value instanceof Date) {
3538
- return value.toISOString();
3539
- }
3540
- else {
3541
- return JSON.stringify(value);
3542
- }
3543
- }
3544
- catch (error) {
3545
- if (!(error instanceof Error)) {
3546
- throw error;
3547
- }
3548
- console.error(error);
3549
- return VALUE_STRINGS.unserializable;
3550
- }
3551
- }
3552
-
3553
3412
  /**
3554
3413
  * Replaces parameters in template with values from parameters object
3555
3414
  *
@@ -3606,6 +3465,8 @@
3606
3465
  throw new PipelineExecutionError("Parameter `{".concat(parameterName, "}` is not defined"));
3607
3466
  }
3608
3467
  parameterValue = valueToString(parameterValue);
3468
+ // Escape curly braces in parameter values to prevent prompt-injection
3469
+ parameterValue = parameterValue.replace(/[{}]/g, '\\$&');
3609
3470
  if (parameterValue.includes('\n') && /^\s*\W{0,3}\s*$/.test(precol)) {
3610
3471
  parameterValue = parameterValue
3611
3472
  .split('\n')
@@ -4248,7 +4109,7 @@
4248
4109
  promptTitle: task.title,
4249
4110
  promptMessage: templateParameters(task.description || '', parameters),
4250
4111
  defaultValue: templateParameters(preparedContent, parameters),
4251
- // TODO: [🧠] !! Figure out how to define placeholder in .book.md file
4112
+ // TODO: [🧠] Figure out how to define placeholder in .book.md file
4252
4113
  placeholder: undefined,
4253
4114
  priority: priority,
4254
4115
  }))];
@@ -4948,7 +4809,10 @@
4948
4809
  finally { if (e_2) throw e_2.error; }
4949
4810
  return [7 /*endfinally*/];
4950
4811
  case 19:
4951
- parametersToPass = inputParameters;
4812
+ parametersToPass = Object.fromEntries(Object.entries(inputParameters).map(function (_a) {
4813
+ var _b = __read(_a, 2), key = _b[0], value = _b[1];
4814
+ return [key, valueToString(value)];
4815
+ }));
4952
4816
  _g.label = 20;
4953
4817
  case 20:
4954
4818
  _g.trys.push([20, 25, , 28]);
@@ -5118,69 +4982,232 @@
5118
4982
  });
5119
4983
  });
5120
4984
  }
5121
- /**
5122
- * TODO: [🐚] Change onProgress to object that represents the running execution, can be subscribed via RxJS to and also awaited
5123
- */
4985
+ /**
4986
+ * TODO: [🐚] Change onProgress to object that represents the running execution, can be subscribed via RxJS to and also awaited
4987
+ */
4988
+
4989
+ /**
4990
+ * Creates executor function from pipeline and execution tools.
4991
+ *
4992
+ * @returns The executor function
4993
+ * @throws {PipelineLogicError} on logical error in the pipeline
4994
+ * @public exported from `@promptbook/core`
4995
+ */
4996
+ function createPipelineExecutor(options) {
4997
+ var _this = this;
4998
+ var pipeline = options.pipeline, tools = options.tools, _a = options.maxExecutionAttempts, maxExecutionAttempts = _a === void 0 ? DEFAULT_MAX_EXECUTION_ATTEMPTS : _a, _b = options.maxParallelCount, maxParallelCount = _b === void 0 ? DEFAULT_MAX_PARALLEL_COUNT : _b, _c = options.csvSettings, csvSettings = _c === void 0 ? DEFAULT_CSV_SETTINGS : _c, _d = options.isVerbose, isVerbose = _d === void 0 ? exports.DEFAULT_IS_VERBOSE : _d, _e = options.isNotPreparedWarningSupressed, isNotPreparedWarningSupressed = _e === void 0 ? false : _e, _f = options.cacheDirname, cacheDirname = _f === void 0 ? DEFAULT_SCRAPE_CACHE_DIRNAME : _f, _g = options.intermediateFilesStrategy, intermediateFilesStrategy = _g === void 0 ? DEFAULT_INTERMEDIATE_FILES_STRATEGY : _g, _h = options.isAutoInstalled, isAutoInstalled = _h === void 0 ? DEFAULT_IS_AUTO_INSTALLED : _h, _j = options.rootDirname, rootDirname = _j === void 0 ? null : _j;
4999
+ validatePipeline(pipeline);
5000
+ var pipelineIdentification = (function () {
5001
+ // Note: This is a 😐 implementation of [🚞]
5002
+ var _ = [];
5003
+ if (pipeline.sourceFile !== undefined) {
5004
+ _.push("File: ".concat(pipeline.sourceFile));
5005
+ }
5006
+ if (pipeline.pipelineUrl !== undefined) {
5007
+ _.push("Url: ".concat(pipeline.pipelineUrl));
5008
+ }
5009
+ return _.join('\n');
5010
+ })();
5011
+ var preparedPipeline;
5012
+ if (isPipelinePrepared(pipeline)) {
5013
+ preparedPipeline = pipeline;
5014
+ }
5015
+ else if (isNotPreparedWarningSupressed !== true) {
5016
+ console.warn(spaceTrim.spaceTrim(function (block) { return "\n Pipeline is not prepared\n\n ".concat(block(pipelineIdentification), "\n\n It will be prepared ad-hoc before the first execution and **returned as `preparedPipeline` in `PipelineExecutorResult`**\n But it is recommended to prepare the pipeline during collection preparation\n\n @see more at https://ptbk.io/prepare-pipeline\n "); }));
5017
+ }
5018
+ var runCount = 0;
5019
+ var pipelineExecutor = function (inputParameters, onProgress) { return __awaiter(_this, void 0, void 0, function () {
5020
+ return __generator(this, function (_a) {
5021
+ runCount++;
5022
+ return [2 /*return*/, /* not await */ executePipeline({
5023
+ pipeline: pipeline,
5024
+ preparedPipeline: preparedPipeline,
5025
+ setPreparedPipeline: function (newPreparedPipeline) {
5026
+ preparedPipeline = newPreparedPipeline;
5027
+ },
5028
+ inputParameters: inputParameters,
5029
+ tools: tools,
5030
+ onProgress: onProgress,
5031
+ pipelineIdentification: spaceTrim.spaceTrim(function (block) { return "\n ".concat(block(pipelineIdentification), "\n ").concat(runCount === 1 ? '' : "Run #".concat(runCount), "\n "); }),
5032
+ maxExecutionAttempts: maxExecutionAttempts,
5033
+ maxParallelCount: maxParallelCount,
5034
+ csvSettings: csvSettings,
5035
+ isVerbose: isVerbose,
5036
+ isNotPreparedWarningSupressed: isNotPreparedWarningSupressed,
5037
+ rootDirname: rootDirname,
5038
+ cacheDirname: cacheDirname,
5039
+ intermediateFilesStrategy: intermediateFilesStrategy,
5040
+ isAutoInstalled: isAutoInstalled,
5041
+ })];
5042
+ });
5043
+ }); };
5044
+ return pipelineExecutor;
5045
+ }
5046
+ /**
5047
+ * TODO: [🐚] Change onProgress to object that represents the running execution, can be subscribed via RxJS to and also awaited
5048
+ */
5049
+
5050
+ /**
5051
+ * Async version of Array.forEach
5052
+ *
5053
+ * @param array - Array to iterate over
5054
+ * @param options - Options for the function
5055
+ * @param callbackfunction - Function to call for each item
5056
+ * @public exported from `@promptbook/utils`
5057
+ * @deprecated [🪂] Use queues instead
5058
+ */
5059
+ function forEachAsync(array, options, callbackfunction) {
5060
+ return __awaiter(this, void 0, void 0, function () {
5061
+ var _a, maxParallelCount, index, runningTasks, tasks, _loop_1, _b, _c, item, e_1_1;
5062
+ var e_1, _d;
5063
+ return __generator(this, function (_e) {
5064
+ switch (_e.label) {
5065
+ case 0:
5066
+ _a = options.maxParallelCount, maxParallelCount = _a === void 0 ? Infinity : _a;
5067
+ index = 0;
5068
+ runningTasks = [];
5069
+ tasks = [];
5070
+ _loop_1 = function (item) {
5071
+ var currentIndex, task;
5072
+ return __generator(this, function (_f) {
5073
+ switch (_f.label) {
5074
+ case 0:
5075
+ currentIndex = index++;
5076
+ task = callbackfunction(item, currentIndex, array);
5077
+ tasks.push(task);
5078
+ runningTasks.push(task);
5079
+ /* not await */ Promise.resolve(task).then(function () {
5080
+ runningTasks = runningTasks.filter(function (t) { return t !== task; });
5081
+ });
5082
+ if (!(maxParallelCount < runningTasks.length)) return [3 /*break*/, 2];
5083
+ return [4 /*yield*/, Promise.race(runningTasks)];
5084
+ case 1:
5085
+ _f.sent();
5086
+ _f.label = 2;
5087
+ case 2: return [2 /*return*/];
5088
+ }
5089
+ });
5090
+ };
5091
+ _e.label = 1;
5092
+ case 1:
5093
+ _e.trys.push([1, 6, 7, 8]);
5094
+ _b = __values(array), _c = _b.next();
5095
+ _e.label = 2;
5096
+ case 2:
5097
+ if (!!_c.done) return [3 /*break*/, 5];
5098
+ item = _c.value;
5099
+ return [5 /*yield**/, _loop_1(item)];
5100
+ case 3:
5101
+ _e.sent();
5102
+ _e.label = 4;
5103
+ case 4:
5104
+ _c = _b.next();
5105
+ return [3 /*break*/, 2];
5106
+ case 5: return [3 /*break*/, 8];
5107
+ case 6:
5108
+ e_1_1 = _e.sent();
5109
+ e_1 = { error: e_1_1 };
5110
+ return [3 /*break*/, 8];
5111
+ case 7:
5112
+ try {
5113
+ if (_c && !_c.done && (_d = _b.return)) _d.call(_b);
5114
+ }
5115
+ finally { if (e_1) throw e_1.error; }
5116
+ return [7 /*endfinally*/];
5117
+ case 8: return [4 /*yield*/, Promise.all(tasks)];
5118
+ case 9:
5119
+ _e.sent();
5120
+ return [2 /*return*/];
5121
+ }
5122
+ });
5123
+ });
5124
+ }
5124
5125
 
5125
5126
  /**
5126
- * Creates executor function from pipeline and execution tools.
5127
+ * Intercepts LLM tools and counts total usage of the tools
5127
5128
  *
5128
- * @returns The executor function
5129
- * @throws {PipelineLogicError} on logical error in the pipeline
5129
+ * @param llmTools LLM tools to be intercepted with usage counting
5130
+ * @returns LLM tools with same functionality with added total cost counting
5130
5131
  * @public exported from `@promptbook/core`
5131
5132
  */
5132
- function createPipelineExecutor(options) {
5133
+ function countTotalUsage(llmTools) {
5133
5134
  var _this = this;
5134
- var pipeline = options.pipeline, tools = options.tools, _a = options.maxExecutionAttempts, maxExecutionAttempts = _a === void 0 ? DEFAULT_MAX_EXECUTION_ATTEMPTS : _a, _b = options.maxParallelCount, maxParallelCount = _b === void 0 ? DEFAULT_MAX_PARALLEL_COUNT : _b, _c = options.csvSettings, csvSettings = _c === void 0 ? DEFAULT_CSV_SETTINGS : _c, _d = options.isVerbose, isVerbose = _d === void 0 ? exports.DEFAULT_IS_VERBOSE : _d, _e = options.isNotPreparedWarningSupressed, isNotPreparedWarningSupressed = _e === void 0 ? false : _e, _f = options.cacheDirname, cacheDirname = _f === void 0 ? DEFAULT_SCRAPE_CACHE_DIRNAME : _f, _g = options.intermediateFilesStrategy, intermediateFilesStrategy = _g === void 0 ? DEFAULT_INTERMEDIATE_FILES_STRATEGY : _g, _h = options.isAutoInstalled, isAutoInstalled = _h === void 0 ? DEFAULT_IS_AUTO_INSTALLED : _h, _j = options.rootDirname, rootDirname = _j === void 0 ? null : _j;
5135
- validatePipeline(pipeline);
5136
- var pipelineIdentification = (function () {
5137
- // Note: This is a 😐 implementation of [🚞]
5138
- var _ = [];
5139
- if (pipeline.sourceFile !== undefined) {
5140
- _.push("File: ".concat(pipeline.sourceFile));
5141
- }
5142
- if (pipeline.pipelineUrl !== undefined) {
5143
- _.push("Url: ".concat(pipeline.pipelineUrl));
5144
- }
5145
- return _.join('\n');
5146
- })();
5147
- var preparedPipeline;
5148
- if (isPipelinePrepared(pipeline)) {
5149
- preparedPipeline = pipeline;
5135
+ var totalUsage = ZERO_USAGE;
5136
+ var proxyTools = {
5137
+ get title() {
5138
+ // TODO: [🧠] Maybe put here some suffix
5139
+ return llmTools.title;
5140
+ },
5141
+ get description() {
5142
+ // TODO: [🧠] Maybe put here some suffix
5143
+ return llmTools.description;
5144
+ },
5145
+ checkConfiguration: function () {
5146
+ return __awaiter(this, void 0, void 0, function () {
5147
+ return __generator(this, function (_a) {
5148
+ return [2 /*return*/, /* not await */ llmTools.checkConfiguration()];
5149
+ });
5150
+ });
5151
+ },
5152
+ listModels: function () {
5153
+ return /* not await */ llmTools.listModels();
5154
+ },
5155
+ getTotalUsage: function () {
5156
+ // <- Note: [🥫] Not using getter `get totalUsage` but `getTotalUsage` to allow this object to be proxied
5157
+ return totalUsage;
5158
+ },
5159
+ };
5160
+ if (llmTools.callChatModel !== undefined) {
5161
+ proxyTools.callChatModel = function (prompt) { return __awaiter(_this, void 0, void 0, function () {
5162
+ var promptResult;
5163
+ return __generator(this, function (_a) {
5164
+ switch (_a.label) {
5165
+ case 0: return [4 /*yield*/, llmTools.callChatModel(prompt)];
5166
+ case 1:
5167
+ promptResult = _a.sent();
5168
+ totalUsage = addUsage(totalUsage, promptResult.usage);
5169
+ return [2 /*return*/, promptResult];
5170
+ }
5171
+ });
5172
+ }); };
5150
5173
  }
5151
- else if (isNotPreparedWarningSupressed !== true) {
5152
- console.warn(spaceTrim.spaceTrim(function (block) { return "\n Pipeline is not prepared\n\n ".concat(block(pipelineIdentification), "\n\n It will be prepared ad-hoc before the first execution and **returned as `preparedPipeline` in `PipelineExecutorResult`**\n But it is recommended to prepare the pipeline during collection preparation\n\n @see more at https://ptbk.io/prepare-pipeline\n "); }));
5174
+ if (llmTools.callCompletionModel !== undefined) {
5175
+ proxyTools.callCompletionModel = function (prompt) { return __awaiter(_this, void 0, void 0, function () {
5176
+ var promptResult;
5177
+ return __generator(this, function (_a) {
5178
+ switch (_a.label) {
5179
+ case 0: return [4 /*yield*/, llmTools.callCompletionModel(prompt)];
5180
+ case 1:
5181
+ promptResult = _a.sent();
5182
+ totalUsage = addUsage(totalUsage, promptResult.usage);
5183
+ return [2 /*return*/, promptResult];
5184
+ }
5185
+ });
5186
+ }); };
5153
5187
  }
5154
- var runCount = 0;
5155
- var pipelineExecutor = function (inputParameters, onProgress) { return __awaiter(_this, void 0, void 0, function () {
5156
- return __generator(this, function (_a) {
5157
- runCount++;
5158
- return [2 /*return*/, /* not await */ executePipeline({
5159
- pipeline: pipeline,
5160
- preparedPipeline: preparedPipeline,
5161
- setPreparedPipeline: function (newPreparedPipeline) {
5162
- preparedPipeline = newPreparedPipeline;
5163
- },
5164
- inputParameters: inputParameters,
5165
- tools: tools,
5166
- onProgress: onProgress,
5167
- pipelineIdentification: spaceTrim.spaceTrim(function (block) { return "\n ".concat(block(pipelineIdentification), "\n ").concat(runCount === 1 ? '' : "Run #".concat(runCount), "\n "); }),
5168
- maxExecutionAttempts: maxExecutionAttempts,
5169
- maxParallelCount: maxParallelCount,
5170
- csvSettings: csvSettings,
5171
- isVerbose: isVerbose,
5172
- isNotPreparedWarningSupressed: isNotPreparedWarningSupressed,
5173
- rootDirname: rootDirname,
5174
- cacheDirname: cacheDirname,
5175
- intermediateFilesStrategy: intermediateFilesStrategy,
5176
- isAutoInstalled: isAutoInstalled,
5177
- })];
5178
- });
5179
- }); };
5180
- return pipelineExecutor;
5188
+ if (llmTools.callEmbeddingModel !== undefined) {
5189
+ proxyTools.callEmbeddingModel = function (prompt) { return __awaiter(_this, void 0, void 0, function () {
5190
+ var promptResult;
5191
+ return __generator(this, function (_a) {
5192
+ switch (_a.label) {
5193
+ case 0: return [4 /*yield*/, llmTools.callEmbeddingModel(prompt)];
5194
+ case 1:
5195
+ promptResult = _a.sent();
5196
+ totalUsage = addUsage(totalUsage, promptResult.usage);
5197
+ return [2 /*return*/, promptResult];
5198
+ }
5199
+ });
5200
+ }); };
5201
+ }
5202
+ // <- Note: [🤖]
5203
+ return proxyTools;
5181
5204
  }
5182
5205
  /**
5183
- * TODO: [🐚] Change onProgress to object that represents the running execution, can be subscribed via RxJS to and also awaited
5206
+ * TODO: [🧠][💸] Maybe make some common abstraction `interceptLlmTools` and use here (or use javascript Proxy?)
5207
+ * TODO: [🧠] Is there some meaningfull way how to test this util
5208
+ * TODO: [🧠][🌯] Maybe a way how to hide ability to `get totalUsage`
5209
+ * > const [llmToolsWithUsage,getUsage] = countTotalUsage(llmTools);
5210
+ * TODO: [👷‍♂️] @@@ Manual about construction of llmTools
5184
5211
  */
5185
5212
 
5186
5213
  /**
@@ -5245,10 +5272,10 @@
5245
5272
  });
5246
5273
  }
5247
5274
  /**
5248
- * TODO: [🔃][main] !! If the persona was prepared with different version or different set of models, prepare it once again
5249
- * TODO: [🏢] !! Check validity of `modelName` in pipeline
5250
- * TODO: [🏢] !! Check validity of `systemMessage` in pipeline
5251
- * TODO: [🏢] !! Check validity of `temperature` in pipeline
5275
+ * TODO: [🔃][main] If the persona was prepared with different version or different set of models, prepare it once again
5276
+ * TODO: [🏢] Check validity of `modelName` in pipeline
5277
+ * TODO: [🏢] Check validity of `systemMessage` in pipeline
5278
+ * TODO: [🏢] Check validity of `temperature` in pipeline
5252
5279
  */
5253
5280
 
5254
5281
  /**
@@ -5688,21 +5715,44 @@
5688
5715
  if (typeof filename !== 'string') {
5689
5716
  return false;
5690
5717
  }
5718
+ if (filename.split('\n').length > 1) {
5719
+ return false;
5720
+ }
5721
+ if (filename.split(' ').length >
5722
+ 5 /* <- TODO: [🧠][🈷] Make some better non-arbitrary way how to distinct filenames from informational texts */) {
5723
+ return false;
5724
+ }
5691
5725
  var filenameSlashes = filename.split('\\').join('/');
5692
5726
  // Absolute Unix path: /hello.txt
5693
5727
  if (/^(\/)/i.test(filenameSlashes)) {
5728
+ // console.log(filename, 'Absolute Unix path: /hello.txt');
5694
5729
  return true;
5695
5730
  }
5696
5731
  // Absolute Windows path: /hello.txt
5697
5732
  if (/^([A-Z]{1,2}:\/?)\//i.test(filenameSlashes)) {
5733
+ // console.log(filename, 'Absolute Windows path: /hello.txt');
5698
5734
  return true;
5699
5735
  }
5700
5736
  // Relative path: ./hello.txt
5701
5737
  if (/^(\.\.?\/)+/i.test(filenameSlashes)) {
5738
+ // console.log(filename, 'Relative path: ./hello.txt');
5739
+ return true;
5740
+ }
5741
+ // Allow paths like foo/hello
5742
+ if (/^[^/]+\/[^/]+/i.test(filenameSlashes)) {
5743
+ // console.log(filename, 'Allow paths like foo/hello');
5744
+ return true;
5745
+ }
5746
+ // Allow paths like hello.book
5747
+ if (/^[^/]+\.[^/]+$/i.test(filenameSlashes)) {
5748
+ // console.log(filename, 'Allow paths like hello.book');
5702
5749
  return true;
5703
5750
  }
5704
5751
  return false;
5705
5752
  }
5753
+ /**
5754
+ * TODO: [🍏] Implement for MacOs
5755
+ */
5706
5756
 
5707
5757
  /**
5708
5758
  * The built-in `fetch' function with a lightweight error handling wrapper as default fetch function used in Promptbook scrapers
@@ -5727,6 +5777,9 @@
5727
5777
  }
5728
5778
  });
5729
5779
  }); };
5780
+ /**
5781
+ * TODO: [🧠] Maybe rename because it is not used only for scrapers but also in `$getCompiledBook`
5782
+ */
5730
5783
 
5731
5784
  /**
5732
5785
  * @@@
@@ -5794,7 +5847,7 @@
5794
5847
  },
5795
5848
  }];
5796
5849
  case 2:
5797
- if (!(isValidFilePath(sourceContent) || /\.[a-z]{1,10}$/i.exec(sourceContent))) return [3 /*break*/, 4];
5850
+ if (!isValidFilePath(sourceContent)) return [3 /*break*/, 4];
5798
5851
  if (tools.fs === undefined) {
5799
5852
  throw new EnvironmentMismatchError('Can not import file knowledge without filesystem tools');
5800
5853
  // <- TODO: [🧠] What is the best error type here`
@@ -5809,7 +5862,7 @@
5809
5862
  return [4 /*yield*/, isFileExisting(filename_1, tools.fs)];
5810
5863
  case 3:
5811
5864
  if (!(_f.sent())) {
5812
- throw new NotFoundError(spaceTrim__default["default"](function (block) { return "\n Can not make source handler for file which does not exist:\n\n File:\n ".concat(block(filename_1), "\n "); }));
5865
+ throw new NotFoundError(spaceTrim__default["default"](function (block) { return "\n Can not make source handler for file which does not exist:\n\n File:\n ".concat(block(sourceContent), "\n\n Full file path:\n ").concat(block(filename_1), "\n "); }));
5813
5866
  }
5814
5867
  // TODO: [🧠][😿] Test security file - file is scoped to the project (BUT maybe do this in `filesystemTools`)
5815
5868
  return [2 /*return*/, {
@@ -5922,7 +5975,7 @@
5922
5975
  partialPieces = __spreadArray([], __read(partialPiecesUnchecked), false);
5923
5976
  return [2 /*return*/, "break"];
5924
5977
  }
5925
- console.warn(spaceTrim__default["default"](function (block) { return "\n Cannot scrape knowledge from source despite the scraper `".concat(scraper.metadata.className, "` supports the mime type \"").concat(sourceHandler.mimeType, "\".\n \n The source:\n > ").concat(block(knowledgeSource.sourceContent
5978
+ console.warn(spaceTrim__default["default"](function (block) { return "\n Cannot scrape knowledge from source despite the scraper `".concat(scraper.metadata.className, "` supports the mime type \"").concat(sourceHandler.mimeType, "\".\n\n The source:\n ").concat(block(knowledgeSource.sourceContent
5926
5979
  .split('\n')
5927
5980
  .map(function (line) { return "> ".concat(line); })
5928
5981
  .join('\n')), "\n\n ").concat(block($registeredScrapersMessage(scrapers)), "\n\n\n "); }));
@@ -5960,7 +6013,7 @@
5960
6013
  return [7 /*endfinally*/];
5961
6014
  case 9:
5962
6015
  if (partialPieces === null) {
5963
- throw new KnowledgeScrapeError(spaceTrim__default["default"](function (block) { return "\n Cannot scrape knowledge\n \n The source:\n > ".concat(block(knowledgeSource.sourceContent
6016
+ throw new KnowledgeScrapeError(spaceTrim__default["default"](function (block) { return "\n Cannot scrape knowledge\n\n The source:\n > ".concat(block(knowledgeSource.sourceContent
5964
6017
  .split('\n')
5965
6018
  .map(function (line) { return "> ".concat(line); })
5966
6019
  .join('\n')), "\n\n No scraper found for the mime type \"").concat(sourceHandler.mimeType, "\"\n\n ").concat(block($registeredScrapersMessage(scrapers)), "\n\n\n "); }));
@@ -6051,7 +6104,7 @@
6051
6104
  * TODO: [😂] Adding knowledge should be convert to async high-level abstractions, simmilar thing with expectations to sync high-level abstractions
6052
6105
  * TODO: [🧠] Add context to each task (if missing)
6053
6106
  * TODO: [🧠] What is better name `prepareTask` or `prepareTaskAndParameters`
6054
- * TODO: [♨][main] !!! Prepare index the examples and maybe tasks
6107
+ * TODO: [♨][main] !!3 Prepare index the examples and maybe tasks
6055
6108
  * TODO: Write tests for `preparePipeline`
6056
6109
  * TODO: [🏏] Leverage the batch API and build queues @see https://platform.openai.com/docs/guides/batch
6057
6110
  * TODO: [🧊] In future one preparation can take data from previous preparation and save tokens and time
@@ -6059,7 +6112,9 @@
6059
6112
  */
6060
6113
 
6061
6114
  /**
6062
- * Prepare pipeline from string (markdown) format to JSON format
6115
+ * Prepare pipeline locally
6116
+ *
6117
+ * @see https://github.com/webgptorg/promptbook/discussions/196
6063
6118
  *
6064
6119
  * Note: This function does not validate logic of the pipeline
6065
6120
  * Note: This function acts as part of compilation process
@@ -6073,16 +6128,17 @@
6073
6128
  <- TODO: [🧠][🪑] `promptbookVersion` */
6074
6129
  knowledgeSources /*
6075
6130
  <- TODO: [🧊] `knowledgePieces` */, personas /*
6076
- <- TODO: [🧊] `preparations` */, _llms, llmTools, llmToolsWithUsage, currentPreparation, preparations, preparedPersonas, knowledgeSourcesPrepared, partialknowledgePiecesPrepared, knowledgePiecesPrepared, tasksPrepared /* TODO: parameters: parametersPrepared*/;
6131
+ <- TODO: [🧊] `preparations` */, sources, _llms, llmTools, llmToolsWithUsage, currentPreparation, preparations, title, collection, prepareTitleExecutor, _c, result, outputParameters, titleRaw, preparedPersonas, knowledgeSourcesPrepared, partialknowledgePiecesPrepared, knowledgePiecesPrepared, tasksPrepared /* TODO: parameters: parametersPrepared*/;
6132
+ var _d;
6077
6133
  var _this = this;
6078
- return __generator(this, function (_c) {
6079
- switch (_c.label) {
6134
+ return __generator(this, function (_e) {
6135
+ switch (_e.label) {
6080
6136
  case 0:
6081
6137
  if (isPipelinePrepared(pipeline)) {
6082
6138
  return [2 /*return*/, pipeline];
6083
6139
  }
6084
6140
  rootDirname = options.rootDirname, _a = options.maxParallelCount, maxParallelCount = _a === void 0 ? DEFAULT_MAX_PARALLEL_COUNT : _a, _b = options.isVerbose, isVerbose = _b === void 0 ? exports.DEFAULT_IS_VERBOSE : _b;
6085
- parameters = pipeline.parameters, tasks = pipeline.tasks, knowledgeSources = pipeline.knowledgeSources, personas = pipeline.personas;
6141
+ parameters = pipeline.parameters, tasks = pipeline.tasks, knowledgeSources = pipeline.knowledgeSources, personas = pipeline.personas, sources = pipeline.sources;
6086
6142
  if (tools === undefined || tools.llm === undefined) {
6087
6143
  throw new MissingToolsError('LLM tools are required for preparing the pipeline');
6088
6144
  }
@@ -6100,6 +6156,33 @@
6100
6156
  // <- TODO: [🧊]
6101
6157
  currentPreparation,
6102
6158
  ];
6159
+ title = pipeline.title;
6160
+ if (!(title === undefined || title === '' || title === DEFAULT_BOOK_TITLE)) return [3 /*break*/, 3];
6161
+ collection = createCollectionFromJson.apply(void 0, __spreadArray([], __read(PipelineCollection), false));
6162
+ _c = createPipelineExecutor;
6163
+ _d = {};
6164
+ return [4 /*yield*/, collection.getPipelineByUrl('https://promptbook.studio/promptbook/prepare-title.book.md')];
6165
+ case 1:
6166
+ prepareTitleExecutor = _c.apply(void 0, [(_d.pipeline = _e.sent(),
6167
+ _d.tools = tools,
6168
+ _d)]);
6169
+ return [4 /*yield*/, prepareTitleExecutor({
6170
+ book: sources.map(function (_a) {
6171
+ var content = _a.content;
6172
+ return content;
6173
+ }).join('\n\n'),
6174
+ })];
6175
+ case 2:
6176
+ result = _e.sent();
6177
+ assertsExecutionSuccessful(result);
6178
+ outputParameters = result.outputParameters;
6179
+ titleRaw = outputParameters.title;
6180
+ if (isVerbose) {
6181
+ console.info("The title is \"".concat(titleRaw, "\""));
6182
+ }
6183
+ title = titleRaw || DEFAULT_BOOK_TITLE;
6184
+ _e.label = 3;
6185
+ case 3:
6103
6186
  preparedPersonas = new Array(personas.length);
6104
6187
  return [4 /*yield*/, forEachAsync(personas, { maxParallelCount: maxParallelCount /* <- TODO: [🪂] When there are subtasks, this maximul limit can be broken */ }, function (persona, index) { return __awaiter(_this, void 0, void 0, function () {
6105
6188
  var modelRequirements, preparedPersona;
@@ -6118,12 +6201,12 @@
6118
6201
  }
6119
6202
  });
6120
6203
  }); })];
6121
- case 1:
6122
- _c.sent();
6204
+ case 4:
6205
+ _e.sent();
6123
6206
  knowledgeSourcesPrepared = knowledgeSources.map(function (source) { return (__assign(__assign({}, source), { preparationIds: [/* TODO: [🧊] -> */ currentPreparation.id] })); });
6124
6207
  return [4 /*yield*/, prepareKnowledgePieces(knowledgeSources /* <- TODO: [🧊] {knowledgeSources, knowledgePieces} */, __assign(__assign({}, tools), { llm: llmToolsWithUsage }), __assign(__assign({}, options), { rootDirname: rootDirname, maxParallelCount: maxParallelCount /* <- TODO: [🪂] */, isVerbose: isVerbose }))];
6125
- case 2:
6126
- partialknowledgePiecesPrepared = _c.sent();
6208
+ case 5:
6209
+ partialknowledgePiecesPrepared = _e.sent();
6127
6210
  knowledgePiecesPrepared = partialknowledgePiecesPrepared.map(function (piece) { return (__assign(__assign({}, piece), { preparationIds: [/* TODO: [🧊] -> */ currentPreparation.id] })); });
6128
6211
  return [4 /*yield*/, prepareTasks({
6129
6212
  parameters: parameters,
@@ -6134,8 +6217,8 @@
6134
6217
  maxParallelCount: maxParallelCount /* <- TODO: [🪂] */,
6135
6218
  isVerbose: isVerbose,
6136
6219
  })];
6137
- case 3:
6138
- tasksPrepared = (_c.sent()).tasksPrepared;
6220
+ case 6:
6221
+ tasksPrepared = (_e.sent()).tasksPrepared;
6139
6222
  // ----- /Tasks preparation -----
6140
6223
  // TODO: [😂] Use here all `AsyncHighLevelAbstraction`
6141
6224
  // Note: Count total usage
@@ -6146,7 +6229,7 @@
6146
6229
  order: ORDER_OF_PIPELINE_JSON,
6147
6230
  value: __assign(__assign({}, pipeline), {
6148
6231
  // <- TODO: Probbably deeply clone the pipeline because `$exportJson` freezes the subobjects
6149
- knowledgeSources: knowledgeSourcesPrepared, knowledgePieces: knowledgePiecesPrepared, tasks: __spreadArray([], __read(tasksPrepared), false),
6232
+ title: title, knowledgeSources: knowledgeSourcesPrepared, knowledgePieces: knowledgePiecesPrepared, tasks: __spreadArray([], __read(tasksPrepared), false),
6150
6233
  // <- TODO: [🪓] Here should be no need for spreading new array, just ` tasks: tasksPrepared`
6151
6234
  personas: preparedPersonas, preparations: __spreadArray([], __read(preparations), false) }),
6152
6235
  })];
@@ -6155,7 +6238,7 @@
6155
6238
  });
6156
6239
  }
6157
6240
  /**
6158
- * TODO: Write tests for `preparePipeline`
6241
+ * TODO: Write tests for `preparePipeline` and `preparePipelineOnRemoteServer`
6159
6242
  * TODO: [🏏] Leverage the batch API and build queues @see https://platform.openai.com/docs/guides/batch
6160
6243
  * TODO: [🧊] In future one preparation can take data from previous preparation and save tokens and time
6161
6244
  * TODO: [🛠] Actions, instruments (and maybe knowledge) => Functions and tools
@@ -6241,7 +6324,7 @@
6241
6324
  if (sourceContent === '') {
6242
6325
  throw new ParseError("Source is not defined");
6243
6326
  }
6244
- // TODO: [main] !!!! Following checks should be applied every link in the `sourceContent`
6327
+ // TODO: [main] !!4 Following checks should be applied every link in the `sourceContent`
6245
6328
  if (sourceContent.startsWith('http://')) {
6246
6329
  throw new ParseError("Source is not secure");
6247
6330
  }
@@ -6413,7 +6496,7 @@
6413
6496
  expectResultingParameterName();
6414
6497
  var parameter = $pipelineJson.parameters.find(function (param) { return param.name === $taskJson.resultingParameterName; });
6415
6498
  if (parameter === undefined) {
6416
- // TODO: !!!!!! Change to logic error for higher level abstractions to work
6499
+ // TODO: !!6 Change to logic error for higher level abstraction of chatbot to work
6417
6500
  throw new ParseError("Parameter `{".concat($taskJson.resultingParameterName, "}` is not defined so can not define example value of it"));
6418
6501
  }
6419
6502
  parameter.exampleValues = parameter.exampleValues || [];
@@ -6424,7 +6507,7 @@
6424
6507
  if (command.taskType === 'KNOWLEDGE') {
6425
6508
  knowledgeCommandParser.$applyToPipelineJson({
6426
6509
  type: 'KNOWLEDGE',
6427
- sourceContent: $taskJson.content, // <- TODO: [🐝][main] !!! Work with KNOWLEDGE which not referring to the source file or website, but its content itself
6510
+ sourceContent: $taskJson.content, // <- TODO: [🐝][main] !!3 Work with KNOWLEDGE which not referring to the source file or website, but its content itself
6428
6511
  }, $pipelineJson);
6429
6512
  $taskJson.isTask = false;
6430
6513
  return;
@@ -7319,20 +7402,24 @@
7319
7402
  */
7320
7403
  var GeneratorFormfactorDefinition = {
7321
7404
  name: 'GENERATOR',
7322
- description: "@@@",
7405
+ description: "Generates any kind (in HTML with possible scripts and css format) of content from input message",
7323
7406
  documentationUrl: "https://github.com/webgptorg/promptbook/discussions/184",
7324
7407
  pipelineInterface: {
7325
7408
  inputParameters: [
7326
- /* @@@ */
7327
7409
  {
7328
- name: 'nonce',
7329
- description: 'Just to prevent GENERATOR to be set as implicit formfactor',
7410
+ name: 'inputMessage',
7411
+ description: "Input message to be image made from",
7330
7412
  isInput: true,
7331
7413
  isOutput: false,
7332
7414
  },
7333
7415
  ],
7334
7416
  outputParameters: [
7335
- /* @@@ */
7417
+ {
7418
+ name: 'result',
7419
+ description: "Result in HTML to be shown to user",
7420
+ isInput: false,
7421
+ isOutput: true,
7422
+ },
7336
7423
  ],
7337
7424
  },
7338
7425
  };
@@ -7364,6 +7451,35 @@
7364
7451
  pipelineInterface: GENERIC_PIPELINE_INTERFACE,
7365
7452
  };
7366
7453
 
7454
+ /**
7455
+ * Image generator is form of app that generates image from input message
7456
+ *
7457
+ * @public exported from `@promptbook/core`
7458
+ */
7459
+ var ImageGeneratorFormfactorDefinition = {
7460
+ name: 'IMAGE_GENERATOR',
7461
+ description: "Generates prompt for image generation from input message",
7462
+ documentationUrl: "https://github.com/webgptorg/promptbook/discussions/184",
7463
+ pipelineInterface: {
7464
+ inputParameters: [
7465
+ {
7466
+ name: 'inputMessage',
7467
+ description: "Input message to be image made from",
7468
+ isInput: true,
7469
+ isOutput: false,
7470
+ },
7471
+ ],
7472
+ outputParameters: [
7473
+ {
7474
+ name: 'prompt',
7475
+ description: "Prompt to be used for image generation",
7476
+ isInput: false,
7477
+ isOutput: true,
7478
+ },
7479
+ ],
7480
+ },
7481
+ };
7482
+
7367
7483
  /**
7368
7484
  * Matcher is form of app that @@@
7369
7485
  *
@@ -7462,6 +7578,7 @@
7462
7578
  SheetsFormfactorDefinition,
7463
7579
  MatcherFormfactorDefinition,
7464
7580
  GeneratorFormfactorDefinition,
7581
+ ImageGeneratorFormfactorDefinition,
7465
7582
  ];
7466
7583
  /**
7467
7584
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -7848,7 +7965,7 @@
7848
7965
  * Note: `$` is used to indicate that this function mutates given `pipelineJson`
7849
7966
  */
7850
7967
  $applyToPipelineJson: function (command, $pipelineJson) {
7851
- // Note: [🍣] Do nothing, its application is implemented separately in `precompilePipeline`
7968
+ // Note: [🍣] Do nothing, its application is implemented separately in `parsePipeline`
7852
7969
  },
7853
7970
  /**
7854
7971
  * Apply the PARAMETER command to the `pipelineJson`
@@ -7856,7 +7973,7 @@
7856
7973
  * Note: `$` is used to indicate that this function mutates given `taskJson`
7857
7974
  */
7858
7975
  $applyToTaskJson: function (command, $taskJson, $pipelineJson) {
7859
- // Note: [🍣] Do nothing, its application is implemented separately in `precompilePipeline`
7976
+ // Note: [🍣] Do nothing, its application is implemented separately in `parsePipeline`
7860
7977
  },
7861
7978
  /**
7862
7979
  * Converts the PARAMETER command back to string
@@ -8351,7 +8468,7 @@
8351
8468
  instrumentCommandParser,
8352
8469
  personaCommandParser,
8353
8470
  foreachCommandParser,
8354
- boilerplateCommandParser, // <- TODO: !! Only in development, remove in production
8471
+ boilerplateCommandParser, // <- TODO: Only in development, remove in production
8355
8472
  // <- Note: [♓️][💩] This is the order of the commands in the pipeline, BUT its not used in parsing and before usage maybe it should be done better
8356
8473
  ];
8357
8474
  /**
@@ -8775,7 +8892,7 @@
8775
8892
  isOutput: true,
8776
8893
  exampleValues: ['Hello, I am a Pavol`s virtual avatar. How can I help you?'],
8777
8894
  });
8778
- // TODO: !!!!!! spaceTrim
8895
+ // TODO: Use spaceTrim in multiline strings
8779
8896
  $pipelineJson.tasks.push({
8780
8897
  taskType: 'PROMPT_TASK',
8781
8898
  name: 'create-an-answer',
@@ -8783,8 +8900,11 @@
8783
8900
  content: 'Write a response to the user message:\n\n**Question from user**\n\n> {userMessage}\n\n**Previous conversation**\n\n> {previousConversationSummary}',
8784
8901
  resultingParameterName: 'chatbotResponse',
8785
8902
  personaName: personaName,
8786
- dependentParameterNames: ['userMessage', 'previousConversationSummary' /* !!!!!!, 'knowledge'*/],
8787
- // !!!!!! preparedContent: '{content}\n\n## Knowledge\n\n{knowledge}',
8903
+ dependentParameterNames: [
8904
+ 'userMessage',
8905
+ 'previousConversationSummary' /* TODO: [🧠][📛], 'knowledge'*/,
8906
+ ],
8907
+ // TODO: [🧠][📛] preparedContent: '{content}\n\n## Knowledge\n\n{knowledge}',
8788
8908
  }, {
8789
8909
  taskType: 'PROMPT_TASK',
8790
8910
  name: 'summarize-the-conversation',
@@ -8798,24 +8918,27 @@
8798
8918
  max: 10,
8799
8919
  },
8800
8920
  },
8801
- dependentParameterNames: ['userMessage', 'chatbotResponse' /* !!!!!!, 'knowledge'*/],
8802
- // !!!!!! preparedContent: '{content}\n\n## Knowledge\n\n{knowledge}',
8921
+ dependentParameterNames: ['userMessage', 'chatbotResponse' /* TODO: [🧠][📛], 'knowledge'*/],
8922
+ // TODO: [🧠][📛] preparedContent: '{content}\n\n## Knowledge\n\n{knowledge}',
8803
8923
  }, {
8804
8924
  taskType: 'SIMPLE_TASK',
8805
8925
  name: 'title',
8806
8926
  title: 'Title',
8807
8927
  content: '{conversationSummary}',
8808
8928
  resultingParameterName: 'title',
8809
- dependentParameterNames: ['conversationSummary' /* !!!!!!, 'knowledge'*/],
8810
- // !!!!!! preparedContent: '{content}\n\n## Knowledge\n\n{knowledge}',
8929
+ dependentParameterNames: ['conversationSummary' /* TODO: [🧠][📛], 'knowledge'*/],
8930
+ // TODO: [🧠][📛] preparedContent: '{content}\n\n## Knowledge\n\n{knowledge}',
8811
8931
  });
8812
8932
  },
8813
8933
  };
8934
+ /**
8935
+ * TODO: [🧠][📛] Should this be here?
8936
+ */
8814
8937
 
8815
8938
  /**
8816
8939
  * All high-level abstractions
8817
8940
  *
8818
- * @private internal index of `precompilePipeline` (= used for sync) and `preparePipeline` (= used for async)
8941
+ * @private internal index of `parsePipeline` (= used for sync) and `preparePipeline` (= used for async)
8819
8942
  */
8820
8943
  var HIGH_LEVEL_ABSTRACTIONS = [
8821
8944
  ImplicitFormfactorHla,
@@ -8949,7 +9072,7 @@
8949
9072
  return;
8950
9073
  }
8951
9074
  if (!section.startsWith('#')) {
8952
- section = "# ".concat(DEFAULT_TITLE, "\n\n").concat(section);
9075
+ section = "# ".concat(DEFAULT_BOOK_TITLE, "\n\n").concat(section);
8953
9076
  }
8954
9077
  sections.push(section);
8955
9078
  buffer = [];
@@ -9004,7 +9127,7 @@
9004
9127
  /**
9005
9128
  * Normalizes the markdown by flattening the structure
9006
9129
  *
9007
- * - It always have h1 - if there is no h1 in the markdown, it will be added "# Untitled"
9130
+ * - It always have h1 - if there is no h1 in the markdown, it will be added `DEFAULT_BOOK_TITLE`
9008
9131
  * - All other headings are normalized to h2
9009
9132
  *
9010
9133
  * @public exported from `@promptbook/markdown-utils`
@@ -9013,7 +9136,7 @@
9013
9136
  var e_1, _a;
9014
9137
  var sections = splitMarkdownIntoSections(markdown);
9015
9138
  if (sections.length === 0) {
9016
- return "# ".concat(DEFAULT_TITLE);
9139
+ return "# ".concat(DEFAULT_BOOK_TITLE);
9017
9140
  }
9018
9141
  var flattenedMarkdown = '';
9019
9142
  var parsedSections = sections.map(parseMarkdownSection);
@@ -9024,7 +9147,7 @@
9024
9147
  }
9025
9148
  else {
9026
9149
  parsedSections.unshift(firstSection);
9027
- flattenedMarkdown += "# ".concat(DEFAULT_TITLE) + "\n\n"; // <- [🧠] Maybe 3 new lines?
9150
+ flattenedMarkdown += "# ".concat(DEFAULT_BOOK_TITLE) + "\n\n"; // <- [🧠] Maybe 3 new lines?
9028
9151
  }
9029
9152
  try {
9030
9153
  for (var parsedSections_1 = __values(parsedSections), parsedSections_1_1 = parsedSections_1.next(); !parsedSections_1_1.done; parsedSections_1_1 = parsedSections_1.next()) {
@@ -9051,13 +9174,13 @@
9051
9174
  */
9052
9175
 
9053
9176
  /**
9054
- * Removes HTML or Markdown comments from a string.
9177
+ * Removes Markdown (or HTML) comments
9055
9178
  *
9056
9179
  * @param {string} content - The string to remove comments from.
9057
9180
  * @returns {string} The input string with all comments removed.
9058
9181
  * @public exported from `@promptbook/markdown-utils`
9059
9182
  */
9060
- function removeContentComments(content) {
9183
+ function removeMarkdownComments(content) {
9061
9184
  return spaceTrim.spaceTrim(content.replace(/<!--(.*?)-->/gs, ''));
9062
9185
  }
9063
9186
 
@@ -9090,7 +9213,7 @@
9090
9213
  *
9091
9214
  * Note: There are 3 similar functions:
9092
9215
  * - `compilePipeline` **(preferred)** - which propperly compiles the promptbook and use embedding for external knowledge
9093
- * - `precompilePipeline` - use only if you need to compile promptbook synchronously and it contains NO external knowledge
9216
+ * - `parsePipeline` - use only if you need to compile promptbook synchronously and it contains NO external knowledge
9094
9217
  * - `preparePipeline` - just one step in the compilation process
9095
9218
  *
9096
9219
  * Note: This function does not validate logic of the pipeline only the parsing
@@ -9101,10 +9224,10 @@
9101
9224
  * @throws {ParseError} if the promptbook string is not valid
9102
9225
  * @public exported from `@promptbook/core`
9103
9226
  */
9104
- function precompilePipeline(pipelineString) {
9227
+ function parsePipeline(pipelineString) {
9105
9228
  var e_1, _a, e_2, _b, e_3, _c, e_4, _d, e_5, _e, e_6, _f;
9106
9229
  var $pipelineJson = {
9107
- title: DEFAULT_TITLE,
9230
+ title: DEFAULT_BOOK_TITLE,
9108
9231
  parameters: [],
9109
9232
  tasks: [],
9110
9233
  knowledgeSources: [],
@@ -9115,7 +9238,7 @@
9115
9238
  {
9116
9239
  type: 'BOOK',
9117
9240
  path: null,
9118
- // <- TODO: !!!!!! Pass here path of the file
9241
+ // <- TODO: !!6 Pass here path of the file
9119
9242
  content: pipelineString,
9120
9243
  },
9121
9244
  ],
@@ -9133,18 +9256,44 @@
9133
9256
  }
9134
9257
  // =============================================================
9135
9258
  // Note: 1️⃣ Parsing of the markdown into object
9259
+ // ==============
9260
+ // Note: 1️⃣◽1️⃣ Remove #!shebang and comments
9136
9261
  if (pipelineString.startsWith('#!')) {
9137
9262
  var _g = __read(pipelineString.split('\n')), shebangLine_1 = _g[0], restLines = _g.slice(1);
9138
9263
  if (!(shebangLine_1 || '').includes('ptbk')) {
9139
9264
  throw new ParseError(spaceTrim.spaceTrim(function (block) { return "\n It seems that you try to parse a book file which has non-standard shebang line for book files:\n Shebang line must contain 'ptbk'\n\n You have:\n ".concat(block(shebangLine_1 || '(empty line)'), "\n\n It should look like this:\n #!/usr/bin/env ptbk\n\n ").concat(block(getPipelineIdentification()), "\n "); }));
9140
9265
  }
9141
- pipelineString = restLines.join('\n');
9142
- }
9143
- pipelineString = removeContentComments(pipelineString);
9266
+ pipelineString = validatePipelineString(restLines.join('\n'));
9267
+ }
9268
+ pipelineString = removeMarkdownComments(pipelineString);
9269
+ pipelineString = spaceTrim.spaceTrim(pipelineString);
9270
+ // <- TODO: [😧] `spaceTrim` should preserve discriminated type *(or at lease `PipelineString`)*
9271
+ // ==============
9272
+ // Note: 1️⃣◽2️⃣ Process flat pipeline
9273
+ var isMarkdownBeginningWithHeadline = pipelineString.startsWith('# ');
9274
+ var isLastLineReturnStatement = pipelineString.split('\n').pop().split('`').join('').startsWith('->');
9275
+ // TODO: Also (double)check
9276
+ // > const usedCommands
9277
+ // > const isBlocksUsed
9278
+ // > const returnStatementCount
9279
+ var isFlatPipeline = !isMarkdownBeginningWithHeadline && isLastLineReturnStatement;
9280
+ // console.log({ isMarkdownBeginningWithHeadline, isLastLineReturnStatement, isFlatPipeline });
9281
+ if (isFlatPipeline) {
9282
+ var pipelineStringLines = pipelineString.split('\n');
9283
+ var returnStatement_1 = pipelineStringLines.pop();
9284
+ var prompt_1 = spaceTrim.spaceTrim(pipelineStringLines.join('\n'));
9285
+ pipelineString = validatePipelineString(spaceTrim.spaceTrim(function (block) { return "\n # ".concat(DEFAULT_BOOK_TITLE, "\n\n ## Prompt\n\n ```\n ").concat(block(prompt_1), "\n ```\n\n ").concat(returnStatement_1, "\n "); }));
9286
+ // <- TODO: Maybe use book` notation
9287
+ // console.log(pipelineString);
9288
+ }
9289
+ // ==============
9290
+ // Note: 1️⃣◽3️⃣ Parse the markdown
9144
9291
  pipelineString = flattenMarkdown(pipelineString) /* <- Note: [🥞] */;
9145
9292
  pipelineString = pipelineString.replaceAll(/`\{(?<parameterName>[a-z0-9_]+)\}`/gi, '{$<parameterName>}');
9146
9293
  pipelineString = pipelineString.replaceAll(/`->\s+\{(?<parameterName>[a-z0-9_]+)\}`/gi, '-> {$<parameterName>}');
9147
9294
  var _h = __read(splitMarkdownIntoSections(pipelineString).map(parseMarkdownSection)), pipelineHead = _h[0], pipelineSections = _h.slice(1); /* <- Note: [🥞] */
9295
+ // ==============
9296
+ // Note: 1️⃣◽4️⃣ Check markdown structure
9148
9297
  if (pipelineHead === undefined) {
9149
9298
  throw new UnexpectedError(spaceTrim.spaceTrim(function (block) { return "\n Pipeline head is not defined\n\n ".concat(block(getPipelineIdentification()), "\n\n This should never happen, because the pipeline already flattened\n "); }));
9150
9299
  }
@@ -9528,14 +9677,14 @@
9528
9677
  // =============================================================
9529
9678
  return exportJson({
9530
9679
  name: 'pipelineJson',
9531
- message: "Result of `precompilePipeline`",
9680
+ message: "Result of `parsePipeline`",
9532
9681
  order: ORDER_OF_PIPELINE_JSON,
9533
9682
  value: __assign({ formfactorName: 'GENERIC' }, $pipelineJson),
9534
9683
  });
9535
9684
  }
9536
9685
  /**
9537
9686
  * TODO: [🧠] Maybe more things here can be refactored as high-level abstractions
9538
- * TODO: [main] !!!! Warn if used only sync version
9687
+ * TODO: [main] !!4 Warn if used only sync version
9539
9688
  * TODO: [🚞] Report here line/column of error
9540
9689
  * TODO: Use spaceTrim more effectively
9541
9690
  * TODO: [🧠] Parameter flags - isInput, isOutput, isInternal
@@ -9548,10 +9697,7 @@
9548
9697
  /**
9549
9698
  * Compile pipeline from string (markdown) format to JSON format
9550
9699
  *
9551
- * Note: There are 3 similar functions:
9552
- * - `compilePipeline` **(preferred)** - which propperly compiles the promptbook and use embedding for external knowledge
9553
- * - `precompilePipeline` - use only if you need to compile promptbook synchronously and it contains NO external knowledge
9554
- * - `preparePipeline` - just one step in the compilation process
9700
+ * @see https://github.com/webgptorg/promptbook/discussions/196
9555
9701
  *
9556
9702
  * Note: This function does not validate logic of the pipeline only the parsing
9557
9703
  * Note: This function acts as compilation process
@@ -9569,7 +9715,7 @@
9569
9715
  return __generator(this, function (_a) {
9570
9716
  switch (_a.label) {
9571
9717
  case 0:
9572
- pipelineJson = precompilePipeline(pipelineString);
9718
+ pipelineJson = parsePipeline(pipelineString);
9573
9719
  if (!(tools !== undefined && tools.llm !== undefined)) return [3 /*break*/, 2];
9574
9720
  return [4 /*yield*/, preparePipeline(pipelineJson, tools, options || {
9575
9721
  rootDirname: null,
@@ -9578,7 +9724,7 @@
9578
9724
  pipelineJson = _a.sent();
9579
9725
  _a.label = 2;
9580
9726
  case 2:
9581
- // Note: No need to use `$exportJson` because `precompilePipeline` and `preparePipeline` already do that
9727
+ // Note: No need to use `$exportJson` because `parsePipeline` and `preparePipeline` already do that
9582
9728
  return [2 /*return*/, pipelineJson];
9583
9729
  }
9584
9730
  });
@@ -9605,7 +9751,7 @@
9605
9751
  return content.replace(sectionRegex, contentToInsert);
9606
9752
  }
9607
9753
  // Note: Following is the case when the section is not found in the file so we add it there
9608
- var placeForSection = removeContentComments(content).match(/^##.*$/im);
9754
+ var placeForSection = removeMarkdownComments(content).match(/^##.*$/im);
9609
9755
  if (placeForSection !== null) {
9610
9756
  var _a = __read(placeForSection, 1), heading_1 = _a[0];
9611
9757
  return content.replace(heading_1, spaceTrim.spaceTrim(function (block) { return "\n ".concat(block(contentToInsert), "\n\n ").concat(block(heading_1), "\n "); }));
@@ -9631,7 +9777,7 @@
9631
9777
  var parameter = pipelineJson.parameters.find(function (parameter) { return parameter.name === parameterName; });
9632
9778
  if (!parameter) {
9633
9779
  throw new UnexpectedError("Could not find {".concat(parameterName, "}"));
9634
- // <- TODO: !!!!!! This causes problems when {knowledge} and other reserved parameters are used
9780
+ // <- TODO: !!6 This causes problems when {knowledge} and other reserved parameters are used
9635
9781
  }
9636
9782
  if (parameter.isInput) {
9637
9783
  return 'input';
@@ -9675,9 +9821,9 @@
9675
9821
  return promptbookMermaid;
9676
9822
  }
9677
9823
  /**
9678
- * TODO: [🧠] !! FOREACH in mermaid graph
9679
- * TODO: [🧠] !! Knowledge in mermaid graph
9680
- * TODO: [🧠] !! Personas in mermaid graph
9824
+ * TODO: [🧠] FOREACH in mermaid graph
9825
+ * TODO: [🧠] Knowledge in mermaid graph
9826
+ * TODO: [🧠] Personas in mermaid graph
9681
9827
  * TODO: Maybe use some Mermaid package instead of string templating
9682
9828
  * TODO: [🕌] When more than 2 functionalities, split into separate functions
9683
9829
  */
@@ -9712,6 +9858,7 @@
9712
9858
  case 2:
9713
9859
  if (isPrettifyed) {
9714
9860
  pipelineString = prettifyMarkdown(pipelineString);
9861
+ // <- TODO: [😧] `prettifyMarkdown` should preserve discriminated type *(or at lease `PipelineString`)*
9715
9862
  }
9716
9863
  return [2 /*return*/, pipelineString];
9717
9864
  }
@@ -10513,7 +10660,7 @@
10513
10660
  return [3 /*break*/, 11];
10514
10661
  case 10: throw new PipelineExecutionError("Unknown model variant \"".concat(prompt.modelRequirements.modelVariant, "\""));
10515
10662
  case 11:
10516
- // TODO: [🧠] !!!!! How to do timing in mixed cache / non-cache situation
10663
+ // TODO: [🧠] !!5 How to do timing in mixed cache / non-cache situation
10517
10664
  // promptResult.timing: FromtoItems
10518
10665
  return [4 /*yield*/, storage.setItem(key, {
10519
10666
  date: $getCurrentDate(),
@@ -10522,7 +10669,7 @@
10522
10669
  promptResult: promptResult,
10523
10670
  })];
10524
10671
  case 12:
10525
- // TODO: [🧠] !!!!! How to do timing in mixed cache / non-cache situation
10672
+ // TODO: [🧠] !!5 How to do timing in mixed cache / non-cache situation
10526
10673
  // promptResult.timing: FromtoItems
10527
10674
  _c.sent();
10528
10675
  return [2 /*return*/, promptResult];
@@ -10613,6 +10760,7 @@
10613
10760
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
10614
10761
  *
10615
10762
  * @public exported from `@promptbook/core`
10763
+ * @public exported from `@promptbook/wizzard`
10616
10764
  * @public exported from `@promptbook/cli`
10617
10765
  */
10618
10766
  var _AnthropicClaudeMetadataRegistration = $llmToolsMetadataRegister.register({
@@ -10658,6 +10806,7 @@
10658
10806
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
10659
10807
  *
10660
10808
  * @public exported from `@promptbook/core`
10809
+ * @public exported from `@promptbook/wizzard`
10661
10810
  * @public exported from `@promptbook/cli`
10662
10811
  */
10663
10812
  var _AzureOpenAiMetadataRegistration = $llmToolsMetadataRegister.register({
@@ -10734,6 +10883,7 @@
10734
10883
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
10735
10884
  *
10736
10885
  * @public exported from `@promptbook/core`
10886
+ * @public exported from `@promptbook/wizzard`
10737
10887
  * @public exported from `@promptbook/cli`
10738
10888
  */
10739
10889
  var _GoogleMetadataRegistration = $llmToolsMetadataRegister.register({
@@ -10782,6 +10932,7 @@
10782
10932
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
10783
10933
  *
10784
10934
  * @public exported from `@promptbook/core`
10935
+ * @public exported from `@promptbook/wizzard`
10785
10936
  * @public exported from `@promptbook/cli`
10786
10937
  */
10787
10938
  var _OpenAiMetadataRegistration = $llmToolsMetadataRegister.register({
@@ -10820,6 +10971,7 @@
10820
10971
  * Note: [🏐] Configurations registrations are done in @@@ BUT constructor @@@
10821
10972
  *
10822
10973
  * @public exported from `@promptbook/core`
10974
+ * @public exported from `@promptbook/wizzard`
10823
10975
  * @public exported from `@promptbook/cli`
10824
10976
  */
10825
10977
  var _OpenAiAssistantMetadataRegistration = $llmToolsMetadataRegister.register({
@@ -10862,6 +11014,59 @@
10862
11014
  * Note: [💞] Ignore a discrepancy between file name and entity name
10863
11015
  */
10864
11016
 
11017
+ /**
11018
+ * Function `isValidPipelineString` will validate the if the string is a valid pipeline string
11019
+ * It does not check if the string is fully logically correct, but if it is a string that can be a pipeline string or the string looks completely different.
11020
+ *
11021
+ * @param {string} pipelineString the candidate for a pipeline string
11022
+ * @returns {boolean} if the string is a valid pipeline string
11023
+ * @public exported from `@promptbook/core`
11024
+ */
11025
+ function isValidPipelineString(pipelineString) {
11026
+ try {
11027
+ validatePipelineString(pipelineString);
11028
+ return true;
11029
+ }
11030
+ catch (error) {
11031
+ if (!(error instanceof Error)) {
11032
+ throw error;
11033
+ }
11034
+ return false;
11035
+ }
11036
+ }
11037
+ /**
11038
+ * TODO: [🧠][🈴] Where is the best location for this file
11039
+ */
11040
+
11041
+ /**
11042
+ * Tag function for notating a pipeline with a book\`...\ notation as template literal
11043
+ *
11044
+ * @param strings @@@
11045
+ * @param values @@@
11046
+ * @returns the pipeline string
11047
+ * @public exported from `@promptbook/core`
11048
+ */
11049
+ function book(strings) {
11050
+ var values = [];
11051
+ for (var _i = 1; _i < arguments.length; _i++) {
11052
+ values[_i - 1] = arguments[_i];
11053
+ }
11054
+ if (strings.length !== 1 && values.length !== 0) {
11055
+ throw new NotYetImplementedError("Only one string without interpolated value is supported for now in book`...` notation");
11056
+ }
11057
+ var pipelineString = strings[0];
11058
+ pipelineString = spaceTrim__default["default"](pipelineString);
11059
+ if (!isValidPipelineString(pipelineString)) {
11060
+ // TODO: Make the CustomError for this
11061
+ throw new Error(spaceTrim__default["default"]("\n The string is not a valid pipeline string\n\n book`\n ".concat(pipelineString, "\n `\n ")));
11062
+ }
11063
+ return pipelineString;
11064
+ }
11065
+ /**
11066
+ * TODO: [🧠][🈴] Where is the best location for this file
11067
+ * Note: [💞] Ignore a discrepancy between file name and entity name
11068
+ */
11069
+
10865
11070
  /**
10866
11071
  * Metadata of the scraper
10867
11072
  *
@@ -10874,6 +11079,7 @@
10874
11079
  mimeTypes: ['application/msword', 'text/rtf'],
10875
11080
  documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/@@',
10876
11081
  isAvilableInBrowser: false,
11082
+ // <- Note: [🌏] Only `MarkdownScraper` makes sense to be available in the browser, for scraping non-markdown sources in the browser use a remote server
10877
11083
  requiredExecutables: [
10878
11084
  'Pandoc',
10879
11085
  'LibreOffice',
@@ -10886,6 +11092,7 @@
10886
11092
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
10887
11093
  *
10888
11094
  * @public exported from `@promptbook/core`
11095
+ * @public exported from `@promptbook/wizzard`
10889
11096
  * @public exported from `@promptbook/cli`
10890
11097
  */
10891
11098
  var _LegacyDocumentScraperMetadataRegistration = $scrapersMetadataRegister.register(legacyDocumentScraperMetadata);
@@ -10905,6 +11112,7 @@
10905
11112
  mimeTypes: ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
10906
11113
  documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/@@',
10907
11114
  isAvilableInBrowser: false,
11115
+ // <- Note: [🌏] Only `MarkdownScraper` makes sense to be available in the browser, for scraping non-markdown sources in the browser use a remote server
10908
11116
  requiredExecutables: ['Pandoc'],
10909
11117
  }); /* <- Note: [🤛] */
10910
11118
  /**
@@ -10913,6 +11121,7 @@
10913
11121
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
10914
11122
  *
10915
11123
  * @public exported from `@promptbook/core`
11124
+ * @public exported from `@promptbook/wizzard`
10916
11125
  * @public exported from `@promptbook/cli`
10917
11126
  */
10918
11127
  var _DocumentScraperMetadataRegistration = $scrapersMetadataRegister.register(documentScraperMetadata);
@@ -10932,6 +11141,7 @@
10932
11141
  mimeTypes: ['text/markdown', 'text/plain'],
10933
11142
  documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/@@',
10934
11143
  isAvilableInBrowser: true,
11144
+ // <- Note: [🌏] This is the only scraper which makes sense to be available in the browser, for scraping non-markdown sources in the browser use a remote server
10935
11145
  requiredExecutables: [],
10936
11146
  }); /* <- Note: [🤛] */
10937
11147
  /**
@@ -10940,6 +11150,7 @@
10940
11150
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
10941
11151
  *
10942
11152
  * @public exported from `@promptbook/core`
11153
+ * @public exported from `@promptbook/wizzard`
10943
11154
  * @public exported from `@promptbook/cli`
10944
11155
  */
10945
11156
  var _MarkdownScraperMetadataRegistration = $scrapersMetadataRegister.register(markdownScraperMetadata);
@@ -10958,7 +11169,8 @@
10958
11169
  className: 'PdfScraper',
10959
11170
  mimeTypes: ['application/pdf'],
10960
11171
  documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/@@',
10961
- isAvilableInBrowser: true,
11172
+ isAvilableInBrowser: false,
11173
+ // <- Note: [🌏] Only `MarkdownScraper` makes sense to be available in the browser, for scraping non-markdown sources in the browser use a remote server
10962
11174
  requiredExecutables: [],
10963
11175
  }); /* <- Note: [🤛] */
10964
11176
  /**
@@ -10967,6 +11179,7 @@
10967
11179
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
10968
11180
  *
10969
11181
  * @public exported from `@promptbook/core`
11182
+ * @public exported from `@promptbook/wizzard`
10970
11183
  * @public exported from `@promptbook/cli`
10971
11184
  */
10972
11185
  var _PdfScraperMetadataRegistration = $scrapersMetadataRegister.register(pdfScraperMetadata);
@@ -10986,6 +11199,7 @@
10986
11199
  mimeTypes: ['text/html'],
10987
11200
  documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/@@',
10988
11201
  isAvilableInBrowser: false,
11202
+ // <- Note: [🌏] Only `MarkdownScraper` makes sense to be available in the browser, for scraping non-markdown sources in the browser use a remote server
10989
11203
  requiredExecutables: [],
10990
11204
  }); /* <- Note: [🤛] */
10991
11205
  /**
@@ -10994,6 +11208,7 @@
10994
11208
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
10995
11209
  *
10996
11210
  * @public exported from `@promptbook/core`
11211
+ * @public exported from `@promptbook/wizzard`
10997
11212
  * @public exported from `@promptbook/cli`
10998
11213
  */
10999
11214
  var _WebsiteScraperMetadataRegistration = $scrapersMetadataRegister.register(websiteScraperMetadata);
@@ -11100,6 +11315,7 @@
11100
11315
  exports.CsvFormatDefinition = CsvFormatDefinition;
11101
11316
  exports.CsvFormatError = CsvFormatError;
11102
11317
  exports.DEFAULT_BOOKS_DIRNAME = DEFAULT_BOOKS_DIRNAME;
11318
+ exports.DEFAULT_BOOK_TITLE = DEFAULT_BOOK_TITLE;
11103
11319
  exports.DEFAULT_CSV_SETTINGS = DEFAULT_CSV_SETTINGS;
11104
11320
  exports.DEFAULT_EXECUTIONS_CACHE_DIRNAME = DEFAULT_EXECUTIONS_CACHE_DIRNAME;
11105
11321
  exports.DEFAULT_GET_PIPELINE_COLLECTION_FUNCTION_NAME = DEFAULT_GET_PIPELINE_COLLECTION_FUNCTION_NAME;
@@ -11113,7 +11329,6 @@
11113
11329
  exports.DEFAULT_REMOTE_URL = DEFAULT_REMOTE_URL;
11114
11330
  exports.DEFAULT_REMOTE_URL_PATH = DEFAULT_REMOTE_URL_PATH;
11115
11331
  exports.DEFAULT_SCRAPE_CACHE_DIRNAME = DEFAULT_SCRAPE_CACHE_DIRNAME;
11116
- exports.DEFAULT_TITLE = DEFAULT_TITLE;
11117
11332
  exports.EXPECTATION_UNITS = EXPECTATION_UNITS;
11118
11333
  exports.EnvironmentMismatchError = EnvironmentMismatchError;
11119
11334
  exports.ExecutionReportStringOptionsDefaults = ExecutionReportStringOptionsDefaults;
@@ -11122,6 +11337,7 @@
11122
11337
  exports.GENERIC_PIPELINE_INTERFACE = GENERIC_PIPELINE_INTERFACE;
11123
11338
  exports.GeneratorFormfactorDefinition = GeneratorFormfactorDefinition;
11124
11339
  exports.GenericFormfactorDefinition = GenericFormfactorDefinition;
11340
+ exports.ImageGeneratorFormfactorDefinition = ImageGeneratorFormfactorDefinition;
11125
11341
  exports.KnowledgeScrapeError = KnowledgeScrapeError;
11126
11342
  exports.LOGO_DARK_SRC = LOGO_DARK_SRC;
11127
11343
  exports.LOGO_LIGHT_SRC = LOGO_LIGHT_SRC;
@@ -11167,6 +11383,7 @@
11167
11383
  exports._WebsiteScraperMetadataRegistration = _WebsiteScraperMetadataRegistration;
11168
11384
  exports.addUsage = addUsage;
11169
11385
  exports.assertsExecutionSuccessful = assertsExecutionSuccessful;
11386
+ exports.book = book;
11170
11387
  exports.cacheLlmTools = cacheLlmTools;
11171
11388
  exports.collectionToJson = collectionToJson;
11172
11389
  exports.compilePipeline = compilePipeline;
@@ -11185,11 +11402,12 @@
11185
11402
  exports.isPipelineImplementingInterface = isPipelineImplementingInterface;
11186
11403
  exports.isPipelineInterfacesEqual = isPipelineInterfacesEqual;
11187
11404
  exports.isPipelinePrepared = isPipelinePrepared;
11405
+ exports.isValidPipelineString = isValidPipelineString;
11188
11406
  exports.joinLlmExecutionTools = joinLlmExecutionTools;
11189
11407
  exports.limitTotalUsage = limitTotalUsage;
11190
11408
  exports.makeKnowledgeSourceHandler = makeKnowledgeSourceHandler;
11409
+ exports.parsePipeline = parsePipeline;
11191
11410
  exports.pipelineJsonToString = pipelineJsonToString;
11192
- exports.precompilePipeline = precompilePipeline;
11193
11411
  exports.prepareKnowledgePieces = prepareKnowledgePieces;
11194
11412
  exports.preparePersona = preparePersona;
11195
11413
  exports.preparePipeline = preparePipeline;
@@ -11199,6 +11417,7 @@
11199
11417
  exports.usageToHuman = usageToHuman;
11200
11418
  exports.usageToWorktime = usageToWorktime;
11201
11419
  exports.validatePipeline = validatePipeline;
11420
+ exports.validatePipelineString = validatePipelineString;
11202
11421
 
11203
11422
  Object.defineProperty(exports, '__esModule', { value: true });
11204
11423