@promptbook/cli 0.80.0 → 0.81.0-12

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 (70) hide show
  1. package/README.md +8 -1
  2. package/esm/index.es.js +712 -415
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/books/index.d.ts +15 -0
  5. package/esm/typings/src/_packages/core.index.d.ts +2 -6
  6. package/esm/typings/src/_packages/editable.index.d.ts +10 -0
  7. package/esm/typings/src/_packages/templates.index.d.ts +4 -0
  8. package/esm/typings/src/_packages/types.index.d.ts +6 -0
  9. package/esm/typings/src/_packages/utils.index.d.ts +12 -2
  10. package/esm/typings/src/_packages/wizzard.index.d.ts +44 -0
  11. package/esm/typings/src/config.d.ts +26 -0
  12. package/esm/typings/src/execution/ExecutionTools.d.ts +7 -0
  13. package/esm/typings/src/execution/PipelineExecutor.d.ts +2 -2
  14. package/esm/typings/src/execution/PromptbookFetch.d.ts +5 -0
  15. package/esm/typings/src/execution/PromptbookFetch.test-type.d.ts +5 -0
  16. package/esm/typings/src/execution/createPipelineExecutor/10-executePipeline.d.ts +2 -2
  17. package/esm/typings/src/expectations/drafts/isDomainNameFree.d.ts +2 -1
  18. package/esm/typings/src/expectations/drafts/isGithubNameFree.d.ts +2 -1
  19. package/esm/typings/src/high-level-abstractions/index.d.ts +10 -0
  20. package/esm/typings/src/llm-providers/_common/register/{$provideLlmToolsForCli.d.ts → $provideLlmToolsForWizzardOrCli.d.ts} +2 -2
  21. package/esm/typings/src/llm-providers/anthropic-claude/register-configuration.d.ts +1 -0
  22. package/esm/typings/src/llm-providers/anthropic-claude/register-constructor.d.ts +2 -0
  23. package/esm/typings/src/llm-providers/azure-openai/register-configuration.d.ts +1 -0
  24. package/esm/typings/src/llm-providers/azure-openai/register-constructor.d.ts +1 -0
  25. package/esm/typings/src/llm-providers/google/register-configuration.d.ts +1 -0
  26. package/esm/typings/src/llm-providers/google/register-constructor.d.ts +1 -0
  27. package/esm/typings/src/llm-providers/openai/register-configuration.d.ts +2 -0
  28. package/esm/typings/src/llm-providers/openai/register-constructor.d.ts +2 -0
  29. package/esm/typings/src/other/templates/getBookTemplate.d.ts +19 -0
  30. package/esm/typings/src/other/templates/getTemplatesPipelineCollection.d.ts +10 -0
  31. package/esm/typings/src/pipeline/PipelineJson/PipelineJson.d.ts +10 -0
  32. package/esm/typings/src/scrapers/_common/utils/makeKnowledgeSourceHandler.d.ts +1 -1
  33. package/esm/typings/src/scrapers/_common/utils/scraperFetch.d.ts +10 -0
  34. package/esm/typings/src/scrapers/document/register-constructor.d.ts +1 -0
  35. package/esm/typings/src/scrapers/document/register-metadata.d.ts +1 -0
  36. package/esm/typings/src/scrapers/document-legacy/register-constructor.d.ts +1 -0
  37. package/esm/typings/src/scrapers/document-legacy/register-metadata.d.ts +1 -0
  38. package/esm/typings/src/scrapers/markdown/register-constructor.d.ts +1 -0
  39. package/esm/typings/src/scrapers/markdown/register-metadata.d.ts +1 -0
  40. package/esm/typings/src/scrapers/pdf/register-constructor.d.ts +1 -0
  41. package/esm/typings/src/scrapers/pdf/register-metadata.d.ts +1 -0
  42. package/esm/typings/src/scrapers/website/register-constructor.d.ts +1 -0
  43. package/esm/typings/src/scrapers/website/register-metadata.d.ts +1 -0
  44. package/esm/typings/src/scripting/javascript/utils/preserve.d.ts +1 -0
  45. package/esm/typings/src/types/typeAliases.d.ts +8 -0
  46. package/esm/typings/src/utils/editable/types/PipelineEditableSerialized.d.ts +27 -0
  47. package/esm/typings/src/{conversion → utils/editable}/utils/removePipelineCommand.d.ts +3 -3
  48. package/esm/typings/src/{conversion → utils/editable}/utils/renamePipelineParameter.d.ts +3 -3
  49. package/esm/typings/src/{conversion → utils/editable}/utils/stringifyPipelineJson.d.ts +2 -2
  50. package/esm/typings/src/utils/parameters/numberToString.d.ts +7 -0
  51. package/esm/typings/src/utils/parameters/{replaceParameters.d.ts → templateParameters.d.ts} +6 -2
  52. package/esm/typings/src/utils/parameters/valueToString.d.ts +17 -0
  53. package/esm/typings/src/utils/parameters/valueToString.test.d.ts +1 -0
  54. package/esm/typings/src/utils/serialization/asSerializable.d.ts +4 -0
  55. package/esm/typings/src/utils/validators/filePath/isPathRoot.d.ts +12 -0
  56. package/esm/typings/src/utils/validators/filePath/isPathRoot.test.d.ts +4 -0
  57. package/esm/typings/src/utils/validators/filePath/isValidFilePath.d.ts +3 -0
  58. package/esm/typings/src/version.d.ts +7 -0
  59. package/esm/typings/src/wizzard/$getCompiledBook.d.ts +16 -0
  60. package/esm/typings/src/wizzard/wizzard.d.ts +51 -0
  61. package/package.json +1 -1
  62. package/umd/index.umd.js +712 -415
  63. package/umd/index.umd.js.map +1 -1
  64. package/esm/typings/src/scripting/javascript/utils/unknownToString.d.ts +0 -8
  65. package/esm/typings/src/utils/formatNumber.d.ts +0 -6
  66. /package/esm/typings/src/{conversion → utils/editable}/utils/removePipelineCommand.test.d.ts +0 -0
  67. /package/esm/typings/src/{conversion → utils/editable}/utils/renamePipelineParameter.test.d.ts +0 -0
  68. /package/esm/typings/src/{conversion → utils/editable}/utils/stringifyPipelineJson.test.d.ts +0 -0
  69. /package/esm/typings/src/utils/{formatNumber.test.d.ts → parameters/numberToString.test.d.ts} +0 -0
  70. /package/esm/typings/src/utils/parameters/{replaceParameters.test.d.ts → templateParameters.test.d.ts} +0 -0
package/esm/index.es.js CHANGED
@@ -29,15 +29,17 @@ import { Converter } from 'showdown';
29
29
  /**
30
30
  * The version of the Book language
31
31
  *
32
+ * @generated
32
33
  * @see https://github.com/webgptorg/book
33
34
  */
34
35
  var BOOK_LANGUAGE_VERSION = '1.0.0';
35
36
  /**
36
37
  * The version of the Promptbook engine
37
38
  *
39
+ * @generated
38
40
  * @see https://github.com/webgptorg/promptbook
39
41
  */
40
- var PROMPTBOOK_ENGINE_VERSION = '0.80.0-1';
42
+ var PROMPTBOOK_ENGINE_VERSION = '0.81.0-11';
41
43
  /**
42
44
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
43
45
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -235,6 +237,26 @@ var GENERATOR_WARNING_BY_PROMPTBOOK_CLI = "\u26A0\uFE0F WARNING: This code has b
235
237
  * @private within the repository - too low-level in comparison with other `MAX_...`
236
238
  */
237
239
  var LOOP_LIMIT = 1000;
240
+ /**
241
+ * Strings to represent various values in the context of parameter values
242
+ *
243
+ * @public exported from `@promptbook/utils`
244
+ */
245
+ var VALUE_STRINGS = {
246
+ empty: '(nothing; empty string)',
247
+ null: '(no value; null)',
248
+ undefined: '(unknown value; undefined)',
249
+ nan: '(not a number; NaN)',
250
+ infinity: '(infinity; ∞)',
251
+ negativeInfinity: '(negative infinity; -∞)',
252
+ unserializable: '(unserializable value)',
253
+ };
254
+ /**
255
+ * Small number limit
256
+ *
257
+ * @public exported from `@promptbook/utils`
258
+ */
259
+ var SMALL_NUMBER = 0.001;
238
260
  /**
239
261
  * Timeout for the connections in milliseconds
240
262
  *
@@ -353,6 +375,12 @@ var DEFAULT_IS_VERBOSE = false;
353
375
  * @public exported from `@promptbook/core`
354
376
  */
355
377
  var DEFAULT_IS_AUTO_INSTALLED = false;
378
+ /**
379
+ * Function name for generated function via `ptbk make` to get the pipeline collection
380
+ *
381
+ * @public exported from `@promptbook/core`
382
+ */
383
+ var DEFAULT_GET_PIPELINE_COLLECTION_FUNCTION_NAME = "getPipelineCollection";
356
384
  /**
357
385
  * @@@
358
386
  *
@@ -488,6 +516,40 @@ function $provideFilesystemForNode(options) {
488
516
  * Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
489
517
  */
490
518
 
519
+ /**
520
+ * Make error report URL for the given error
521
+ *
522
+ * @private !!!!!!
523
+ */
524
+ function getErrorReportUrl(error) {
525
+ var report = {
526
+ title: "\uD83D\uDC1C Error report from ".concat(NAME),
527
+ body: spaceTrim(function (block) { return "\n\n\n `".concat(error.name || 'Error', "` has occurred in the [").concat(NAME, "], please look into it @").concat(ADMIN_GITHUB_NAME, ".\n\n ```\n ").concat(block(error.message || '(no error message)'), "\n ```\n\n\n ## More info:\n\n - **Promptbook engine version:** ").concat(PROMPTBOOK_ENGINE_VERSION, "\n - **Book language version:** ").concat(BOOK_LANGUAGE_VERSION, "\n - **Time:** ").concat(new Date().toISOString(), "\n\n <details>\n <summary>Stack trace:</summary>\n\n ## Stack trace:\n\n ```stacktrace\n ").concat(block(error.stack || '(empty)'), "\n ```\n </details>\n\n "); }),
528
+ };
529
+ var reportUrl = new URL("https://github.com/webgptorg/promptbook/issues/new");
530
+ reportUrl.searchParams.set('labels', 'bug');
531
+ reportUrl.searchParams.set('assignees', ADMIN_GITHUB_NAME);
532
+ reportUrl.searchParams.set('title', report.title);
533
+ reportUrl.searchParams.set('body', report.body);
534
+ return reportUrl;
535
+ }
536
+
537
+ /**
538
+ * This error type indicates that the error should not happen and its last check before crashing with some other error
539
+ *
540
+ * @public exported from `@promptbook/core`
541
+ */
542
+ var UnexpectedError = /** @class */ (function (_super) {
543
+ __extends(UnexpectedError, _super);
544
+ function UnexpectedError(message) {
545
+ var _this = _super.call(this, spaceTrim$1(function (block) { return "\n ".concat(block(message), "\n\n Note: This error should not happen.\n It's probbably a bug in the pipeline collection\n\n Please report issue:\n ").concat(block(getErrorReportUrl(new Error(message)).href), "\n\n Or contact us on ").concat(ADMIN_EMAIL, "\n\n "); })) || this;
546
+ _this.name = 'UnexpectedError';
547
+ Object.setPrototypeOf(_this, UnexpectedError.prototype);
548
+ return _this;
549
+ }
550
+ return UnexpectedError;
551
+ }(Error));
552
+
491
553
  /**
492
554
  * Orders JSON object by keys
493
555
  *
@@ -538,40 +600,6 @@ function $deepFreeze(objectValue) {
538
600
  * TODO: [🧠] Is there a way how to meaningfully test this utility
539
601
  */
540
602
 
541
- /**
542
- * Make error report URL for the given error
543
- *
544
- * @private !!!!!!
545
- */
546
- function getErrorReportUrl(error) {
547
- var report = {
548
- title: "\uD83D\uDC1C Error report from ".concat(NAME),
549
- body: spaceTrim(function (block) { return "\n\n\n `".concat(error.name || 'Error', "` has occurred in the [").concat(NAME, "], please look into it @").concat(ADMIN_GITHUB_NAME, ".\n\n ```\n ").concat(block(error.message || '(no error message)'), "\n ```\n\n\n ## More info:\n\n - **Promptbook engine version:** ").concat(PROMPTBOOK_ENGINE_VERSION, "\n - **Book language version:** ").concat(BOOK_LANGUAGE_VERSION, "\n - **Time:** ").concat(new Date().toISOString(), "\n\n <details>\n <summary>Stack trace:</summary>\n\n ## Stack trace:\n\n ```stacktrace\n ").concat(block(error.stack || '(empty)'), "\n ```\n </details>\n\n "); }),
550
- };
551
- var reportUrl = new URL("https://github.com/webgptorg/promptbook/issues/new");
552
- reportUrl.searchParams.set('labels', 'bug');
553
- reportUrl.searchParams.set('assignees', ADMIN_GITHUB_NAME);
554
- reportUrl.searchParams.set('title', report.title);
555
- reportUrl.searchParams.set('body', report.body);
556
- return reportUrl;
557
- }
558
-
559
- /**
560
- * This error type indicates that the error should not happen and its last check before crashing with some other error
561
- *
562
- * @public exported from `@promptbook/core`
563
- */
564
- var UnexpectedError = /** @class */ (function (_super) {
565
- __extends(UnexpectedError, _super);
566
- function UnexpectedError(message) {
567
- var _this = _super.call(this, spaceTrim$1(function (block) { return "\n ".concat(block(message), "\n\n Note: This error should not happen.\n It's probbably a bug in the pipeline collection\n\n Please report issue:\n ").concat(block(getErrorReportUrl(new Error(message)).href), "\n\n Or contact us on ").concat(ADMIN_EMAIL, "\n\n "); })) || this;
568
- _this.name = 'UnexpectedError';
569
- Object.setPrototypeOf(_this, UnexpectedError.prototype);
570
- return _this;
571
- }
572
- return UnexpectedError;
573
- }(Error));
574
-
575
603
  /**
576
604
  * Checks if the value is [🚉] serializable as JSON
577
605
  * If not, throws an UnexpectedError with a rich error message and tracking
@@ -662,7 +690,7 @@ function checkSerializableAsJson(options) {
662
690
  if (!(error instanceof Error)) {
663
691
  throw error;
664
692
  }
665
- throw new UnexpectedError(spaceTrim(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 "); }));
693
+ throw new UnexpectedError(spaceTrim(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 "); }));
666
694
  }
667
695
  /*
668
696
  TODO: [0] Is there some more elegant way to check circular references?
@@ -760,6 +788,7 @@ function exportJson(options) {
760
788
  * @public exported from `@promptbook/core`
761
789
  */
