@promptbook/cli 0.80.0 → 0.81.0-6

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 (39) hide show
  1. package/README.md +6 -0
  2. package/esm/index.es.js +264 -135
  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 +4 -0
  9. package/esm/typings/src/_packages/utils.index.d.ts +10 -2
  10. package/esm/typings/src/config.d.ts +26 -0
  11. package/esm/typings/src/execution/ExecutionTools.d.ts +7 -0
  12. package/esm/typings/src/execution/PromptbookFetch.d.ts +5 -0
  13. package/esm/typings/src/execution/PromptbookFetch.test-type.d.ts +5 -0
  14. package/esm/typings/src/expectations/drafts/isDomainNameFree.d.ts +2 -1
  15. package/esm/typings/src/expectations/drafts/isGithubNameFree.d.ts +2 -1
  16. package/esm/typings/src/high-level-abstractions/index.d.ts +10 -0
  17. package/esm/typings/src/other/templates/getBookTemplate.d.ts +12 -0
  18. package/esm/typings/src/other/templates/getTemplatesPipelineCollection.d.ts +10 -0
  19. package/esm/typings/src/pipeline/PipelineJson/PipelineJson.d.ts +10 -0
  20. package/esm/typings/src/scrapers/_common/utils/makeKnowledgeSourceHandler.d.ts +1 -1
  21. package/esm/typings/src/scrapers/_common/utils/scraperFetch.d.ts +7 -0
  22. package/esm/typings/src/utils/editable/types/PipelineEditableSerialized.d.ts +27 -0
  23. package/esm/typings/src/{conversion → utils/editable}/utils/removePipelineCommand.d.ts +3 -3
  24. package/esm/typings/src/{conversion → utils/editable}/utils/renamePipelineParameter.d.ts +3 -3
  25. package/esm/typings/src/{conversion → utils/editable}/utils/stringifyPipelineJson.d.ts +2 -2
  26. package/esm/typings/src/utils/parameters/numberToString.d.ts +7 -0
  27. package/esm/typings/src/utils/parameters/{replaceParameters.d.ts → templateParameters.d.ts} +6 -2
  28. package/esm/typings/src/utils/parameters/valueToString.d.ts +17 -0
  29. package/esm/typings/src/utils/parameters/valueToString.test.d.ts +1 -0
  30. package/esm/typings/src/utils/serialization/asSerializable.d.ts +4 -0
  31. package/package.json +1 -1
  32. package/umd/index.umd.js +264 -135
  33. package/umd/index.umd.js.map +1 -1
  34. package/esm/typings/src/utils/formatNumber.d.ts +0 -6
  35. /package/esm/typings/src/{conversion → utils/editable}/utils/removePipelineCommand.test.d.ts +0 -0
  36. /package/esm/typings/src/{conversion → utils/editable}/utils/renamePipelineParameter.test.d.ts +0 -0
  37. /package/esm/typings/src/{conversion → utils/editable}/utils/stringifyPipelineJson.test.d.ts +0 -0
  38. /package/esm/typings/src/utils/{formatNumber.test.d.ts → parameters/numberToString.test.d.ts} +0 -0
  39. /package/esm/typings/src/utils/parameters/{replaceParameters.test.d.ts → templateParameters.test.d.ts} +0 -0
package/umd/index.umd.js CHANGED
@@ -49,7 +49,7 @@
49
49
  *
50
50
  * @see https://github.com/webgptorg/promptbook
51
51
  */
52
- var PROMPTBOOK_ENGINE_VERSION = '0.80.0-1';
52
+ var PROMPTBOOK_ENGINE_VERSION = '0.81.0-5';
53
53
  /**
54
54
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
55
55
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -247,6 +247,26 @@
247
247
  * @private within the repository - too low-level in comparison with other `MAX_...`
248
248
  */
249
249
  var LOOP_LIMIT = 1000;
250
+ /**
251
+ * Strings to represent various values in the context of parameter values
252
+ *
253
+ * @public exported from `@promptbook/utils`
254
+ */
255
+ var VALUE_STRINGS = {
256
+ empty: '(nothing; empty string)',
257
+ null: '(no value; null)',
258
+ undefined: '(unknown value; undefined)',
259
+ nan: '(not a number; NaN)',
260
+ infinity: '(infinity; ∞)',
261
+ negativeInfinity: '(negative infinity; -∞)',
262
+ unserializable: '(unserializable value)',
263
+ };
264
+ /**
265
+ * Small number limit
266
+ *
267
+ * @public exported from `@promptbook/utils`
268
+ */
269
+ var SMALL_NUMBER = 0.001;
250
270
  /**
251
271
  * Timeout for the connections in milliseconds
252
272
  *
@@ -365,6 +385,12 @@
365
385
  * @public exported from `@promptbook/core`
366
386
  */
367
387
  var DEFAULT_IS_AUTO_INSTALLED = false;
388
+ /**
389
+ * Function name for generated function via `ptbk make` to get the pipeline collection
390
+ *
391
+ * @public exported from `@promptbook/core`
392
+ */
393
+ var DEFAULT_GET_PIPELINE_COLLECTION_FUNCTION_NAME = "getPipelineCollection";
368
394
  /**
369
395
  * @@@
370
396
  *
@@ -500,6 +526,40 @@
500
526
  * Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
501
527
  */
502
528
 