762
790
  var ORDER_OF_PIPELINE_JSON = [
791
+ // Note: [🍙] In this order will be pipeline serialized
763
792
  'title',
764
793
  'pipelineUrl',
765
794
  'bookVersion',
@@ -771,6 +800,7 @@ var ORDER_OF_PIPELINE_JSON = [
771
800
  'preparations',
772
801
  'knowledgeSources',
773
802
  'knowledgePieces',
803
+ 'sources', // <- TODO: [🧠] Where should the `sources` be
774
804
  ];
775
805
  /**
776
806
  * Nonce which is used for replacing things in strings
@@ -854,7 +884,7 @@ function isSerializableAsJson(value) {
854
884
  * Note: [0] It can be used for more JSON types like whole collection of pipelines, single knowledge piece, etc.
855
885
  * Note: In contrast to JSON.stringify, this function ensures that **embedding index** is on single line
856
886
  *
857
- * @public exported from `@promptbook/core`
887
+ * @public exported from `@promptbook/editable`
858
888
  */
859
889
  function stringifyPipelineJson(pipeline) {
860
890
  if (!isSerializableAsJson(pipeline)) {
@@ -937,21 +967,44 @@ function isValidFilePath(filename) {
937
967
  if (typeof filename !== 'string') {
938
968
  return false;
939
969
  }
970
+ if (filename.split('\n').length > 1) {
971
+ return false;
972
+ }
973
+ if (filename.split(' ').length >
974
+ 5 /* <- TODO: [🧠][🈷] Make some better non-arbitrary way how to distinct filenames from informational texts */) {
975
+ return false;
976
+ }
940
977
  var filenameSlashes = filename.split('\\').join('/');
941
978
  // Absolute Unix path: /hello.txt
942
979
  if (/^(\/)/i.test(filenameSlashes)) {
980
+ // console.log(filename, 'Absolute Unix path: /hello.txt');
943
981
  return true;
944
982
  }
945
983
  // Absolute Windows path: /hello.txt
946
984
  if (/^([A-Z]{1,2}:\/?)\//i.test(filenameSlashes)) {
985
+ // console.log(filename, 'Absolute Windows path: /hello.txt');
947
986
  return true;
948
987
  }
949
988
  // Relative path: ./hello.txt
950
989
  if (/^(\.\.?\/)+/i.test(filenameSlashes)) {
990
+ // console.log(filename, 'Relative path: ./hello.txt');
991
+ return true;
992
+ }
993
+ // Allow paths like foo/hello
994
+ if (/^[^/]+\/[^/]+/i.test(filenameSlashes)) {
995
+ // console.log(filename, 'Allow paths like foo/hello');
996
+ return true;
997
+ }
998
+ // Allow paths like hello.book
999
+ if (/^[^/]+\.[^/]+$/i.test(filenameSlashes)) {
1000
+ // console.log(filename, 'Allow paths like hello.book');
951
1001
  return true;
952
1002
  }
953
1003
  return false;
954
1004
  }
1005
+ /**
1006
+ * TODO: [🍏] Implement for MacOs
1007
+ */
955
1008
 
956
1009
  /**
957
1010
  * Tests if given string is valid URL.
@@ -2560,8 +2613,11 @@ function $provideLlmToolsFromEnv(options) {
2560
2613
  }
2561
2614
  var configuration = $provideLlmToolsConfigurationFromEnv();
2562
2615
  if (configuration.length === 0) {
2616
+ if ($llmToolsMetadataRegister.list().length === 0) {
2617
+ throw new UnexpectedError(spaceTrim(function (block) { return "\n No LLM tools registered, this is probably a bug in the Promptbook library\n\n ".concat(block($registeredLlmToolsMessage()), "}\n "); }));
2618
+ }
2563
2619
  // TODO: [🥃]
2564
- throw new Error(spaceTrim(function (block) { return "\n No LLM tools found in the environment\n\n Please set one of environment variables:\n - OPENAI_API_KEY\n - ANTHROPIC_CLAUDE_API_KEY\n\n ".concat(block($registeredLlmToolsMessage()), "}\n "); }));
2620
+ throw new Error(spaceTrim(function (block) { return "\n No LLM tools found in the environment\n\n ".concat(block($registeredLlmToolsMessage()), "}\n "); }));
2565
2621
  }
2566
2622
  return createLlmToolsFromConfiguration(configuration, options);
2567
2623
  }
@@ -2580,9 +2636,9 @@ function $provideLlmToolsFromEnv(options) {
2580
2636
  *
2581
2637
  * @private within the repository - for CLI utils
2582
2638
  */
2583
- function $provideLlmToolsForCli(options) {
2639
+ function $provideLlmToolsForWizzardOrCli(options) {
2584
2640
  if (!$isRunningInNode()) {
2585
- throw new EnvironmentMismatchError('Function `$provideLlmToolsForTestingAndScriptsAndPlayground` works only in Node.js environment');
2641
+ throw new EnvironmentMismatchError('Function `$provideLlmToolsForWizzardOrCli` works only in Node.js environment');
2586
2642
  }
2587
2643
  var isCacheReloaded = (options !== null && options !== void 0 ? options : {}).isCacheReloaded;
2588
2644
  return cacheLlmTools(countTotalUsage(
@@ -2595,7 +2651,7 @@ function $provideLlmToolsForCli(options) {
2595
2651
  });
2596
2652
  }
2597
2653
  /**
2598
- * Note: [🟡] Code in this file should never be published outside of `@promptbook/cli`
2654
+ * Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
2599
2655
  * TODO: [👷‍♂️] @@@ Manual about construction of llmTools
2600
2656
  * TODO: [🥃] Allow `ptbk make` without llm tools
2601
2657
  * TODO: This should be maybe not under `_common` but under `utils-internal` / `utils/internal`
@@ -2613,7 +2669,7 @@ function initializeListModelsCommand(program) {
2613
2669
  listModelsCommand.description(spaceTrim("\n List all available and configured LLM models\n "));
2614
2670
  listModelsCommand.action(function () { return __awaiter(_this, void 0, void 0, function () {
2615
2671
  return __generator(this, function (_a) {
2616
- $provideLlmToolsForCli({});
2672
+ $provideLlmToolsForWizzardOrCli({});
2617
2673
  // <- Note: Providing LLM tools will make a side effect of registering all available LLM tools to show the message
2618
2674
  console.info($registeredLlmToolsMessage());
2619
2675
  return [2 /*return*/, process.exit(0)];
@@ -2744,7 +2800,7 @@ function forEachAsync(array, options, callbackfunction) {
2744
2800
  });
2745
2801
  }
2746
2802
 
2747
- 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:[],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:[],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:[],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:[],sourceFile:"./books/prepare-persona.book.md"}];
2803
+ 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"}];
2748
2804
 
2749
2805
  /**
2750
2806
  * Prettify the html code
@@ -3140,9 +3196,6 @@ function isValidPipelineUrl(url) {
3140
3196
  if (!url.startsWith('https://')) {
3141
3197
  return false;
3142
3198
  }
3143
- if (!(url.endsWith('.book.md') || url.endsWith('.book') || url.endsWith('.book.md') || url.endsWith('.ptbk'))) {
3144
- return false;
3145
- }
3146
3199
  if (url.includes('#')) {
3147
3200
  // TODO: [🐠]
3148
3201
  return false;
@@ -3872,6 +3925,81 @@ function isPipelinePrepared(pipeline) {
3872
3925
  * - [♨] Are tasks prepared
3873
3926
  */
3874
3927
 
3928
+ /**
3929
+ * Format either small or big number
3930
+ *
3931
+ * @public exported from `@promptbook/utils`
3932
+ */
3933
+ function numberToString(value) {
3934
+ if (value === 0) {
3935
+ return '0';
3936
+ }
3937
+ else if (Number.isNaN(value)) {
3938
+ return VALUE_STRINGS.nan;
3939
+ }
3940
+ else if (value === Infinity) {
3941
+ return VALUE_STRINGS.infinity;
3942
+ }
3943
+ else if (value === -Infinity) {
3944
+ return VALUE_STRINGS.negativeInfinity;
3945
+ }
3946
+ for (var exponent = 0; exponent < 15; exponent++) {
3947
+ var factor = Math.pow(10, exponent);
3948
+ var valueRounded = Math.round(value * factor) / factor;
3949
+ if (Math.abs(value - valueRounded) / value < SMALL_NUMBER) {
3950
+ return valueRounded.toFixed(exponent);
3951
+ }
3952
+ }
3953
+ return value.toString();
3954
+ }
3955
+
3956
+ /**
3957
+ * Function `valueToString` will convert the given value to string
3958
+ * This is useful and used in the `templateParameters` function
3959
+ *
3960
+ * Note: This function is not just calling `toString` method
3961
+ * It's more complex and can handle this conversion specifically for LLM models
3962
+ * See `VALUE_STRINGS`
3963
+ *
3964
+ * Note: There are 2 similar functions
3965
+ * - `valueToString` converts value to string for LLM models as human-readable string
3966
+ * - `asSerializable` converts value to string to preserve full information to be able to convert it back
3967
+ *
3968
+ * @public exported from `@promptbook/utils`
3969
+ */
3970
+ function valueToString(value) {
3971
+ try {
3972
+ if (value === '') {
3973
+ return VALUE_STRINGS.empty;
3974
+ }
3975
+ else if (value === null) {
3976
+ return VALUE_STRINGS.null;
3977
+ }
3978
+ else if (value === undefined) {
3979
+ return VALUE_STRINGS.undefined;
3980
+ }
3981
+ else if (typeof value === 'string') {
3982
+ return value;
3983
+ }
3984
+ else if (typeof value === 'number') {
3985
+ return numberToString(value);
3986
+ }
3987
+ else if (value instanceof Date) {
3988
+ return value.toISOString();
3989
+ }
3990
+ else {
3991
+ return JSON.stringify(value);
3992
+ }
3993
+ }
3994
+ catch (error) {
3995
+ if (!(error instanceof Error)) {
3996
+ throw error;
3997
+ }
3998
+ console.error(error);
3999
+ return VALUE_STRINGS.unserializable;
4000
+ }
4001
+ }
4002
+
3875
4003
  /**
3876
4004
  * Serializes an error into a [🚉] JSON-serializable object
3877
4005
  *
@@ -3943,7 +4071,7 @@ function extractVariablesFromScript(script) {
3943
4071
  if (!(error instanceof Error)) {
3944
4072
  throw error;
3945
4073
  }
3946
- throw new ParseError(spaceTrim$1(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)
4074
+ throw new ParseError(spaceTrim$1(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)
3947
4075
  .map(function (variableName, i) { return "".concat(i + 1, ") ").concat(variableName); })
3948
4076
  .join('\n'), "\n\n\n The script:\n\n ```javascript\n ").concat(block(originalScript), "\n ```\n "); }));
3949
4077
  }
@@ -4584,13 +4712,16 @@ function arrayableToArray(input) {
4584
4712
  /**
4585
4713
  * Replaces parameters in template with values from parameters object
4586
4714
  *
4715
+ * Note: This function is not places strings into string,
4716
+ * It's more complex and can handle this operation specifically for LLM models
4717
+ *
4587
4718
  * @param template the template with parameters in {curly} braces
4588
4719
  * @param parameters the object with parameters
4589
4720
  * @returns the template with replaced parameters
4590
4721
  * @throws {PipelineExecutionError} if parameter is not defined, not closed, or not opened
4591
4722
  * @public exported from `@promptbook/utils`
4592
4723
  */