529
+ /**
530
+ * Make error report URL for the given error
531
+ *
532
+ * @private !!!!!!
533
+ */
534
+ function getErrorReportUrl(error) {
535
+ var report = {
536
+ title: "\uD83D\uDC1C Error report from ".concat(NAME),
537
+ body: spaceTrim__default["default"](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 "); }),
538
+ };
539
+ var reportUrl = new URL("https://github.com/webgptorg/promptbook/issues/new");
540
+ reportUrl.searchParams.set('labels', 'bug');
541
+ reportUrl.searchParams.set('assignees', ADMIN_GITHUB_NAME);
542
+ reportUrl.searchParams.set('title', report.title);
543
+ reportUrl.searchParams.set('body', report.body);
544
+ return reportUrl;
545
+ }
546
+
547
+ /**
548
+ * This error type indicates that the error should not happen and its last check before crashing with some other error
549
+ *
550
+ * @public exported from `@promptbook/core`
551
+ */
552
+ var UnexpectedError = /** @class */ (function (_super) {
553
+ __extends(UnexpectedError, _super);
554
+ function UnexpectedError(message) {
555
+ var _this = _super.call(this, spaceTrim.spaceTrim(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;
556
+ _this.name = 'UnexpectedError';
557
+ Object.setPrototypeOf(_this, UnexpectedError.prototype);
558
+ return _this;
559
+ }
560
+ return UnexpectedError;
561
+ }(Error));
562
+
503
563
  /**
504
564
  * Orders JSON object by keys
505
565
  *
@@ -550,40 +610,6 @@
550
610
  * TODO: [🧠] Is there a way how to meaningfully test this utility
551
611
  */
552
612
 
553
- /**
554
- * Make error report URL for the given error
555
- *
556
- * @private !!!!!!
557
- */
558
- function getErrorReportUrl(error) {
559
- var report = {
560
- title: "\uD83D\uDC1C Error report from ".concat(NAME),
561
- body: spaceTrim__default["default"](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 "); }),
562
- };
563
- var reportUrl = new URL("https://github.com/webgptorg/promptbook/issues/new");
564
- reportUrl.searchParams.set('labels', 'bug');
565
- reportUrl.searchParams.set('assignees', ADMIN_GITHUB_NAME);
566
- reportUrl.searchParams.set('title', report.title);
567
- reportUrl.searchParams.set('body', report.body);
568
- return reportUrl;
569
- }
570
-
571
- /**
572
- * This error type indicates that the error should not happen and its last check before crashing with some other error
573
- *
574
- * @public exported from `@promptbook/core`
575
- */
576
- var UnexpectedError = /** @class */ (function (_super) {
577
- __extends(UnexpectedError, _super);
578
- function UnexpectedError(message) {
579
- var _this = _super.call(this, spaceTrim.spaceTrim(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;
580
- _this.name = 'UnexpectedError';
581
- Object.setPrototypeOf(_this, UnexpectedError.prototype);
582
- return _this;
583
- }
584
- return UnexpectedError;
585
- }(Error));
586
-
587
613
  /**
588
614
  * Checks if the value is [🚉] serializable as JSON
589
615
  * If not, throws an UnexpectedError with a rich error message and tracking
@@ -772,6 +798,7 @@
772
798
  * @public exported from `@promptbook/core`
773
799
  */
774
800
  var ORDER_OF_PIPELINE_JSON = [
801
+ // Note: [🍙] In this order will be pipeline serialized
775
802
  'title',
776
803
  'pipelineUrl',
777
804
  'bookVersion',
@@ -783,6 +810,7 @@
783
810
  'preparations',
784
811
  'knowledgeSources',
785
812
  'knowledgePieces',
813
+ 'sources', // <- TODO: [🧠] Where should the `sources` be
786
814
  ];
787
815
  /**
788
816
  * Nonce which is used for replacing things in strings
@@ -866,7 +894,7 @@
866
894
  * Note: [0] It can be used for more JSON types like whole collection of pipelines, single knowledge piece, etc.
867
895
  * Note: In contrast to JSON.stringify, this function ensures that **embedding index** is on single line
868
896
  *
869
- * @public exported from `@promptbook/core`
897
+ * @public exported from `@promptbook/editable`
870
898
  */
871
899
  function stringifyPipelineJson(pipeline) {
872
900
  if (!isSerializableAsJson(pipeline)) {
@@ -2756,7 +2784,7 @@
2756
2784
  });
2757
2785
  }
2758
2786
 
2759
- 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"}];
2787
+ 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"}];
2760
2788
 
2761
2789
  /**
2762
2790
  * Prettify the html code
@@ -4593,16 +4621,94 @@
4593
4621
  return [input];
4594
4622
  }
4595
4623
 
4624
+ /**
4625
+ * Format either small or big number
4626
+ *
4627
+ * @public exported from `@promptbook/utils`
4628
+ */
4629
+ function numberToString(value) {
4630
+ if (value === 0) {
4631
+ return '0';
4632
+ }
4633
+ else if (Number.isNaN(value)) {
4634
+ return VALUE_STRINGS.nan;
4635
+ }
4636
+ else if (value === Infinity) {
4637
+ return VALUE_STRINGS.infinity;
4638
+ }
4639
+ else if (value === -Infinity) {
4640
+ return VALUE_STRINGS.negativeInfinity;
4641
+ }
4642
+ for (var exponent = 0; exponent < 15; exponent++) {
4643
+ var factor = Math.pow(10, exponent);
4644
+ var valueRounded = Math.round(value * factor) / factor;
4645
+ if (Math.abs(value - valueRounded) / value < SMALL_NUMBER) {
4646
+ return valueRounded.toFixed(exponent);
4647
+ }
4648
+ }
4649
+ return value.toString();
4650
+ }
4651
+
4652
+ /**
4653
+ * Function `valueToString` will convert the given value to string
4654
+ * This is useful and used in the `templateParameters` function
4655
+ *
4656
+ * Note: This function is not just calling `toString` method
4657
+ * It's more complex and can handle this conversion specifically for LLM models
4658
+ * See `VALUE_STRINGS`
4659
+ *
4660
+ * Note: There are 2 similar functions
4661
+ * - `valueToString` converts value to string for LLM models as human-readable string
4662
+ * - `asSerializable` converts value to string to preserve full information to be able to convert it back
4663
+ *
4664
+ * @public exported from `@promptbook/utils`
4665
+ */
4666
+ function valueToString(value) {
4667
+ try {
4668
+ if (value === '') {
4669
+ return VALUE_STRINGS.empty;
4670
+ }
4671
+ else if (value === null) {
4672
+ return VALUE_STRINGS.null;
4673
+ }
4674
+ else if (value === undefined) {
4675
+ return VALUE_STRINGS.undefined;
4676
+ }
4677
+ else if (typeof value === 'string') {
4678
+ return value;
4679
+ }
4680
+ else if (typeof value === 'number') {
4681
+ return numberToString(value);
4682
+ }
4683
+ else if (value instanceof Date) {
4684
+ return value.toISOString();
4685
+ }
4686
+ else {
4687
+ return JSON.stringify(value);
4688
+ }
4689
+ }
4690
+ catch (error) {
4691
+ if (!(error instanceof Error)) {
4692
+ throw error;
4693
+ }
4694
+ console.error(error);
4695
+ return VALUE_STRINGS.unserializable;
4696
+ }
4697
+ }
4698
+
4596
4699
  /**
4597
4700
  * Replaces parameters in template with values from parameters object
4598
4701
  *
4702
+ * Note: This function is not places strings into string,
4703
+ * It's more complex and can handle this operation specifically for LLM models
4704
+ *
4599
4705
  * @param template the template with parameters in {curly} braces
4600
4706
  * @param parameters the object with parameters
4601
4707
  * @returns the template with replaced parameters
4602
4708
  * @throws {PipelineExecutionError} if parameter is not defined, not closed, or not opened
4603
4709
  * @public exported from `@promptbook/utils`
4604
4710
  */
4605
- function replaceParameters(template, parameters) {
4711
+ function templateParameters(template, parameters) {
4606
4712
  var e_1, _a;
4607
4713
  try {
4608
4714
  for (var _b = __values(Object.entries(parameters)), _c = _b.next(); !_c.done; _c = _b.next()) {
@@ -4628,7 +4734,7 @@
4628
4734
  var loopLimit = LOOP_LIMIT;
4629
4735
  var _loop_1 = function () {
4630
4736
  if (loopLimit-- < 0) {
4631
- throw new LimitReachedError('Loop limit reached during parameters replacement in `replaceParameters`');
4737
+ throw new LimitReachedError('Loop limit reached during parameters replacement in `templateParameters`');
4632
4738
  }
4633
4739
  var precol = match.groups.precol;
4634
4740
  var parameterName = match.groups.parameterName;
@@ -4645,7 +4751,7 @@
4645
4751
  if (parameterValue === undefined) {
4646
4752
  throw new PipelineExecutionError("Parameter `{".concat(parameterName, "}` is not defined"));
4647
4753
  }
4648
- parameterValue = parameterValue.toString();
4754
+ parameterValue = valueToString(parameterValue);
4649
4755
  if (parameterValue.includes('\n') && /^\s*\W{0,3}\s*$/.test(precol)) {
4650
4756
  parameterValue = parameterValue
4651
4757
  .split('\n')
@@ -4880,7 +4986,7 @@
4880
4986
  }
4881
4987
  return [3 /*break*/, 24];
4882
4988
  case 2:
4883
- $ongoingTaskResult.$resultString = replaceParameters(preparedContent, parameters);
4989
+ $ongoingTaskResult.$resultString = templateParameters(preparedContent, parameters);
4884
4990
  return [3 /*break*/, 25];
4885
4991
  case 3:
4886
4992
  modelRequirements = __assign(__assign({ modelVariant: 'CHAT' }, (preparedPipeline.defaultModelRequirements || {})), (task.modelRequirements || {}));
@@ -5003,8 +5109,8 @@
5003
5109
  _j = $ongoingTaskResult;
5004
5110
  return [4 /*yield*/, tools.userInterface.promptDialog($deepFreeze({
5005
5111
  promptTitle: task.title,
5006
- promptMessage: replaceParameters(task.description || '', parameters),
5007
- defaultValue: replaceParameters(preparedContent, parameters),
5112
+ promptMessage: templateParameters(task.description || '', parameters),
5113
+ defaultValue: templateParameters(preparedContent, parameters),
5008
5114
  // TODO: [🧠] !! Figure out how to define placeholder in .book.md file
5009
5115
  placeholder: undefined,
5010
5116
  priority: priority,
@@ -5128,7 +5234,7 @@
5128
5234
  if (!isJokerAttempt &&
5129
5235
  task.taskType === 'PROMPT_TASK' &&
5130
5236
  $ongoingTaskResult.$prompt
5131
- // <- Note: [2] When some expected parameter is not defined, error will occur in replaceParameters
5237
+ // <- Note: [2] When some expected parameter is not defined, error will occur in templateParameters
5132
5238
  // In that case we don’t want to make a report about it because it’s not a llm execution error
5133
5239
  ) {
5134
5240
  // TODO: [🧠] Maybe put other taskTypes into report
@@ -6192,6 +6298,30 @@
6192
6298
  return match ? match[1].toLowerCase() : null;
6193
6299
  }
6194
6300
 
6301
+ /**
6302
+ * The built-in `fetch' function with a lightweight error handling wrapper as default fetch function used in Promptbook scrapers
6303
+ *
6304
+ * @private as default `fetch` function used in Promptbook scrapers
6305
+ */
6306
+ var scraperFetch = function (url, init) { return __awaiter(void 0, void 0, void 0, function () {
6307
+ var error_1;
6308
+ return __generator(this, function (_a) {
6309
+ switch (_a.label) {
6310
+ case 0:
6311
+ _a.trys.push([0, 2, , 3]);
6312
+ return [4 /*yield*/, fetch(url, init)];
6313
+ case 1: return [2 /*return*/, _a.sent()];
6314
+ case 2:
6315
+ error_1 = _a.sent();
6316
+ if (!(error_1 instanceof Error)) {
6317
+ throw error_1;
6318
+ }
6319
+ throw new KnowledgeScrapeError(spaceTrim__default["default"](function (block) { return "\n Can not fetch \"".concat(url, "\"\n\n Fetch error:\n ").concat(block(error_1.message), "\n\n "); }));
6320
+ case 3: return [2 /*return*/];
6321
+ }
6322
+ });
6323
+ }); };
6324
+
6195
6325
  /**
6196
6326
  * @@@
6197
6327
  *
@@ -6200,13 +6330,14 @@
6200
6330
  function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
6201
6331
  var _a;
6202
6332
  return __awaiter(this, void 0, void 0, function () {
6203
- var sourceContent, name, _b, _c, rootDirname, url, response_1, mimeType, filename_1, fileExtension, mimeType;
6204
- return __generator(this, function (_e) {
6205
- switch (_e.label) {
6333
+ var _b, fetch, sourceContent, name, _c, _d, rootDirname, url, response_1, mimeType, filename_1, fileExtension, mimeType;
6334
+ return __generator(this, function (_f) {
6335
+ switch (_f.label) {
6206
6336
  case 0:
6337
+ _b = tools.fetch, fetch = _b === void 0 ? scraperFetch : _b;
6207
6338
  sourceContent = knowledgeSource.sourceContent;
6208
6339
  name = knowledgeSource.name;
6209
- _b = options || {}, _c = _b.rootDirname, rootDirname = _c === void 0 ? null : _c, _b.isVerbose;
6340
+ _c = options || {}, _d = _c.rootDirname, rootDirname = _d === void 0 ? null : _d, _c.isVerbose;
6210
6341
  if (!name) {
6211
6342
  name = sourceContentToName(sourceContent);
6212
6343
  }
@@ -6214,7 +6345,7 @@
6214
6345
  url = sourceContent;
6215
6346
  return [4 /*yield*/, fetch(url)];
6216
6347
  case 1:
6217
- response_1 = _e.sent();
6348
+ response_1 = _f.sent();
6218
6349
  mimeType = ((_a = response_1.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.split(';')[0]) || 'text/html';
6219
6350
  return [2 /*return*/, {
6220
6351
  source: name,
@@ -6271,7 +6402,7 @@
6271
6402
  mimeType = extensionToMimeType(fileExtension || '');
6272
6403
  return [4 /*yield*/, isFileExisting(filename_1, tools.fs)];
6273
6404
  case 3:
6274
- if (!(_e.sent())) {
6405
+ if (!(_f.sent())) {
6275
6406
  throw new NotFoundError(spaceTrim__default["default"](function (block) { return "\n Can not make source handler for file which does not exist:\n\n File:\n ".concat(block(filename_1), "\n "); }));
6276
6407
  }
6277
6408
  // TODO: [🧠][😿] Test security file - file is scoped to the project (BUT maybe do this in `filesystemTools`)
@@ -9534,6 +9665,14 @@
9534
9665
  knowledgePieces: [],
9535
9666
  personas: [],
9536
9667
  preparations: [],
9668
+ sources: [
9669
+ {
9670
+ type: 'BOOK',
9671
+ path: null,
9672
+ // <- TODO: !!!!!! Pass here path of the file
9673
+ content: pipelineString,
9674
+ },
9675
+ ],
9537
9676
  };
9538
9677
  function getPipelineIdentification() {
9539
9678
  // Note: This is a 😐 implementation of [🚞]
@@ -9941,7 +10080,6 @@
9941
10080
  $pipelineJson.formfactorName = 'GENERIC';
9942
10081
  }
9943
10082
  // =============================================================
9944
- // TODO: [🍙] Maybe do reorder of `$pipelineJson` here
9945
10083
  return exportJson({
9946
10084
  name: 'pipelineJson',
9947
10085
  message: "Result of `precompilePipeline`",
@@ -11073,11 +11211,9 @@
11073
11211
  , ".json"));
11074
11212
  return [4 /*yield*/, isFileExisting(makedLibraryFilePath, tools.fs)];
11075
11213
  case 3:
11076
- if (!(_f.sent())) {
11077
- console.info(colors__default["default"].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.")));
11078
- }
11214
+ if (!(_f.sent())) ;
11079
11215
  else {
11080
- colors__default["default"].green("(In future, not implemented yet) Using your prebuild pipeline collection ".concat(makedLibraryFilePath));
11216
+ colors__default["default"].green("(In future, not implemented yet) Using your compiled pipeline collection ".concat(makedLibraryFilePath));
11081
11217
  // TODO: !! Implement;
11082
11218
  // TODO: [🌗]
11083
11219
  }
@@ -11097,10 +11233,10 @@
11097
11233
  // Note: First load all .book.json and then .book.md files
11098
11234
  // .book.json can be prepared so it is faster to load
11099
11235
  fileNames.sort(function (a, b) {
11100
- if (a.endsWith('.book.json') && b.endsWith('.book.md')) {
11236
+ if (a.endsWith('.json') && b.endsWith('.md')) {
11101
11237
  return -1;
11102
11238
  }
11103
- if (a.endsWith('.book.md') && b.endsWith('.book.json')) {
11239
+ if (a.endsWith('.md') && b.endsWith('.json')) {
11104
11240
  return 1;
11105
11241
  }
11106
11242
  return 0;
@@ -11149,7 +11285,7 @@
11149
11285
  // TODO: [👠] DRY
11150
11286
  if (pipeline.pipelineUrl === undefined) {
11151
11287
  if (isVerbose) {
11152
- console.info(colors__default["default"].red("Can not load pipeline from ".concat(fileName
11288
+ console.info(colors__default["default"].yellow("Can not load pipeline from ".concat(fileName
11153
11289
  .split('\\')
11154
11290
  .join('/'), " because of missing URL")));
11155
11291
  }
@@ -11327,16 +11463,21 @@
11327
11463
  makeCommand.option('--validation', "Types of validations separated by comma (options \"logic\",\"imports\")", 'logic,imports');
11328
11464
  makeCommand.option('-r, --reload', "Call LLM models even if same prompt with result is in the cache", false);
11329
11465
  makeCommand.option('-v, --verbose', "Is output verbose", false);
11330
- makeCommand.option('-o, --out-file <path>', spaceTrim__default["default"]("\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);
11466
+ makeCommand.option('-o, --output <path>', spaceTrim__default["default"]("\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);
11467
+ makeCommand.option('-fn, --function-name <functionName>', spaceTrim__default["default"]("\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);
11331
11468
  makeCommand.action(function (path$1, _a) {
11332
- var projectName = _a.projectName, format = _a.format, validation = _a.validation, isCacheReloaded = _a.reload, isVerbose = _a.verbose, outFile = _a.outFile;
11469
+ var projectName = _a.projectName, format = _a.format, functionName = _a.functionName, validation = _a.validation, isCacheReloaded = _a.reload, isVerbose = _a.verbose, output = _a.output;
11333
11470
  return __awaiter(_this, void 0, void 0, function () {
11334
- 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;
11335
- var _d, e_2, _e, e_1, _f;
11471
+ 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;
11472
+ var _b, e_2, _c, e_1, _d;
11336
11473
  var _this = this;
11337
- return __generator(this, function (_g) {
11338
- switch (_g.label) {
11474
+ return __generator(this, function (_e) {
11475
+ switch (_e.label) {
11339
11476
  case 0:
11477
+ if (!isValidJavascriptName(functionName)) {
11478
+ console.error(colors__default["default"].red("Function name \"".concat(functionName, "\" is not valid javascript name")));
11479
+ return [2 /*return*/, process.exit(1)];
11480
+ }
11340
11481
  formats = (format || '')
11341
11482
  .split(',')
11342
11483
  .map(function (_) { return _.trim(); })
@@ -11345,7 +11486,7 @@
11345
11486
  .split(',')
11346
11487
  .map(function (_) { return _.trim(); })
11347
11488
  .filter(function (_) { return _ !== ''; });
11348
- if (outFile !== DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME && formats.length !== 1) {
11489
+ if (output !== DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME && formats.length !== 1) {
11349
11490
  console.error(colors__default["default"].red("You can only use one format if you specify --out-file"));
11350
11491
  return [2 /*return*/, process.exit(1)];
11351
11492
  }
@@ -11357,85 +11498,89 @@
11357
11498
  llm = $provideLlmToolsForCli(prepareAndScrapeOptions);
11358
11499
  return [4 /*yield*/, $provideExecutablesForNode(prepareAndScrapeOptions)];
11359
11500
  case 1:
11360
- executables = _g.sent();
11361
- _d = {
11501
+ executables = _e.sent();
11502
+ _b = {
11362
11503
  llm: llm,
11363
11504
  fs: fs
11364
11505
  };
11365
11506
  return [4 /*yield*/, $provideScrapersForNode({ fs: fs, llm: llm, executables: executables }, prepareAndScrapeOptions)];
11366
11507
  case 2:
11367
- tools = (_d.scrapers = _g.sent(),
11368
- _d.script = [
11508
+ tools = (_b.scrapers = _e.sent(),
11509
+ _b.script = [
11369
11510
  /*new JavascriptExecutionTools(options)*/
11370
11511
  ],
11371
- _d);
11512
+ _b);
11372
11513
  return [4 /*yield*/, createCollectionFromDirectory(path$1, tools, {
11373
11514
  isVerbose: isVerbose,
11374
11515
  isRecursive: true,
11375
11516
  // <- TODO: [🍖] Add `intermediateFilesStrategy`
11376
11517
  })];
11377
11518
  case 3:
11378
- collection = _g.sent();
11379
- _g.label = 4;
11519
+ collection = _e.sent();
11520
+ return [4 /*yield*/, collection.listPipelines()];
11380
11521
  case 4:
11381
- _g.trys.push([4, 16, 17, 18]);
11382
- validations_1 = __values(validations), validations_1_1 = validations_1.next();
11383
- _g.label = 5;
11522
+ pipelinesUrls = _e.sent();
11523
+ if (pipelinesUrls.length === 0) {
11524
+ console.error(colors__default["default"].red("No books found in \"".concat(path$1, "\"")));
11525
+ return [2 /*return*/, process.exit(1)];
11526
+ }
11527
+ _e.label = 5;
11384
11528
  case 5:
11529
+ _e.trys.push([5, 16, 17, 18]);
11530
+ validations_1 = __values(validations), validations_1_1 = validations_1.next();
11531
+ _e.label = 6;
11532
+ case 6:
11385
11533
  if (!!validations_1_1.done) return [3 /*break*/, 15];
11386
11534
  validation_1 = validations_1_1.value;
11387
- _g.label = 6;
11388
- case 6:
11389
- _g.trys.push([6, 12, 13, 14]);
11390
- e_1 = void 0;
11391
- return [4 /*yield*/, collection.listPipelines()];
11535
+ _e.label = 7;
11392
11536
  case 7:
11393
- _b = (__values.apply(void 0, [_g.sent()])), _c = _b.next();
11394
- _g.label = 8;
11537
+ _e.trys.push([7, 12, 13, 14]);
11538
+ pipelinesUrls_1 = (e_1 = void 0, __values(pipelinesUrls)), pipelinesUrls_1_1 = pipelinesUrls_1.next();
11539
+ _e.label = 8;
11395
11540
  case 8:
11396
- if (!!_c.done) return [3 /*break*/, 11];
11397
- pipelineUrl = _c.value;
11541
+ if (!!pipelinesUrls_1_1.done) return [3 /*break*/, 11];
11542
+ pipelineUrl = pipelinesUrls_1_1.value;
11398
11543
  return [4 /*yield*/, collection.getPipelineByUrl(pipelineUrl)];
11399
11544
  case 9:
11400
- pipeline = _g.sent();
11545
+ pipeline = _e.sent();
11401
11546
  if (validation_1 === 'logic') {
11402
11547
  validatePipeline(pipeline);
11403
11548
  if (isVerbose) {
11404
11549
  console.info(colors__default["default"].cyan("Validated logic of ".concat(pipeline.pipelineUrl)));
11405
11550
  }
11406
11551
  }
11407
- _g.label = 10;
11552
+ _e.label = 10;
11408
11553
  case 10:
11409
- _c = _b.next();
11554
+ pipelinesUrls_1_1 = pipelinesUrls_1.next();
11410
11555
  return [3 /*break*/, 8];
11411
11556
  case 11: return [3 /*break*/, 14];
11412
11557
  case 12:
11413
- e_1_1 = _g.sent();
11558
+ e_1_1 = _e.sent();
11414
11559
  e_1 = { error: e_1_1 };
11415
11560
  return [3 /*break*/, 14];
11416
11561
  case 13:
11417
11562
  try {
11418
- if (_c && !_c.done && (_f = _b.return)) _f.call(_b);
11563
+ if (pipelinesUrls_1_1 && !pipelinesUrls_1_1.done && (_d = pipelinesUrls_1.return)) _d.call(pipelinesUrls_1);
11419
11564
  }
11420
11565
  finally { if (e_1) throw e_1.error; }
11421
11566
  return [7 /*endfinally*/];
11422
11567
  case 14:
11423
11568
  validations_1_1 = validations_1.next();
11424
- return [3 /*break*/, 5];
11569
+ return [3 /*break*/, 6];
11425
11570
  case 15: return [3 /*break*/, 18];
11426
11571
  case 16:
11427
- e_2_1 = _g.sent();
11572
+ e_2_1 = _e.sent();
11428
11573
  e_2 = { error: e_2_1 };
11429
11574
  return [3 /*break*/, 18];
11430
11575
  case 17:
11431
11576
  try {
11432
- if (validations_1_1 && !validations_1_1.done && (_e = validations_1.return)) _e.call(validations_1);
11577
+ if (validations_1_1 && !validations_1_1.done && (_c = validations_1.return)) _c.call(validations_1);
11433
11578
  }
11434
11579
  finally { if (e_2) throw e_2.error; }
11435
11580
  return [7 /*endfinally*/];
11436
11581
  case 18: return [4 /*yield*/, collectionToJson(collection)];
11437
11582
  case 19:
11438
- collectionJson = _g.sent();
11583
+ collectionJson = _e.sent();
11439
11584
  collectionJsonString = stringifyPipelineJson(collectionJson).trim();
11440
11585
  collectionJsonItems = (function () {
11441
11586
  var firstChar = collectionJsonString.charAt(0);
@@ -11453,10 +11598,10 @@
11453
11598
  return __generator(this, function (_a) {
11454
11599
  switch (_a.label) {
11455
11600
  case 0:
11456
- filename = outFile !== DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME
11457
- ? outFile
11601
+ filename = output !== DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME
11602
+ ? output
11458
11603
  : path.join(path$1, "".concat(DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME, ".").concat(extension));
11459
- if (!outFile.endsWith(".".concat(extension))) {
11604
+ if (!output.endsWith(".".concat(extension))) {
11460
11605
  console.warn(colors__default["default"].yellow("Warning: Extension of output file should be \"".concat(extension, "\"")));
11461
11606
  }
11462
11607
  return [4 /*yield*/, promises.mkdir(path.dirname(filename), { recursive: true })];
@@ -11475,22 +11620,22 @@
11475
11620
  formats = formats.filter(function (format) { return format !== 'json'; });
11476
11621
  return [4 /*yield*/, saveFile('json', collectionJsonString)];
11477
11622
  case 20:
11478
- _g.sent();
11479
- _g.label = 21;
11623
+ _e.sent();
11624
+ _e.label = 21;
11480
11625
  case 21:
11481
11626
  if (!(formats.includes('javascript') || formats.includes('js'))) return [3 /*break*/, 23];
11482
11627
  formats = formats.filter(function (format) { return format !== 'javascript' && format !== 'js'; });
11483
- return [4 /*yield*/, saveFile('js', spaceTrim__default["default"](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 "); }))];
11628
+ return [4 /*yield*/, saveFile('js', spaceTrim__default["default"](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 "); }))];
11484
11629
  case 22:
11485
- (_g.sent()) + '\n';
11486
- _g.label = 23;
11630
+ (_e.sent()) + '\n';
11631
+ _e.label = 23;
11487
11632
  case 23:
11488
11633
  if (!(formats.includes('typescript') || formats.includes('ts'))) return [3 /*break*/, 25];
11489
11634
  formats = formats.filter(function (format) { return format !== 'typescript' && format !== 'ts'; });
11490
- return [4 /*yield*/, saveFile('ts', spaceTrim__default["default"](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')];
11635
+ return [4 /*yield*/, saveFile('ts', spaceTrim__default["default"](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')];
11491
11636
  case 24:
11492
- _g.sent();
11493
- _g.label = 25;
11637
+ _e.sent();
11638
+ _e.label = 25;
11494
11639
  case 25:
11495
11640
  if (formats.length > 0) {
11496
11641
  console.warn(colors__default["default"].yellow("Format ".concat(formats.join(' and '), " is not supported")));
@@ -11740,26 +11885,6 @@
11740
11885
  * TODO: [🖇] What about symlinks? Maybe flag --follow-symlinks
11741
11886
  */
11742
11887
 
11743
- /**
11744
- * Format either small or big number
11745
- *
11746
- * @private within the repository
11747
- */
11748
- function formatNumber(value) {
11749
- if (value === 0) {
11750
- return '0';
11751
- }
11752
- for (var exponent = 0; exponent < 15; exponent++) {
11753
- var factor = Math.pow(10, exponent);
11754
- var valueRounded = Math.round(value * factor) / factor;
11755
- if (Math.abs(value - valueRounded) / value <
11756
- 0.001 /* <- TODO: Pass as option, pass to executionReportJsonToString as option */) {
11757
- return valueRounded.toFixed(exponent);
11758
- }
11759
- }
11760
- return value.toString();
11761
- }
11762
-
11763
11888
  /**
11764
11889
  * Create a markdown table from a 2D array of strings
11765
11890
  *
@@ -11819,7 +11944,7 @@
11819
11944
  }
11820
11945
  finally { if (e_1) throw e_1.error; }
11821
11946
  }
11822
- 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_");
11947
+ 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_");
11823
11948
  return createMarkdownTable(table) + '\n\n' + legend;
11824
11949
  }
11825
11950
  /**
@@ -11948,7 +12073,7 @@
11948
12073
  headerList.push("COMPLETED AT ".concat(moment__default["default"](completedAt).format("YYYY-MM-DD HH:mm:ss")));
11949
12074
  headerList.push("TOTAL DURATION ".concat(duration.humanize(MOMENT_ARG_THRESHOLDS)));
11950
12075
  headerList.push("TOTAL LLM DURATION ".concat(llmDuration.humanize(MOMENT_ARG_THRESHOLDS)));
11951
- headerList.push("TOTAL COST $".concat(formatNumber(cost * (1 + taxRate))) +
12076
+ headerList.push("TOTAL COST $".concat(numberToString(cost * (1 + taxRate))) +
11952
12077
  (executionsWithKnownCost.length === executionReportJson.promptExecutions.length
11953
12078
  ? ''
11954
12079
  : " *(Some cost is unknown)*") +
@@ -12006,7 +12131,7 @@
12006
12131
  // > taskList.push(`STARTED AT ${moment(startedAt).calendar()}`);
12007
12132
  taskList.push("DURATION ".concat(duration.humanize(MOMENT_ARG_THRESHOLDS)));
12008
12133
  if (typeof ((_g = (_f = promptExecution.result) === null || _f === void 0 ? void 0 : _f.usage) === null || _g === void 0 ? void 0 : _g.price) === 'number') {
12009
- taskList.push("COST $".concat(formatNumber(promptExecution.result.usage.price * (1 + taxRate))) +
12134
+ taskList.push("COST $".concat(numberToString(promptExecution.result.usage.price * (1 + taxRate))) +
12010
12135
  (taxRate !== 0 ? " *(with tax ".concat(taxRate * 100, "%)*") : ''));
12011
12136
  }
12012
12137
  else {
@@ -13198,7 +13323,7 @@
13198
13323
  throw new PipelineExecutionError('Use callChatModel only for CHAT variant');
13199
13324
  }
13200
13325
  modelName = modelRequirements.modelName || this.getDefaultChatModel().modelName;
13201
- rawPromptContent = replaceParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
13326
+ rawPromptContent = templateParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
13202
13327
  rawRequest = {
13203
13328
  model: modelRequirements.modelName || this.getDefaultChatModel().modelName,
13204
13329
  max_tokens: modelRequirements.maxTokens || 4096,
@@ -14004,7 +14129,7 @@
14004
14129
  // <- TODO: [🈁] Use `seed` here AND/OR use is `isDeterministic` for entire execution tools
14005
14130
  // <- Note: [🧆]
14006
14131
  };
14007
- rawPromptContent = replaceParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
14132
+ rawPromptContent = templateParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
14008
14133
  messages = __spreadArray(__spreadArray([], __read((modelRequirements.systemMessage === undefined
14009
14134
  ? []
14010
14135
  : [
@@ -14119,7 +14244,7 @@
14119
14244
  console.info(colors__default["default"].bgWhite('content'), JSON.stringify(content, null, 4));
14120
14245
  console.info(colors__default["default"].bgWhite('parameters'), JSON.stringify(parameters, null, 4));
14121
14246
  }
14122
- rawPromptContent = replaceParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
14247
+ rawPromptContent = templateParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
14123
14248
  rawRequest = [
14124
14249
  modelName,
14125
14250
  [rawPromptContent],
@@ -14310,6 +14435,10 @@
14310
14435
  * For example:
14311
14436
  * - `Date` objects will be converted to string
14312
14437
  *
14438
+ * Note: There are 2 similar functions
14439
+ * - `valueToString` converts value to string for LLM models as human-readable string
14440
+ * - `asSerializable` converts value to string to preserve full information to be able to convert it back
14441
+ *
14313
14442
  * @private Internal helper function
14314
14443
  */
14315
14444
  function asSerializable(value) {
@@ -14387,7 +14516,7 @@
14387
14516
  return [4 /*yield*/, vercelProvider.chat(modelName, __assign({ user: (userId === null || userId === void 0 ? void 0 : userId.toString()) || undefined }, additionalChatSettings))];
14388
14517
  case 1:
14389
14518
  model = _b.sent();
14390
- rawPromptContent = replaceParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
14519
+ rawPromptContent = templateParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
14391
14520
  rawRequest = {
14392
14521
  // <- TODO: [☂]
14393
14522
  inputFormat: 'messages',
@@ -14784,7 +14913,7 @@
14784
14913
  type: 'json_object',
14785
14914
  };
14786
14915
  }
14787
- rawPromptContent = replaceParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
14916
+ rawPromptContent = templateParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
14788
14917
  rawRequest = __assign(__assign({}, modelSettings), { messages: __spreadArray(__spreadArray([], __read((modelRequirements.systemMessage === undefined
14789
14918
  ? []
14790
14919
  : [
@@ -14880,7 +15009,7 @@
14880
15009
  // <- TODO: [🈁] Use `seed` here AND/OR use is `isDeterministic` for entire execution tools
14881
15010
  // <- Note: [🧆]
14882
15011
  };
14883
- rawPromptContent = replaceParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
15012
+ rawPromptContent = templateParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
14884
15013
  rawRequest = __assign(__assign({}, modelSettings), { prompt: rawPromptContent, user: (_a = this.options.userId) === null || _a === void 0 ? void 0 : _a.toString() });
14885
15014
  start = $getCurrentDate();
14886
15015
  if (this.options.isVerbose) {
@@ -14952,7 +15081,7 @@
14952
15081
  throw new PipelineExecutionError('Use embed only for EMBEDDING variant');
14953
15082
  }
14954
15083
  modelName = modelRequirements.modelName || this.getDefaultEmbeddingModel().modelName;
14955
- rawPromptContent = replaceParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
15084
+ rawPromptContent = templateParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
14956
15085
  rawRequest = {
14957
15086
  input: rawPromptContent,
14958
15087
  model: modelName,
@@ -15122,7 +15251,7 @@
15122
15251
  }
15123
15252
  finally { if (e_1) throw e_1.error; }
15124
15253
  }
15125
- rawPromptContent = replaceParameters(content, __assign(__assign({}, parameters), { modelName: 'assistant' }));
15254
+ rawPromptContent = templateParameters(content, __assign(__assign({}, parameters), { modelName: 'assistant' }));
15126
15255
  rawRequest = {
15127
15256
  // TODO: [👨‍👨‍👧‍👧] ...modelSettings,
15128
15257
  // TODO: [👨‍👨‍👧‍👧][🧠] What about system message for assistants, does it make sence - combination of OpenAI assistants with Promptbook Personas