4593
- function replaceParameters(template, parameters) {
4724
+ function templateParameters(template, parameters) {
4594
4725
  var e_1, _a;
4595
4726
  try {
4596
4727
  for (var _b = __values(Object.entries(parameters)), _c = _b.next(); !_c.done; _c = _b.next()) {
@@ -4616,7 +4747,7 @@ function replaceParameters(template, parameters) {
4616
4747
  var loopLimit = LOOP_LIMIT;
4617
4748
  var _loop_1 = function () {
4618
4749
  if (loopLimit-- < 0) {
4619
- throw new LimitReachedError('Loop limit reached during parameters replacement in `replaceParameters`');
4750
+ throw new LimitReachedError('Loop limit reached during parameters replacement in `templateParameters`');
4620
4751
  }
4621
4752
  var precol = match.groups.precol;
4622
4753
  var parameterName = match.groups.parameterName;
@@ -4633,7 +4764,7 @@ function replaceParameters(template, parameters) {
4633
4764
  if (parameterValue === undefined) {
4634
4765
  throw new PipelineExecutionError("Parameter `{".concat(parameterName, "}` is not defined"));
4635
4766
  }
4636
- parameterValue = parameterValue.toString();
4767
+ parameterValue = valueToString(parameterValue);
4637
4768
  if (parameterValue.includes('\n') && /^\s*\W{0,3}\s*$/.test(precol)) {
4638
4769
  parameterValue = parameterValue
4639
4770
  .split('\n')
@@ -4868,7 +4999,7 @@ function executeAttempts(options) {
4868
4999
  }
4869
5000
  return [3 /*break*/, 24];
4870
5001
  case 2:
4871
- $ongoingTaskResult.$resultString = replaceParameters(preparedContent, parameters);
5002
+ $ongoingTaskResult.$resultString = templateParameters(preparedContent, parameters);
4872
5003
  return [3 /*break*/, 25];
4873
5004
  case 3:
4874
5005
  modelRequirements = __assign(__assign({ modelVariant: 'CHAT' }, (preparedPipeline.defaultModelRequirements || {})), (task.modelRequirements || {}));
@@ -4991,8 +5122,8 @@ function executeAttempts(options) {
4991
5122
  _j = $ongoingTaskResult;
4992
5123
  return [4 /*yield*/, tools.userInterface.promptDialog($deepFreeze({
4993
5124
  promptTitle: task.title,
4994
- promptMessage: replaceParameters(task.description || '', parameters),
4995
- defaultValue: replaceParameters(preparedContent, parameters),
5125
+ promptMessage: templateParameters(task.description || '', parameters),
5126
+ defaultValue: templateParameters(preparedContent, parameters),
4996
5127
  // TODO: [🧠] !! Figure out how to define placeholder in .book.md file
4997
5128
  placeholder: undefined,
4998
5129
  priority: priority,
@@ -5116,7 +5247,7 @@ function executeAttempts(options) {
5116
5247
  if (!isJokerAttempt &&
5117
5248
  task.taskType === 'PROMPT_TASK' &&
5118
5249
  $ongoingTaskResult.$prompt
5119
- // <- Note: [2] When some expected parameter is not defined, error will occur in replaceParameters
5250
+ // <- Note: [2] When some expected parameter is not defined, error will occur in templateParameters
5120
5251
  // In that case we don’t want to make a report about it because it’s not a llm execution error
5121
5252
  ) {
5122
5253
  // TODO: [🧠] Maybe put other taskTypes into report
@@ -5693,7 +5824,10 @@ function executePipeline(options) {
5693
5824
  finally { if (e_2) throw e_2.error; }
5694
5825
  return [7 /*endfinally*/];
5695
5826
  case 19:
5696
- parametersToPass = inputParameters;
5827
+ parametersToPass = Object.fromEntries(Object.entries(inputParameters).map(function (_a) {
5828
+ var _b = __read(_a, 2), key = _b[0], value = _b[1];
5829
+ return [key, valueToString(value)];
5830
+ }));
5697
5831
  _g.label = 20;
5698
5832
  case 20:
5699
5833
  _g.trys.push([20, 25, , 28]);
@@ -6180,6 +6314,33 @@ function getFileExtension(value) {
6180
6314
  return match ? match[1].toLowerCase() : null;
6181
6315
  }
6182
6316
 
6317
+ /**
6318
+ * The built-in `fetch' function with a lightweight error handling wrapper as default fetch function used in Promptbook scrapers
6319
+ *
6320
+ * @private as default `fetch` function used in Promptbook scrapers
6321
+ */
6322
+ var scraperFetch = function (url, init) { return __awaiter(void 0, void 0, void 0, function () {
6323
+ var error_1;
6324
+ return __generator(this, function (_a) {
6325
+ switch (_a.label) {
6326
+ case 0:
6327
+ _a.trys.push([0, 2, , 3]);
6328
+ return [4 /*yield*/, fetch(url, init)];
6329
+ case 1: return [2 /*return*/, _a.sent()];
6330
+ case 2:
6331
+ error_1 = _a.sent();
6332
+ if (!(error_1 instanceof Error)) {
6333
+ throw error_1;
6334
+ }
6335
+ throw new KnowledgeScrapeError(spaceTrim(function (block) { return "\n Can not fetch \"".concat(url, "\"\n\n Fetch error:\n ").concat(block(error_1.message), "\n\n "); }));
6336
+ case 3: return [2 /*return*/];
6337
+ }
6338
+ });
6339
+ }); };
6340
+ /**
6341
+ * TODO: [🧠] Maybe rename because it is not used only for scrapers but also in `$getCompiledBook`
6342
+ */
6343
+
6183
6344
  /**
6184
6345
  * @@@
6185
6346
  *
@@ -6188,13 +6349,14 @@ function getFileExtension(value) {
6188
6349
  function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
6189
6350
  var _a;
6190
6351
  return __awaiter(this, void 0, void 0, function () {
6191
- var sourceContent, name, _b, _c, rootDirname, url, response_1, mimeType, filename_1, fileExtension, mimeType;
6192
- return __generator(this, function (_e) {
6193
- switch (_e.label) {
6352
+ var _b, fetch, sourceContent, name, _c, _d, rootDirname, url, response_1, mimeType, filename_1, fileExtension, mimeType;
6353
+ return __generator(this, function (_f) {
6354
+ switch (_f.label) {
6194
6355
  case 0:
6356
+ _b = tools.fetch, fetch = _b === void 0 ? scraperFetch : _b;
6195
6357
  sourceContent = knowledgeSource.sourceContent;
6196
6358
  name = knowledgeSource.name;
6197
- _b = options || {}, _c = _b.rootDirname, rootDirname = _c === void 0 ? null : _c, _b.isVerbose;
6359
+ _c = options || {}, _d = _c.rootDirname, rootDirname = _d === void 0 ? null : _d, _c.isVerbose;
6198
6360
  if (!name) {
6199
6361
  name = sourceContentToName(sourceContent);
6200
6362
  }
@@ -6202,7 +6364,7 @@ function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
6202
6364
  url = sourceContent;
6203
6365
  return [4 /*yield*/, fetch(url)];
6204
6366
  case 1:
6205
- response_1 = _e.sent();
6367
+ response_1 = _f.sent();
6206
6368
  mimeType = ((_a = response_1.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.split(';')[0]) || 'text/html';
6207
6369
  return [2 /*return*/, {
6208
6370
  source: name,
@@ -6245,7 +6407,7 @@ function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
6245
6407
  },
6246
6408
  }];
6247
6409
  case 2:
6248
- if (!(isValidFilePath(sourceContent) || /\.[a-z]{1,10}$/i.exec(sourceContent))) return [3 /*break*/, 4];
6410
+ if (!isValidFilePath(sourceContent)) return [3 /*break*/, 4];
6249
6411
  if (tools.fs === undefined) {
6250
6412
  throw new EnvironmentMismatchError('Can not import file knowledge without filesystem tools');
6251
6413
  // <- TODO: [🧠] What is the best error type here`
@@ -6259,8 +6421,8 @@ function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
6259
6421
  mimeType = extensionToMimeType(fileExtension || '');
6260
6422
  return [4 /*yield*/, isFileExisting(filename_1, tools.fs)];
6261
6423
  case 3:
6262
- if (!(_e.sent())) {
6263
- throw new NotFoundError(spaceTrim(function (block) { return "\n Can not make source handler for file which does not exist:\n\n File:\n ".concat(block(filename_1), "\n "); }));
6424
+ if (!(_f.sent())) {
6425
+ throw new NotFoundError(spaceTrim(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 "); }));
6264
6426
  }
6265
6427
  // TODO: [🧠][😿] Test security file - file is scoped to the project (BUT maybe do this in `filesystemTools`)
6266
6428
  return [2 /*return*/, {
@@ -9522,6 +9684,14 @@ function precompilePipeline(pipelineString) {
9522
9684
  knowledgePieces: [],
9523
9685
  personas: [],
9524
9686
  preparations: [],
9687
+ sources: [
9688
+ {
9689
+ type: 'BOOK',
9690
+ path: null,
9691
+ // <- TODO: !!!!!! Pass here path of the file
9692
+ content: pipelineString,
9693
+ },
9694
+ ],
9525
9695
  };
9526
9696
  function getPipelineIdentification() {
9527
9697
  // Note: This is a 😐 implementation of [🚞]
@@ -9536,6 +9706,8 @@ function precompilePipeline(pipelineString) {
9536
9706
  }
9537
9707
  // =============================================================
9538
9708
  // Note: 1️⃣ Parsing of the markdown into object
9709
+ // ==============
9710
+ // Note: 1️⃣◽1️⃣ Remove #!shebang and comments
9539
9711
  if (pipelineString.startsWith('#!')) {
9540
9712
  var _g = __read(pipelineString.split('\n')), shebangLine_1 = _g[0], restLines = _g.slice(1);
9541
9713
  if (!(shebangLine_1 || '').includes('ptbk')) {
@@ -9544,10 +9716,33 @@ function precompilePipeline(pipelineString) {
9544
9716
  pipelineString = restLines.join('\n');
9545
9717
  }
9546
9718
  pipelineString = removeContentComments(pipelineString);
9719
+ pipelineString = spaceTrim$1(pipelineString);
9720
+ // ==============
9721
+ // Note: 1️⃣◽2️⃣ Process flat pipeline
9722
+ var isMarkdownBeginningWithHeadline = pipelineString.startsWith('# ');
9723
+ var isLastLineReturnStatement = pipelineString.split('\n').pop().split('`').join('').startsWith('->');
9724
+ // TODO: Also (double)check
9725
+ // > const usedCommands
9726
+ // > const isBlocksUsed
9727
+ // > const returnStatementCount
9728
+ var isFlatPipeline = !isMarkdownBeginningWithHeadline && isLastLineReturnStatement;
9729
+ // console.log({ isMarkdownBeginningWithHeadline, isLastLineReturnStatement, isFlatPipeline });
9730
+ if (isFlatPipeline) {
9731
+ var pipelineStringLines = pipelineString.split('\n');
9732
+ var returnStatement_1 = pipelineStringLines.pop();
9733
+ var prompt_1 = spaceTrim$1(pipelineStringLines.join('\n'));
9734
+ pipelineString = spaceTrim$1(function (block) { return "\n # ".concat(DEFAULT_TITLE /* <- TODO: !!!!!! Title for flat pipelines */, "\n\n ## Prompt\n\n ```\n ").concat(block(prompt_1), "\n ```\n\n ").concat(returnStatement_1, "\n "); });
9735
+ // <- TODO: !!!!!! Use `book notation
9736
+ // console.log(pipelineString);
9737
+ }
9738
+ // ==============
9739
+ // Note: 1️⃣◽3️⃣ Parse the markdown
9547
9740
  pipelineString = flattenMarkdown(pipelineString) /* <- Note: [🥞] */;
9548
9741
  pipelineString = pipelineString.replaceAll(/`\{(?<parameterName>[a-z0-9_]+)\}`/gi, '{$<parameterName>}');
9549
9742
  pipelineString = pipelineString.replaceAll(/`->\s+\{(?<parameterName>[a-z0-9_]+)\}`/gi, '-> {$<parameterName>}');
9550
9743
  var _h = __read(splitMarkdownIntoSections(pipelineString).map(parseMarkdownSection)), pipelineHead = _h[0], pipelineSections = _h.slice(1); /* <- Note: [🥞] */
9744
+ // ==============
9745
+ // Note: 1️⃣◽4️⃣ Check markdown structure
9551
9746
  if (pipelineHead === undefined) {
9552
9747
  throw new UnexpectedError(spaceTrim$1(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 "); }));
9553
9748
  }
@@ -9929,7 +10124,6 @@ function precompilePipeline(pipelineString) {
9929
10124
  $pipelineJson.formfactorName = 'GENERIC';
9930
10125
  }
9931
10126
  // =============================================================
9932
- // TODO: [🍙] Maybe do reorder of `$pipelineJson` here
9933
10127
  return exportJson({
9934
10128
  name: 'pipelineJson',
9935
10129
  message: "Result of `precompilePipeline`",
@@ -10346,53 +10540,140 @@ function $provideScrapersForNode(tools, options) {
10346
10540
  */
10347
10541
 
10348
10542
  /**
10349
- * Extracts code block from markdown.
10350
- *
10351
- * - When there are multiple or no code blocks the function throws a `ParseError`
10543
+ * Creates a Mermaid graph based on the promptbook
10352
10544
  *
10353
- * Note: There are multiple simmilar function:
10354
- * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
10355
- * - `extractJsonBlock` extracts exactly one valid JSON code block
10356
- * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
10357
- * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
10545
+ * Note: The result is not wrapped in a Markdown code block
10358
10546
  *
10359
- * @public exported from `@promptbook/markdown-utils`
10360
- * @throws {ParseError} if there is not exactly one code block in the markdown
10547
+ * @public exported from `@promptbook/utils`
10361
10548
  */
10362
- function extractBlock(markdown) {
10363
- var content = extractOneBlockFromMarkdown(markdown).content;
10364
- return content;
10549
+ function renderPromptbookMermaid(pipelineJson, options) {
10550
+ var _a = (options || {}).linkTask, linkTask = _a === void 0 ? function () { return null; } : _a;
10551
+ var parameterNameToTaskName = function (parameterName) {
10552
+ var parameter = pipelineJson.parameters.find(function (parameter) { return parameter.name === parameterName; });
10553
+ if (!parameter) {
10554
+ throw new UnexpectedError("Could not find {".concat(parameterName, "}"));
10555
+ // <- TODO: !!!!!! This causes problems when {knowledge} and other reserved parameters are used
10556
+ }
10557
+ if (parameter.isInput) {
10558
+ return 'input';
10559
+ }
10560
+ var task = pipelineJson.tasks.find(function (task) { return task.resultingParameterName === parameterName; });
10561
+ if (!task) {
10562
+ throw new Error("Could not find task for {".concat(parameterName, "}"));
10563
+ }
10564
+ return task.name || normalizeTo_camelCase('task-' + titleToName(task.title));
10565
+ };
10566
+ var promptbookMermaid = spaceTrim$1(function (block) { return "\n\n %% \uD83D\uDD2E Tip: Open this on GitHub or in the VSCode website to see the Mermaid graph visually\n\n flowchart LR\n subgraph \"".concat(pipelineJson.title, "\"\n\n direction TB\n\n input((Input)):::input\n ").concat(block(pipelineJson.tasks
10567
+ .flatMap(function (_a) {
10568
+ var title = _a.title, dependentParameterNames = _a.dependentParameterNames, resultingParameterName = _a.resultingParameterName;
10569
+ return __spreadArray([
10570
+ "".concat(parameterNameToTaskName(resultingParameterName), "(\"").concat(title, "\")")
10571
+ ], __read(dependentParameterNames.map(function (dependentParameterName) {
10572
+ return "".concat(parameterNameToTaskName(dependentParameterName), "--\"{").concat(dependentParameterName, "}\"-->").concat(parameterNameToTaskName(resultingParameterName));
10573
+ })), false);
10574
+ })
10575
+ .join('\n')), "\n\n ").concat(block(pipelineJson.parameters
10576
+ .filter(function (_a) {
10577
+ var isOutput = _a.isOutput;
10578
+ return isOutput;
10579
+ })
10580
+ .map(function (_a) {
10581
+ var name = _a.name;
10582
+ return "".concat(parameterNameToTaskName(name), "--\"{").concat(name, "}\"-->output");
10583
+ })
10584
+ .join('\n')), "\n output((Output)):::output\n\n ").concat(block(pipelineJson.tasks
10585
+ .map(function (task) {
10586
+ var link = linkTask(task);
10587
+ if (link === null) {
10588
+ return '';
10589
+ }
10590
+ var href = link.href, title = link.title;
10591
+ var taskName = parameterNameToTaskName(task.resultingParameterName);
10592
+ return "click ".concat(taskName, " href \"").concat(href, "\" \"").concat(title, "\";");
10593
+ })
10594
+ .filter(function (line) { return line !== ''; })
10595
+ .join('\n')), "\n\n classDef input color: grey;\n classDef output color: grey;\n\n end;\n\n "); });
10596
+ return promptbookMermaid;
10365
10597
  }
10598
+ /**
10599
+ * TODO: [🧠] !! FOREACH in mermaid graph
10600
+ * TODO: [🧠] !! Knowledge in mermaid graph
10601
+ * TODO: [🧠] !! Personas in mermaid graph
10602
+ * TODO: Maybe use some Mermaid package instead of string templating
10603
+ * TODO: [🕌] When more than 2 functionalities, split into separate functions
10604
+ */
10366
10605
 
10367
10606
  /**
10368
- * Makes first letter of a string uppercase
10607
+ * Detects if the code is running in a browser environment in main thread (Not in a web worker)
10608
+ *
10609
+ * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
10369
10610
  *
10370
10611
  * @public exported from `@promptbook/utils`
10371
10612
  */
10372
- function decapitalize(word) {
10373
- return word.substring(0, 1).toLowerCase() + word.substring(1);
10374
- }
10613
+ var $isRunningInBrowser = new Function("\n try {\n return this === window;\n } catch (e) {\n return false;\n }\n");
10375
10614
 
10376
10615
  /**
10377
- * @@@
10616
+ * Detects if the code is running in jest environment
10617
+ *
10618
+ * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
10378
10619
  *
10379
- * @param name @@@
10380
- * @returns @@@
10381
- * @example @@@
10382
10620
  * @public exported from `@promptbook/utils`
10383
10621
  */
10384
- function nameToUriPart(name) {
10385
- var uriPart = name;
10386
- uriPart = uriPart.toLowerCase();
10387
- uriPart = removeDiacritics(uriPart);
10388
- uriPart = uriPart.replace(/[^a-zA-Z0-9]+/g, '-');
10389
- uriPart = uriPart.replace(/^-+/, '');
10390
- uriPart = uriPart.replace(/-+$/, '');
10391
- return uriPart;
10392
- }
10622
+ var $isRunningInJest = new Function("\n try {\n return process.env.JEST_WORKER_ID !== undefined;\n } catch (e) {\n return false;\n }\n");
10393
10623
 
10394
10624
  /**
10395
- * @@@
10625
+ * Detects if the code is running in a web worker
10626
+ *
10627
+ * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
10628
+ *
10629
+ * @public exported from `@promptbook/utils`
10630
+ */
10631
+ var $isRunningInWebWorker = new Function("\n try {\n if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {\n return true;\n } else {\n return false;\n }\n } catch (e) {\n return false;\n }\n");
10632
+
10633
+ /**
10634
+ * Makes first letter of a string uppercase
10635
+ *
10636
+ * @public exported from `@promptbook/utils`
10637
+ */
10638
+ function decapitalize(word) {
10639
+ return word.substring(0, 1).toLowerCase() + word.substring(1);
10640
+ }
10641
+
10642
+ /**
10643
+ * Parses keywords from a string
10644
+ *
10645
+ * @param {string} input
10646
+ * @returns {Set} of keywords without diacritics in lowercase
10647
+ * @public exported from `@promptbook/utils`
10648
+ */
10649
+ function parseKeywordsFromString(input) {
10650
+ var keywords = normalizeTo_SCREAMING_CASE(removeDiacritics(input))
10651
+ .toLowerCase()
10652
+ .split(/[^a-z0-9]+/gs)
10653
+ .filter(function (value) { return value; });
10654
+ return new Set(keywords);
10655
+ }
10656
+
10657
+ /**
10658
+ * @@@
10659
+ *
10660
+ * @param name @@@
10661
+ * @returns @@@
10662
+ * @example @@@
10663
+ * @public exported from `@promptbook/utils`
10664
+ */
10665
+ function nameToUriPart(name) {
10666
+ var uriPart = name;
10667
+ uriPart = uriPart.toLowerCase();
10668
+ uriPart = removeDiacritics(uriPart);
10669
+ uriPart = uriPart.replace(/[^a-zA-Z0-9]+/g, '-');
10670
+ uriPart = uriPart.replace(/^-+/, '');
10671
+ uriPart = uriPart.replace(/-+$/, '');
10672
+ return uriPart;
10673
+ }
10674
+
10675
+ /**
10676
+ * @@@
10396
10677
  *
10397
10678
  * @param name @@@
10398
10679
  * @returns @@@
@@ -10426,21 +10707,6 @@ function normalizeWhitespaces(sentence) {
10426
10707
  return sentence.replace(/\s+/gs, ' ').trim();
10427
10708
  }
10428
10709
 
10429
- /**
10430
- * Parses keywords from a string
10431
- *
10432
- * @param {string} input
10433
- * @returns {Set} of keywords without diacritics in lowercase
10434
- * @public exported from `@promptbook/utils`
10435
- */
10436
- function parseKeywordsFromString(input) {
10437
- var keywords = normalizeTo_SCREAMING_CASE(removeDiacritics(input))
10438
- .toLowerCase()
10439
- .split(/[^a-z0-9]+/gs)
10440
- .filter(function (value) { return value; });
10441
- return new Set(keywords);
10442
- }
10443
-
10444
10710
  /**
10445
10711
  * Function trimCodeBlock will trim starting and ending code block from the string if it is present.
10446
10712
  *
@@ -10547,6 +10813,44 @@ function unwrapResult(text, options) {
10547
10813
  * TODO: [🧠] Should this also unwrap the (parenthesis)
10548
10814
  */
10549
10815
 
10816
+ /**
10817
+ * Determines if the given path is a root path.
10818
+ *
10819
+ * Note: This does not check if the file exists only if the path is valid
10820
+ * @public exported from `@promptbook/utils`
10821
+ */
10822
+ function isPathRoot(value) {
10823
+ if (value === '/') {
10824
+ return true;
10825
+ }
10826
+ if (/^[A-Z]:\\$/i.test(value)) {
10827
+ return true;
10828
+ }
10829
+ return false;
10830
+ }
10831
+ /**
10832
+ * TODO: [🍏] Make for MacOS paths
10833
+ */
10834
+
10835
+ /**
10836
+ * Extracts code block from markdown.
10837
+ *
10838
+ * - When there are multiple or no code blocks the function throws a `ParseError`
10839
+ *
10840
+ * Note: There are multiple simmilar function:
10841
+ * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
10842
+ * - `extractJsonBlock` extracts exactly one valid JSON code block
10843
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
10844
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
10845
+ *
10846
+ * @public exported from `@promptbook/markdown-utils`
10847
+ * @throws {ParseError} if there is not exactly one code block in the markdown
10848
+ */
10849
+ function extractBlock(markdown) {
10850
+ var content = extractOneBlockFromMarkdown(markdown).content;
10851
+ return content;
10852
+ }
10853
+
10550
10854
  /**
10551
10855
  * Does nothing, but preserves the function in the bundle
10552
10856
  * Compiler is tricked into thinking the function is used
@@ -10581,37 +10885,10 @@ function preserve(func) {
10581
10885
  }); })();
10582
10886
  }
10583
10887
  /**
10888
+ * TODO: Probbably remove in favour of `keepImported`
10584
10889
  * TODO: !! [1] This maybe does memory leak
10585
10890
  */
10586
10891
 
10587
- /**
10588
- * Converts anything to string that can be used for debugging and logging
10589
- *
10590
- * @param value String value for logging
10591
- * @private internal util
10592
- */
10593
- function unknownToString(value) {
10594
- if (value === undefined) {
10595
- return 'undefined';
10596
- }
10597
- else if (value === null) {
10598
- return 'null';
10599
- }
10600
- else if (['number', 'string', 'boolean'].includes(typeof value)) {
10601
- return typeof value + ' ' + value.toString();
10602
- }
10603
- else if (typeof value === 'object' && Array.isArray(value)) {
10604
- return 'array containing [' + value.map(function (item) { return unknownToString(item); }).join(', ') + ']';
10605
- }
10606
- else if (typeof value === 'object') {
10607
- // TODO: Maybe serialize the object
10608
- return 'object';
10609
- }
10610
- else {
10611
- return 'unknown (Search in promptbook code for [🔹])';
10612
- }
10613
- }
10614
-
10615
10892
  /**
10616
10893
  * ScriptExecutionTools for JavaScript implemented via eval
10617
10894
  *
@@ -10741,7 +11018,7 @@ var JavascriptEvalExecutionTools = /** @class */ (function () {
10741
11018
  case 2:
10742
11019
  result = _a.sent();
10743
11020
  if (typeof result !== 'string') {
10744
- throw new PipelineExecutionError("Script must return a string, but returned ".concat(unknownToString(result)));
11021
+ throw new PipelineExecutionError("Script must return a string, but returned ".concat(valueToString(result)));
10745
11022
  }
10746
11023
  return [3 /*break*/, 4];
10747
11024
  case 3:
@@ -10768,7 +11045,7 @@ var JavascriptEvalExecutionTools = /** @class */ (function () {
10768
11045
  throw error_1;
10769
11046
  case 4:
10770
11047
  if (typeof result !== 'string') {
10771
- throw new PipelineExecutionError("Script must return a string, but ".concat(unknownToString(result)));
11048
+ throw new PipelineExecutionError("Script must return a string, but ".concat(valueToString(result)));
10772
11049
  }
10773
11050
  return [2 /*return*/, result];
10774
11051
  }
@@ -11041,7 +11318,7 @@ function createCollectionFromPromise(promptbookSourcesPromiseOrFactory) {
11041
11318
  */
11042
11319
  function createCollectionFromDirectory(path, tools, options) {
11043
11320
  return __awaiter(this, void 0, void 0, function () {
11044
- var makedLibraryFilePath, _a, _b, isRecursive, _c, isVerbose, _d, isLazyLoaded, _e, isCrashedOnError, collection;
11321
+ var madeLibraryFilePath, _a, _b, isRecursive, _c, isVerbose, _d, isLazyLoaded, _e, isCrashedOnError, collection;
11045
11322
  var _this = this;
11046
11323
  return __generator(this, function (_f) {
11047
11324
  switch (_f.label) {
@@ -11056,16 +11333,14 @@ function createCollectionFromDirectory(path, tools, options) {
11056
11333
  throw new EnvironmentMismatchError('Can not create collection without filesystem tools');
11057
11334
  // <- TODO: [🧠] What is the best error type here`
11058
11335
  }
11059
- makedLibraryFilePath = join(path, "".concat(DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME
11336
+ madeLibraryFilePath = join(path, "".concat(DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME
11060
11337
  // <- TODO: [🦒] Allow to override (pass different value into the function)
11061
11338
  , ".json"));
11062
- return [4 /*yield*/, isFileExisting(makedLibraryFilePath, tools.fs)];
11339
+ return [4 /*yield*/, isFileExisting(madeLibraryFilePath, tools.fs)];
11063
11340
  case 3:
11064
- if (!(_f.sent())) {
11065
- console.info(colors.yellow("Tip: Prebuild your pipeline collection (file with supposed prebuild ".concat(makedLibraryFilePath, " not found) with CLI util \"ptbk make\" to speed up the collection creation.")));
11066
- }
11341
+ if (!(_f.sent())) ;
11067
11342
  else {
11068
- colors.green("(In future, not implemented yet) Using your prebuild pipeline collection ".concat(makedLibraryFilePath));
11343
+ colors.green("(In future, not implemented yet) Using your compiled pipeline collection ".concat(madeLibraryFilePath));
11069
11344
  // TODO: !! Implement;
11070
11345
  // TODO: [🌗]
11071
11346
  }
@@ -11085,10 +11360,10 @@ function createCollectionFromDirectory(path, tools, options) {
11085
11360
  // Note: First load all .book.json and then .book.md files
11086
11361
  // .book.json can be prepared so it is faster to load
11087
11362
  fileNames.sort(function (a, b) {
11088
- if (a.endsWith('.book.json') && b.endsWith('.book.md')) {
11363
+ if (a.endsWith('.json') && b.endsWith('.md')) {
11089
11364
  return -1;
11090
11365
  }
11091
- if (a.endsWith('.book.md') && b.endsWith('.book.json')) {
11366
+ if (a.endsWith('.md') && b.endsWith('.json')) {
11092
11367
  return 1;
11093
11368
  }
11094
11369
  return 0;
@@ -11137,7 +11412,7 @@ function createCollectionFromDirectory(path, tools, options) {
11137
11412
  // TODO: [👠] DRY
11138
11413
  if (pipeline.pipelineUrl === undefined) {
11139
11414
  if (isVerbose) {
11140
- console.info(colors.red("Can not load pipeline from ".concat(fileName
11415
+ console.info(colors.yellow("Can not load pipeline from ".concat(fileName
11141
11416
  .split('\\')
11142
11417
  .join('/'), " because of missing URL")));
11143
11418
  }
@@ -11315,16 +11590,21 @@ function initializeMakeCommand(program) {
11315
11590
  makeCommand.option('--validation', "Types of validations separated by comma (options \"logic\",\"imports\")", 'logic,imports');
11316
11591
  makeCommand.option('-r, --reload', "Call LLM models even if same prompt with result is in the cache", false);
11317
11592
  makeCommand.option('-v, --verbose', "Is output verbose", false);
11318
- makeCommand.option('-o, --out-file <path>', spaceTrim("\n Where to save the builded collection\n\n Note: If you keep it \"".concat(DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME, "\" it will be saved in the root of the promptbook directory\n If you set it to a path, it will be saved in that path\n BUT you can use only one format and set correct extension\n ")), DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME);
11593
+ makeCommand.option('-o, --output <path>', spaceTrim("\n Where to save the builded collection\n\n Note: If you keep it \"".concat(DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME, "\" it will be saved in the root of the promptbook directory\n If you set it to a path, it will be saved in that path\n BUT you can use only one format and set correct extension\n ")), DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME);
11594
+ makeCommand.option('-fn, --function-name <functionName>', spaceTrim("\n Name of the function to get pipeline collection\n\n Note: This can be used only with \"javascript\" or \"typescript\" format\n\n "), DEFAULT_GET_PIPELINE_COLLECTION_FUNCTION_NAME);
11319
11595
  makeCommand.action(function (path, _a) {
11320
- var projectName = _a.projectName, format = _a.format, validation = _a.validation, isCacheReloaded = _a.reload, isVerbose = _a.verbose, outFile = _a.outFile;
11596
+ var projectName = _a.projectName, format = _a.format, functionName = _a.functionName, validation = _a.validation, isCacheReloaded = _a.reload, isVerbose = _a.verbose, output = _a.output;
11321
11597
  return __awaiter(_this, void 0, void 0, function () {
11322
- var formats, validations, prepareAndScrapeOptions, fs, llm, executables, tools, collection, validations_1, validations_1_1, validation_1, _b, _c, pipelineUrl, pipeline, e_1_1, e_2_1, collectionJson, collectionJsonString, collectionJsonItems, saveFile;
11323
- var _d, e_2, _e, e_1, _f;
11598
+ var formats, validations, prepareAndScrapeOptions, fs, llm, executables, tools, collection, pipelinesUrls, validations_1, validations_1_1, validation_1, pipelinesUrls_1, pipelinesUrls_1_1, pipelineUrl, pipeline, e_1_1, e_2_1, collectionJson, collectionJsonString, collectionJsonItems, saveFile;
11599
+ var _b, e_2, _c, e_1, _d;
11324
11600
  var _this = this;
11325
- return __generator(this, function (_g) {
11326
- switch (_g.label) {
11601
+ return __generator(this, function (_e) {
11602
+ switch (_e.label) {
11327
11603
  case 0:
11604
+ if (!isValidJavascriptName(functionName)) {
11605
+ console.error(colors.red("Function name \"".concat(functionName, "\" is not valid javascript name")));
11606
+ return [2 /*return*/, process.exit(1)];
11607
+ }
11328
11608
  formats = (format || '')
11329
11609
  .split(',')
11330
11610
  .map(function (_) { return _.trim(); })
@@ -11333,7 +11613,7 @@ function initializeMakeCommand(program) {
11333
11613
  .split(',')
11334
11614
  .map(function (_) { return _.trim(); })
11335
11615
  .filter(function (_) { return _ !== ''; });
11336
- if (outFile !== DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME && formats.length !== 1) {
11616
+ if (output !== DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME && formats.length !== 1) {
11337
11617
  console.error(colors.red("You can only use one format if you specify --out-file"));
11338
11618
  return [2 /*return*/, process.exit(1)];
11339
11619
  }
@@ -11342,88 +11622,92 @@ function initializeMakeCommand(program) {
11342
11622
  isCacheReloaded: isCacheReloaded,
11343
11623
  };
11344
11624
  fs = $provideFilesystemForNode(prepareAndScrapeOptions);
11345
- llm = $provideLlmToolsForCli(prepareAndScrapeOptions);
11625
+ llm = $provideLlmToolsForWizzardOrCli(prepareAndScrapeOptions);
11346
11626
  return [4 /*yield*/, $provideExecutablesForNode(prepareAndScrapeOptions)];
11347
11627
  case 1:
11348
- executables = _g.sent();
11349
- _d = {
11628
+ executables = _e.sent();
11629
+ _b = {
11350
11630
  llm: llm,
11351
11631
  fs: fs
11352
11632
  };
11353
11633
  return [4 /*yield*/, $provideScrapersForNode({ fs: fs, llm: llm, executables: executables }, prepareAndScrapeOptions)];
11354
11634
  case 2:
11355
- tools = (_d.scrapers = _g.sent(),
11356
- _d.script = [
11635
+ tools = (_b.scrapers = _e.sent(),
11636
+ _b.script = [
11357
11637
  /*new JavascriptExecutionTools(options)*/
11358
11638
  ],
11359
- _d);
11639
+ _b);
11360
11640
  return [4 /*yield*/, createCollectionFromDirectory(path, tools, {
11361
11641
  isVerbose: isVerbose,
11362
11642
  isRecursive: true,
11363
11643
  // <- TODO: [🍖] Add `intermediateFilesStrategy`
11364
11644
  })];
11365
11645
  case 3:
11366
- collection = _g.sent();
11367
- _g.label = 4;
11646
+ collection = _e.sent();
11647
+ return [4 /*yield*/, collection.listPipelines()];
11368
11648
  case 4:
11369
- _g.trys.push([4, 16, 17, 18]);
11370
- validations_1 = __values(validations), validations_1_1 = validations_1.next();
11371
- _g.label = 5;
11649
+ pipelinesUrls = _e.sent();
11650
+ if (pipelinesUrls.length === 0) {
11651
+ console.error(colors.red("No books found in \"".concat(path, "\"")));
11652
+ return [2 /*return*/, process.exit(1)];
11653
+ }
11654
+ _e.label = 5;
11372
11655
  case 5:
11656
+ _e.trys.push([5, 16, 17, 18]);
11657
+ validations_1 = __values(validations), validations_1_1 = validations_1.next();
11658
+ _e.label = 6;
11659
+ case 6:
11373
11660
  if (!!validations_1_1.done) return [3 /*break*/, 15];
11374
11661
  validation_1 = validations_1_1.value;
11375
- _g.label = 6;
11376
- case 6:
11377
- _g.trys.push([6, 12, 13, 14]);
11378
- e_1 = void 0;
11379
- return [4 /*yield*/, collection.listPipelines()];
11662
+ _e.label = 7;
11380
11663
  case 7:
11381
- _b = (__values.apply(void 0, [_g.sent()])), _c = _b.next();
11382
- _g.label = 8;
11664
+ _e.trys.push([7, 12, 13, 14]);
11665
+ pipelinesUrls_1 = (e_1 = void 0, __values(pipelinesUrls)), pipelinesUrls_1_1 = pipelinesUrls_1.next();
11666
+ _e.label = 8;
11383
11667
  case 8:
11384
- if (!!_c.done) return [3 /*break*/, 11];
11385
- pipelineUrl = _c.value;
11668
+ if (!!pipelinesUrls_1_1.done) return [3 /*break*/, 11];
11669
+ pipelineUrl = pipelinesUrls_1_1.value;
11386
11670
  return [4 /*yield*/, collection.getPipelineByUrl(pipelineUrl)];
11387
11671
  case 9:
11388
- pipeline = _g.sent();
11672
+ pipeline = _e.sent();
11389
11673
  if (validation_1 === 'logic') {
11390
11674
  validatePipeline(pipeline);
11391
11675
  if (isVerbose) {
11392
11676
  console.info(colors.cyan("Validated logic of ".concat(pipeline.pipelineUrl)));
11393
11677
  }
11394
11678
  }
11395
- _g.label = 10;
11679
+ _e.label = 10;
11396
11680
  case 10:
11397
- _c = _b.next();
11681
+ pipelinesUrls_1_1 = pipelinesUrls_1.next();
11398
11682
  return [3 /*break*/, 8];
11399
11683
  case 11: return [3 /*break*/, 14];
11400
11684
  case 12:
11401
- e_1_1 = _g.sent();
11685
+ e_1_1 = _e.sent();
11402
11686
  e_1 = { error: e_1_1 };
11403
11687
  return [3 /*break*/, 14];
11404
11688
  case 13:
11405
11689
  try {
11406
- if (_c && !_c.done && (_f = _b.return)) _f.call(_b);
11690
+ if (pipelinesUrls_1_1 && !pipelinesUrls_1_1.done && (_d = pipelinesUrls_1.return)) _d.call(pipelinesUrls_1);
11407
11691
  }
11408
11692
  finally { if (e_1) throw e_1.error; }
11409
11693
  return [7 /*endfinally*/];
11410
11694
  case 14:
11411
11695
  validations_1_1 = validations_1.next();
11412
- return [3 /*break*/, 5];
11696
+ return [3 /*break*/, 6];
11413
11697
  case 15: return [3 /*break*/, 18];
11414
11698
  case 16:
11415
- e_2_1 = _g.sent();
11699
+ e_2_1 = _e.sent();
11416
11700
  e_2 = { error: e_2_1 };
11417
11701
  return [3 /*break*/, 18];
11418
11702
  case 17:
11419
11703
  try {
11420
- if (validations_1_1 && !validations_1_1.done && (_e = validations_1.return)) _e.call(validations_1);
11704
+ if (validations_1_1 && !validations_1_1.done && (_c = validations_1.return)) _c.call(validations_1);
11421
11705
  }
11422
11706
  finally { if (e_2) throw e_2.error; }
11423
11707
  return [7 /*endfinally*/];
11424
11708
  case 18: return [4 /*yield*/, collectionToJson(collection)];
11425
11709
  case 19:
11426
- collectionJson = _g.sent();
11710
+ collectionJson = _e.sent();
11427
11711
  collectionJsonString = stringifyPipelineJson(collectionJson).trim();
11428
11712
  collectionJsonItems = (function () {
11429
11713
  var firstChar = collectionJsonString.charAt(0);
@@ -11441,10 +11725,10 @@ function initializeMakeCommand(program) {
11441
11725
  return __generator(this, function (_a) {
11442
11726
  switch (_a.label) {
11443
11727
  case 0:
11444
- filename = outFile !== DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME
11445
- ? outFile
11728
+ filename = output !== DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME
11729
+ ? output
11446
11730
  : join(path, "".concat(DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME, ".").concat(extension));
11447
- if (!outFile.endsWith(".".concat(extension))) {
11731
+ if (!output.endsWith(".".concat(extension))) {
11448
11732
  console.warn(colors.yellow("Warning: Extension of output file should be \"".concat(extension, "\"")));
11449
11733
  }
11450
11734
  return [4 /*yield*/, mkdir(dirname(filename), { recursive: true })];
@@ -11454,7 +11738,7 @@ function initializeMakeCommand(program) {
11454
11738
  case 2:
11455
11739
  _a.sent();
11456
11740
  // Note: Log despite of verbose mode
11457
- console.info(colors.green("Maked ".concat(filename.split('\\').join('/'))));
11741
+ console.info(colors.green("Made ".concat(filename.split('\\').join('/'))));
11458
11742
  return [2 /*return*/];
11459
11743
  }
11460
11744
  });
@@ -11463,22 +11747,22 @@ function initializeMakeCommand(program) {
11463
11747
  formats = formats.filter(function (format) { return format !== 'json'; });
11464
11748
  return [4 /*yield*/, saveFile('json', collectionJsonString)];
11465
11749
  case 20:
11466
- _g.sent();
11467
- _g.label = 21;
11750
+ _e.sent();
11751
+ _e.label = 21;
11468
11752
  case 21:
11469
11753
  if (!(formats.includes('javascript') || formats.includes('js'))) return [3 /*break*/, 23];
11470
11754
  formats = formats.filter(function (format) { return format !== 'javascript' && format !== 'js'; });
11471
- return [4 /*yield*/, saveFile('js', spaceTrim(function (block) { return "\n // ".concat(block(GENERATOR_WARNING_BY_PROMPTBOOK_CLI), "\n\n import { createCollectionFromJson } from '@promptbook/core';\n\n /**\n * Pipeline collection for ").concat(projectName, "\n *\n * ").concat(block(GENERATOR_WARNING_BY_PROMPTBOOK_CLI), "\n *\n * @private internal cache for `getPipelineCollection`\n */\n let pipelineCollection = null;\n\n\n /**\n * Get pipeline collection for ").concat(projectName, "\n *\n * ").concat(block(GENERATOR_WARNING_BY_PROMPTBOOK_CLI), "\n *\n * @returns {PipelineCollection} Library of promptbooks for ").concat(projectName, "\n */\n export function getPipelineCollection(){\n if(pipelineCollection===null){\n pipelineCollection = createCollectionFromJson(\n ").concat(block(collectionJsonItems), "\n );\n }\n\n return pipelineCollection;\n }\n "); }))];
11755
+ return [4 /*yield*/, saveFile('js', spaceTrim(function (block) { return "\n // ".concat(block(GENERATOR_WARNING_BY_PROMPTBOOK_CLI), "\n\n import { createCollectionFromJson } from '@promptbook/core';\n\n /**\n * Pipeline collection for ").concat(projectName, "\n *\n * ").concat(block(GENERATOR_WARNING_BY_PROMPTBOOK_CLI), "\n *\n * @generated\n * @private internal cache for `").concat(functionName, "`\n */\n let pipelineCollection = null;\n\n\n /**\n * Get pipeline collection for ").concat(projectName, "\n *\n * ").concat(block(GENERATOR_WARNING_BY_PROMPTBOOK_CLI), "\n *\n * @generated\n * @returns {PipelineCollection} Library of promptbooks for ").concat(projectName, "\n */\n export function ").concat(functionName, "(){\n if(pipelineCollection===null){\n pipelineCollection = createCollectionFromJson(\n ").concat(block(collectionJsonItems), "\n );\n }\n\n return pipelineCollection;\n }\n "); }))];
11472
11756
  case 22:
11473
- (_g.sent()) + '\n';
11474
- _g.label = 23;
11757
+ (_e.sent()) + '\n';
11758
+ _e.label = 23;
11475
11759
  case 23:
11476
11760
  if (!(formats.includes('typescript') || formats.includes('ts'))) return [3 /*break*/, 25];
11477
11761
  formats = formats.filter(function (format) { return format !== 'typescript' && format !== 'ts'; });
11478
- return [4 /*yield*/, saveFile('ts', spaceTrim(function (block) { return "\n // ".concat(block(GENERATOR_WARNING_BY_PROMPTBOOK_CLI), "\n\n import { createCollectionFromJson } from '@promptbook/core';\n import type { PipelineCollection } from '@promptbook/types';\n\n /**\n * Pipeline collection for ").concat(projectName, "\n *\n * ").concat(block(GENERATOR_WARNING_BY_PROMPTBOOK_CLI), "\n *\n * @private internal cache for `getPipelineCollection`\n */\n let pipelineCollection: null | PipelineCollection = null;\n\n\n /**\n * Get pipeline collection for ").concat(projectName, "\n *\n * ").concat(block(GENERATOR_WARNING_BY_PROMPTBOOK_CLI), "\n *\n * @returns {PipelineCollection} Library of promptbooks for ").concat(projectName, "\n */\n export function getPipelineCollection(): PipelineCollection{\n if(pipelineCollection===null){\n pipelineCollection = createCollectionFromJson(\n ").concat(block(collectionJsonItems), "\n );\n }\n\n return pipelineCollection;\n }\n "); }) + '\n')];
11762
+ return [4 /*yield*/, saveFile('ts', spaceTrim(function (block) { return "\n // ".concat(block(GENERATOR_WARNING_BY_PROMPTBOOK_CLI), "\n\n import { createCollectionFromJson } from '@promptbook/core';\n import type { PipelineCollection } from '@promptbook/types';\n\n /**\n * Pipeline collection for ").concat(projectName, "\n *\n * ").concat(block(GENERATOR_WARNING_BY_PROMPTBOOK_CLI), "\n *\n * @private internal cache for `").concat(functionName, "`\n * @generated\n */\n let pipelineCollection: null | PipelineCollection = null;\n\n\n /**\n * Get pipeline collection for ").concat(projectName, "\n *\n * ").concat(block(GENERATOR_WARNING_BY_PROMPTBOOK_CLI), "\n *\n * @generated\n * @returns {PipelineCollection} Library of promptbooks for ").concat(projectName, "\n */\n export function ").concat(functionName, "(): PipelineCollection{\n if(pipelineCollection===null){\n\n // TODO: !!!!!! Use book string literal notation\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n pipelineCollection = (createCollectionFromJson as (..._: any) => PipelineCollection)(\n ").concat(block(collectionJsonItems), "\n );\n }\n\n return pipelineCollection;\n }\n "); }) + '\n')];
11479
11763
  case 24:
11480
- _g.sent();
11481
- _g.label = 25;
11764
+ _e.sent();
11765
+ _e.label = 25;
11482
11766
  case 25:
11483
11767
  if (formats.length > 0) {
11484
11768
  console.warn(colors.yellow("Format ".concat(formats.join(' and '), " is not supported")));
@@ -11529,70 +11813,6 @@ function addAutoGeneratedSection(content, options) {
11529
11813
  * TODO: [🏛] This can be part of markdown builder
11530
11814
  */
11531
11815
 
11532
- /**
11533
- * Creates a Mermaid graph based on the promptbook
11534
- *
11535
- * Note: The result is not wrapped in a Markdown code block
11536
- *
11537
- * @public exported from `@promptbook/utils`
11538
- */
11539
- function renderPromptbookMermaid(pipelineJson, options) {
11540
- var _a = (options || {}).linkTask, linkTask = _a === void 0 ? function () { return null; } : _a;
11541
- var parameterNameToTaskName = function (parameterName) {
11542
- var parameter = pipelineJson.parameters.find(function (parameter) { return parameter.name === parameterName; });
11543
- if (!parameter) {
11544
- throw new UnexpectedError("Could not find {".concat(parameterName, "}"));
11545
- // <- TODO: !!!!!! This causes problems when {knowledge} and other reserved parameters are used
11546
- }
11547
- if (parameter.isInput) {
11548
- return 'input';
11549
- }
11550
- var task = pipelineJson.tasks.find(function (task) { return task.resultingParameterName === parameterName; });
11551
- if (!task) {
11552
- throw new Error("Could not find task for {".concat(parameterName, "}"));
11553
- }
11554
- return task.name || normalizeTo_camelCase('task-' + titleToName(task.title));
11555
- };
11556
- var promptbookMermaid = spaceTrim$1(function (block) { return "\n\n %% \uD83D\uDD2E Tip: Open this on GitHub or in the VSCode website to see the Mermaid graph visually\n\n flowchart LR\n subgraph \"".concat(pipelineJson.title, "\"\n\n direction TB\n\n input((Input)):::input\n ").concat(block(pipelineJson.tasks
11557
- .flatMap(function (_a) {
11558
- var title = _a.title, dependentParameterNames = _a.dependentParameterNames, resultingParameterName = _a.resultingParameterName;
11559
- return __spreadArray([
11560
- "".concat(parameterNameToTaskName(resultingParameterName), "(\"").concat(title, "\")")
11561
- ], __read(dependentParameterNames.map(function (dependentParameterName) {
11562
- return "".concat(parameterNameToTaskName(dependentParameterName), "--\"{").concat(dependentParameterName, "}\"-->").concat(parameterNameToTaskName(resultingParameterName));
11563
- })), false);
11564
- })
11565
- .join('\n')), "\n\n ").concat(block(pipelineJson.parameters
11566
- .filter(function (_a) {
11567
- var isOutput = _a.isOutput;
11568
- return isOutput;
11569
- })
11570
- .map(function (_a) {
11571
- var name = _a.name;
11572
- return "".concat(parameterNameToTaskName(name), "--\"{").concat(name, "}\"-->output");
11573
- })
11574
- .join('\n')), "\n output((Output)):::output\n\n ").concat(block(pipelineJson.tasks
11575
- .map(function (task) {
11576
- var link = linkTask(task);
11577
- if (link === null) {
11578
- return '';
11579
- }
11580
- var href = link.href, title = link.title;
11581
- var taskName = parameterNameToTaskName(task.resultingParameterName);
11582
- return "click ".concat(taskName, " href \"").concat(href, "\" \"").concat(title, "\";");
11583
- })
11584
- .filter(function (line) { return line !== ''; })
11585
- .join('\n')), "\n\n classDef input color: grey;\n classDef output color: grey;\n\n end;\n\n "); });
11586
- return promptbookMermaid;
11587
- }
11588
- /**
11589
- * TODO: [🧠] !! FOREACH in mermaid graph
11590
- * TODO: [🧠] !! Knowledge in mermaid graph
11591
- * TODO: [🧠] !! Personas in mermaid graph
11592
- * TODO: Maybe use some Mermaid package instead of string templating
11593
- * TODO: [🕌] When more than 2 functionalities, split into separate functions
11594
- */
11595
-
11596
11816
  /**
11597
11817
  * Prettyfies Promptbook string and adds Mermaid graph
11598
11818
  *
@@ -11728,26 +11948,6 @@ function initializePrettifyCommand(program) {
11728
11948
  * TODO: [🖇] What about symlinks? Maybe flag --follow-symlinks
11729
11949
  */
11730
11950
 
11731
- /**
11732
- * Format either small or big number
11733
- *
11734
- * @private within the repository
11735
- */
11736
- function formatNumber(value) {
11737
- if (value === 0) {
11738
- return '0';
11739
- }
11740
- for (var exponent = 0; exponent < 15; exponent++) {
11741
- var factor = Math.pow(10, exponent);
11742
- var valueRounded = Math.round(value * factor) / factor;
11743
- if (Math.abs(value - valueRounded) / value <
11744
- 0.001 /* <- TODO: Pass as option, pass to executionReportJsonToString as option */) {
11745
- return valueRounded.toFixed(exponent);
11746
- }
11747
- }
11748
- return value.toString();
11749
- }
11750
-
11751
11951
  /**
11752
11952
  * Create a markdown table from a 2D array of strings
11753
11953
  *
@@ -11807,7 +12007,7 @@ function createMarkdownChart(options) {
11807
12007
  }
11808
12008
  finally { if (e_1) throw e_1.error; }
11809
12009
  }
11810
- var legend = "_Note: Each \u2588 represents ".concat(formatNumber(1 / scale), " ").concat(unitName, ", width of ").concat(valueHeader.toLowerCase(), " is ").concat(formatNumber(to - from), " ").concat(unitName, " = ").concat(width, " squares_");
12010
+ var legend = "_Note: Each \u2588 represents ".concat(numberToString(1 / scale), " ").concat(unitName, ", width of ").concat(valueHeader.toLowerCase(), " is ").concat(numberToString(to - from), " ").concat(unitName, " = ").concat(width, " squares_");
11811
12011
  return createMarkdownTable(table) + '\n\n' + legend;
11812
12012
  }
11813
12013
  /**
@@ -11936,7 +12136,7 @@ function executionReportJsonToString(executionReportJson, options) {
11936
12136
  headerList.push("COMPLETED AT ".concat(moment(completedAt).format("YYYY-MM-DD HH:mm:ss")));
11937
12137
  headerList.push("TOTAL DURATION ".concat(duration.humanize(MOMENT_ARG_THRESHOLDS)));
11938
12138
  headerList.push("TOTAL LLM DURATION ".concat(llmDuration.humanize(MOMENT_ARG_THRESHOLDS)));
11939
- headerList.push("TOTAL COST $".concat(formatNumber(cost * (1 + taxRate))) +
12139
+ headerList.push("TOTAL COST $".concat(numberToString(cost * (1 + taxRate))) +
11940
12140
  (executionsWithKnownCost.length === executionReportJson.promptExecutions.length
11941
12141
  ? ''
11942
12142
  : " *(Some cost is unknown)*") +
@@ -11994,7 +12194,7 @@ function executionReportJsonToString(executionReportJson, options) {
11994
12194
  // > taskList.push(`STARTED AT ${moment(startedAt).calendar()}`);
11995
12195
  taskList.push("DURATION ".concat(duration.humanize(MOMENT_ARG_THRESHOLDS)));
11996
12196
  if (typeof ((_g = (_f = promptExecution.result) === null || _f === void 0 ? void 0 : _f.usage) === null || _g === void 0 ? void 0 : _g.price) === 'number') {
11997
- taskList.push("COST $".concat(formatNumber(promptExecution.result.usage.price * (1 + taxRate))) +
12197
+ taskList.push("COST $".concat(numberToString(promptExecution.result.usage.price * (1 + taxRate))) +
11998
12198
  (taxRate !== 0 ? " *(with tax ".concat(taxRate * 100, "%)*") : ''));
11999
12199
  }
12000
12200
  else {
@@ -12055,6 +12255,148 @@ function executionReportJsonToString(executionReportJson, options) {
12055
12255
  * TODO: [🧠] Should be in generated file GENERATOR_WARNING
12056
12256
  */
12057
12257
 
12258
+ /**
12259
+ * @see ./wizzard.ts `getPipeline` method
12260
+ *
12261
+ * @private usable through `ptbk run` and `@prompbook/wizzard`
12262
+ */
12263
+ function $getCompiledBook(tools, pipelineSource, options) {
12264
+ return __awaiter(this, void 0, void 0, function () {
12265
+ var fs, fetch, filePathRaw, filePath, filePathCandidates, filePathCandidates_1, filePathCandidates_1_1, filePathCandidate, pipelineString, pipelineJson, e_1_1, rootDirname, _loop_1, i, state_1, response_1, pipelineString, pipelineJson;
12266
+ var e_1, _a;
12267
+ var _this = this;
12268
+ return __generator(this, function (_b) {
12269
+ switch (_b.label) {
12270
+ case 0:
12271
+ fs = tools.fs, fetch = tools.fetch;
12272
+ if (!isValidFilePath(pipelineSource)) return [3 /*break*/, 10];
12273
+ filePathRaw = pipelineSource;
12274
+ filePath = null;
12275
+ filePathCandidates = [filePathRaw, "".concat(filePathRaw, ".md"), "".concat(filePathRaw, ".book.md"), "".concat(filePathRaw, ".book.md")];
12276
+ filePathCandidates = __spreadArray(__spreadArray([], __read(filePathCandidates), false), __read(filePathCandidates.map(function (path) { return path.split('\\').join('/'); })), false);
12277
+ _b.label = 1;
12278
+ case 1:
12279
+ _b.trys.push([1, 8, 9, 10]);
12280
+ filePathCandidates_1 = __values(filePathCandidates), filePathCandidates_1_1 = filePathCandidates_1.next();
12281
+ _b.label = 2;
12282
+ case 2:
12283
+ if (!!filePathCandidates_1_1.done) return [3 /*break*/, 7];
12284
+ filePathCandidate = filePathCandidates_1_1.value;
12285
+ return [4 /*yield*/, isFileExisting(filePathCandidate, fs)
12286
+ // <- TODO: Also test that among the candidates the file is book not just any file
12287
+ ];
12288
+ case 3:
12289
+ if (!_b.sent()) return [3 /*break*/, 6];
12290
+ filePath = filePathCandidate;
12291
+ return [4 /*yield*/, fs.readFile(filePath, 'utf-8')];
12292
+ case 4:
12293
+ pipelineString = (_b.sent());
12294
+ return [4 /*yield*/, compilePipeline(pipelineString, tools, __assign({ rootDirname: process.cwd() }, options))];
12295
+ case 5:
12296
+ pipelineJson = _b.sent();
12297
+ return [2 /*return*/, pipelineJson];
12298
+ case 6:
12299
+ filePathCandidates_1_1 = filePathCandidates_1.next();
12300
+ return [3 /*break*/, 2];
12301
+ case 7: return [3 /*break*/, 10];
12302
+ case 8:
12303
+ e_1_1 = _b.sent();
12304
+ e_1 = { error: e_1_1 };
12305
+ return [3 /*break*/, 10];
12306
+ case 9:
12307
+ try {
12308
+ if (filePathCandidates_1_1 && !filePathCandidates_1_1.done && (_a = filePathCandidates_1.return)) _a.call(filePathCandidates_1);
12309
+ }
12310
+ finally { if (e_1) throw e_1.error; }
12311
+ return [7 /*endfinally*/];
12312
+ case 10:
12313
+ if (!isValidPipelineUrl(pipelineSource)) return [3 /*break*/, 14];
12314
+ rootDirname = process.cwd();
12315
+ _loop_1 = function (i) {
12316
+ var collection, pipeline;
12317
+ return __generator(this, function (_c) {
12318
+ switch (_c.label) {
12319
+ case 0: return [4 /*yield*/, createCollectionFromDirectory('./books', tools, __assign({ isRecursive: true, rootDirname: rootDirname }, options))];
12320
+ case 1:
12321
+ collection = _c.sent();
12322
+ return [4 /*yield*/, (function () { return __awaiter(_this, void 0, void 0, function () {
12323
+ var error_1;
12324
+ return __generator(this, function (_a) {
12325
+ switch (_a.label) {
12326
+ case 0:
12327
+ _a.trys.push([0, 2, , 3]);
12328
+ return [4 /*yield*/, collection.getPipelineByUrl(pipelineSource)];
12329
+ case 1: return [2 /*return*/, _a.sent()];
12330
+ case 2:
12331
+ error_1 = _a.sent();
12332
+ if (!(error_1 instanceof NotFoundError)) {
12333
+ throw error_1;
12334
+ }
12335
+ // Note: If the pipeline was not found in the collection, try next strategy
12336
+ return [2 /*return*/, null];
12337
+ case 3: return [2 /*return*/];
12338
+ }
12339
+ });
12340
+ }); })()];
12341
+ case 2:
12342
+ pipeline = _c.sent();
12343
+ if (pipeline !== null) {
12344
+ return [2 /*return*/, { value: pipeline }];
12345
+ }
12346
+ // Note: searches recursivelly for books
12347
+ if (isPathRoot(rootDirname)) {
12348
+ return [2 /*return*/, "break"];
12349
+ }
12350
+ rootDirname = join(rootDirname, '..');
12351
+ return [2 /*return*/];
12352
+ }
12353
+ });
12354
+ };
12355
+ i = 0;
12356
+ _b.label = 11;
12357
+ case 11:
12358
+ if (!(i < LOOP_LIMIT)) return [3 /*break*/, 14];
12359
+ return [5 /*yield**/, _loop_1(i)];
12360
+ case 12:
12361
+ state_1 = _b.sent();
12362
+ if (typeof state_1 === "object")
12363
+ return [2 /*return*/, state_1.value];
12364
+ if (state_1 === "break")
12365
+ return [3 /*break*/, 14];
12366
+ _b.label = 13;
12367
+ case 13:
12368
+ i++;
12369
+ return [3 /*break*/, 11];
12370
+ case 14:
12371
+ if (!isValidPipelineUrl(pipelineSource)) return [3 /*break*/, 18];
12372
+ return [4 /*yield*/, fetch(pipelineSource)];
12373
+ case 15:
12374
+ response_1 = _b.sent();
12375
+ if (response_1.status >= 300) {
12376
+ throw new NotFoundError(spaceTrim(function (block) { return "\n No book found on URL:\n ".concat(block(pipelineSource), "\n\n Request failed with status ").concat(block(response_1.status.toString()), " ").concat(block(response_1.statusText), "\n "); }));
12377
+ }
12378
+ return [4 /*yield*/, response_1.text()];
12379
+ case 16:
12380
+ pipelineString = _b.sent();
12381
+ return [4 /*yield*/, compilePipeline(pipelineString /* <- TODO: !!!!!! Remove */, tools, __assign({ rootDirname: null }, options))];
12382
+ case 17:
12383
+ pipelineJson = _b.sent();
12384
+ return [2 /*return*/, pipelineJson];
12385
+ case 18:
12386
+ // Strategy 4️⃣: If the pipelineSource is a PipelineString - try to parse it
12387
+ if (just(false) /* <- TODO: !!!!!! Implement, use and export `isValidPipelineString` */) {
12388
+ throw new NotYetImplementedError('Strategy 4️⃣: If the pipelineSource is a PipelineString - try to parse it');
12389
+ } /* not else */
12390
+ throw new NotFoundError(spaceTrim(function (block) { return "\n No book found:\n ".concat(block(pipelineSource), "\n\n Pipelines can be loaded from:\n 1) As a file ./books/write-cv.book.md\n 2) As a URL https://promptbook.studio/hejny/write-cv.book.md found in ./books folder recursively\n 2) As a URL https://promptbook.studio/hejny/write-cv.book.md fetched from the internet\n 3) As a string\n\n\n "); }));
12391
+ }
12392
+ });
12393
+ });
12394
+ }
12395
+ /**
12396
+ * TODO: Write unit test
12397
+ * Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
12398
+ */
12399
+
12058
12400
  /**
12059
12401
  * Run the interactive chatbot in CLI
12060
12402
  *
@@ -12181,20 +12523,20 @@ function initializeRunCommand(program) {
12181
12523
  var runCommand = program.command('run', { isDefault: true });
12182
12524
  runCommand.description(spaceTrim("\n Runs a pipeline\n "));
12183
12525
  // TODO: [🧅] DRY command arguments
12184
- runCommand.argument('<path>',
12526
+ runCommand.argument('<pipelineSource>',
12185
12527
  // <- Note: [🧟‍♂️] This is NOT promptbook collection directory BUT direct path to .book.md file
12186
- 'Path to book file');
12528
+ 'Path to book file OR URL to book file');
12187
12529
  runCommand.option('-r, --reload', "Call LLM models even if same prompt with result is in the cache", false);
12188
12530
  runCommand.option('-v, --verbose', "Is output verbose", false);
12189
12531
  runCommand.option('--no-interactive', "Input is not interactive, if true you need to pass all the input parameters through --json");
12190
12532
  runCommand.option('--no-formfactor', "When set, behavior of the interactive mode is not changed by the formfactor of the pipeline");
12191
12533
  runCommand.option('-j, --json <json>', "Pass all or some input parameters as JSON record, if used the output is also returned as JSON");
12192
12534
  runCommand.option('-s, --save-report <path>', "Save report to file");
12193
- runCommand.action(function (filePathRaw, options) { return __awaiter(_this, void 0, void 0, function () {
12194
- var isCacheReloaded, isInteractive, isFormfactorUsed, json, isVerbose, saveReport, inputParameters, prepareAndScrapeOptions, fs, filePath, filePathCandidates, filePathCandidates_1, filePathCandidates_1_1, filePathCandidate, e_1_1, llm, executables, tools, pipelineString, pipeline, error_1, pipelineExecutor, questions, response, result, isSuccessful, errors, warnings, outputParameters, executionReport, executionReportString, _a, _b, error, _c, _d, warning, _e, _f, key, value, separator;
12195
- var e_1, _g, _h, e_2, _j, e_3, _k, e_4, _l;
12196
- return __generator(this, function (_m) {
12197
- switch (_m.label) {
12535
+ runCommand.action(function (pipelineSource, options) { return __awaiter(_this, void 0, void 0, function () {
12536
+ var isCacheReloaded, isInteractive, isFormfactorUsed, json, isVerbose, saveReport, inputParameters, prepareAndScrapeOptions, fs, llm, executables, tools, pipeline, error_1, pipelineExecutor, questions, response, result, isSuccessful, errors, warnings, outputParameters, executionReport, executionReportString, _a, _b, error, _c, _d, warning, _e, _f, key, value, separator;
12537
+ var _g, e_1, _h, e_2, _j, e_3, _k;
12538
+ return __generator(this, function (_l) {
12539
+ switch (_l.label) {
12198
12540
  case 0:
12199
12541
  isCacheReloaded = options.reload, isInteractive = options.interactive, isFormfactorUsed = options.formfactor, json = options.json, isVerbose = options.verbose, saveReport = options.saveReport;
12200
12542
  if (saveReport && !saveReport.endsWith('.json') && !saveReport.endsWith('.md')) {
@@ -12214,49 +12556,8 @@ function initializeRunCommand(program) {
12214
12556
  console.info(colors.gray('--- Preparing tools ---'));
12215
12557
  }
12216
12558
  fs = $provideFilesystemForNode(prepareAndScrapeOptions);
12217
- filePath = null;
12218
- filePathCandidates = [filePathRaw, "".concat(filePathRaw, ".md"), "".concat(filePathRaw, ".book.md"), "".concat(filePathRaw, ".book.md")];
12219
- filePathCandidates = __spreadArray(__spreadArray([], __read(filePathCandidates), false), __read(filePathCandidates.map(function (path) { return path.split('\\').join('/'); })), false);
12220
- _m.label = 1;
12221
- case 1:
12222
- _m.trys.push([1, 6, 7, 8]);
12223
- filePathCandidates_1 = __values(filePathCandidates), filePathCandidates_1_1 = filePathCandidates_1.next();
12224
- _m.label = 2;
12225
- case 2:
12226
- if (!!filePathCandidates_1_1.done) return [3 /*break*/, 5];
12227
- filePathCandidate = filePathCandidates_1_1.value;
12228
- return [4 /*yield*/, isFileExisting(filePathCandidate, fs)
12229
- // <- TODO: Also test that among the candidates the file is book not just any file
12230
- ];
12231
- case 3:
12232
- if (_m.sent()
12233
- // <- TODO: Also test that among the candidates the file is book not just any file
12234
- ) {
12235
- filePath = filePathCandidate;
12236
- return [3 /*break*/, 5];
12237
- }
12238
- _m.label = 4;
12239
- case 4:
12240
- filePathCandidates_1_1 = filePathCandidates_1.next();
12241
- return [3 /*break*/, 2];
12242
- case 5: return [3 /*break*/, 8];
12243
- case 6:
12244
- e_1_1 = _m.sent();
12245
- e_1 = { error: e_1_1 };
12246
- return [3 /*break*/, 8];
12247
- case 7:
12248
- try {
12249
- if (filePathCandidates_1_1 && !filePathCandidates_1_1.done && (_g = filePathCandidates_1.return)) _g.call(filePathCandidates_1);
12250
- }
12251
- finally { if (e_1) throw e_1.error; }
12252
- return [7 /*endfinally*/];
12253
- case 8:
12254
- if (filePath === null) {
12255
- console.error(colors.red("File \"".concat(filePathRaw, "\" does not exist")));
12256
- return [2 /*return*/, process.exit(1)];
12257
- }
12258
12559
  try {
12259
- llm = $provideLlmToolsForCli(prepareAndScrapeOptions);
12560
+ llm = $provideLlmToolsForWizzardOrCli(prepareAndScrapeOptions);
12260
12561
  }
12261
12562
  catch (error) {
12262
12563
  if (!(error instanceof Error)) {
@@ -12275,43 +12576,41 @@ function initializeRunCommand(program) {
12275
12576
  return [2 /*return*/, process.exit(1)];
12276
12577
  }
12277
12578
  return [4 /*yield*/, $provideExecutablesForNode(prepareAndScrapeOptions)];
12278
- case 9:
12279
- executables = _m.sent();
12280
- _h = {
12579
+ case 1:
12580
+ executables = _l.sent();
12581
+ _g = {
12281
12582
  llm: llm,
12282
- fs: fs
12583
+ fs: fs,
12584
+ fetch: scraperFetch
12283
12585
  };
12284
12586
  return [4 /*yield*/, $provideScrapersForNode({ fs: fs, llm: llm, executables: executables }, prepareAndScrapeOptions)];
12285
- case 10:
12286
- tools = (_h.scrapers = _m.sent(),
12287
- _h.script = [
12587
+ case 2:
12588
+ tools = (_g.scrapers = _l.sent(),
12589
+ _g.script = [
12288
12590
  /*new JavascriptExecutionTools(options)*/
12289
12591
  ],
12290
- _h);
12592
+ _g);
12291
12593
  if (isVerbose) {
12292
12594
  console.info(colors.gray('--- Reading file ---'));
12293
12595
  }
12294
- return [4 /*yield*/, readFile(filePath, 'utf-8')];
12295
- case 11:
12296
- pipelineString = (_m.sent());
12297
12596
  if (isVerbose) {
12298
12597
  console.info(colors.gray('--- Preparing pipeline ---'));
12299
12598
  }
12300
- _m.label = 12;
12301
- case 12:
12302
- _m.trys.push([12, 14, , 15]);
12303
- return [4 /*yield*/, compilePipeline(pipelineString, tools)];
12304
- case 13:
12305
- pipeline = _m.sent();
12306
- return [3 /*break*/, 15];
12307
- case 14:
12308
- error_1 = _m.sent();
12599
+ _l.label = 3;
12600
+ case 3:
12601
+ _l.trys.push([3, 5, , 6]);
12602
+ return [4 /*yield*/, $getCompiledBook(tools, pipelineSource, prepareAndScrapeOptions)];
12603
+ case 4:
12604
+ pipeline = _l.sent();
12605
+ return [3 /*break*/, 6];
12606
+ case 5:
12607
+ error_1 = _l.sent();
12309
12608
  if (!(error_1 instanceof ParseError)) {
12310
12609
  throw error_1;
12311
12610
  }
12312
- console.error(colors.red(spaceTrim(function (block) { return "\n ".concat(block(error_1.message), "\n\n in ").concat(filePath, "\n "); })));
12611
+ console.error(colors.red(spaceTrim(function (block) { return "\n ".concat(block(error_1.message), "\n\n in ").concat(pipelineSource, "\n "); })));
12313
12612
  return [2 /*return*/, process.exit(1)];
12314
- case 15:
12613
+ case 6:
12315
12614
  if (isVerbose) {
12316
12615
  console.info(colors.gray('--- Validating pipeline ---'));
12317
12616
  }
@@ -12397,8 +12696,8 @@ function initializeRunCommand(program) {
12397
12696
  return [2 /*return*/, process.exit(1)];
12398
12697
  }
12399
12698
  return [4 /*yield*/, prompts(questions)];
12400
- case 16:
12401
- response = _m.sent();
12699
+ case 7:
12700
+ response = _l.sent();
12402
12701
  // <- TODO: [🧠][🍼] Change behavior according to the formfactor
12403
12702
  inputParameters = __assign(__assign({}, inputParameters), response);
12404
12703
  // TODO: Maybe do some validation of the response (and --json argument which is passed)
@@ -12411,26 +12710,26 @@ function initializeRunCommand(program) {
12411
12710
  console.info(taskProgress);
12412
12711
  }
12413
12712
  })];
12414
- case 17:
12415
- result = _m.sent();
12713
+ case 8:
12714
+ result = _l.sent();
12416
12715
  isSuccessful = result.isSuccessful, errors = result.errors, warnings = result.warnings, outputParameters = result.outputParameters, executionReport = result.executionReport;
12417
12716
  if (isVerbose) {
12418
12717
  console.info(colors.gray('--- Detailed Result ---'));
12419
12718
  console.info({ isSuccessful: isSuccessful, errors: errors, warnings: warnings, outputParameters: outputParameters, executionReport: executionReport });
12420
12719
  }
12421
- if (!(saveReport && saveReport.endsWith('.json'))) return [3 /*break*/, 19];
12720
+ if (!(saveReport && saveReport.endsWith('.json'))) return [3 /*break*/, 10];
12422
12721
  return [4 /*yield*/, writeFile(saveReport, JSON.stringify(executionReport, null, 4) + '\n', 'utf-8')];
12423
- case 18:
12424
- _m.sent();
12425
- return [3 /*break*/, 21];
12426
- case 19:
12427
- if (!(saveReport && saveReport.endsWith('.md'))) return [3 /*break*/, 21];
12722
+ case 9:
12723
+ _l.sent();
12724
+ return [3 /*break*/, 12];
12725
+ case 10:
12726
+ if (!(saveReport && saveReport.endsWith('.md'))) return [3 /*break*/, 12];
12428
12727
  executionReportString = executionReportJsonToString(executionReport);
12429
12728
  return [4 /*yield*/, writeFile(saveReport, executionReportString, 'utf-8')];
12430
- case 20:
12431
- _m.sent();
12432
- _m.label = 21;
12433
- case 21:
12729
+ case 11:
12730
+ _l.sent();
12731
+ _l.label = 12;
12732
+ case 12:
12434
12733
  if (saveReport && isVerbose) {
12435
12734
  console.info(colors.green("Report saved to ".concat(saveReport)));
12436
12735
  }
@@ -12448,12 +12747,12 @@ function initializeRunCommand(program) {
12448
12747
  console.error(colors.red(colors.bold(error.name) + ': ' + error.message));
12449
12748
  }
12450
12749
  }
12451
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
12750
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
12452
12751
  finally {
12453
12752
  try {
12454
- if (_b && !_b.done && (_j = _a.return)) _j.call(_a);
12753
+ if (_b && !_b.done && (_h = _a.return)) _h.call(_a);
12455
12754
  }
12456
- finally { if (e_2) throw e_2.error; }
12755
+ finally { if (e_1) throw e_1.error; }
12457
12756
  }
12458
12757
  try {
12459
12758
  for (_c = __values(warnings || []), _d = _c.next(); !_d.done; _d = _c.next()) {
@@ -12461,12 +12760,12 @@ function initializeRunCommand(program) {
12461
12760
  console.error(colors.red(colors.bold(warning.name) + ': ' + warning.message));
12462
12761
  }
12463
12762
  }
12464
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
12763
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
12465
12764
  finally {
12466
12765
  try {
12467
- if (_d && !_d.done && (_k = _c.return)) _k.call(_c);
12766
+ if (_d && !_d.done && (_j = _c.return)) _j.call(_c);
12468
12767
  }
12469
- finally { if (e_3) throw e_3.error; }
12768
+ finally { if (e_2) throw e_2.error; }
12470
12769
  }
12471
12770
  if (json === undefined) {
12472
12771
  try {
@@ -12477,12 +12776,12 @@ function initializeRunCommand(program) {
12477
12776
  console.info(colors.green(colors.bold(key) + separator + value));
12478
12777
  }
12479
12778
  }
12480
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
12779
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
12481
12780
  finally {
12482
12781
  try {
12483
- if (_f && !_f.done && (_l = _e.return)) _l.call(_e);
12782
+ if (_f && !_f.done && (_k = _e.return)) _k.call(_e);
12484
12783
  }
12485
- finally { if (e_4) throw e_4.error; }
12784
+ finally { if (e_3) throw e_3.error; }
12486
12785
  }
12487
12786
  }
12488
12787
  else {
@@ -12530,7 +12829,7 @@ function initializeTestCommand(program) {
12530
12829
  isCacheReloaded: isCacheReloaded,
12531
12830
  };
12532
12831
  fs = $provideFilesystemForNode(prepareAndScrapeOptions);
12533
- llm = $provideLlmToolsForCli(prepareAndScrapeOptions);
12832
+ llm = $provideLlmToolsForWizzardOrCli(prepareAndScrapeOptions);
12534
12833
  return [4 /*yield*/, $provideExecutablesForNode(prepareAndScrapeOptions)];
12535
12834
  case 1:
12536
12835
  executables = _f.sent();
@@ -12691,6 +12990,7 @@ var _CLI = {
12691
12990
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
12692
12991
  *
12693
12992
  * @public exported from `@promptbook/core`
12993
+ * @public exported from `@promptbook/wizzard`
12694
12994
  * @public exported from `@promptbook/cli`
12695
12995
  */
12696
12996
  var _AnthropicClaudeMetadataRegistration = $llmToolsMetadataRegister.register({
@@ -13186,7 +13486,7 @@ var AnthropicClaudeExecutionTools = /** @class */ (function () {
13186
13486
  throw new PipelineExecutionError('Use callChatModel only for CHAT variant');
13187
13487
  }
13188
13488
  modelName = modelRequirements.modelName || this.getDefaultChatModel().modelName;
13189
- rawPromptContent = replaceParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
13489
+ rawPromptContent = templateParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
13190
13490
  rawRequest = {
13191
13491
  model: modelRequirements.modelName || this.getDefaultChatModel().modelName,
13192
13492
  max_tokens: modelRequirements.maxTokens || 4096,
@@ -13405,7 +13705,9 @@ var createAnthropicClaudeExecutionTools = Object.assign(function (options) {
13405
13705
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
13406
13706
  *
13407
13707
  * @public exported from `@promptbook/anthropic-claude`
13708
+ * @public exported from `@promptbook/wizzard`
13408
13709
  * @public exported from `@promptbook/cli`
13710
+ *
13409
13711
  */
13410
13712
  var _AnthropicClaudeRegistration = $llmToolsRegister.register(createAnthropicClaudeExecutionTools);
13411
13713
  /**
@@ -13419,6 +13721,7 @@ var _AnthropicClaudeRegistration = $llmToolsRegister.register(createAnthropicCla
13419
13721
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
13420
13722
  *
13421
13723
  * @public exported from `@promptbook/core`
13724
+ * @public exported from `@promptbook/wizzard`
13422
13725
  * @public exported from `@promptbook/cli`
13423
13726
  */
13424
13727
  var _AzureOpenAiMetadataRegistration = $llmToolsMetadataRegister.register({
@@ -13992,7 +14295,7 @@ var AzureOpenAiExecutionTools = /** @class */ (function () {
13992
14295
  // <- TODO: [🈁] Use `seed` here AND/OR use is `isDeterministic` for entire execution tools
13993
14296
  // <- Note: [🧆]
13994
14297
  };
13995
- rawPromptContent = replaceParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
14298
+ rawPromptContent = templateParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
13996
14299
  messages = __spreadArray(__spreadArray([], __read((modelRequirements.systemMessage === undefined
13997
14300
  ? []
13998
14301
  : [
@@ -14107,7 +14410,7 @@ var AzureOpenAiExecutionTools = /** @class */ (function () {
14107
14410
  console.info(colors.bgWhite('content'), JSON.stringify(content, null, 4));
14108
14411
  console.info(colors.bgWhite('parameters'), JSON.stringify(parameters, null, 4));
14109
14412
  }
14110
- rawPromptContent = replaceParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
14413
+ rawPromptContent = templateParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
14111
14414
  rawRequest = [
14112
14415
  modelName,
14113
14416
  [rawPromptContent],
@@ -14226,6 +14529,7 @@ var createAzureOpenAiExecutionTools = Object.assign(function (options) {
14226
14529
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
14227
14530
  *
14228
14531
  * @public exported from `@promptbook/azure-openai`
14532
+ * @public exported from `@promptbook/wizzard`
14229
14533
  * @public exported from `@promptbook/cli`
14230
14534
  */
14231
14535
  var _AzureOpenAiRegistration = $llmToolsRegister.register(createAzureOpenAiExecutionTools);
@@ -14234,21 +14538,13 @@ var _AzureOpenAiRegistration = $llmToolsRegister.register(createAzureOpenAiExecu
14234
14538
  * Note: [💞] Ignore a discrepancy between file name and entity name
14235
14539
  */
14236
14540
 
14237
- /**
14238
- * Detects if the code is running in jest environment
14239
- *
14240
- * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
14241
- *
14242
- * @public exported from `@promptbook/utils`
14243
- */
14244
- var $isRunningInJest = new Function("\n try {\n return process.env.JEST_WORKER_ID !== undefined;\n } catch (e) {\n return false;\n }\n");
14245
-
14246
14541
  /**
14247
14542
  * Registration of LLM provider metadata
14248
14543
  *
14249
14544
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
14250
14545
  *
14251
14546
  * @public exported from `@promptbook/core`
14547
+ * @public exported from `@promptbook/wizzard`
14252
14548
  * @public exported from `@promptbook/cli`
14253
14549
  */
14254
14550
  var _GoogleMetadataRegistration = $llmToolsMetadataRegister.register({
@@ -14298,6 +14594,10 @@ var _GoogleMetadataRegistration = $llmToolsMetadataRegister.register({
14298
14594
  * For example:
14299
14595
  * - `Date` objects will be converted to string
14300
14596
  *
14597
+ * Note: There are 2 similar functions
14598
+ * - `valueToString` converts value to string for LLM models as human-readable string
14599
+ * - `asSerializable` converts value to string to preserve full information to be able to convert it back
14600
+ *
14301
14601
  * @private Internal helper function
14302
14602
  */
14303
14603
  function asSerializable(value) {
@@ -14375,7 +14675,7 @@ function createExecutionToolsFromVercelProvider(options) {
14375
14675
  return [4 /*yield*/, vercelProvider.chat(modelName, __assign({ user: (userId === null || userId === void 0 ? void 0 : userId.toString()) || undefined }, additionalChatSettings))];
14376
14676
  case 1:
14377
14677
  model = _b.sent();
14378
- rawPromptContent = replaceParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
14678
+ rawPromptContent = templateParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
14379
14679
  rawRequest = {
14380
14680
  // <- TODO: [☂]
14381
14681
  inputFormat: 'messages',
@@ -14503,6 +14803,7 @@ var createGoogleExecutionTools = Object.assign(function (options) {
14503
14803
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
14504
14804
  *
14505
14805
  * @public exported from `@promptbook/google`
14806
+ * @public exported from `@promptbook/wizzard`
14506
14807
  * @public exported from `@promptbook/cli`
14507
14808
  */
14508
14809
  var _GoogleRegistration = $llmToolsRegister.register(createGoogleExecutionTools);
@@ -14517,6 +14818,7 @@ var _GoogleRegistration = $llmToolsRegister.register(createGoogleExecutionTools)
14517
14818
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
14518
14819
  *
14519
14820
  * @public exported from `@promptbook/core`
14821
+ * @public exported from `@promptbook/wizzard`
14520
14822
  * @public exported from `@promptbook/cli`
14521
14823
  */
14522
14824
  var _OpenAiMetadataRegistration = $llmToolsMetadataRegister.register({
@@ -14555,6 +14857,7 @@ var _OpenAiMetadataRegistration = $llmToolsMetadataRegister.register({
14555
14857
  * Note: [🏐] Configurations registrations are done in @@@ BUT constructor @@@
14556
14858
  *
14557
14859
  * @public exported from `@promptbook/core`
14860
+ * @public exported from `@promptbook/wizzard`
14558
14861
  * @public exported from `@promptbook/cli`
14559
14862
  */
14560
14863
  var _OpenAiAssistantMetadataRegistration = $llmToolsMetadataRegister.register({
@@ -14597,24 +14900,6 @@ var _OpenAiAssistantMetadataRegistration = $llmToolsMetadataRegister.register({
14597
14900
  * Note: [💞] Ignore a discrepancy between file name and entity name
14598
14901
  */
14599
14902
 
14600
- /**
14601
- * Detects if the code is running in a browser environment in main thread (Not in a web worker)
14602
- *
14603
- * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
14604
- *
14605
- * @public exported from `@promptbook/utils`
14606
- */
14607
- var $isRunningInBrowser = new Function("\n try {\n return this === window;\n } catch (e) {\n return false;\n }\n");
14608
-
14609
- /**
14610
- * Detects if the code is running in a web worker
14611
- *
14612
- * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
14613
- *
14614
- * @public exported from `@promptbook/utils`
14615
- */
14616
- var $isRunningInWebWorker = new Function("\n try {\n if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {\n return true;\n } else {\n return false;\n }\n } catch (e) {\n return false;\n }\n");
14617
-
14618
14903
  /**
14619
14904
  * Computes the usage of the OpenAI API based on the response from OpenAI
14620
14905
  *
@@ -14772,7 +15057,7 @@ var OpenAiExecutionTools = /** @class */ (function () {
14772
15057
  type: 'json_object',
14773
15058
  };
14774
15059
  }
14775
- rawPromptContent = replaceParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
15060
+ rawPromptContent = templateParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
14776
15061
  rawRequest = __assign(__assign({}, modelSettings), { messages: __spreadArray(__spreadArray([], __read((modelRequirements.systemMessage === undefined
14777
15062
  ? []
14778
15063
  : [
@@ -14868,7 +15153,7 @@ var OpenAiExecutionTools = /** @class */ (function () {
14868
15153
  // <- TODO: [🈁] Use `seed` here AND/OR use is `isDeterministic` for entire execution tools
14869
15154
  // <- Note: [🧆]
14870
15155
  };
14871
- rawPromptContent = replaceParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
15156
+ rawPromptContent = templateParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
14872
15157
  rawRequest = __assign(__assign({}, modelSettings), { prompt: rawPromptContent, user: (_a = this.options.userId) === null || _a === void 0 ? void 0 : _a.toString() });
14873
15158
  start = $getCurrentDate();
14874
15159
  if (this.options.isVerbose) {
@@ -14940,7 +15225,7 @@ var OpenAiExecutionTools = /** @class */ (function () {
14940
15225
  throw new PipelineExecutionError('Use embed only for EMBEDDING variant');
14941
15226
  }
14942
15227
  modelName = modelRequirements.modelName || this.getDefaultEmbeddingModel().modelName;
14943
- rawPromptContent = replaceParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
15228
+ rawPromptContent = templateParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
14944
15229
  rawRequest = {
14945
15230
  input: rawPromptContent,
14946
15231
  model: modelName,
@@ -15110,7 +15395,7 @@ var OpenAiAssistantExecutionTools = /** @class */ (function (_super) {
15110
15395
  }
15111
15396
  finally { if (e_1) throw e_1.error; }
15112
15397
  }
15113
- rawPromptContent = replaceParameters(content, __assign(__assign({}, parameters), { modelName: 'assistant' }));
15398
+ rawPromptContent = templateParameters(content, __assign(__assign({}, parameters), { modelName: 'assistant' }));
15114
15399
  rawRequest = {
15115
15400
  // TODO: [👨‍👨‍👧‍👧] ...modelSettings,
15116
15401
  // TODO: [👨‍👨‍👧‍👧][🧠] What about system message for assistants, does it make sence - combination of OpenAI assistants with Promptbook Personas
@@ -15260,6 +15545,7 @@ var createOpenAiExecutionTools = Object.assign(function (options) {
15260
15545
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
15261
15546
  *
15262
15547
  * @public exported from `@promptbook/openai`
15548
+ * @public exported from `@promptbook/wizzard`
15263
15549
  * @public exported from `@promptbook/cli`
15264
15550
  */
15265
15551
  var _OpenAiRegistration = $llmToolsRegister.register(createOpenAiExecutionTools);
@@ -15269,6 +15555,7 @@ var _OpenAiRegistration = $llmToolsRegister.register(createOpenAiExecutionTools)
15269
15555
  * Note: [🏐] Configurations registrations are done in @@@ BUT constructor @@@
15270
15556
  *
15271
15557
  * @public exported from `@promptbook/openai`
15558
+ * @public exported from `@promptbook/wizzard`
15272
15559
  * @public exported from `@promptbook/cli`
15273
15560
  */
15274
15561
  var _OpenAiAssistantRegistration = $llmToolsRegister.register(createOpenAiAssistantExecutionTools);
@@ -15530,6 +15817,7 @@ var markdownScraperMetadata = $deepFreeze({
15530
15817
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
15531
15818
  *
15532
15819
  * @public exported from `@promptbook/core`
15820
+ * @public exported from `@promptbook/wizzard`
15533
15821
  * @public exported from `@promptbook/cli`
15534
15822
  */
15535
15823
  var _MarkdownScraperMetadataRegistration = $scrapersMetadataRegister.register(markdownScraperMetadata);
@@ -15727,6 +16015,7 @@ var documentScraperMetadata = $deepFreeze({
15727
16015
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
15728
16016
  *
15729
16017
  * @public exported from `@promptbook/core`
16018
+ * @public exported from `@promptbook/wizzard`
15730
16019
  * @public exported from `@promptbook/cli`
15731
16020
  */
15732
16021
  var _DocumentScraperMetadataRegistration = $scrapersMetadataRegister.register(documentScraperMetadata);
@@ -15894,6 +16183,7 @@ var legacyDocumentScraperMetadata = $deepFreeze({
15894
16183
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
15895
16184
  *
15896
16185
  * @public exported from `@promptbook/core`
16186
+ * @public exported from `@promptbook/wizzard`
15897
16187
  * @public exported from `@promptbook/cli`
15898
16188
  */
15899
16189
  var _LegacyDocumentScraperMetadataRegistration = $scrapersMetadataRegister.register(legacyDocumentScraperMetadata);
@@ -16064,6 +16354,7 @@ var createLegacyDocumentScraper = Object.assign(function (tools, options) {
16064
16354
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
16065
16355
  *
16066
16356
  * @public exported from `@promptbook/legacy-documents`
16357
+ * @public exported from `@promptbook/wizzard`
16067
16358
  * @public exported from `@promptbook/cli`
16068
16359
  */
16069
16360
  var _LegacyDocumentScraperRegistration = $scrapersRegister.register(createLegacyDocumentScraper);
@@ -16090,6 +16381,7 @@ var createDocumentScraper = Object.assign(function (tools, options) {
16090
16381
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
16091
16382
  *
16092
16383
  * @public exported from `@promptbook/documents`
16384
+ * @public exported from `@promptbook/wizzard`
16093
16385
  * @public exported from `@promptbook/cli`
16094
16386
  */
16095
16387
  var _DocumentScraperRegistration = $scrapersRegister.register(createDocumentScraper);
@@ -16116,6 +16408,7 @@ var createMarkdownScraper = Object.assign(function (tools, options) {
16116
16408
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
16117
16409
  *
16118
16410
  * @public exported from `@promptbook/markdown-utils`
16411
+ * @public exported from `@promptbook/wizzard`
16119
16412
  * @public exported from `@promptbook/cli`
16120
16413
  */
16121
16414
  var _MarkdownScraperRegistration = $scrapersRegister.register(createMarkdownScraper);
@@ -16144,6 +16437,7 @@ var pdfScraperMetadata = $deepFreeze({
16144
16437
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
16145
16438
  *
16146
16439
  * @public exported from `@promptbook/core`
16440
+ * @public exported from `@promptbook/wizzard`
16147
16441
  * @public exported from `@promptbook/cli`
16148
16442
  */
16149
16443
  var _PdfScraperMetadataRegistration = $scrapersMetadataRegister.register(pdfScraperMetadata);
@@ -16228,6 +16522,7 @@ var createPdfScraper = Object.assign(function (tools, options) {
16228
16522
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
16229
16523
  *
16230
16524
  * @public exported from `@promptbook/pdf`
16525
+ * @public exported from `@promptbook/wizzard`
16231
16526
  * @public exported from `@promptbook/cli`
16232
16527
  */
16233
16528
  var _PdfScraperRegistration = $scrapersRegister.register(createPdfScraper);
@@ -16256,6 +16551,7 @@ var websiteScraperMetadata = $deepFreeze({
16256
16551
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
16257
16552
  *
16258
16553
  * @public exported from `@promptbook/core`
16554
+ * @public exported from `@promptbook/wizzard`
16259
16555
  * @public exported from `@promptbook/cli`
16260
16556
  */
16261
16557
  var _WebsiteScraperMetadataRegistration = $scrapersMetadataRegister.register(websiteScraperMetadata);
@@ -16429,6 +16725,7 @@ var createWebsiteScraper = Object.assign(function (tools, options) {
16429
16725
  * Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
16430
16726
  *
16431
16727
  * @public exported from `@promptbook/website-crawler`
16728
+ * @public exported from `@promptbook/wizzard`
16432
16729
  * @public exported from `@promptbook/cli`
16433
16730
  */
16434
16731
  var _WebsiteScraperRegistration = $scrapersRegister.register(createWebsiteScraper);