@promptbook/core 0.69.0-2 → 0.69.0-21

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 (75) hide show
  1. package/README.md +21 -58
  2. package/esm/index.es.js +2002 -1260
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/promptbook-collection/index.d.ts +0 -3
  5. package/esm/typings/src/_packages/core.index.d.ts +9 -1
  6. package/esm/typings/src/_packages/types.index.d.ts +10 -0
  7. package/esm/typings/src/_packages/utils.index.d.ts +4 -4
  8. package/esm/typings/src/cli/cli-commands/make.d.ts +1 -1
  9. package/esm/typings/src/collection/constructors/createCollectionFromUrl.d.ts +1 -1
  10. package/esm/typings/src/commands/FOREACH/ForeachCommand.d.ts +1 -1
  11. package/esm/typings/src/commands/FOREACH/ForeachJson.d.ts +6 -5
  12. package/esm/typings/src/commands/FOREACH/foreachCommandParser.d.ts +1 -2
  13. package/esm/typings/src/commands/_common/types/CommandParser.d.ts +1 -1
  14. package/esm/typings/src/config.d.ts +11 -4
  15. package/esm/typings/src/conversion/pipelineStringToJsonSync.d.ts +1 -1
  16. package/esm/typings/src/conversion/prettify/renderPipelineMermaidOptions.d.ts +3 -3
  17. package/esm/typings/src/conversion/utils/extractParameterNamesFromTemplate.d.ts +2 -1
  18. package/esm/typings/src/conversion/validation/validatePipeline.d.ts +6 -5
  19. package/esm/typings/src/execution/PipelineExecutorResult.d.ts +9 -8
  20. package/esm/typings/src/execution/createPipelineExecutor/$OngoingTemplateResult.d.ts +45 -0
  21. package/esm/typings/src/execution/createPipelineExecutor/00-CreatePipelineExecutorOptions.d.ts +20 -0
  22. package/esm/typings/src/execution/createPipelineExecutor/00-CreatePipelineExecutorSettings.d.ts +40 -0
  23. package/esm/typings/src/execution/createPipelineExecutor/00-createPipelineExecutor.d.ts +10 -0
  24. package/esm/typings/src/execution/createPipelineExecutor/10-executePipeline.d.ts +55 -0
  25. package/esm/typings/src/execution/createPipelineExecutor/20-executeTemplate.d.ts +62 -0
  26. package/esm/typings/src/execution/createPipelineExecutor/30-executeFormatCells.d.ts +19 -0
  27. package/esm/typings/src/execution/createPipelineExecutor/40-executeAttempts.d.ts +74 -0
  28. package/esm/typings/src/execution/createPipelineExecutor/filterJustOutputParameters.d.ts +34 -0
  29. package/esm/typings/src/execution/createPipelineExecutor/getContextForTemplate.d.ts +10 -0
  30. package/esm/typings/src/execution/createPipelineExecutor/getKnowledgeForTemplate.d.ts +27 -0
  31. package/esm/typings/src/execution/createPipelineExecutor/getReservedParametersForTemplate.d.ts +30 -0
  32. package/esm/typings/src/execution/createPipelineExecutor/getSamplesForTemplate.d.ts +10 -0
  33. package/esm/typings/src/execution/embeddingVectorToString.d.ts +1 -1
  34. package/esm/typings/src/execution/utils/checkExpectations.d.ts +2 -0
  35. package/esm/typings/src/execution/utils/usageToHuman.d.ts +3 -4
  36. package/esm/typings/src/formats/_common/FormatDefinition.d.ts +14 -15
  37. package/esm/typings/src/formats/_common/FormatSubvalueDefinition.d.ts +31 -0
  38. package/esm/typings/src/formats/csv/{ListFormatDefinition.d.ts → CsvFormatDefinition.d.ts} +6 -3
  39. package/esm/typings/src/formats/csv/CsvSettings.d.ts +13 -0
  40. package/esm/typings/src/formats/index.d.ts +1 -1
  41. package/esm/typings/src/formats/json/JsonFormatDefinition.d.ts +4 -3
  42. package/esm/typings/src/formats/text/TextFormatDefinition.d.ts +19 -0
  43. package/esm/typings/src/formats/xml/XmlFormatDefinition.d.ts +4 -3
  44. package/esm/typings/src/knowledge/prepare-knowledge/markdown/prepareKnowledgeFromMarkdown.d.ts +1 -1
  45. package/esm/typings/src/knowledge/prepare-knowledge/pdf/prepareKnowledgeFromPdf.d.ts +1 -1
  46. package/esm/typings/src/llm-providers/_common/utils/cache/CacheItem.d.ts +1 -1
  47. package/esm/typings/src/llm-providers/anthropic-claude/anthropic-claude-models.d.ts +1 -1
  48. package/esm/typings/src/llm-providers/anthropic-claude/createAnthropicClaudeExecutionTools.d.ts +2 -2
  49. package/esm/typings/src/llm-providers/anthropic-claude/playground/playground.d.ts +2 -2
  50. package/esm/typings/src/llm-providers/openai/playground/playground.d.ts +1 -1
  51. package/esm/typings/src/personas/preparePersona.d.ts +1 -1
  52. package/esm/typings/src/prepare/isPipelinePrepared.d.ts +1 -1
  53. package/esm/typings/src/prepare/prepareTemplates.d.ts +1 -1
  54. package/esm/typings/src/types/PipelineJson/ParameterJson.d.ts +1 -1
  55. package/esm/typings/src/types/PipelineJson/PipelineJson.d.ts +1 -1
  56. package/esm/typings/src/types/execution-report/executionReportJsonToString.d.ts +2 -1
  57. package/esm/typings/src/types/typeAliases.d.ts +1 -1
  58. package/esm/typings/src/utils/expectation-counters/index.d.ts +3 -0
  59. package/esm/typings/src/utils/organization/{f.d.ts → empty_object.d.ts} +5 -1
  60. package/esm/typings/src/utils/organization/just_empty_object.d.ts +12 -0
  61. package/esm/typings/src/utils/{extractParameterNames.d.ts → parameters/extractParameterNames.d.ts} +2 -2
  62. package/esm/typings/src/utils/parameters/mapAvailableToExpectedParameters.d.ts +27 -0
  63. package/esm/typings/src/utils/{replaceParameters.d.ts → parameters/replaceParameters.d.ts} +2 -2
  64. package/esm/typings/src/utils/serialization/checkSerializableAsJson.d.ts +1 -1
  65. package/esm/typings/src/utils/serialization/isSerializableAsJson.d.ts +1 -1
  66. package/esm/typings/src/utils/validators/parameterName/validateParameterName.d.ts +10 -0
  67. package/package.json +17 -12
  68. package/umd/index.umd.js +2008 -1263
  69. package/umd/index.umd.js.map +1 -1
  70. package/esm/typings/src/execution/createPipelineExecutor.d.ts +0 -72
  71. package/esm/typings/src/formats/list/ListFormatDefinition.d.ts +0 -16
  72. /package/esm/typings/src/utils/{extractParameterNames.test.d.ts → parameters/extractParameterNames.test.d.ts} +0 -0
  73. /package/esm/typings/src/{execution/utils/usageToHuman.test.d.ts → utils/parameters/mapAvailableToExpectedParameters.test.d.ts} +0 -0
  74. /package/esm/typings/src/utils/{replaceParameters.test.d.ts → parameters/replaceParameters.test.d.ts} +0 -0
  75. /package/esm/typings/src/{personas/preparePersona.test.d.ts → utils/validators/parameterName/validateParameterName.test.d.ts} +0 -0
package/esm/index.es.js CHANGED
@@ -2,6 +2,7 @@ import spaceTrim, { spaceTrim as spaceTrim$1 } from 'spacetrim';
2
2
  import { format } from 'prettier';
3
3
  import parserHtml from 'prettier/parser-html';
4
4
  import { forTime } from 'waitasecond';
5
+ import { unparse, parse } from 'papaparse';
5
6
  import hexEncoder from 'crypto-js/enc-hex';
6
7
  import sha256 from 'crypto-js/sha256';
7
8
  import moment from 'moment';
@@ -10,8 +11,8 @@ import moment from 'moment';
10
11
  /**
11
12
  * The version of the Promptbook library
12
13
  */
13
- var PROMPTBOOK_VERSION = '0.69.0-1';
14
- // TODO: !!!! List here all the versions and annotate + put into script
14
+ var PROMPTBOOK_VERSION = '0.69.0-20';
15
+ // TODO:[main] !!!! List here all the versions and annotate + put into script
15
16
 
16
17
  /*! *****************************************************************************
17
18
  Copyright (c) Microsoft Corporation.
@@ -223,7 +224,7 @@ function pipelineJsonToString(pipelineJson) {
223
224
  commands.push("PIPELINE URL ".concat(pipelineUrl));
224
225
  }
225
226
  commands.push("PROMPTBOOK VERSION ".concat(promptbookVersion));
226
- // TODO: !!! This increase size of the bundle and is probbably not necessary
227
+ // TODO:[main] !!! This increase size of the bundle and is probbably not necessary
227
228
  pipelineString = prettifyMarkdown(pipelineString);
228
229
  try {
229
230
  for (var _g = __values(parameters.filter(function (_a) {
@@ -371,12 +372,12 @@ function pipelineJsonToString(pipelineJson) {
371
372
  pipelineString += '```' + contentLanguage;
372
373
  pipelineString += '\n';
373
374
  pipelineString += spaceTrim(content);
374
- // <- TODO: !!! Escape
375
+ // <- TODO:[main] !!! Escape
375
376
  // <- TODO: [🧠] Some clear strategy how to spaceTrim the blocks
376
377
  pipelineString += '\n';
377
378
  pipelineString += '```';
378
379
  pipelineString += '\n\n';
379
- pipelineString += "`-> {".concat(resultingParameterName, "}`"); // <- TODO: !!! If the parameter here has description, add it and use templateParameterJsonToString
380
+ pipelineString += "`-> {".concat(resultingParameterName, "}`"); // <- TODO:[main] !!! If the parameter here has description, add it and use templateParameterJsonToString
380
381
  }
381
382
  }
382
383
  catch (e_3_1) { e_3 = { error: e_3_1 }; }
@@ -596,7 +597,7 @@ function checkSerializableAsJson(name, value) {
596
597
  }
597
598
  /**
598
599
  * TODO: [🧠][🛣] More elegant way to tracking than passing `name`
599
- * TODO: [🧠] !!! In-memory cache of same values to prevent multiple checks
600
+ * TODO: [🧠][main] !!! In-memory cache of same values to prevent multiple checks
600
601
  * Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
601
602
  */
602
603
 
@@ -652,13 +653,13 @@ var IMMEDIATE_TIME = 10;
652
653
  *
653
654
  * @public exported from `@promptbook/core`
654
655
  */
655
- var MAX_PARALLEL_COUNT = 5;
656
+ var MAX_PARALLEL_COUNT = 5; // <- TODO: [🤹‍♂️]
656
657
  /**
657
658
  * The maximum number of attempts to execute LLM task before giving up
658
659
  *
659
660
  * @public exported from `@promptbook/core`
660
661
  */
661
- var MAX_EXECUTION_ATTEMPTS = 3;
662
+ var MAX_EXECUTION_ATTEMPTS = 3; // <- TODO: [🤹‍♂️]
662
663
  /**
663
664
  * The maximum length of the (generated) filename
664
665
  *
@@ -667,14 +668,14 @@ var MAX_EXECUTION_ATTEMPTS = 3;
667
668
  var MAX_FILENAME_LENGTH = 30;
668
669
  /**
669
670
  * @@@
670
- * TODO: [🐝] !!! Use
671
+ * TODO: [🐝][main] !!! Use
671
672
  *
672
673
  * @public exported from `@promptbook/core`
673
674
  */
674
675
  var MAX_KNOWLEDGE_SOURCES_SCRAPING_DEPTH = 3;
675
676
  /**
676
677
  * @@@
677
- * TODO: [🐝] !!! Use
678
+ * TODO: [🐝][main] !!! Use
678
679
  *
679
680
  * @public exported from `@promptbook/core`
680
681
  */
@@ -709,6 +710,7 @@ var RESERVED_PARAMETER_NAMES = $asDeeplyFrozenSerializableJson('RESERVED_PARAMET
709
710
  'samples',
710
711
  'modelName',
711
712
  'currentDate',
713
+ // <- TODO: !!!!! list here all command names
712
714
  // <- TODO: Add more like 'date', 'modelName',...
713
715
  // <- TODO: Add [emoji] + instructions ACRY when adding new reserved parameter
714
716
  ]);
@@ -746,6 +748,17 @@ var DEFAULT_REMOTE_URL = 'https://api.pavolhejny.com/';
746
748
  */
747
749
  var DEFAULT_REMOTE_URL_PATH = '/promptbook/socket.io';
748
750
  // <- TODO: [🧜‍♂️]
751
+ /**
752
+ * @@@
753
+ *
754
+ * @public exported from `@promptbook/core`
755
+ */
756
+ var DEFAULT_CSV_SETTINGS = Object.freeze({
757
+ delimiter: ',',
758
+ quoteChar: '"',
759
+ newline: '\n',
760
+ skipEmptyLines: true,
761
+ });
749
762
  /**
750
763
  * @@@
751
764
  *
@@ -838,7 +851,7 @@ function isValidPromptbookVersion(version) {
838
851
  if ( /* version === '1.0.0' || */version === '2.0.0' || version === '3.0.0') {
839
852
  return false;
840
853
  }
841
- // <- TODO: !!! Check isValidPromptbookVersion against PROMPTBOOK_VERSIONS
854
+ // <- TODO:[main] !!! Check isValidPromptbookVersion against PROMPTBOOK_VERSIONS
842
855
  return true;
843
856
  }
844
857
 
@@ -1007,19 +1020,19 @@ function validatePipelineCore(pipeline) {
1007
1020
  // <- Note: [🚲]
1008
1021
  throw new PipelineLogicError(spaceTrim$1(function (block) { return "\n Invalid promptbook URL \"".concat(pipeline.pipelineUrl, "\"\n\n ").concat(block(pipelineIdentification), "\n "); }));
1009
1022
  }
1010
- if (!isValidPromptbookVersion(pipeline.promptbookVersion)) {
1023
+ if (pipeline.promptbookVersion !== undefined && !isValidPromptbookVersion(pipeline.promptbookVersion)) {
1011
1024
  // <- Note: [🚲]
1012
1025
  throw new PipelineLogicError(spaceTrim$1(function (block) { return "\n Invalid Promptbook Version \"".concat(pipeline.promptbookVersion, "\"\n\n ").concat(block(pipelineIdentification), "\n "); }));
1013
1026
  }
1014
1027
  // TODO: [🧠] Maybe do here some propper JSON-schema / ZOD checking
1015
1028
  if (!Array.isArray(pipeline.parameters)) {
1016
1029
  // TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
1017
- throw new ParseError(spaceTrim$1(function (block) { return "\n Promptbook is valid JSON but with wrong structure\n\n `promptbook.parameters` expected to be an array, but got ".concat(typeof pipeline.parameters, "\n\n ").concat(block(pipelineIdentification), "\n "); }));
1030
+ throw new ParseError(spaceTrim$1(function (block) { return "\n Pipeline is valid JSON but with wrong structure\n\n `PipelineJson.parameters` expected to be an array, but got ".concat(typeof pipeline.parameters, "\n\n ").concat(block(pipelineIdentification), "\n "); }));
1018
1031
  }
1019
1032
  // TODO: [🧠] Maybe do here some propper JSON-schema / ZOD checking
1020
1033
  if (!Array.isArray(pipeline.templates)) {
1021
1034
  // TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
1022
- throw new ParseError(spaceTrim$1(function (block) { return "\n Promptbook is valid JSON but with wrong structure\n\n `promptbook.templates` expected to be an array, but got ".concat(typeof pipeline.templates, "\n\n ").concat(block(pipelineIdentification), "\n "); }));
1035
+ throw new ParseError(spaceTrim$1(function (block) { return "\n Pipeline is valid JSON but with wrong structure\n\n `PipelineJson.templates` expected to be an array, but got ".concat(typeof pipeline.templates, "\n\n ").concat(block(pipelineIdentification), "\n "); }));
1023
1036
  }
1024
1037
  var _loop_1 = function (parameter) {
1025
1038
  if (parameter.isInput && parameter.isOutput) {
@@ -1190,6 +1203,7 @@ function validatePipelineCore(pipeline) {
1190
1203
  }
1191
1204
  }
1192
1205
  /**
1206
+ * TODO: !!!!! [🧞‍♀️] Do not allow joker + foreach
1193
1207
  * TODO: [🧠] Work with promptbookVersion
1194
1208
  * TODO: Use here some json-schema, Zod or something similar and change it to:
1195
1209
  * > /**
@@ -1201,11 +1215,11 @@ function validatePipelineCore(pipeline) {
1201
1215
  * > ex port function validatePipeline(promptbook: really_unknown): asserts promptbook is PipelineJson {
1202
1216
  */
1203
1217
  /**
1204
- * TODO: [🐣] !!!! Validate that all samples match expectations
1205
- * TODO: [🐣][🐝] !!!! Validate that knowledge is valid (non-void)
1206
- * TODO: [🐣] !!!! Validate that persona can be used only with CHAT variant
1207
- * TODO: [🐣] !!!! Validate that parameter with reserved name not used RESERVED_PARAMETER_NAMES
1208
- * TODO: [🐣] !!!! Validate that reserved parameter is not used as joker
1218
+ * TODO: [🐣][main] !!!! Validate that all samples match expectations
1219
+ * TODO: [🐣][🐝][main] !!!! Validate that knowledge is valid (non-void)
1220
+ * TODO: [🐣][main] !!!! Validate that persona can be used only with CHAT variant
1221
+ * TODO: [🐣][main] !!!! Validate that parameter with reserved name not used RESERVED_PARAMETER_NAMES
1222
+ * TODO: [🐣][main] !!!! Validate that reserved parameter is not used as joker
1209
1223
  * TODO: [🧠] Validation not only logic itself but imports around - files and websites and rerefenced pipelines exists
1210
1224
  * TODO: [🛠] Actions, instruments (and maybe knowledge) => Functions and tools
1211
1225
  */
@@ -1519,7 +1533,7 @@ function createCollectionFromUrl(url, options) {
1519
1533
  });
1520
1534
  }
1521
1535
  /**
1522
- * TODO: !!!! [🧠] Library precompilation and do not mix markdown and json promptbooks
1536
+ * TODO:[main] !!!! [🧠] Library precompilation and do not mix markdown and json promptbooks
1523
1537
  */
1524
1538
 
1525
1539
  /**
@@ -1816,7 +1830,7 @@ function forEachAsync(array, options, callbackfunction) {
1816
1830
  });
1817
1831
  }
1818
1832
 
1819
- var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.ptbk.md",promptbookVersion:"0.69.0-1",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],templates:[{templateType:"PROMPT_TEMPLATE",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"]}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[],sourceFile:"./promptbook-collection/prepare-knowledge-from-markdown.ptbk.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.ptbk.md",promptbookVersion:"0.69.0-1",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],templates:[{templateType:"PROMPT_TEMPLATE",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"]}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[],sourceFile:"./promptbook-collection/prepare-knowledge-keywords.ptbk.md"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.ptbk.md",promptbookVersion:"0.69.0-1",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],templates:[{templateType:"PROMPT_TEMPLATE",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"]}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[],sourceFile:"./promptbook-collection/prepare-knowledge-title.ptbk.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.ptbk.md",promptbookVersion:"0.69.0-1",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}],templates:[{templateType:"PROMPT_TEMPLATE",name:"make-model-requirements",title:"Make modelRequirements",content:"You are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Sample\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"]}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[],sourceFile:"./promptbook-collection/prepare-persona.ptbk.md"}];
1833
+ var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.ptbk.md",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],templates:[{templateType:"PROMPT_TEMPLATE",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"]}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[],sourceFile:"./promptbook-collection/prepare-knowledge-from-markdown.ptbk.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.ptbk.md",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],templates:[{templateType:"PROMPT_TEMPLATE",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"]}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[],sourceFile:"./promptbook-collection/prepare-knowledge-keywords.ptbk.md"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.ptbk.md",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],templates:[{templateType:"PROMPT_TEMPLATE",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"]}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[],sourceFile:"./promptbook-collection/prepare-knowledge-title.ptbk.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.ptbk.md",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}],templates:[{templateType:"PROMPT_TEMPLATE",name:"make-model-requirements",title:"Make modelRequirements",content:"You are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Sample\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"]}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[],sourceFile:"./promptbook-collection/prepare-persona.ptbk.md"}];
1820
1834
 
1821
1835
  var defaultDiacriticsRemovalMap = [
1822
1836
  {
@@ -2345,121 +2359,35 @@ function assertsExecutionSuccessful(executionResult) {
2345
2359
  */
2346
2360
 
2347
2361
  /**
2348
- * Parses the given script and returns the list of all used variables that are not defined in the script
2349
- *
2350
- * @param script from which to extract the variables
2351
- * @returns the list of variable names
2352
- * @throws {ParseError} if the script is invalid
2353
- * @public exported from `@promptbook/utils`
2354
- */
2355
- function extractVariables(script) {
2356
- var variables = new Set();
2357
- script = "(()=>{".concat(script, "})()");
2358
- try {
2359
- for (var i = 0; i < 100 /* <- TODO: This limit to configuration */; i++)
2360
- try {
2361
- eval(script);
2362
- }
2363
- catch (error) {
2364
- if (!(error instanceof ReferenceError)) {
2365
- throw error;
2366
- }
2367
- var undefinedName = error.message.split(' ')[0];
2368
- /*
2369
- Note: Parsing the error
2370
- [PipelineUrlError: thing is not defined]
2371
- */
2372
- if (!undefinedName) {
2373
- throw error;
2374
- }
2375
- if (script.includes(undefinedName + '(')) {
2376
- script = "const ".concat(undefinedName, " = ()=>'';") + script;
2377
- }
2378
- else {
2379
- variables.add(undefinedName);
2380
- script = "const ".concat(undefinedName, " = '';") + script;
2381
- }
2382
- }
2383
- }
2384
- catch (error) {
2385
- if (!(error instanceof Error)) {
2386
- throw error;
2387
- }
2388
- throw new ParseError(spaceTrim$1(function (block) { return "\n Can not extract variables from the script\n\n ".concat(block(error.toString()), "}\n "); }));
2389
- }
2390
- return variables;
2391
- }
2392
- /**
2393
- * TODO: [🔣] Support for multiple languages - python, java,...
2394
- */
2395
-
2396
- /**
2397
- * Parses the template and returns the set of all used parameters
2362
+ * Determine if the pipeline is fully prepared
2398
2363
  *
2399
- * @param template the template with used parameters
2400
- * @returns the set of parameter names
2401
- * @throws {ParseError} if the script is invalid
2402
- * @public exported from `@promptbook/utils`
2364
+ * @public exported from `@promptbook/core`
2403
2365
  */
2404
- function extractParameterNamesFromTemplate(template) {
2405
- var e_1, _a, e_2, _b, e_3, _c;
2406
- var title = template.title, description = template.description, templateType = template.templateType, content = template.content, preparedContent = template.preparedContent, jokerParameterNames = template.jokerParameterNames, foreach = template.foreach;
2407
- var parameterNames = new Set();
2408
- try {
2409
- for (var _d = __values(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read(extractParameterNames(title)), false), __read(extractParameterNames(description || '')), false), __read(extractParameterNames(content)), false), __read(extractParameterNames(preparedContent || '')), false)), _e = _d.next(); !_e.done; _e = _d.next()) {
2410
- var parameterName = _e.value;
2411
- parameterNames.add(parameterName);
2412
- }
2413
- }
2414
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
2415
- finally {
2416
- try {
2417
- if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
2418
- }
2419
- finally { if (e_1) throw e_1.error; }
2420
- }
2421
- if (templateType === 'SCRIPT_TEMPLATE') {
2422
- try {
2423
- for (var _f = __values(extractVariables(content)), _g = _f.next(); !_g.done; _g = _f.next()) {
2424
- var parameterName = _g.value;
2425
- parameterNames.add(parameterName);
2426
- }
2427
- }
2428
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
2429
- finally {
2430
- try {
2431
- if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
2432
- }
2433
- finally { if (e_2) throw e_2.error; }
2434
- }
2435
- }
2436
- try {
2437
- for (var _h = __values(jokerParameterNames || []), _j = _h.next(); !_j.done; _j = _h.next()) {
2438
- var jokerName = _j.value;
2439
- parameterNames.add(jokerName);
2440
- }
2441
- }
2442
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
2443
- finally {
2444
- try {
2445
- if (_j && !_j.done && (_c = _h.return)) _c.call(_h);
2446
- }
2447
- finally { if (e_3) throw e_3.error; }
2366
+ function isPipelinePrepared(pipeline) {
2367
+ // Note: Ignoring `pipeline.preparations` @@@
2368
+ // Note: Ignoring `pipeline.knowledgePieces` @@@
2369
+ if (!pipeline.personas.every(function (persona) { return persona.modelRequirements !== undefined; })) {
2370
+ return false;
2448
2371
  }
2449
- parameterNames.delete('content');
2450
- // <- Note {websiteContent} is used in `preparedContent`
2451
- // Note: [🍭] Fixing dependent subparameterName from FOREACH command
2452
- if (foreach !== undefined) {
2453
- if (parameterNames.has(foreach.subparameterName)) {
2454
- parameterNames.delete(foreach.subparameterName);
2455
- parameterNames.add(foreach.parameterName);
2456
- // <- TODO: [🚎] Warn/logic error when `subparameterName` not used
2457
- }
2372
+ if (!pipeline.knowledgeSources.every(function (knowledgeSource) { return knowledgeSource.preparationIds !== undefined; })) {
2373
+ return false;
2458
2374
  }
2459
- return parameterNames;
2375
+ /*
2376
+ TODO: [🧠][🍫] `templates` can not be determined if they are fully prepared SO ignoring them
2377
+ > if (!pipeline.templates.every(({ preparedContent }) => preparedContent === undefined)) {
2378
+ > return false;
2379
+ > }
2380
+ */
2381
+ return true;
2460
2382
  }
2461
2383
  /**
2462
- * TODO: [🔣] If script require contentLanguage
2384
+ * TODO: [🔃][main] !!!!! If the pipeline was prepared with different version or different set of models, prepare it once again
2385
+ * TODO: [🐠] Maybe base this on `makeValidator`
2386
+ * TODO: [🧊] Pipeline can be partially prepared, this should return true ONLY if fully prepared
2387
+ * TODO: [🧿] Maybe do same process with same granularity and subfinctions as `preparePipeline`
2388
+ * - [🏍] ? Is context in each template
2389
+ * - [♨] Are samples prepared
2390
+ * - [♨] Are templates prepared
2463
2391
  */
2464
2392
 
2465
2393
  /**
@@ -2479,27 +2407,6 @@ function serializeError(error) {
2479
2407
  };
2480
2408
  }
2481
2409
 
2482
- /**
2483
- * Function isValidJsonString will tell you if the string is valid JSON or not
2484
- *
2485
- * @public exported from `@promptbook/utils`
2486
- */
2487
- function isValidJsonString(value /* <- [👨‍⚖️] */) {
2488
- try {
2489
- JSON.parse(value);
2490
- return true;
2491
- }
2492
- catch (error) {
2493
- if (!(error instanceof Error)) {
2494
- throw error;
2495
- }
2496
- if (error.message.includes('Unexpected token')) {
2497
- return false;
2498
- }
2499
- return false;
2500
- }
2501
- }
2502
-
2503
2410
  /**
2504
2411
  * Multiple LLM Execution Tools is a proxy server that uses multiple execution tools internally and exposes the executor interface externally.
2505
2412
  *
@@ -2526,9 +2433,10 @@ var MultipleLlmExecutionTools = /** @class */ (function () {
2526
2433
  });
2527
2434
  Object.defineProperty(MultipleLlmExecutionTools.prototype, "description", {
2528
2435
  get: function () {
2529
- return this.llmExecutionTools
2530
- .map(function (tools, index) { return "".concat(index + 1, ") ").concat(tools.title, " ").concat(tools.description || ''); })
2531
- .join('\n');
2436
+ return this.llmExecutionTools.map(function (_a, index) {
2437
+ var title = _a.title;
2438
+ return "".concat(index + 1, ") `").concat(title, "`");
2439
+ }).join('\n');
2532
2440
  },
2533
2441
  enumerable: false,
2534
2442
  configurable: true
@@ -2726,9 +2634,7 @@ var MultipleLlmExecutionTools = /** @class */ (function () {
2726
2634
  throw new PipelineExecutionError("You have not provided any `LlmExecutionTools`");
2727
2635
  }
2728
2636
  else {
2729
- throw new PipelineExecutionError(spaceTrim(function (block) { return "\n You have not provided any `LlmExecutionTools` that support model variant \"".concat(prompt.modelRequirements.modelVariant, "\n\n Available `LlmExecutionTools`:\n ").concat(block(_this.llmExecutionTools
2730
- .map(function (tools) { return "- ".concat(tools.title, " ").concat(tools.description || ''); })
2731
- .join('\n')), "\n\n "); }));
2637
+ throw new PipelineExecutionError(spaceTrim(function (block) { return "\n You have not provided any `LlmExecutionTools` that support model variant \"".concat(prompt.modelRequirements.modelVariant, "\"\n\n Available `LlmExecutionTools`:\n ").concat(block(_this.description), "\n\n "); }));
2732
2638
  }
2733
2639
  }
2734
2640
  });
@@ -2794,288 +2700,153 @@ function joinLlmExecutionTools() {
2794
2700
  */
2795
2701
 
2796
2702
  /**
2797
- * Extracts all code blocks from markdown.
2703
+ * Takes an item or an array of items and returns an array of items
2798
2704
  *
2799
- * Note: There are multiple simmilar function:
2800
- * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
2801
- * - `extractJsonBlock` extracts exactly one valid JSON code block
2802
- * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
2803
- * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
2705
+ * 1) Any item except array and undefined returns array with that one item (also null)
2706
+ * 2) Undefined returns empty array
2707
+ * 3) Array returns itself
2804
2708
  *
2805
- * @param markdown any valid markdown
2806
- * @returns code blocks with language and content
2807
- * @throws {ParseError} if block is not closed properly
2808
- * @public exported from `@promptbook/markdown-utils`
2709
+ * @private internal utility
2809
2710
  */
2810
- function extractAllBlocksFromMarkdown(markdown) {
2811
- var e_1, _a;
2812
- var codeBlocks = [];
2813
- var lines = markdown.split('\n');
2814
- // Note: [0] Ensure that the last block notated by gt > will be closed
2815
- lines.push('');
2816
- var currentCodeBlock = null;
2711
+ function arrayableToArray(input) {
2712
+ if (input === undefined) {
2713
+ return [];
2714
+ }
2715
+ if (input instanceof Array) {
2716
+ return input;
2717
+ }
2718
+ return [input];
2719
+ }
2720
+
2721
+ /**
2722
+ * Parses the given script and returns the list of all used variables that are not defined in the script
2723
+ *
2724
+ * @param script from which to extract the variables
2725
+ * @returns the list of variable names
2726
+ * @throws {ParseError} if the script is invalid
2727
+ * @public exported from `@promptbook/utils`
2728
+ */
2729
+ function extractVariables(script) {
2730
+ var variables = new Set();
2731
+ script = "(()=>{".concat(script, "})()");
2817
2732
  try {
2818
- for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
2819
- var line = lines_1_1.value;
2820
- if (line.startsWith('> ') || line === '>') {
2821
- if (currentCodeBlock === null) {
2822
- currentCodeBlock = { blockNotation: '>', language: null, content: '' };
2823
- } /* not else */
2824
- if (currentCodeBlock.blockNotation === '>') {
2825
- if (currentCodeBlock.content !== '') {
2826
- currentCodeBlock.content += '\n';
2827
- }
2828
- currentCodeBlock.content += line.slice(2);
2829
- }
2830
- }
2831
- else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '>' /* <- Note: [0] */) {
2832
- codeBlocks.push(currentCodeBlock);
2833
- currentCodeBlock = null;
2733
+ for (var i = 0; i < 100 /* <- TODO: This limit to configuration */; i++)
2734
+ try {
2735
+ eval(script);
2834
2736
  }
2835
- /* not else */
2836
- if (line.startsWith('```')) {
2837
- var language = line.slice(3).trim() || null;
2838
- if (currentCodeBlock === null) {
2839
- currentCodeBlock = { blockNotation: '```', language: language, content: '' };
2737
+ catch (error) {
2738
+ if (!(error instanceof ReferenceError)) {
2739
+ throw error;
2840
2740
  }
2841
- else {
2842
- if (language !== null) {
2843
- throw new ParseError("".concat(capitalize(currentCodeBlock.language || 'the'), " code block was not closed and already opening new ").concat(language, " code block"));
2844
- }
2845
- codeBlocks.push(currentCodeBlock);
2846
- currentCodeBlock = null;
2741
+ var undefinedName = error.message.split(' ')[0];
2742
+ /*
2743
+ Note: Parsing the error
2744
+ [PipelineUrlError: thing is not defined]
2745
+ */
2746
+ if (!undefinedName) {
2747
+ throw error;
2847
2748
  }
2848
- }
2849
- else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '```') {
2850
- if (currentCodeBlock.content !== '') {
2851
- currentCodeBlock.content += '\n';
2749
+ if (script.includes(undefinedName + '(')) {
2750
+ script = "const ".concat(undefinedName, " = ()=>'';") + script;
2751
+ }
2752
+ else {
2753
+ variables.add(undefinedName);
2754
+ script = "const ".concat(undefinedName, " = '';") + script;
2852
2755
  }
2853
- currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make propper unescape */;
2854
2756
  }
2855
- }
2856
2757
  }
2857
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
2858
- finally {
2859
- try {
2860
- if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
2758
+ catch (error) {
2759
+ if (!(error instanceof Error)) {
2760
+ throw error;
2861
2761
  }
2862
- finally { if (e_1) throw e_1.error; }
2863
- }
2864
- if (currentCodeBlock !== null) {
2865
- throw new ParseError("".concat(capitalize(currentCodeBlock.language || 'the'), " code block was not closed at the end of the markdown"));
2866
- }
2867
- return codeBlocks;
2868
- }
2869
- /**
2870
- * TODO: Maybe name for `blockNotation` instead of '```' and '>'
2871
- */
2872
-
2873
- /**
2874
- * Extracts extracts exactly one valid JSON code block
2875
- *
2876
- * - When given string is a valid JSON as it is, it just returns it
2877
- * - When there is no JSON code block the function throws a `ParseError`
2878
- * - When there are multiple JSON code blocks the function throws a `ParseError`
2879
- *
2880
- * Note: It is not important if marked as ```json BUT if it is VALID JSON
2881
- * Note: There are multiple simmilar function:
2882
- * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
2883
- * - `extractJsonBlock` extracts exactly one valid JSON code block
2884
- * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
2885
- * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
2886
- *
2887
- * @public exported from `@promptbook/markdown-utils`
2888
- * @throws {ParseError} if there is no valid JSON block in the markdown
2889
- */
2890
- function extractJsonBlock(markdown) {
2891
- if (isValidJsonString(markdown)) {
2892
- return markdown;
2893
- }
2894
- var codeBlocks = extractAllBlocksFromMarkdown(markdown);
2895
- var jsonBlocks = codeBlocks.filter(function (_a) {
2896
- var content = _a.content;
2897
- return isValidJsonString(content);
2898
- });
2899
- if (jsonBlocks.length === 0) {
2900
- throw new Error('There is no valid JSON block in the markdown');
2901
- }
2902
- if (jsonBlocks.length > 1) {
2903
- throw new Error('There are multiple JSON code blocks in the markdown');
2904
- }
2905
- return jsonBlocks[0].content;
2906
- }
2907
- /**
2908
- * TODO: Add some auto-healing logic + extract YAML, JSON5, TOML, etc.
2909
- * TODO: [🏢] Make this logic part of `JsonFormatDefinition` or `isValidJsonString`
2910
- */
2911
-
2912
- /**
2913
- * Determine if the pipeline is fully prepared
2914
- *
2915
- * @public exported from `@promptbook/core`
2916
- */
2917
- function isPipelinePrepared(pipeline) {
2918
- // Note: Ignoring `pipeline.preparations` @@@
2919
- // Note: Ignoring `pipeline.knowledgePieces` @@@
2920
- if (!pipeline.personas.every(function (persona) { return persona.modelRequirements !== undefined; })) {
2921
- return false;
2922
- }
2923
- if (!pipeline.knowledgeSources.every(function (knowledgeSource) { return knowledgeSource.preparationIds !== undefined; })) {
2924
- return false;
2925
- }
2926
- /*
2927
- TODO: [🧠][🍫] `templates` can not be determined if they are fully prepared SO ignoring them
2928
- > if (!pipeline.templates.every(({ preparedContent }) => preparedContent === undefined)) {
2929
- > return false;
2930
- > }
2931
- */
2932
- return true;
2933
- }
2934
- /**
2935
- * TODO: [🔃] !!!!! If the pipeline was prepared with different version or different set of models, prepare it once again
2936
- * TODO: [🐠] Maybe base this on `makeValidator`
2937
- * TODO: [🧊] Pipeline can be partially prepared, this should return true ONLY if fully prepared
2938
- * TODO: [🧿] Maybe do same process with same granularity and subfinctions as `preparePipeline`
2939
- * - [🏍] ? Is context in each template
2940
- * - [♨] Are samples prepared
2941
- * - [♨] Are templates prepared
2942
- */
2943
-
2944
- /**
2945
- * Takes an item or an array of items and returns an array of items
2946
- *
2947
- * 1) Any item except array and undefined returns array with that one item (also null)
2948
- * 2) Undefined returns empty array
2949
- * 3) Array returns itself
2950
- *
2951
- * @private internal utility
2952
- */
2953
- function arrayableToArray(input) {
2954
- if (input === undefined) {
2955
- return [];
2956
- }
2957
- if (input instanceof Array) {
2958
- return input;
2959
- }
2960
- return [input];
2961
- }
2962
-
2963
- /**
2964
- * Just says that the variable is not used but should be kept
2965
- * No side effects.
2966
- *
2967
- * Note: It can be usefull for:
2968
- *
2969
- * 1) Suppressing eager optimization of unused imports
2970
- * 2) Suppressing eslint errors of unused variables in the tests
2971
- * 3) Keeping the type of the variable for type testing
2972
- *
2973
- * @param value any values
2974
- * @returns void
2975
- * @private within the repository
2976
- */
2977
- function keepUnused() {
2978
- var valuesToKeep = [];
2979
- for (var _i = 0; _i < arguments.length; _i++) {
2980
- valuesToKeep[_i] = arguments[_i];
2762
+ throw new ParseError(spaceTrim$1(function (block) { return "\n Can not extract variables from the script\n\n ".concat(block(error.toString()), "}\n "); }));
2981
2763
  }
2764
+ return variables;
2982
2765
  }
2983
-
2984
2766
  /**
2985
- * Just marks a place of place where should be something implemented
2986
- * No side effects.
2987
- *
2988
- * Note: It can be usefull suppressing eslint errors of unused variables
2989
- *
2990
- * @param value any values
2991
- * @returns void
2992
- * @private within the repository
2767
+ * TODO: [🔣] Support for multiple languages - python, java,...
2993
2768
  */
2994
- function TODO_USE() {
2995
- var value = [];
2996
- for (var _i = 0; _i < arguments.length; _i++) {
2997
- value[_i] = arguments[_i];
2998
- }
2999
- }
3000
2769
 
3001
2770
  /**
3002
- * Replaces parameters in template with values from parameters object
2771
+ * Parses the template and returns the set of all used parameters
3003
2772
  *
3004
- * @param template the template with parameters in {curly} braces
3005
- * @param parameters the object with parameters
3006
- * @returns the template with replaced parameters
3007
- * @throws {PipelineExecutionError} if parameter is not defined, not closed, or not opened
2773
+ * @param template the template with used parameters
2774
+ * @returns the set of parameter names
2775
+ * @throws {ParseError} if the script is invalid
3008
2776
  * @public exported from `@promptbook/utils`
3009
2777
  */
3010
- function replaceParameters(template, parameters) {
3011
- var e_1, _a;
2778
+ function extractParameterNamesFromTemplate(template) {
2779
+ var e_1, _a, e_2, _b, e_3, _c, e_4, _d;
2780
+ var title = template.title, description = template.description, templateType = template.templateType, content = template.content, preparedContent = template.preparedContent, jokerParameterNames = template.jokerParameterNames, foreach = template.foreach;
2781
+ var parameterNames = new Set();
3012
2782
  try {
3013
- for (var _b = __values(Object.entries(parameters)), _c = _b.next(); !_c.done; _c = _b.next()) {
3014
- var _d = __read(_c.value, 2), parameterName = _d[0], parameterValue = _d[1];
3015
- if (parameterValue === RESERVED_PARAMETER_MISSING_VALUE) {
3016
- throw new UnexpectedError("Parameter {".concat(parameterName, "} has missing value"));
3017
- }
3018
- else if (parameterValue === RESERVED_PARAMETER_RESTRICTED) {
3019
- // TODO: [🍵]
3020
- throw new UnexpectedError("Parameter {".concat(parameterName, "} is restricted to use"));
3021
- }
2783
+ for (var _e = __values(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read(extractParameterNames(title)), false), __read(extractParameterNames(description || '')), false), __read(extractParameterNames(content)), false), __read(extractParameterNames(preparedContent || '')), false)), _f = _e.next(); !_f.done; _f = _e.next()) {
2784
+ var parameterName = _f.value;
2785
+ parameterNames.add(parameterName);
3022
2786
  }
3023
2787
  }
3024
2788
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
3025
2789
  finally {
3026
2790
  try {
3027
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
2791
+ if (_f && !_f.done && (_a = _e.return)) _a.call(_e);
3028
2792
  }
3029
2793
  finally { if (e_1) throw e_1.error; }
3030
2794
  }
3031
- var replacedTemplate = template;
3032
- var match;
3033
- var loopLimit = LOOP_LIMIT;
3034
- var _loop_1 = function () {
3035
- if (loopLimit-- < 0) {
3036
- throw new LimitReachedError('Loop limit reached during parameters replacement in `replaceParameters`');
2795
+ if (templateType === 'SCRIPT_TEMPLATE') {
2796
+ try {
2797
+ for (var _g = __values(extractVariables(content)), _h = _g.next(); !_h.done; _h = _g.next()) {
2798
+ var parameterName = _h.value;
2799
+ parameterNames.add(parameterName);
2800
+ }
3037
2801
  }
3038
- var precol = match.groups.precol;
3039
- var parameterName = match.groups.parameterName;
3040
- if (parameterName === '') {
3041
- return "continue";
2802
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
2803
+ finally {
2804
+ try {
2805
+ if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
2806
+ }
2807
+ finally { if (e_2) throw e_2.error; }
3042
2808
  }
3043
- if (parameterName.indexOf('{') !== -1 || parameterName.indexOf('}') !== -1) {
3044
- throw new PipelineExecutionError('Parameter is already opened or not closed');
2809
+ }
2810
+ try {
2811
+ for (var _j = __values(jokerParameterNames || []), _k = _j.next(); !_k.done; _k = _j.next()) {
2812
+ var jokerName = _k.value;
2813
+ parameterNames.add(jokerName);
3045
2814
  }
3046
- if (parameters[parameterName] === undefined) {
3047
- throw new PipelineExecutionError("Parameter {".concat(parameterName, "} is not defined"));
2815
+ }
2816
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
2817
+ finally {
2818
+ try {
2819
+ if (_k && !_k.done && (_c = _j.return)) _c.call(_j);
3048
2820
  }
3049
- var parameterValue = parameters[parameterName];
3050
- if (parameterValue === undefined) {
3051
- throw new PipelineExecutionError("Parameter {".concat(parameterName, "} is not defined"));
2821
+ finally { if (e_3) throw e_3.error; }
2822
+ }
2823
+ parameterNames.delete('content');
2824
+ // <- Note {websiteContent} is used in `preparedContent`
2825
+ // Note: [🍭] Fixing dependent subparameterName from FOREACH command
2826
+ if (foreach !== undefined) {
2827
+ try {
2828
+ for (var _l = __values(foreach.inputSubparameterNames), _m = _l.next(); !_m.done; _m = _l.next()) {
2829
+ var subparameterName = _m.value;
2830
+ if (parameterNames.has(subparameterName)) {
2831
+ parameterNames.delete(subparameterName);
2832
+ parameterNames.add(foreach.parameterName);
2833
+ // <- TODO: [🚎] Warn/logic error when `subparameterName` not used
2834
+ }
2835
+ }
3052
2836
  }
3053
- parameterValue = parameterValue.toString();
3054
- if (parameterValue.includes('\n') && /^\s*\W{0,3}\s*$/.test(precol)) {
3055
- parameterValue = parameterValue
3056
- .split('\n')
3057
- .map(function (line, index) { return (index === 0 ? line : "".concat(precol).concat(line)); })
3058
- .join('\n');
2837
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
2838
+ finally {
2839
+ try {
2840
+ if (_m && !_m.done && (_d = _l.return)) _d.call(_l);
2841
+ }
2842
+ finally { if (e_4) throw e_4.error; }
3059
2843
  }
3060
- replacedTemplate =
3061
- replacedTemplate.substring(0, match.index + precol.length) +
3062
- parameterValue +
3063
- replacedTemplate.substring(match.index + precol.length + parameterName.length + 2);
3064
- };
3065
- while ((match = /^(?<precol>.*){(?<parameterName>\w+)}(.*)/m /* <- Not global */
3066
- .exec(replacedTemplate))) {
3067
- _loop_1();
3068
- }
3069
- // [💫] Check if there are parameters that are not closed properly
3070
- if (/{\w+$/.test(replacedTemplate)) {
3071
- throw new PipelineExecutionError('Parameter is not closed');
3072
- }
3073
- // [💫] Check if there are parameters that are not opened properly
3074
- if (/^\w+}/.test(replacedTemplate)) {
3075
- throw new PipelineExecutionError('Parameter is not opened');
3076
2844
  }
3077
- return replacedTemplate;
2845
+ return parameterNames;
3078
2846
  }
2847
+ /**
2848
+ * TODO: [🔣] If script require contentLanguage
2849
+ */
3079
2850
 
3080
2851
  /**
3081
2852
  * Create difference set of two sets.
@@ -3153,117 +2924,351 @@ function union() {
3153
2924
  }
3154
2925
 
3155
2926
  /**
3156
- * Counts number of characters in the text
2927
+ * Just marks a place of place where should be something implemented
2928
+ * No side effects.
3157
2929
  *
3158
- * @public exported from `@promptbook/utils`
2930
+ * Note: It can be usefull suppressing eslint errors of unused variables
2931
+ *
2932
+ * @param value any values
2933
+ * @returns void
2934
+ * @private within the repository
3159
2935
  */
3160
- function countCharacters(text) {
3161
- // Remove null characters
3162
- text = text.replace(/\0/g, '');
3163
- // Replace emojis (and also ZWJ sequence) with hyphens
3164
- text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
3165
- text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
3166
- text = text.replace(/\p{Extended_Pictographic}(\u{200D}\p{Extended_Pictographic})*/gu, '-');
3167
- return text.length;
2936
+ function TODO_USE() {
2937
+ var value = [];
2938
+ for (var _i = 0; _i < arguments.length; _i++) {
2939
+ value[_i] = arguments[_i];
2940
+ }
3168
2941
  }
3169
2942
 
3170
2943
  /**
3171
- * Counts number of lines in the text
2944
+ * @@@
3172
2945
  *
3173
- * @public exported from `@promptbook/utils`
2946
+ * @public exported from `@promptbook/core`
3174
2947
  */
3175
- function countLines(text) {
3176
- if (text === '') {
3177
- return 0;
3178
- }
3179
- return text.split('\n').length;
3180
- }
2948
+ var MANDATORY_CSV_SETTINGS = Object.freeze({
2949
+ header: true,
2950
+ // encoding: 'utf8',
2951
+ });
3181
2952
 
3182
2953
  /**
3183
- * Counts number of pages in the text
2954
+ * Definition for CSV spreadsheet
3184
2955
  *
3185
- * @public exported from `@promptbook/utils`
2956
+ * @public exported from `@promptbook/core`
2957
+ * <- TODO: [🏢] Export from package `@promptbook/csv`
2958
+ */
2959
+ var CsvFormatDefinition = {
2960
+ formatName: 'CSV',
2961
+ aliases: ['SPREADSHEET', 'TABLE'],
2962
+ isValid: function (value, settings, schema) {
2963
+ // TODO: !!!!!! Implement CSV validation
2964
+ TODO_USE(value /* <- TODO: Use value here */);
2965
+ TODO_USE(settings /* <- TODO: Use settings here */);
2966
+ TODO_USE(schema /* <- TODO: Use schema here */);
2967
+ return true;
2968
+ },
2969
+ canBeValid: function (partialValue, settings, schema) {
2970
+ TODO_USE(partialValue /* <- TODO: Use partialValue here */);
2971
+ TODO_USE(settings /* <- TODO: Use settings here */);
2972
+ TODO_USE(schema /* <- TODO: Use schema here */);
2973
+ return true;
2974
+ },
2975
+ heal: function (value, settings, schema) {
2976
+ TODO_USE(value /* <- TODO: Use partialValue here */);
2977
+ TODO_USE(settings /* <- TODO: Use settings here */);
2978
+ TODO_USE(schema /* <- TODO: Use schema here */);
2979
+ throw new Error('Not implemented');
2980
+ },
2981
+ subvalueDefinitions: [
2982
+ {
2983
+ subvalueName: 'ROW',
2984
+ mapValues: function (value, outputParameterName, settings, mapCallback) {
2985
+ return __awaiter(this, void 0, void 0, function () {
2986
+ var csv, mappedData;
2987
+ var _this = this;
2988
+ return __generator(this, function (_a) {
2989
+ switch (_a.label) {
2990
+ case 0:
2991
+ csv = parse(value, __assign(__assign({}, settings), MANDATORY_CSV_SETTINGS));
2992
+ if (csv.errors.length !== 0) {
2993
+ throw new ParseError(// <- TODO: !!!!!! Split PipelineParseError and FormatParseError -> CsvParseError
2994
+ spaceTrim(function (block) { return "\n CSV parsing error\n\n ".concat(block(csv.errors.map(function (error) { return error.message; }).join('\n\n')), "\n "); }));
2995
+ }
2996
+ return [4 /*yield*/, Promise.all(csv.data.map(function (row, index) { return __awaiter(_this, void 0, void 0, function () {
2997
+ var _a, _b;
2998
+ var _c;
2999
+ return __generator(this, function (_d) {
3000
+ switch (_d.label) {
3001
+ case 0:
3002
+ if (row[outputParameterName]) {
3003
+ throw new ParseError(// <- TODO: !!!!!! Split PipelineParseError and FormatParseError -> CsvParseError
3004
+ "Can not overwrite existing column \"".concat(outputParameterName, "\" in CSV row"));
3005
+ }
3006
+ _a = [__assign({}, row)];
3007
+ _c = {};
3008
+ _b = outputParameterName;
3009
+ return [4 /*yield*/, mapCallback(row, index)];
3010
+ case 1: return [2 /*return*/, __assign.apply(void 0, _a.concat([(_c[_b] = _d.sent(), _c)]))];
3011
+ }
3012
+ });
3013
+ }); }))];
3014
+ case 1:
3015
+ mappedData = _a.sent();
3016
+ return [2 /*return*/, unparse(mappedData, __assign(__assign({}, settings), MANDATORY_CSV_SETTINGS))];
3017
+ }
3018
+ });
3019
+ });
3020
+ },
3021
+ },
3022
+ {
3023
+ subvalueName: 'CELL',
3024
+ mapValues: function (value, outputParameterName, settings, mapCallback) {
3025
+ return __awaiter(this, void 0, void 0, function () {
3026
+ var csv, mappedData;
3027
+ var _this = this;
3028
+ return __generator(this, function (_a) {
3029
+ switch (_a.label) {
3030
+ case 0:
3031
+ csv = parse(value, __assign(__assign({}, settings), MANDATORY_CSV_SETTINGS));
3032
+ if (csv.errors.length !== 0) {
3033
+ throw new ParseError(// <- TODO: !!!!!! Split PipelineParseError and FormatParseError -> CsvParseError
3034
+ spaceTrim(function (block) { return "\n CSV parsing error\n\n ".concat(block(csv.errors.map(function (error) { return error.message; }).join('\n\n')), "\n "); }));
3035
+ }
3036
+ return [4 /*yield*/, Promise.all(csv.data.map(function (row, rowIndex) { return __awaiter(_this, void 0, void 0, function () {
3037
+ var _this = this;
3038
+ return __generator(this, function (_a) {
3039
+ return [2 /*return*/, /* not await */ Promise.all(Object.entries(row).map(function (_a, columnIndex) {
3040
+ var _b = __read(_a, 2), key = _b[0], value = _b[1];
3041
+ return __awaiter(_this, void 0, void 0, function () {
3042
+ var index;
3043
+ var _c;
3044
+ return __generator(this, function (_d) {
3045
+ index = rowIndex * Object.keys(row).length + columnIndex;
3046
+ return [2 /*return*/, /* not await */ mapCallback((_c = {}, _c[key] = value, _c), index)];
3047
+ });
3048
+ });
3049
+ }))];
3050
+ });
3051
+ }); }))];
3052
+ case 1:
3053
+ mappedData = _a.sent();
3054
+ return [2 /*return*/, unparse(mappedData, __assign(__assign({}, settings), MANDATORY_CSV_SETTINGS))];
3055
+ }
3056
+ });
3057
+ });
3058
+ },
3059
+ },
3060
+ ],
3061
+ };
3062
+ /**
3063
+ * TODO: [🍓] In `CsvFormatDefinition` implement simple `isValid`
3064
+ * TODO: [🍓] In `CsvFormatDefinition` implement partial `canBeValid`
3065
+ * TODO: [🍓] In `CsvFormatDefinition` implement `heal
3066
+ * TODO: [🍓] In `CsvFormatDefinition` implement `subvalueDefinitions`
3067
+ * TODO: [🏢] Allow to expect something inside CSV objects and other formats
3186
3068
  */
3187
- function countPages(text) {
3188
- var sentencesPerPage = 5; // Assuming each page has 5 sentences
3189
- var sentences = text.split(/[.!?]+/).filter(function (sentence) { return sentence.trim() !== ''; });
3190
- var pageCount = Math.ceil(sentences.length / sentencesPerPage);
3191
- return pageCount;
3192
- }
3193
3069
 
3194
3070
  /**
3195
- * Counts number of paragraphs in the text
3071
+ * Function isValidJsonString will tell you if the string is valid JSON or not
3196
3072
  *
3197
3073
  * @public exported from `@promptbook/utils`
3198
3074
  */
3199
- function countParagraphs(text) {
3200
- return text.split(/\n\s*\n/).filter(function (paragraph) { return paragraph.trim() !== ''; }).length;
3075
+ function isValidJsonString(value /* <- [👨‍⚖️] */) {
3076
+ try {
3077
+ JSON.parse(value);
3078
+ return true;
3079
+ }
3080
+ catch (error) {
3081
+ if (!(error instanceof Error)) {
3082
+ throw error;
3083
+ }
3084
+ if (error.message.includes('Unexpected token')) {
3085
+ return false;
3086
+ }
3087
+ return false;
3088
+ }
3201
3089
  }
3202
3090
 
3203
3091
  /**
3204
- * Split text into sentences
3092
+ * Definition for JSON format
3205
3093
  *
3206
- * @public exported from `@promptbook/utils`
3094
+ * @private still in development [🏢]
3207
3095
  */
3208
- function splitIntoSentences(text) {
3209
- return text.split(/[.!?]+/).filter(function (sentence) { return sentence.trim() !== ''; });
3210
- }
3096
+ var JsonFormatDefinition = {
3097
+ formatName: 'JSON',
3098
+ mimeType: 'application/json',
3099
+ isValid: function (value, settings, schema) {
3100
+ TODO_USE(schema /* <- TODO: Use schema here */);
3101
+ TODO_USE(settings /* <- TODO: Use settings here */);
3102
+ return isValidJsonString(value);
3103
+ },
3104
+ canBeValid: function (partialValue, settings, schema) {
3105
+ TODO_USE(partialValue /* <- TODO: Use partialValue here */);
3106
+ TODO_USE(settings /* <- TODO: Use settings here */);
3107
+ TODO_USE(schema /* <- TODO: Use schema here */);
3108
+ return true;
3109
+ },
3110
+ heal: function (value, settings, schema) {
3111
+ TODO_USE(value /* <- TODO: Use partialValue here */);
3112
+ TODO_USE(settings /* <- TODO: Use settings here */);
3113
+ TODO_USE(schema /* <- TODO: Use schema here */);
3114
+ throw new Error('Not implemented');
3115
+ },
3116
+ subvalueDefinitions: [],
3117
+ };
3211
3118
  /**
3212
- * Counts number of sentences in the text
3213
- *
3214
- * @public exported from `@promptbook/utils`
3119
+ * TODO: [🧠] Maybe propper instance of object
3120
+ * TODO: [0] Make string_serialized_json
3121
+ * TODO: [1] Make type for JSON Settings and Schema
3122
+ * TODO: [🧠] What to use for validating JSONs - JSON Schema, ZoD, typescript types/interfaces,...?
3123
+ * TODO: [🍓] In `JsonFormatDefinition` implement simple `isValid`
3124
+ * TODO: [🍓] In `JsonFormatDefinition` implement partial `canBeValid`
3125
+ * TODO: [🍓] In `JsonFormatDefinition` implement `heal
3126
+ * TODO: [🍓] In `JsonFormatDefinition` implement `subvalueDefinitions`
3127
+ * TODO: [🏢] Allow to expect something inside JSON objects and other formats
3215
3128
  */
3216
- function countSentences(text) {
3217
- return splitIntoSentences(text).length;
3218
- }
3219
3129
 
3220
3130
  /**
3221
- * Counts number of words in the text
3131
+ * Definition for any text - this will be always valid
3222
3132
  *
3223
- * @public exported from `@promptbook/utils`
3133
+ * Note: This is not useful for validation, but for splitting and mapping with `subvalueDefinitions`
3134
+ *
3135
+ * @public exported from `@promptbook/core`
3136
+ */
3137
+ var TextFormatDefinition = {
3138
+ formatName: 'TEXT',
3139
+ isValid: function (value) {
3140
+ return typeof value === 'string';
3141
+ },
3142
+ canBeValid: function (partialValue) {
3143
+ return typeof partialValue === 'string';
3144
+ },
3145
+ heal: function () {
3146
+ throw new UnexpectedError('It does not make sense to call `TextFormatDefinition.heal`');
3147
+ },
3148
+ subvalueDefinitions: [
3149
+ {
3150
+ subvalueName: 'LINE',
3151
+ mapValues: function (value, outputParameterName, settings, mapCallback) {
3152
+ return __awaiter(this, void 0, void 0, function () {
3153
+ var lines, mappedLines;
3154
+ return __generator(this, function (_a) {
3155
+ switch (_a.label) {
3156
+ case 0:
3157
+ lines = value.split('\n');
3158
+ return [4 /*yield*/, Promise.all(lines.map(function (lineContent, lineNumber) {
3159
+ // TODO: [🧠] Maybe option to skip empty line
3160
+ /* not await */ return mapCallback({
3161
+ lineContent: lineContent,
3162
+ // TODO: [🧠] Maybe also put here `lineNumber`
3163
+ }, lineNumber);
3164
+ }))];
3165
+ case 1:
3166
+ mappedLines = _a.sent();
3167
+ return [2 /*return*/, mappedLines.join('\n')];
3168
+ }
3169
+ });
3170
+ });
3171
+ },
3172
+ },
3173
+ // <- TODO: [🧠][🤠] Here should be all words, characters, lines, paragraphs, pages aviable as subvalues
3174
+ ],
3175
+ };
3176
+ /**
3177
+ * TODO: [1] Make type for XML Text and Schema
3178
+ * TODO: [🧠][🤠] Here should be all words, characters, lines, paragraphs, pages aviable as subvalues
3179
+ * TODO: [🍓] In `TextFormatDefinition` implement simple `isValid`
3180
+ * TODO: [🍓] In `TextFormatDefinition` implement partial `canBeValid`
3181
+ * TODO: [🍓] In `TextFormatDefinition` implement `heal
3182
+ * TODO: [🍓] In `TextFormatDefinition` implement `subvalueDefinitions`
3183
+ * TODO: [🏢] Allow to expect something inside each item of list and other formats
3224
3184
  */
3225
- function countWords(text) {
3226
- text = text.replace(/[\p{Extended_Pictographic}]/gu, 'a');
3227
- text = removeDiacritics(text);
3228
- return text.split(/[^a-zа-я0-9]+/i).filter(function (word) { return word.length > 0; }).length;
3229
- }
3230
3185
 
3231
3186
  /**
3232
- * Index of all counter functions
3187
+ * Definition for XML format
3233
3188
  *
3234
- * @public exported from `@promptbook/utils`
3189
+ * @private still in development [🏢]
3235
3190
  */
3236
- var CountUtils = {
3237
- CHARACTERS: countCharacters,
3238
- WORDS: countWords,
3239
- SENTENCES: countSentences,
3240
- PARAGRAPHS: countParagraphs,
3241
- LINES: countLines,
3242
- PAGES: countPages,
3191
+ var XmlFormatDefinition = {
3192
+ formatName: 'XML',
3193
+ mimeType: 'application/xml',
3194
+ isValid: function (value, settings, schema) {
3195
+ TODO_USE(value /* <- TODO: Use value here */);
3196
+ TODO_USE(settings /* <- TODO: Use settings here */);
3197
+ TODO_USE(schema /* <- TODO: Use schema here */);
3198
+ return true;
3199
+ },
3200
+ canBeValid: function (partialValue, settings, schema) {
3201
+ TODO_USE(partialValue /* <- TODO: Use partialValue here */);
3202
+ TODO_USE(settings /* <- TODO: Use settings here */);
3203
+ TODO_USE(schema /* <- TODO: Use schema here */);
3204
+ return true;
3205
+ },
3206
+ heal: function (value, settings, schema) {
3207
+ TODO_USE(value /* <- TODO: Use partialValue here */);
3208
+ TODO_USE(settings /* <- TODO: Use settings here */);
3209
+ TODO_USE(schema /* <- TODO: Use schema here */);
3210
+ throw new Error('Not implemented');
3211
+ },
3212
+ subvalueDefinitions: [],
3243
3213
  };
3214
+ /**
3215
+ * TODO: [🧠] Maybe propper instance of object
3216
+ * TODO: [0] Make string_serialized_xml
3217
+ * TODO: [1] Make type for XML Settings and Schema
3218
+ * TODO: [🧠] What to use for validating XMLs - XSD,...
3219
+ * TODO: [🍓] In `XmlFormatDefinition` implement simple `isValid`
3220
+ * TODO: [🍓] In `XmlFormatDefinition` implement partial `canBeValid`
3221
+ * TODO: [🍓] In `XmlFormatDefinition` implement `heal
3222
+ * TODO: [🍓] In `XmlFormatDefinition` implement `subvalueDefinitions`
3223
+ * TODO: [🏢] Allow to expect something inside XML and other formats
3224
+ */
3244
3225
 
3245
3226
  /**
3246
- * Function checkExpectations will check if the expectations on given value are met
3227
+ * Definitions for all formats supported by Promptbook
3247
3228
  *
3248
- * Note: There are two simmilar functions:
3249
- * - `checkExpectations` which throws an error if the expectations are not met
3250
- * - `isPassingExpectations` which returns a boolean
3229
+ * @private internal index of `...` <- TODO [🏢]
3230
+ */
3231
+ var FORMAT_DEFINITIONS = [
3232
+ JsonFormatDefinition,
3233
+ XmlFormatDefinition,
3234
+ TextFormatDefinition,
3235
+ CsvFormatDefinition,
3236
+ ];
3237
+
3238
+ /**
3239
+ * Maps available parameters to expected parameters
3251
3240
  *
3252
- * @throws {ExpectError} if the expectations are not met
3253
- * @returns {void} Nothing
3254
- * @private internal function of `createPipelineExecutor`
3241
+ * The strategy is:
3242
+ * 1) @@@
3243
+ * 2) @@@
3244
+ *
3245
+ * @throws {PipelineExecutionError} @@@
3246
+ * @private within the repository used in `createPipelineExecutor`
3255
3247
  */
3256
- function checkExpectations(expectations, value) {
3248
+ function mapAvailableToExpectedParameters(options) {
3257
3249
  var e_1, _a;
3250
+ var expectedParameters = options.expectedParameters, availableParameters = options.availableParameters;
3251
+ var availableParametersNames = new Set(Object.keys(availableParameters));
3252
+ var expectedParameterNames = new Set(Object.keys(expectedParameters));
3253
+ var mappedParameters = {};
3258
3254
  try {
3259
- for (var _b = __values(Object.entries(expectations)), _c = _b.next(); !_c.done; _c = _b.next()) {
3260
- var _d = __read(_c.value, 2), unit = _d[0], _e = _d[1], max = _e.max, min = _e.min;
3261
- var amount = CountUtils[unit.toUpperCase()](value);
3262
- if (min && amount < min) {
3263
- throw new ExpectError("Expected at least ".concat(min, " ").concat(unit, " but got ").concat(amount));
3264
- } /* not else */
3265
- if (max && amount > max) {
3266
- throw new ExpectError("Expected at most ".concat(max, " ").concat(unit, " but got ").concat(amount));
3255
+ // Phase 1️⃣: Matching mapping
3256
+ for (var _b = __values(Array.from(union(availableParametersNames, expectedParameterNames))), _c = _b.next(); !_c.done; _c = _b.next()) {
3257
+ var parameterName = _c.value;
3258
+ // Situation: Parameter is available and expected
3259
+ if (availableParametersNames.has(parameterName) && expectedParameterNames.has(parameterName)) {
3260
+ mappedParameters[parameterName] = availableParameters[parameterName];
3261
+ // <- Note: [👩‍👩‍👧] Maybe detect parameter collision here?
3262
+ availableParametersNames.delete(parameterName);
3263
+ expectedParameterNames.delete(parameterName);
3264
+ }
3265
+ // Situation: Parameter is available but NOT expected
3266
+ else if (availableParametersNames.has(parameterName) && !expectedParameterNames.has(parameterName)) {
3267
+ // [🐱‍👤] Do not pass this parameter to prompt - Maybe use it non-matching mapping
3268
+ }
3269
+ // Situation: Parameter is NOT available BUT expected
3270
+ else if (!availableParametersNames.has(parameterName) && expectedParameterNames.has(parameterName)) {
3271
+ // Do nothing here - this will be maybe fixed in the non-matching mapping
3267
3272
  }
3268
3273
  }
3269
3274
  }
@@ -3274,636 +3279,1139 @@ function checkExpectations(expectations, value) {
3274
3279
  }
3275
3280
  finally { if (e_1) throw e_1.error; }
3276
3281
  }
3282
+ if (expectedParameterNames.size === 0) {
3283
+ // Note: [👨‍👨‍👧] Now we can freeze `mappedParameters` to prevent @@@
3284
+ Object.freeze(mappedParameters);
3285
+ return mappedParameters;
3286
+ }
3287
+ // Phase 2️⃣: Non-matching mapping
3288
+ if (expectedParameterNames.size !== availableParametersNames.size) {
3289
+ throw new PipelineExecutionError(spaceTrim(function (block) { return "\n Can not map available parameters to expected parameters\n\n Mapped parameters:\n ".concat(block(Object.keys(mappedParameters)
3290
+ .map(function (parameterName) { return "- {".concat(parameterName, "}"); })
3291
+ .join('\n')), "\n\n Expected parameters which can not be mapped:\n ").concat(block(Array.from(expectedParameterNames)
3292
+ .map(function (parameterName) { return "- {".concat(parameterName, "}"); })
3293
+ .join('\n')), "\n\n Remaining available parameters:\n ").concat(block(Array.from(availableParametersNames)
3294
+ .map(function (parameterName) { return "- {".concat(parameterName, "}"); })
3295
+ .join('\n')), "\n\n "); }));
3296
+ }
3297
+ var expectedParameterNamesArray = Array.from(expectedParameterNames);
3298
+ var availableParametersNamesArray = Array.from(availableParametersNames);
3299
+ for (var i = 0; i < expectedParameterNames.size; i++) {
3300
+ mappedParameters[expectedParameterNamesArray[i]] = availableParameters[availableParametersNamesArray[i]];
3301
+ }
3302
+ // Note: [👨‍👨‍👧] Now we can freeze `mappedParameters` to prevent @@@
3303
+ Object.freeze(mappedParameters);
3304
+ return mappedParameters;
3277
3305
  }
3306
+
3278
3307
  /**
3279
- * Function checkExpectations will check if the expectations on given value are met
3308
+ * Extracts all code blocks from markdown.
3280
3309
  *
3281
- * Note: There are two simmilar functions:
3282
- * - `checkExpectations` which throws an error if the expectations are not met
3283
- * - `isPassingExpectations` which returns a boolean
3310
+ * Note: There are multiple simmilar function:
3311
+ * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
3312
+ * - `extractJsonBlock` extracts exactly one valid JSON code block
3313
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
3314
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
3284
3315
  *
3285
- * @returns {boolean} True if the expectations are met
3286
- * @public exported from `@promptbook/core`
3316
+ * @param markdown any valid markdown
3317
+ * @returns code blocks with language and content
3318
+ * @throws {ParseError} if block is not closed properly
3319
+ * @public exported from `@promptbook/markdown-utils`
3287
3320
  */
3288
- function isPassingExpectations(expectations, value) {
3321
+ function extractAllBlocksFromMarkdown(markdown) {
3322
+ var e_1, _a;
3323
+ var codeBlocks = [];
3324
+ var lines = markdown.split('\n');
3325
+ // Note: [0] Ensure that the last block notated by gt > will be closed
3326
+ lines.push('');
3327
+ var currentCodeBlock = null;
3289
3328
  try {
3290
- checkExpectations(expectations, value);
3291
- return true;
3329
+ for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
3330
+ var line = lines_1_1.value;
3331
+ if (line.startsWith('> ') || line === '>') {
3332
+ if (currentCodeBlock === null) {
3333
+ currentCodeBlock = { blockNotation: '>', language: null, content: '' };
3334
+ } /* not else */
3335
+ if (currentCodeBlock.blockNotation === '>') {
3336
+ if (currentCodeBlock.content !== '') {
3337
+ currentCodeBlock.content += '\n';
3338
+ }
3339
+ currentCodeBlock.content += line.slice(2);
3340
+ }
3341
+ }
3342
+ else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '>' /* <- Note: [0] */) {
3343
+ codeBlocks.push(currentCodeBlock);
3344
+ currentCodeBlock = null;
3345
+ }
3346
+ /* not else */
3347
+ if (line.startsWith('```')) {
3348
+ var language = line.slice(3).trim() || null;
3349
+ if (currentCodeBlock === null) {
3350
+ currentCodeBlock = { blockNotation: '```', language: language, content: '' };
3351
+ }
3352
+ else {
3353
+ if (language !== null) {
3354
+ throw new ParseError("".concat(capitalize(currentCodeBlock.language || 'the'), " code block was not closed and already opening new ").concat(language, " code block"));
3355
+ }
3356
+ codeBlocks.push(currentCodeBlock);
3357
+ currentCodeBlock = null;
3358
+ }
3359
+ }
3360
+ else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '```') {
3361
+ if (currentCodeBlock.content !== '') {
3362
+ currentCodeBlock.content += '\n';
3363
+ }
3364
+ currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make propper unescape */;
3365
+ }
3366
+ }
3292
3367
  }
3293
- catch (error) {
3294
- if (!(error instanceof ExpectError)) {
3295
- throw error;
3368
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
3369
+ finally {
3370
+ try {
3371
+ if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
3296
3372
  }
3297
- return false;
3373
+ finally { if (e_1) throw e_1.error; }
3374
+ }
3375
+ if (currentCodeBlock !== null) {
3376
+ throw new ParseError("".concat(capitalize(currentCodeBlock.language || 'the'), " code block was not closed at the end of the markdown"));
3298
3377
  }
3378
+ return codeBlocks;
3299
3379
  }
3300
3380
  /**
3301
- * TODO: [💝] Unite object for expecting amount and format
3381
+ * TODO: Maybe name for `blockNotation` instead of '```' and '>'
3302
3382
  */
3303
3383
 
3304
3384
  /**
3305
- * Creates executor function from pipeline and execution tools.
3385
+ * Extracts extracts exactly one valid JSON code block
3306
3386
  *
3307
- * @returns The executor function
3308
- * @throws {PipelineLogicError} on logical error in the pipeline
3309
- * @public exported from `@promptbook/core`
3387
+ * - When given string is a valid JSON as it is, it just returns it
3388
+ * - When there is no JSON code block the function throws a `ParseError`
3389
+ * - When there are multiple JSON code blocks the function throws a `ParseError`
3390
+ *
3391
+ * Note: It is not important if marked as ```json BUT if it is VALID JSON
3392
+ * Note: There are multiple simmilar function:
3393
+ * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
3394
+ * - `extractJsonBlock` extracts exactly one valid JSON code block
3395
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
3396
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
3397
+ *
3398
+ * @public exported from `@promptbook/markdown-utils`
3399
+ * @throws {ParseError} if there is no valid JSON block in the markdown
3310
3400
  */
3311
- function createPipelineExecutor(options) {
3312
- var _this = this;
3313
- var pipeline = options.pipeline, tools = options.tools, _a = options.settings, settings = _a === void 0 ? {} : _a;
3314
- var _b = settings.maxExecutionAttempts, maxExecutionAttempts = _b === void 0 ? MAX_EXECUTION_ATTEMPTS : _b, _c = settings.maxParallelCount, maxParallelCount = _c === void 0 ? MAX_PARALLEL_COUNT : _c, _d = settings.isVerbose, isVerbose = _d === void 0 ? IS_VERBOSE : _d, _e = settings.isNotPreparedWarningSupressed, isNotPreparedWarningSupressed = _e === void 0 ? false : _e;
3315
- validatePipeline(pipeline);
3316
- var pipelineIdentification = (function () {
3317
- // Note: This is a 😐 implementation of [🚞]
3318
- var _ = [];
3319
- if (pipeline.sourceFile !== undefined) {
3320
- _.push("File: ".concat(pipeline.sourceFile));
3321
- }
3322
- if (pipeline.pipelineUrl !== undefined) {
3323
- _.push("Url: ".concat(pipeline.pipelineUrl));
3324
- }
3325
- return _.join('\n');
3326
- })();
3327
- var llmTools = joinLlmExecutionTools.apply(void 0, __spreadArray([], __read(arrayableToArray(tools.llm)), false));
3328
- var preparedPipeline;
3329
- if (isPipelinePrepared(pipeline)) {
3330
- preparedPipeline = pipeline;
3401
+ function extractJsonBlock(markdown) {
3402
+ if (isValidJsonString(markdown)) {
3403
+ return markdown;
3331
3404
  }
3332
- else if (isNotPreparedWarningSupressed !== true) {
3333
- console.warn(spaceTrim$1(function (block) { return "\n Pipeline is not prepared\n\n ".concat(block(pipelineIdentification), "\n\n It will be prepared ad-hoc before the first execution and **returned as `preparedPipeline` in `PipelineExecutorResult`**\n But it is recommended to prepare the pipeline during collection preparation\n\n @see more at https://ptbk.io/prepare-pipeline\n "); }));
3405
+ var codeBlocks = extractAllBlocksFromMarkdown(markdown);
3406
+ var jsonBlocks = codeBlocks.filter(function (_a) {
3407
+ var content = _a.content;
3408
+ return isValidJsonString(content);
3409
+ });
3410
+ if (jsonBlocks.length === 0) {
3411
+ throw new Error('There is no valid JSON block in the markdown');
3334
3412
  }
3335
- var pipelineExecutor = function (inputParameters, onProgress) { return __awaiter(_this, void 0, void 0, function () {
3336
- // TODO: !!! Extract to separate functions and files - ALL FUNCTIONS BELOW
3337
- function getContextForTemplate(template) {
3338
- return __awaiter(this, void 0, void 0, function () {
3339
- return __generator(this, function (_a) {
3340
- TODO_USE(template);
3341
- return [2 /*return*/, RESERVED_PARAMETER_MISSING_VALUE /* <- TODO: [🏍] Implement */];
3342
- });
3343
- });
3413
+ if (jsonBlocks.length > 1) {
3414
+ throw new Error('There are multiple JSON code blocks in the markdown');
3415
+ }
3416
+ return jsonBlocks[0].content;
3417
+ }
3418
+ /**
3419
+ * TODO: Add some auto-healing logic + extract YAML, JSON5, TOML, etc.
3420
+ * TODO: [🏢] Make this logic part of `JsonFormatDefinition` or `isValidJsonString`
3421
+ */
3422
+
3423
+ /**
3424
+ * Just says that the variable is not used but should be kept
3425
+ * No side effects.
3426
+ *
3427
+ * Note: It can be usefull for:
3428
+ *
3429
+ * 1) Suppressing eager optimization of unused imports
3430
+ * 2) Suppressing eslint errors of unused variables in the tests
3431
+ * 3) Keeping the type of the variable for type testing
3432
+ *
3433
+ * @param value any values
3434
+ * @returns void
3435
+ * @private within the repository
3436
+ */
3437
+ function keepUnused() {
3438
+ var valuesToKeep = [];
3439
+ for (var _i = 0; _i < arguments.length; _i++) {
3440
+ valuesToKeep[_i] = arguments[_i];
3441
+ }
3442
+ }
3443
+
3444
+ /**
3445
+ * Replaces parameters in template with values from parameters object
3446
+ *
3447
+ * @param template the template with parameters in {curly} braces
3448
+ * @param parameters the object with parameters
3449
+ * @returns the template with replaced parameters
3450
+ * @throws {PipelineExecutionError} if parameter is not defined, not closed, or not opened
3451
+ * @public exported from `@promptbook/utils`
3452
+ */
3453
+ function replaceParameters(template, parameters) {
3454
+ var e_1, _a;
3455
+ try {
3456
+ for (var _b = __values(Object.entries(parameters)), _c = _b.next(); !_c.done; _c = _b.next()) {
3457
+ var _d = __read(_c.value, 2), parameterName = _d[0], parameterValue = _d[1];
3458
+ if (parameterValue === RESERVED_PARAMETER_MISSING_VALUE) {
3459
+ throw new UnexpectedError("Parameter {".concat(parameterName, "} has missing value"));
3460
+ }
3461
+ else if (parameterValue === RESERVED_PARAMETER_RESTRICTED) {
3462
+ // TODO: [🍵]
3463
+ throw new UnexpectedError("Parameter {".concat(parameterName, "} is restricted to use"));
3464
+ }
3344
3465
  }
3345
- function getKnowledgeForTemplate(template) {
3346
- return __awaiter(this, void 0, void 0, function () {
3347
- return __generator(this, function (_a) {
3348
- // TODO: [♨] Implement Better - use real index and keyword search from `template` and {samples}
3349
- TODO_USE(template);
3350
- return [2 /*return*/, preparedPipeline.knowledgePieces.map(function (_a) {
3351
- var content = _a.content;
3352
- return "- ".concat(content);
3353
- }).join('\n')];
3354
- });
3355
- });
3466
+ }
3467
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
3468
+ finally {
3469
+ try {
3470
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
3356
3471
  }
3357
- function getSamplesForTemplate(template) {
3358
- return __awaiter(this, void 0, void 0, function () {
3359
- return __generator(this, function (_a) {
3360
- // TODO: [♨] Implement Better - use real index and keyword search
3361
- TODO_USE(template);
3362
- return [2 /*return*/, RESERVED_PARAMETER_MISSING_VALUE /* <- TODO: [♨] Implement */];
3363
- });
3364
- });
3472
+ finally { if (e_1) throw e_1.error; }
3473
+ }
3474
+ var replacedTemplate = template;
3475
+ var match;
3476
+ var loopLimit = LOOP_LIMIT;
3477
+ var _loop_1 = function () {
3478
+ if (loopLimit-- < 0) {
3479
+ throw new LimitReachedError('Loop limit reached during parameters replacement in `replaceParameters`');
3365
3480
  }
3366
- function getReservedParametersForTemplate(template) {
3367
- return __awaiter(this, void 0, void 0, function () {
3368
- var context, knowledge, samples, currentDate, modelName, reservedParameters, _loop_3, RESERVED_PARAMETER_NAMES_1, RESERVED_PARAMETER_NAMES_1_1, parameterName;
3369
- var e_3, _a;
3370
- return __generator(this, function (_b) {
3371
- switch (_b.label) {
3372
- case 0: return [4 /*yield*/, getContextForTemplate(template)];
3373
- case 1:
3374
- context = _b.sent();
3375
- return [4 /*yield*/, getKnowledgeForTemplate(template)];
3376
- case 2:
3377
- knowledge = _b.sent();
3378
- return [4 /*yield*/, getSamplesForTemplate(template)];
3379
- case 3:
3380
- samples = _b.sent();
3381
- currentDate = new Date().toISOString();
3382
- modelName = RESERVED_PARAMETER_MISSING_VALUE;
3383
- reservedParameters = {
3384
- content: RESERVED_PARAMETER_RESTRICTED,
3385
- context: context,
3386
- knowledge: knowledge,
3387
- samples: samples,
3388
- currentDate: currentDate,
3389
- modelName: modelName,
3390
- };
3391
- _loop_3 = function (parameterName) {
3392
- if (reservedParameters[parameterName] === undefined) {
3393
- throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Reserved parameter {".concat(parameterName, "} is not defined\n\n ").concat(block(pipelineIdentification), "\n "); }));
3394
- }
3395
- };
3396
- try {
3397
- // Note: Doublecheck that ALL reserved parameters are defined:
3398
- for (RESERVED_PARAMETER_NAMES_1 = __values(RESERVED_PARAMETER_NAMES), RESERVED_PARAMETER_NAMES_1_1 = RESERVED_PARAMETER_NAMES_1.next(); !RESERVED_PARAMETER_NAMES_1_1.done; RESERVED_PARAMETER_NAMES_1_1 = RESERVED_PARAMETER_NAMES_1.next()) {
3399
- parameterName = RESERVED_PARAMETER_NAMES_1_1.value;
3400
- _loop_3(parameterName);
3401
- }
3402
- }
3403
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
3404
- finally {
3405
- try {
3406
- if (RESERVED_PARAMETER_NAMES_1_1 && !RESERVED_PARAMETER_NAMES_1_1.done && (_a = RESERVED_PARAMETER_NAMES_1.return)) _a.call(RESERVED_PARAMETER_NAMES_1);
3407
- }
3408
- finally { if (e_3) throw e_3.error; }
3409
- }
3410
- return [2 /*return*/, reservedParameters];
3411
- }
3412
- });
3413
- });
3481
+ var precol = match.groups.precol;
3482
+ var parameterName = match.groups.parameterName;
3483
+ if (parameterName === '') {
3484
+ return "continue";
3414
3485
  }
3415
- function executeSingleTemplate(currentTemplate) {
3416
- return __awaiter(this, void 0, void 0, function () {
3417
- var name, title, priority, progress_1, usedParameterNames, dependentParameterNames, definedParameters, _a, _b, _c, definedParameterNames, parameters, _loop_4, _d, _e, parameterName, prompt, chatResult, completionResult, embeddingResult, result, resultString, expectError, scriptPipelineExecutionErrors, maxAttempts, jokerParameterNames, preparedContent, _loop_5, attempt, state_2, progress_2;
3418
- var e_4, _f, _g;
3419
- return __generator(this, function (_h) {
3420
- switch (_h.label) {
3421
- case 0:
3422
- name = "pipeline-executor-frame-".concat(currentTemplate.name);
3423
- title = currentTemplate.title;
3424
- priority = preparedPipeline.templates.length - preparedPipeline.templates.indexOf(currentTemplate);
3425
- if (!(onProgress !== undefined) /* <- [3] */) return [3 /*break*/, 2]; /* <- [3] */
3426
- progress_1 = {
3427
- name: name,
3428
- title: title,
3429
- isStarted: false,
3430
- isDone: false,
3431
- templateType: currentTemplate.templateType,
3432
- parameterName: currentTemplate.resultingParameterName,
3433
- parameterValue: null,
3434
- // <- [3]
3435
- };
3436
- if (isReturned) {
3437
- throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Can not call `onProgress` after pipeline execution is finished \uD83C\uDF4F\n\n ".concat(block(pipelineIdentification), "\n\n ").concat(block(JSON.stringify(progress_1, null, 4)
3438
- .split('\n')
3439
- .map(function (line) { return "> ".concat(line); })
3440
- .join('\n')), "\n "); }));
3441
- }
3442
- return [4 /*yield*/, onProgress(progress_1)];
3443
- case 1:
3444
- _h.sent();
3445
- _h.label = 2;
3446
- case 2:
3447
- usedParameterNames = extractParameterNamesFromTemplate(currentTemplate);
3448
- dependentParameterNames = new Set(currentTemplate.dependentParameterNames);
3449
- if (union(difference(usedParameterNames, dependentParameterNames), difference(dependentParameterNames, usedParameterNames)).size !== 0) {
3450
- throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Dependent parameters are not consistent with used parameters:\n\n ".concat(block(pipelineIdentification), "\n\n Dependent parameters:\n ").concat(Array.from(dependentParameterNames)
3451
- .map(function (name) { return "{".concat(name, "}"); })
3452
- .join(', '), "\n\n Used parameters:\n ").concat(Array.from(usedParameterNames)
3453
- .map(function (name) { return "{".concat(name, "}"); })
3454
- .join(', '), "\n\n "); }));
3455
- }
3456
- _b = (_a = Object).freeze;
3457
- _c = [{}];
3458
- return [4 /*yield*/, getReservedParametersForTemplate(currentTemplate)];
3459
- case 3:
3460
- definedParameters = _b.apply(_a, [__assign.apply(void 0, [__assign.apply(void 0, _c.concat([(_h.sent())])), parametersToPass])]);
3461
- definedParameterNames = new Set(Object.keys(definedParameters));
3462
- parameters = {};
3463
- _loop_4 = function (parameterName) {
3464
- // Situation: Parameter is defined and used
3465
- if (definedParameterNames.has(parameterName) && usedParameterNames.has(parameterName)) {
3466
- parameters[parameterName] = definedParameters[parameterName];
3467
- }
3468
- // Situation: Parameter is defined but NOT used
3469
- else if (definedParameterNames.has(parameterName) && !usedParameterNames.has(parameterName)) ;
3470
- // Situation: Parameter is NOT defined BUT used
3471
- else if (!definedParameterNames.has(parameterName) && usedParameterNames.has(parameterName)) {
3472
- // Houston, we have a problem
3473
- // Note: Checking part is also done in `validatePipeline`, but it’s good to doublecheck
3474
- throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Parameter {".concat(parameterName, "} is NOT defined\n BUT used in template \"").concat(currentTemplate.title || currentTemplate.name, "\"\n\n This should be catched in `validatePipeline`\n\n ").concat(block(pipelineIdentification), "\n\n "); }));
3475
- }
3476
- };
3477
- try {
3478
- // Note: [2] Check that all used parameters are defined and removing unused parameters for this template
3479
- for (_d = __values(Array.from(union(definedParameterNames, usedParameterNames, dependentParameterNames))), _e = _d.next(); !_e.done; _e = _d.next()) {
3480
- parameterName = _e.value;
3481
- _loop_4(parameterName);
3482
- }
3483
- }
3484
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
3485
- finally {
3486
- try {
3487
- if (_e && !_e.done && (_f = _d.return)) _f.call(_d);
3488
- }
3489
- finally { if (e_4) throw e_4.error; }
3490
- }
3491
- // Note: Now we can freeze `parameters` because we are sure that all and only used parameters are defined
3492
- Object.freeze(parameters);
3493
- result = null;
3494
- resultString = null;
3495
- expectError = null;
3496
- maxAttempts = currentTemplate.templateType === 'DIALOG_TEMPLATE' ? Infinity : maxExecutionAttempts;
3497
- jokerParameterNames = currentTemplate.jokerParameterNames || [];
3498
- preparedContent = (currentTemplate.preparedContent || '{content}')
3499
- .split('{content}')
3500
- .join(currentTemplate.content);
3501
- _loop_5 = function (attempt) {
3502
- var isJokerAttempt, jokerParameterName, _j, modelRequirements, _k, _l, _m, scriptTools, error_2, e_5_1, _o, _p, functionName, postprocessingError, _q, _r, scriptTools, error_3, e_6_1, e_7_1, error_4;
3503
- var e_5, _s, e_7, _t, e_6, _u;
3504
- return __generator(this, function (_v) {
3505
- switch (_v.label) {
3506
- case 0:
3507
- isJokerAttempt = attempt < 0;
3508
- jokerParameterName = jokerParameterNames[jokerParameterNames.length + attempt];
3509
- // TODO: [🧠] !!!!!! JOKERS, EXPECTATIONS, POSTPROCESSING and FOREACH
3510
- if (isJokerAttempt && !jokerParameterName) {
3511
- throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Joker not found in attempt ".concat(attempt, "\n\n ").concat(block(pipelineIdentification), "\n "); }));
3512
- }
3513
- result = null;
3514
- resultString = null;
3515
- expectError = null;
3516
- if (isJokerAttempt) {
3517
- if (parameters[jokerParameterName] === undefined) {
3518
- throw new PipelineExecutionError(spaceTrim$1(function (block) { return "\n Joker parameter {".concat(jokerParameterName, "} not defined\n\n ").concat(block(pipelineIdentification), "\n "); }));
3519
- // <- TODO: This is maybe `PipelineLogicError` which should be detected in `validatePipeline` and here just thrown as `UnexpectedError`
3520
- }
3521
- else {
3522
- resultString = parameters[jokerParameterName];
3523
- }
3524
- }
3525
- _v.label = 1;
3526
- case 1:
3527
- _v.trys.push([1, 44, 45, 46]);
3528
- if (!!isJokerAttempt) return [3 /*break*/, 26];
3529
- _j = currentTemplate.templateType;
3530
- switch (_j) {
3531
- case 'SIMPLE_TEMPLATE': return [3 /*break*/, 2];
3532
- case 'PROMPT_TEMPLATE': return [3 /*break*/, 3];
3533
- case 'SCRIPT_TEMPLATE': return [3 /*break*/, 12];
3534
- case 'DIALOG_TEMPLATE': return [3 /*break*/, 23];
3535
- }
3536
- return [3 /*break*/, 25];
3537
- case 2:
3538
- resultString = replaceParameters(preparedContent, parameters);
3539
- return [3 /*break*/, 26];
3540
- case 3:
3541
- modelRequirements = __assign(__assign({ modelVariant: 'CHAT' }, (pipeline.defaultModelRequirements || {})), (currentTemplate.modelRequirements || {}));
3542
- prompt = {
3543
- title: currentTemplate.title,
3544
- pipelineUrl: "".concat(preparedPipeline.pipelineUrl
3545
- ? preparedPipeline.pipelineUrl
3546
- : 'anonymous' /* <- TODO: [🧠] How to deal with anonymous pipelines, do here some auto-url like SHA-256 based ad-hoc identifier? */, "#").concat(currentTemplate.name),
3547
- parameters: parameters,
3548
- content: preparedContent,
3549
- modelRequirements: modelRequirements,
3550
- expectations: __assign(__assign({}, (preparedPipeline.personas.find(function (_a) {
3551
- var name = _a.name;
3552
- return name === currentTemplate.personaName;
3553
- }) || {})), currentTemplate.expectations),
3554
- format: currentTemplate.format,
3555
- postprocessingFunctionNames: currentTemplate.postprocessingFunctionNames,
3556
- }; // <- TODO: Not very good type guard
3557
- _k = modelRequirements.modelVariant;
3558
- switch (_k) {
3559
- case 'CHAT': return [3 /*break*/, 4];
3560
- case 'COMPLETION': return [3 /*break*/, 6];
3561
- case 'EMBEDDING': return [3 /*break*/, 8];
3562
- }
3563
- return [3 /*break*/, 10];
3564
- case 4: return [4 /*yield*/, llmTools.callChatModel($deepFreeze(prompt))];
3565
- case 5:
3566
- chatResult = _v.sent();
3567
- // TODO: [🍬] Destroy chatThread
3568
- result = chatResult;
3569
- resultString = chatResult.content;
3570
- return [3 /*break*/, 11];
3571
- case 6: return [4 /*yield*/, llmTools.callCompletionModel($deepFreeze(prompt))];
3572
- case 7:
3573
- completionResult = _v.sent();
3574
- result = completionResult;
3575
- resultString = completionResult.content;
3576
- return [3 /*break*/, 11];
3577
- case 8: return [4 /*yield*/, llmTools.callEmbeddingModel($deepFreeze(prompt))];
3578
- case 9:
3579
- embeddingResult = _v.sent();
3580
- result = embeddingResult;
3581
- resultString = embeddingResult.content.join(',');
3582
- return [3 /*break*/, 11];
3583
- case 10: throw new PipelineExecutionError(spaceTrim$1(function (block) { return "\n Unknown model variant \"".concat(currentTemplate.modelRequirements
3584
- .modelVariant, "\"\n\n ").concat(block(pipelineIdentification), "\n\n "); }));
3585
- case 11: return [3 /*break*/, 26];
3586
- case 12:
3587
- if (arrayableToArray(tools.script).length === 0) {
3588
- throw new PipelineExecutionError(spaceTrim$1(function (block) { return "\n No script execution tools are available\n\n ".concat(block(pipelineIdentification), "\n "); }));
3589
- }
3590
- if (!currentTemplate.contentLanguage) {
3591
- throw new PipelineExecutionError(spaceTrim$1(function (block) { return "\n Script language is not defined for SCRIPT TEMPLATE \"".concat(currentTemplate.name, "\"\n\n ").concat(block(pipelineIdentification), "\n "); }));
3592
- }
3593
- // TODO: DRY [1]
3594
- scriptPipelineExecutionErrors = [];
3595
- _v.label = 13;
3596
- case 13:
3597
- _v.trys.push([13, 20, 21, 22]);
3598
- _l = (e_5 = void 0, __values(arrayableToArray(tools.script))), _m = _l.next();
3599
- _v.label = 14;
3600
- case 14:
3601
- if (!!_m.done) return [3 /*break*/, 19];
3602
- scriptTools = _m.value;
3603
- _v.label = 15;
3604
- case 15:
3605
- _v.trys.push([15, 17, , 18]);
3606
- return [4 /*yield*/, scriptTools.execute($deepFreeze({
3607
- scriptLanguage: currentTemplate.contentLanguage,
3608
- script: preparedContent,
3609
- parameters: parameters,
3610
- }))];
3611
- case 16:
3612
- resultString = _v.sent();
3613
- return [3 /*break*/, 19];
3614
- case 17:
3615
- error_2 = _v.sent();
3616
- if (!(error_2 instanceof Error)) {
3617
- throw error_2;
3618
- }
3619
- if (error_2 instanceof UnexpectedError) {
3620
- throw error_2;
3621
- }
3622
- scriptPipelineExecutionErrors.push(error_2);
3623
- return [3 /*break*/, 18];
3624
- case 18:
3625
- _m = _l.next();
3626
- return [3 /*break*/, 14];
3627
- case 19: return [3 /*break*/, 22];
3628
- case 20:
3629
- e_5_1 = _v.sent();
3630
- e_5 = { error: e_5_1 };
3631
- return [3 /*break*/, 22];
3632
- case 21:
3633
- try {
3634
- if (_m && !_m.done && (_s = _l.return)) _s.call(_l);
3635
- }
3636
- finally { if (e_5) throw e_5.error; }
3637
- return [7 /*endfinally*/];
3638
- case 22:
3639
- if (resultString !== null) {
3640
- return [3 /*break*/, 26];
3641
- }
3642
- if (scriptPipelineExecutionErrors.length === 1) {
3643
- throw scriptPipelineExecutionErrors[0];
3644
- }
3645
- else {
3646
- throw new PipelineExecutionError(spaceTrim$1(function (block) { return "\n Script execution failed ".concat(scriptPipelineExecutionErrors.length, " times\n\n ").concat(block(pipelineIdentification), "\n\n ").concat(block(scriptPipelineExecutionErrors
3647
- .map(function (error) { return '- ' + error.message; })
3648
- .join('\n\n')), "\n "); }));
3649
- }
3650
- case 23:
3651
- if (tools.userInterface === undefined) {
3652
- throw new PipelineExecutionError(spaceTrim$1(function (block) { return "\n User interface tools are not available\n\n ".concat(block(pipelineIdentification), "\n "); }));
3653
- }
3654
- return [4 /*yield*/, tools.userInterface.promptDialog($deepFreeze({
3655
- promptTitle: currentTemplate.title,
3656
- promptMessage: replaceParameters(currentTemplate.description || '', parameters),
3657
- defaultValue: replaceParameters(preparedContent, parameters),
3658
- // TODO: [🧠] !! Figure out how to define placeholder in .ptbk.md file
3659
- placeholder: undefined,
3660
- priority: priority,
3661
- }))];
3662
- case 24:
3663
- // TODO: [🌹] When making next attempt for `DIALOG TEMPLATE`, preserve the previous user input
3664
- resultString = _v.sent();
3665
- return [3 /*break*/, 26];
3666
- case 25: throw new PipelineExecutionError(spaceTrim$1(function (block) { return "\n Unknown execution type \"".concat(currentTemplate.templateType, "\"\n\n ").concat(block(pipelineIdentification), "\n "); }));
3667
- case 26:
3668
- if (!(!isJokerAttempt && currentTemplate.postprocessingFunctionNames)) return [3 /*break*/, 43];
3669
- _v.label = 27;
3670
- case 27:
3671
- _v.trys.push([27, 41, 42, 43]);
3672
- _o = (e_7 = void 0, __values(currentTemplate.postprocessingFunctionNames)), _p = _o.next();
3673
- _v.label = 28;
3674
- case 28:
3675
- if (!!_p.done) return [3 /*break*/, 40];
3676
- functionName = _p.value;
3677
- // TODO: DRY [1]
3678
- scriptPipelineExecutionErrors = [];
3679
- postprocessingError = null;
3680
- _v.label = 29;
3681
- case 29:
3682
- _v.trys.push([29, 36, 37, 38]);
3683
- _q = (e_6 = void 0, __values(arrayableToArray(tools.script))), _r = _q.next();
3684
- _v.label = 30;
3685
- case 30:
3686
- if (!!_r.done) return [3 /*break*/, 35];
3687
- scriptTools = _r.value;
3688
- _v.label = 31;
3689
- case 31:
3690
- _v.trys.push([31, 33, , 34]);
3691
- return [4 /*yield*/, scriptTools.execute({
3692
- scriptLanguage: "javascript" /* <- TODO: Try it in each languages; In future allow postprocessing with arbitrary combination of languages to combine */,
3693
- script: "".concat(functionName, "(resultString)"),
3694
- parameters: {
3695
- resultString: resultString || '',
3696
- // Note: No ...parametersForTemplate, because working with result only
3697
- },
3698
- })];
3699
- case 32:
3700
- resultString = _v.sent();
3701
- postprocessingError = null;
3702
- return [3 /*break*/, 35];
3703
- case 33:
3704
- error_3 = _v.sent();
3705
- if (!(error_3 instanceof Error)) {
3706
- throw error_3;
3707
- }
3708
- if (error_3 instanceof UnexpectedError) {
3709
- throw error_3;
3710
- }
3711
- postprocessingError = error_3;
3712
- scriptPipelineExecutionErrors.push(error_3);
3713
- return [3 /*break*/, 34];
3714
- case 34:
3715
- _r = _q.next();
3716
- return [3 /*break*/, 30];
3717
- case 35: return [3 /*break*/, 38];
3718
- case 36:
3719
- e_6_1 = _v.sent();
3720
- e_6 = { error: e_6_1 };
3721
- return [3 /*break*/, 38];
3722
- case 37:
3723
- try {
3724
- if (_r && !_r.done && (_u = _q.return)) _u.call(_q);
3725
- }
3726
- finally { if (e_6) throw e_6.error; }
3727
- return [7 /*endfinally*/];
3728
- case 38:
3729
- if (postprocessingError) {
3730
- throw postprocessingError;
3731
- }
3732
- _v.label = 39;
3733
- case 39:
3734
- _p = _o.next();
3735
- return [3 /*break*/, 28];
3736
- case 40: return [3 /*break*/, 43];
3737
- case 41:
3738
- e_7_1 = _v.sent();
3739
- e_7 = { error: e_7_1 };
3740
- return [3 /*break*/, 43];
3741
- case 42:
3742
- try {
3743
- if (_p && !_p.done && (_t = _o.return)) _t.call(_o);
3744
- }
3745
- finally { if (e_7) throw e_7.error; }
3746
- return [7 /*endfinally*/];
3747
- case 43:
3748
- // TODO: [💝] Unite object for expecting amount and format
3749
- if (currentTemplate.format) {
3750
- if (currentTemplate.format === 'JSON') {
3751
- if (!isValidJsonString(resultString || '')) {
3752
- // TODO: [🏢] Do more universally via `FormatDefinition`
3753
- try {
3754
- resultString = extractJsonBlock(resultString || '');
3755
- }
3756
- catch (error) {
3757
- keepUnused(error);
3758
- throw new ExpectError(spaceTrim$1(function (block) { return "\n Expected valid JSON string\n\n ".concat(block(
3759
- /*<- Note: No need for `pipelineIdentification`, it will be catched and added later */ ''), "\n "); }));
3760
- }
3761
- }
3486
+ if (parameterName.indexOf('{') !== -1 || parameterName.indexOf('}') !== -1) {
3487
+ throw new PipelineExecutionError('Parameter is already opened or not closed');
3488
+ }
3489
+ if (parameters[parameterName] === undefined) {
3490
+ throw new PipelineExecutionError("Parameter {".concat(parameterName, "} is not defined"));
3491
+ }
3492
+ var parameterValue = parameters[parameterName];
3493
+ if (parameterValue === undefined) {
3494
+ throw new PipelineExecutionError("Parameter {".concat(parameterName, "} is not defined"));
3495
+ }
3496
+ parameterValue = parameterValue.toString();
3497
+ if (parameterValue.includes('\n') && /^\s*\W{0,3}\s*$/.test(precol)) {
3498
+ parameterValue = parameterValue
3499
+ .split('\n')
3500
+ .map(function (line, index) { return (index === 0 ? line : "".concat(precol).concat(line)); })
3501
+ .join('\n');
3502
+ }
3503
+ replacedTemplate =
3504
+ replacedTemplate.substring(0, match.index + precol.length) +
3505
+ parameterValue +
3506
+ replacedTemplate.substring(match.index + precol.length + parameterName.length + 2);
3507
+ };
3508
+ while ((match = /^(?<precol>.*){(?<parameterName>\w+)}(.*)/m /* <- Not global */
3509
+ .exec(replacedTemplate))) {
3510
+ _loop_1();
3511
+ }
3512
+ // [💫] Check if there are parameters that are not closed properly
3513
+ if (/{\w+$/.test(replacedTemplate)) {
3514
+ throw new PipelineExecutionError('Parameter is not closed');
3515
+ }
3516
+ // [💫] Check if there are parameters that are not opened properly
3517
+ if (/^\w+}/.test(replacedTemplate)) {
3518
+ throw new PipelineExecutionError('Parameter is not opened');
3519
+ }
3520
+ return replacedTemplate;
3521
+ }
3522
+
3523
+ /**
3524
+ * Counts number of characters in the text
3525
+ *
3526
+ * @public exported from `@promptbook/utils`
3527
+ */
3528
+ function countCharacters(text) {
3529
+ // Remove null characters
3530
+ text = text.replace(/\0/g, '');
3531
+ // Replace emojis (and also ZWJ sequence) with hyphens
3532
+ text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
3533
+ text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
3534
+ text = text.replace(/\p{Extended_Pictographic}(\u{200D}\p{Extended_Pictographic})*/gu, '-');
3535
+ return text.length;
3536
+ }
3537
+
3538
+ /**
3539
+ * Counts number of lines in the text
3540
+ *
3541
+ * @public exported from `@promptbook/utils`
3542
+ */
3543
+ function countLines(text) {
3544
+ if (text === '') {
3545
+ return 0;
3546
+ }
3547
+ return text.split('\n').length;
3548
+ }
3549
+
3550
+ /**
3551
+ * Counts number of pages in the text
3552
+ *
3553
+ * @public exported from `@promptbook/utils`
3554
+ */
3555
+ function countPages(text) {
3556
+ var sentencesPerPage = 5; // Assuming each page has 5 sentences
3557
+ var sentences = text.split(/[.!?]+/).filter(function (sentence) { return sentence.trim() !== ''; });
3558
+ var pageCount = Math.ceil(sentences.length / sentencesPerPage);
3559
+ return pageCount;
3560
+ }
3561
+
3562
+ /**
3563
+ * Counts number of paragraphs in the text
3564
+ *
3565
+ * @public exported from `@promptbook/utils`
3566
+ */
3567
+ function countParagraphs(text) {
3568
+ return text.split(/\n\s*\n/).filter(function (paragraph) { return paragraph.trim() !== ''; }).length;
3569
+ }
3570
+
3571
+ /**
3572
+ * Split text into sentences
3573
+ *
3574
+ * @public exported from `@promptbook/utils`
3575
+ */
3576
+ function splitIntoSentences(text) {
3577
+ return text.split(/[.!?]+/).filter(function (sentence) { return sentence.trim() !== ''; });
3578
+ }
3579
+ /**
3580
+ * Counts number of sentences in the text
3581
+ *
3582
+ * @public exported from `@promptbook/utils`
3583
+ */
3584
+ function countSentences(text) {
3585
+ return splitIntoSentences(text).length;
3586
+ }
3587
+
3588
+ /**
3589
+ * Counts number of words in the text
3590
+ *
3591
+ * @public exported from `@promptbook/utils`
3592
+ */
3593
+ function countWords(text) {
3594
+ text = text.replace(/[\p{Extended_Pictographic}]/gu, 'a');
3595
+ text = removeDiacritics(text);
3596
+ return text.split(/[^a-zа-я0-9]+/i).filter(function (word) { return word.length > 0; }).length;
3597
+ }
3598
+
3599
+ /**
3600
+ * Index of all counter functions
3601
+ *
3602
+ * @public exported from `@promptbook/utils`
3603
+ */
3604
+ var CountUtils = {
3605
+ CHARACTERS: countCharacters,
3606
+ WORDS: countWords,
3607
+ SENTENCES: countSentences,
3608
+ PARAGRAPHS: countParagraphs,
3609
+ LINES: countLines,
3610
+ PAGES: countPages,
3611
+ };
3612
+ /**
3613
+ * TODO: [🧠][🤠] This should be probbably as part of `TextFormatDefinition`
3614
+ */
3615
+
3616
+ /**
3617
+ * Function checkExpectations will check if the expectations on given value are met
3618
+ *
3619
+ * Note: There are two simmilar functions:
3620
+ * - `checkExpectations` which throws an error if the expectations are not met
3621
+ * - `isPassingExpectations` which returns a boolean
3622
+ *
3623
+ * @throws {ExpectError} if the expectations are not met
3624
+ * @returns {void} Nothing
3625
+ * @private internal function of `createPipelineExecutor`
3626
+ */
3627
+ function checkExpectations(expectations, value) {
3628
+ var e_1, _a;
3629
+ try {
3630
+ for (var _b = __values(Object.entries(expectations)), _c = _b.next(); !_c.done; _c = _b.next()) {
3631
+ var _d = __read(_c.value, 2), unit = _d[0], _e = _d[1], max = _e.max, min = _e.min;
3632
+ var amount = CountUtils[unit.toUpperCase()](value);
3633
+ if (min && amount < min) {
3634
+ throw new ExpectError("Expected at least ".concat(min, " ").concat(unit, " but got ").concat(amount));
3635
+ } /* not else */
3636
+ if (max && amount > max) {
3637
+ throw new ExpectError("Expected at most ".concat(max, " ").concat(unit, " but got ").concat(amount));
3638
+ }
3639
+ }
3640
+ }
3641
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
3642
+ finally {
3643
+ try {
3644
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
3645
+ }
3646
+ finally { if (e_1) throw e_1.error; }
3647
+ }
3648
+ }
3649
+ /**
3650
+ * Function checkExpectations will check if the expectations on given value are met
3651
+ *
3652
+ * Note: There are two simmilar functions:
3653
+ * - `checkExpectations` which throws an error if the expectations are not met
3654
+ * - `isPassingExpectations` which returns a boolean
3655
+ *
3656
+ * @returns {boolean} True if the expectations are met
3657
+ * @public exported from `@promptbook/core`
3658
+ */
3659
+ function isPassingExpectations(expectations, value) {
3660
+ try {
3661
+ checkExpectations(expectations, value);
3662
+ return true;
3663
+ }
3664
+ catch (error) {
3665
+ if (!(error instanceof ExpectError)) {
3666
+ throw error;
3667
+ }
3668
+ return false;
3669
+ }
3670
+ }
3671
+ /**
3672
+ * TODO: [💝] Unite object for expecting amount and format
3673
+ * TODO: [🧠][🤠] This should be part of `TextFormatDefinition`
3674
+ * Note: [💝] and [🤠] are interconnected together
3675
+ */
3676
+
3677
+ /**
3678
+ * @@@
3679
+ *
3680
+ * @private internal utility of `createPipelineExecutor`
3681
+ */
3682
+ function executeAttempts(options) {
3683
+ return __awaiter(this, void 0, void 0, function () {
3684
+ var jokerParameterNames, priority, maxAttempts, preparedContent, parameters, template, preparedPipeline, tools, llmTools, settings, $executionReport, pipelineIdentification, maxExecutionAttempts, $ongoingTemplateResult, _loop_1, attempt, state_1;
3685
+ return __generator(this, function (_a) {
3686
+ switch (_a.label) {
3687
+ case 0:
3688
+ jokerParameterNames = options.jokerParameterNames, priority = options.priority, maxAttempts = options.maxAttempts, preparedContent = options.preparedContent, parameters = options.parameters, template = options.template, preparedPipeline = options.preparedPipeline, tools = options.tools, llmTools = options.llmTools, settings = options.settings, $executionReport = options.$executionReport, pipelineIdentification = options.pipelineIdentification;
3689
+ maxExecutionAttempts = settings.maxExecutionAttempts;
3690
+ $ongoingTemplateResult = {
3691
+ $result: null,
3692
+ $resultString: null,
3693
+ $expectError: null,
3694
+ $scriptPipelineExecutionErrors: [],
3695
+ };
3696
+ _loop_1 = function (attempt) {
3697
+ var isJokerAttempt, jokerParameterName, _b, modelRequirements, _c, _d, _e, _f, _g, scriptTools, _h, error_1, e_1_1, _j, _k, _l, functionName, postprocessingError, _m, _o, scriptTools, _p, error_2, e_2_1, e_3_1, error_3;
3698
+ var e_1, _q, e_3, _r, e_2, _s;
3699
+ return __generator(this, function (_t) {
3700
+ switch (_t.label) {
3701
+ case 0:
3702
+ isJokerAttempt = attempt < 0;
3703
+ jokerParameterName = jokerParameterNames[jokerParameterNames.length + attempt];
3704
+ // TODO: [🧠][🍭] JOKERS, EXPECTATIONS, POSTPROCESSING and FOREACH
3705
+ if (isJokerAttempt && !jokerParameterName) {
3706
+ throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Joker not found in attempt ".concat(attempt, "\n\n ").concat(block(pipelineIdentification), "\n "); }));
3707
+ }
3708
+ $ongoingTemplateResult.$result = null;
3709
+ $ongoingTemplateResult.$resultString = null;
3710
+ $ongoingTemplateResult.$expectError = null;
3711
+ if (isJokerAttempt) {
3712
+ if (parameters[jokerParameterName] === undefined) {
3713
+ throw new PipelineExecutionError(spaceTrim$1(function (block) { return "\n Joker parameter {".concat(jokerParameterName, "} not defined\n\n ").concat(block(pipelineIdentification), "\n "); }));
3714
+ // <- TODO: This is maybe `PipelineLogicError` which should be detected in `validatePipeline` and here just thrown as `UnexpectedError`
3715
+ }
3716
+ else {
3717
+ $ongoingTemplateResult.$resultString = parameters[jokerParameterName];
3718
+ }
3719
+ }
3720
+ _t.label = 1;
3721
+ case 1:
3722
+ _t.trys.push([1, 43, 44, 45]);
3723
+ if (!!isJokerAttempt) return [3 /*break*/, 25];
3724
+ _b = template.templateType;
3725
+ switch (_b) {
3726
+ case 'SIMPLE_TEMPLATE': return [3 /*break*/, 2];
3727
+ case 'PROMPT_TEMPLATE': return [3 /*break*/, 3];
3728
+ case 'SCRIPT_TEMPLATE': return [3 /*break*/, 11];
3729
+ case 'DIALOG_TEMPLATE': return [3 /*break*/, 22];
3730
+ }
3731
+ return [3 /*break*/, 24];
3732
+ case 2:
3733
+ $ongoingTemplateResult.$resultString = replaceParameters(preparedContent, parameters);
3734
+ return [3 /*break*/, 25];
3735
+ case 3:
3736
+ modelRequirements = __assign(__assign({ modelVariant: 'CHAT' }, (preparedPipeline.defaultModelRequirements || {})), (template.modelRequirements || {}));
3737
+ $ongoingTemplateResult.$prompt = {
3738
+ title: template.title,
3739
+ pipelineUrl: "".concat(preparedPipeline.pipelineUrl
3740
+ ? preparedPipeline.pipelineUrl
3741
+ : 'anonymous' /* <- TODO: [🧠] How to deal with anonymous pipelines, do here some auto-url like SHA-256 based ad-hoc identifier? */, "#").concat(template.name),
3742
+ parameters: parameters,
3743
+ content: preparedContent,
3744
+ modelRequirements: modelRequirements,
3745
+ expectations: __assign(__assign({}, (preparedPipeline.personas.find(function (_a) {
3746
+ var name = _a.name;
3747
+ return name === template.personaName;
3748
+ }) ||
3749
+ {})), template.expectations),
3750
+ format: template.format,
3751
+ postprocessingFunctionNames: template.postprocessingFunctionNames,
3752
+ }; // <- TODO: Not very good type guard
3753
+ _c = modelRequirements.modelVariant;
3754
+ switch (_c) {
3755
+ case 'CHAT': return [3 /*break*/, 4];
3756
+ case 'COMPLETION': return [3 /*break*/, 6];
3757
+ case 'EMBEDDING': return [3 /*break*/, 8];
3758
+ }
3759
+ return [3 /*break*/, 9];
3760
+ case 4:
3761
+ _d = $ongoingTemplateResult;
3762
+ return [4 /*yield*/, llmTools.callChatModel($deepFreeze($ongoingTemplateResult.$prompt))];
3763
+ case 5:
3764
+ _d.$chatResult = _t.sent();
3765
+ // TODO: [🍬] Destroy chatThread
3766
+ $ongoingTemplateResult.$result = $ongoingTemplateResult.$chatResult;
3767
+ $ongoingTemplateResult.$resultString = $ongoingTemplateResult.$chatResult.content;
3768
+ return [3 /*break*/, 10];
3769
+ case 6:
3770
+ _e = $ongoingTemplateResult;
3771
+ return [4 /*yield*/, llmTools.callCompletionModel($deepFreeze($ongoingTemplateResult.$prompt))];
3772
+ case 7:
3773
+ _e.$completionResult = _t.sent();
3774
+ $ongoingTemplateResult.$result = $ongoingTemplateResult.$completionResult;
3775
+ $ongoingTemplateResult.$resultString =
3776
+ $ongoingTemplateResult.$completionResult.content;
3777
+ return [3 /*break*/, 10];
3778
+ case 8: throw new PipelineExecutionError(spaceTrim$1(function (block) { return "\n Embedding model can not be used in pipeline\n\n This should be catched during parsing\n\n ".concat(block(pipelineIdentification), "\n\n "); }));
3779
+ case 9: throw new PipelineExecutionError(spaceTrim$1(function (block) { return "\n Unknown model variant \"".concat(template.modelRequirements.modelVariant, "\"\n\n ").concat(block(pipelineIdentification), "\n\n "); }));
3780
+ case 10: return [3 /*break*/, 25];
3781
+ case 11:
3782
+ if (arrayableToArray(tools.script).length === 0) {
3783
+ throw new PipelineExecutionError(spaceTrim$1(function (block) { return "\n No script execution tools are available\n\n ".concat(block(pipelineIdentification), "\n "); }));
3784
+ }
3785
+ if (!template.contentLanguage) {
3786
+ throw new PipelineExecutionError(spaceTrim$1(function (block) { return "\n Script language is not defined for SCRIPT TEMPLATE \"".concat(template.name, "\"\n\n ").concat(block(pipelineIdentification), "\n "); }));
3787
+ }
3788
+ _t.label = 12;
3789
+ case 12:
3790
+ _t.trys.push([12, 19, 20, 21]);
3791
+ _f = (e_1 = void 0, __values(arrayableToArray(tools.script))), _g = _f.next();
3792
+ _t.label = 13;
3793
+ case 13:
3794
+ if (!!_g.done) return [3 /*break*/, 18];
3795
+ scriptTools = _g.value;
3796
+ _t.label = 14;
3797
+ case 14:
3798
+ _t.trys.push([14, 16, , 17]);
3799
+ _h = $ongoingTemplateResult;
3800
+ return [4 /*yield*/, scriptTools.execute($deepFreeze({
3801
+ scriptLanguage: template.contentLanguage,
3802
+ script: preparedContent,
3803
+ parameters: parameters,
3804
+ }))];
3805
+ case 15:
3806
+ _h.$resultString = _t.sent();
3807
+ return [3 /*break*/, 18];
3808
+ case 16:
3809
+ error_1 = _t.sent();
3810
+ if (!(error_1 instanceof Error)) {
3811
+ throw error_1;
3812
+ }
3813
+ if (error_1 instanceof UnexpectedError) {
3814
+ throw error_1;
3815
+ }
3816
+ $ongoingTemplateResult.$scriptPipelineExecutionErrors.push(error_1);
3817
+ return [3 /*break*/, 17];
3818
+ case 17:
3819
+ _g = _f.next();
3820
+ return [3 /*break*/, 13];
3821
+ case 18: return [3 /*break*/, 21];
3822
+ case 19:
3823
+ e_1_1 = _t.sent();
3824
+ e_1 = { error: e_1_1 };
3825
+ return [3 /*break*/, 21];
3826
+ case 20:
3827
+ try {
3828
+ if (_g && !_g.done && (_q = _f.return)) _q.call(_f);
3829
+ }
3830
+ finally { if (e_1) throw e_1.error; }
3831
+ return [7 /*endfinally*/];
3832
+ case 21:
3833
+ if ($ongoingTemplateResult.$resultString !== null) {
3834
+ return [3 /*break*/, 25];
3835
+ }
3836
+ if ($ongoingTemplateResult.$scriptPipelineExecutionErrors.length === 1) {
3837
+ throw $ongoingTemplateResult.$scriptPipelineExecutionErrors[0];
3838
+ }
3839
+ else {
3840
+ throw new PipelineExecutionError(spaceTrim$1(function (block) { return "\n Script execution failed ".concat($ongoingTemplateResult.$scriptPipelineExecutionErrors.length, "x\n\n ").concat(block(pipelineIdentification), "\n\n ").concat(block($ongoingTemplateResult.$scriptPipelineExecutionErrors
3841
+ .map(function (error) { return '- ' + error.message; })
3842
+ .join('\n\n')), "\n "); }));
3843
+ }
3844
+ case 22:
3845
+ if (tools.userInterface === undefined) {
3846
+ throw new PipelineExecutionError(spaceTrim$1(function (block) { return "\n User interface tools are not available\n\n ".concat(block(pipelineIdentification), "\n "); }));
3847
+ }
3848
+ // TODO: [🌹] When making next attempt for `DIALOG TEMPLATE`, preserve the previous user input
3849
+ _j = $ongoingTemplateResult;
3850
+ return [4 /*yield*/, tools.userInterface.promptDialog($deepFreeze({
3851
+ promptTitle: template.title,
3852
+ promptMessage: replaceParameters(template.description || '', parameters),
3853
+ defaultValue: replaceParameters(preparedContent, parameters),
3854
+ // TODO: [🧠] !! Figure out how to define placeholder in .ptbk.md file
3855
+ placeholder: undefined,
3856
+ priority: priority,
3857
+ }))];
3858
+ case 23:
3859
+ // TODO: [🌹] When making next attempt for `DIALOG TEMPLATE`, preserve the previous user input
3860
+ _j.$resultString = _t.sent();
3861
+ return [3 /*break*/, 25];
3862
+ case 24: throw new PipelineExecutionError(spaceTrim$1(function (block) { return "\n Unknown execution type \"".concat(template.templateType, "\"\n\n ").concat(block(pipelineIdentification), "\n "); }));
3863
+ case 25:
3864
+ if (!(!isJokerAttempt && template.postprocessingFunctionNames)) return [3 /*break*/, 42];
3865
+ _t.label = 26;
3866
+ case 26:
3867
+ _t.trys.push([26, 40, 41, 42]);
3868
+ _k = (e_3 = void 0, __values(template.postprocessingFunctionNames)), _l = _k.next();
3869
+ _t.label = 27;
3870
+ case 27:
3871
+ if (!!_l.done) return [3 /*break*/, 39];
3872
+ functionName = _l.value;
3873
+ postprocessingError = null;
3874
+ _t.label = 28;
3875
+ case 28:
3876
+ _t.trys.push([28, 35, 36, 37]);
3877
+ _m = (e_2 = void 0, __values(arrayableToArray(tools.script))), _o = _m.next();
3878
+ _t.label = 29;
3879
+ case 29:
3880
+ if (!!_o.done) return [3 /*break*/, 34];
3881
+ scriptTools = _o.value;
3882
+ _t.label = 30;
3883
+ case 30:
3884
+ _t.trys.push([30, 32, , 33]);
3885
+ _p = $ongoingTemplateResult;
3886
+ return [4 /*yield*/, scriptTools.execute({
3887
+ scriptLanguage: "javascript" /* <- TODO: Try it in each languages; In future allow postprocessing with arbitrary combination of languages to combine */,
3888
+ script: "".concat(functionName, "(resultString)"),
3889
+ parameters: {
3890
+ resultString: $ongoingTemplateResult.$resultString || '',
3891
+ // Note: No ...parametersForTemplate, because working with result only
3892
+ },
3893
+ })];
3894
+ case 31:
3895
+ _p.$resultString = _t.sent();
3896
+ postprocessingError = null;
3897
+ return [3 /*break*/, 34];
3898
+ case 32:
3899
+ error_2 = _t.sent();
3900
+ if (!(error_2 instanceof Error)) {
3901
+ throw error_2;
3902
+ }
3903
+ if (error_2 instanceof UnexpectedError) {
3904
+ throw error_2;
3905
+ }
3906
+ postprocessingError = error_2;
3907
+ $ongoingTemplateResult.$scriptPipelineExecutionErrors.push(error_2);
3908
+ return [3 /*break*/, 33];
3909
+ case 33:
3910
+ _o = _m.next();
3911
+ return [3 /*break*/, 29];
3912
+ case 34: return [3 /*break*/, 37];
3913
+ case 35:
3914
+ e_2_1 = _t.sent();
3915
+ e_2 = { error: e_2_1 };
3916
+ return [3 /*break*/, 37];
3917
+ case 36:
3918
+ try {
3919
+ if (_o && !_o.done && (_s = _m.return)) _s.call(_m);
3920
+ }
3921
+ finally { if (e_2) throw e_2.error; }
3922
+ return [7 /*endfinally*/];
3923
+ case 37:
3924
+ if (postprocessingError) {
3925
+ throw postprocessingError;
3926
+ }
3927
+ _t.label = 38;
3928
+ case 38:
3929
+ _l = _k.next();
3930
+ return [3 /*break*/, 27];
3931
+ case 39: return [3 /*break*/, 42];
3932
+ case 40:
3933
+ e_3_1 = _t.sent();
3934
+ e_3 = { error: e_3_1 };
3935
+ return [3 /*break*/, 42];
3936
+ case 41:
3937
+ try {
3938
+ if (_l && !_l.done && (_r = _k.return)) _r.call(_k);
3939
+ }
3940
+ finally { if (e_3) throw e_3.error; }
3941
+ return [7 /*endfinally*/];
3942
+ case 42:
3943
+ // TODO: [💝] Unite object for expecting amount and format
3944
+ if (template.format) {
3945
+ if (template.format === 'JSON') {
3946
+ if (!isValidJsonString($ongoingTemplateResult.$resultString || '')) {
3947
+ // TODO: [🏢] Do more universally via `FormatDefinition`
3948
+ try {
3949
+ $ongoingTemplateResult.$resultString = extractJsonBlock($ongoingTemplateResult.$resultString || '');
3762
3950
  }
3763
- else {
3764
- throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Unknown format \"".concat(currentTemplate.format, "\"\n\n ").concat(block(pipelineIdentification), "\n "); }));
3951
+ catch (error) {
3952
+ keepUnused(error);
3953
+ throw new ExpectError(spaceTrim$1(function (block) { return "\n Expected valid JSON string\n\n ".concat(block(
3954
+ /*<- Note: No need for `pipelineIdentification`, it will be catched and added later */ ''), "\n "); }));
3765
3955
  }
3766
3956
  }
3767
- // TODO: [💝] Unite object for expecting amount and format
3768
- if (currentTemplate.expectations) {
3769
- checkExpectations(currentTemplate.expectations, resultString || '');
3770
- }
3771
- return [2 /*return*/, "break-attempts"];
3772
- case 44:
3773
- error_4 = _v.sent();
3774
- if (!(error_4 instanceof ExpectError)) {
3775
- throw error_4;
3776
- }
3777
- expectError = error_4;
3778
- return [3 /*break*/, 46];
3779
- case 45:
3780
- if (!isJokerAttempt &&
3781
- currentTemplate.templateType === 'PROMPT_TEMPLATE' &&
3782
- prompt
3783
- // <- Note: [2] When some expected parameter is not defined, error will occur in replaceParameters
3784
- // In that case we don’t want to make a report about it because it’s not a llm execution error
3785
- ) {
3786
- // TODO: [🧠] Maybe put other templateTypes into report
3787
- executionReport.promptExecutions.push({
3788
- prompt: __assign({}, prompt),
3789
- result: result || undefined,
3790
- error: expectError === null ? undefined : serializeError(expectError),
3791
- });
3792
- }
3793
- return [7 /*endfinally*/];
3794
- case 46:
3795
- if (expectError !== null && attempt === maxAttempts - 1) {
3796
- throw new PipelineExecutionError(spaceTrim$1(function (block) { return "\n LLM execution failed ".concat(maxExecutionAttempts, "x\n\n ").concat(block(pipelineIdentification), "\n\n ---\n The Prompt:\n ").concat(block(prompt.content
3797
- .split('\n')
3798
- .map(function (line) { return "> ".concat(line); })
3799
- .join('\n')), "\n\n Last error ").concat((expectError === null || expectError === void 0 ? void 0 : expectError.name) || '', ":\n ").concat(block(((expectError === null || expectError === void 0 ? void 0 : expectError.message) || '')
3957
+ }
3958
+ else {
3959
+ throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Unknown format \"".concat(template.format, "\"\n\n ").concat(block(pipelineIdentification), "\n "); }));
3960
+ }
3961
+ }
3962
+ // TODO: [💝] Unite object for expecting amount and format
3963
+ if (template.expectations) {
3964
+ checkExpectations(template.expectations, $ongoingTemplateResult.$resultString || '');
3965
+ }
3966
+ return [2 /*return*/, "break-attempts"];
3967
+ case 43:
3968
+ error_3 = _t.sent();
3969
+ if (!(error_3 instanceof ExpectError)) {
3970
+ throw error_3;
3971
+ }
3972
+ $ongoingTemplateResult.$expectError = error_3;
3973
+ return [3 /*break*/, 45];
3974
+ case 44:
3975
+ if (!isJokerAttempt &&
3976
+ template.templateType === 'PROMPT_TEMPLATE' &&
3977
+ $ongoingTemplateResult.$prompt
3978
+ // <- Note: [2] When some expected parameter is not defined, error will occur in replaceParameters
3979
+ // In that case we don’t want to make a report about it because it’s not a llm execution error
3980
+ ) {
3981
+ // TODO: [🧠] Maybe put other templateTypes into report
3982
+ $executionReport.promptExecutions.push({
3983
+ prompt: __assign({}, $ongoingTemplateResult.$prompt),
3984
+ result: $ongoingTemplateResult.$result || undefined,
3985
+ error: $ongoingTemplateResult.$expectError === null
3986
+ ? undefined
3987
+ : serializeError($ongoingTemplateResult.$expectError),
3988
+ });
3989
+ }
3990
+ return [7 /*endfinally*/];
3991
+ case 45:
3992
+ if ($ongoingTemplateResult.$expectError !== null && attempt === maxAttempts - 1) {
3993
+ throw new PipelineExecutionError(spaceTrim$1(function (block) {
3994
+ var _a, _b, _c;
3995
+ return "\n LLM execution failed ".concat(maxExecutionAttempts, "x\n\n ").concat(block(pipelineIdentification), "\n\n ---\n The Prompt:\n ").concat(block((((_a = $ongoingTemplateResult.$prompt) === null || _a === void 0 ? void 0 : _a.content) || '')
3996
+ .split('\n')
3997
+ .map(function (line) { return "> ".concat(line); })
3998
+ .join('\n')), "\n\n Last error ").concat(((_b = $ongoingTemplateResult.$expectError) === null || _b === void 0 ? void 0 : _b.name) || '', ":\n ").concat(block((((_c = $ongoingTemplateResult.$expectError) === null || _c === void 0 ? void 0 : _c.message) || '')
3999
+ .split('\n')
4000
+ .map(function (line) { return "> ".concat(line); })
4001
+ .join('\n')), "\n\n Last result:\n ").concat(block($ongoingTemplateResult.$resultString === null
4002
+ ? 'null'
4003
+ : $ongoingTemplateResult.$resultString
3800
4004
  .split('\n')
3801
4005
  .map(function (line) { return "> ".concat(line); })
3802
- .join('\n')), "\n\n Last result:\n ").concat(block(resultString === null
3803
- ? 'null'
3804
- : resultString
3805
- .split('\n')
3806
- .map(function (line) { return "> ".concat(line); })
3807
- .join('\n')), "\n ---\n "); }));
3808
- }
3809
- return [2 /*return*/];
4006
+ .join('\n')), "\n ---\n ");
4007
+ }));
3810
4008
  }
3811
- });
3812
- };
3813
- attempt = -jokerParameterNames.length;
3814
- _h.label = 4;
3815
- case 4:
3816
- if (!(attempt < maxAttempts)) return [3 /*break*/, 7];
3817
- return [5 /*yield**/, _loop_5(attempt)];
3818
- case 5:
3819
- state_2 = _h.sent();
3820
- switch (state_2) {
3821
- case "break-attempts": return [3 /*break*/, 7];
4009
+ return [2 /*return*/];
3822
4010
  }
3823
- _h.label = 6;
3824
- case 6:
3825
- attempt++;
3826
- return [3 /*break*/, 4];
3827
- case 7:
3828
- //------------------------------------
3829
- /*
3830
-
3831
-
3832
-
3833
-
3834
-
3835
-
3836
-
3837
-
3838
-
3839
- */
3840
- //------------------------------------
3841
- if (resultString === null) {
3842
- throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Something went wrong and prompt result is null\n\n ".concat(block(pipelineIdentification), "\n "); }));
3843
- }
3844
- if (!(onProgress !== undefined) /* <- [3] */) return [3 /*break*/, 9]; /* <- [3] */
3845
- progress_2 = {
3846
- name: name,
3847
- title: title,
3848
- isStarted: true,
3849
- isDone: true,
3850
- templateType: currentTemplate.templateType,
3851
- parameterName: currentTemplate.resultingParameterName,
3852
- parameterValue: resultString,
3853
- // <- [3]
3854
- };
3855
- if (isReturned) {
3856
- throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Can not call `onProgress` after pipeline execution is finished \uD83C\uDF4E\n\n ".concat(block(pipelineIdentification), "\n\n ").concat(block(JSON.stringify(progress_2, null, 4)
3857
- .split('\n')
3858
- .map(function (line) { return "> ".concat(line); })
3859
- .join('\n')), "\n\n "); }));
3860
- }
3861
- return [4 /*yield*/, onProgress(progress_2)];
3862
- case 8:
3863
- _h.sent();
3864
- _h.label = 9;
3865
- case 9:
3866
- parametersToPass = Object.freeze(__assign(__assign({}, parametersToPass), (_g = {}, _g[currentTemplate.resultingParameterName] = resultString /* <- Note: Not need to detect parameter collision here because pipeline checks logic consistency during construction */, _g)));
3867
- return [2 /*return*/];
4011
+ });
4012
+ };
4013
+ attempt = -jokerParameterNames.length;
4014
+ _a.label = 1;
4015
+ case 1:
4016
+ if (!(attempt < maxAttempts)) return [3 /*break*/, 4];
4017
+ return [5 /*yield**/, _loop_1(attempt)];
4018
+ case 2:
4019
+ state_1 = _a.sent();
4020
+ switch (state_1) {
4021
+ case "break-attempts": return [3 /*break*/, 4];
3868
4022
  }
3869
- });
3870
- });
3871
- }
3872
- function filterJustOutputParameters() {
3873
- var e_8, _a;
3874
- var outputParameters = {};
3875
- var _loop_6 = function (parameter) {
3876
- if (parametersToPass[parameter.name] === undefined) {
3877
- // [4]
3878
- warnings.push(new PipelineExecutionError(spaceTrim$1(function (block) { return "\n Parameter {".concat(parameter.name, "} should be an output parameter, but it was not generated during pipeline execution\n\n ").concat(block(pipelineIdentification), "\n "); })));
3879
- return "continue";
3880
- }
3881
- outputParameters[parameter.name] = parametersToPass[parameter.name] || '';
3882
- };
3883
- try {
3884
- // Note: Filter ONLY output parameters
3885
- for (var _b = __values(preparedPipeline.parameters.filter(function (_a) {
3886
- var isOutput = _a.isOutput;
3887
- return isOutput;
3888
- })), _c = _b.next(); !_c.done; _c = _b.next()) {
3889
- var parameter = _c.value;
3890
- _loop_6(parameter);
3891
- }
4023
+ _a.label = 3;
4024
+ case 3:
4025
+ attempt++;
4026
+ return [3 /*break*/, 1];
4027
+ case 4:
4028
+ if ($ongoingTemplateResult.$resultString === null) {
4029
+ throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Something went wrong and prompt result is null\n\n ".concat(block(pipelineIdentification), "\n "); }));
4030
+ }
4031
+ return [2 /*return*/, $ongoingTemplateResult.$resultString];
3892
4032
  }
3893
- catch (e_8_1) { e_8 = { error: e_8_1 }; }
3894
- finally {
3895
- try {
3896
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
3897
- }
3898
- finally { if (e_8) throw e_8.error; }
4033
+ });
4034
+ });
4035
+ }
4036
+ /**
4037
+ * TODO: Break into smaller functions
4038
+ */
4039
+
4040
+ /**
4041
+ * @@@
4042
+ *
4043
+ * @private internal utility of `createPipelineExecutor`
4044
+ */
4045
+ function executeFormatCells(options) {
4046
+ return __awaiter(this, void 0, void 0, function () {
4047
+ var template, jokerParameterNames, parameters, priority, pipelineIdentification, settings, parameterValue, formatDefinition, subvalueDefinition, formatSettings, resultString;
4048
+ var _this = this;
4049
+ return __generator(this, function (_a) {
4050
+ switch (_a.label) {
4051
+ case 0:
4052
+ template = options.template, jokerParameterNames = options.jokerParameterNames, parameters = options.parameters, priority = options.priority, pipelineIdentification = options.pipelineIdentification, settings = options.settings;
4053
+ if (template.foreach === undefined) {
4054
+ return [2 /*return*/, /* not await */ executeAttempts(options)];
4055
+ }
4056
+ if (jokerParameterNames.length !== 0) {
4057
+ throw new UnexpectedError(spaceTrim(function (block) { return "\n JOKER parameters are not supported together with FOREACH command\n\n [\uD83E\uDDDE\u200D\u2640\uFE0F] This should be prevented in `validatePipeline`\n\n ".concat(block(pipelineIdentification), "\n "); }));
4058
+ }
4059
+ parameterValue = parameters[template.foreach.parameterName] || '';
4060
+ formatDefinition = FORMAT_DEFINITIONS.find(function (formatDefinition) {
4061
+ return __spreadArray([formatDefinition.formatName], __read((formatDefinition.aliases || [])), false).includes(template.foreach.formatName);
4062
+ });
4063
+ if (formatDefinition === undefined) {
4064
+ throw new UnexpectedError(
4065
+ // <- TODO: [🧠][🧐] Should be formats fixed per promptbook version or behave as plugins (=> change UnexpectedError)
4066
+ spaceTrim(function (block) { return "\n Unsupported format \"".concat(template.foreach.formatName, "\"\n\n Available formats:\n ").concat(block(FORMAT_DEFINITIONS.map(function (formatDefinition) { return formatDefinition.formatName; })
4067
+ .map(function (formatName) { return "- ".concat(formatName); })
4068
+ .join('\n')), "\n\n [\u26F7] This should never happen because format name should be validated during parsing\n\n ").concat(block(pipelineIdentification), "\n "); }));
4069
+ }
4070
+ subvalueDefinition = formatDefinition.subvalueDefinitions.find(function (subvalueDefinition) {
4071
+ return __spreadArray([subvalueDefinition.subvalueName], __read((subvalueDefinition.aliases || [])), false).includes(template.foreach.subformatName);
4072
+ });
4073
+ if (subvalueDefinition === undefined) {
4074
+ throw new UnexpectedError(
4075
+ // <- TODO: [🧠][🧐] Should be formats fixed per promptbook version or behave as plugins (=> change UnexpectedError)
4076
+ spaceTrim(function (block) { return "\n Unsupported subformat name \"".concat(template.foreach.subformatName, "\" for format \"").concat(template.foreach.formatName, "\"\n\n Available subformat names for format \"").concat(formatDefinition.formatName, "\":\n ").concat(block(formatDefinition.subvalueDefinitions
4077
+ .map(function (subvalueDefinition) { return subvalueDefinition.subvalueName; })
4078
+ .map(function (subvalueName) { return "- ".concat(subvalueName); })
4079
+ .join('\n')), "\n\n [\u26F7] This should never happen because subformat name should be validated during parsing\n\n ").concat(block(pipelineIdentification), "\n "); }));
4080
+ }
4081
+ if (formatDefinition.formatName === 'CSV') {
4082
+ formatSettings = settings.csvSettings;
4083
+ // <- TODO: !!!!!! More universal, make simmilar pattern for other formats for example \n vs \r\n in text
4084
+ }
4085
+ return [4 /*yield*/, subvalueDefinition.mapValues(parameterValue, template.foreach.outputSubparameterName, formatSettings, function (subparameters, index) { return __awaiter(_this, void 0, void 0, function () {
4086
+ var mappedParameters, allSubparameters, subresultString;
4087
+ return __generator(this, function (_a) {
4088
+ switch (_a.label) {
4089
+ case 0:
4090
+ // TODO: !!!!!!! Limit to N concurrent executions
4091
+ // TODO: !!!!!!! Report progress
4092
+ try {
4093
+ mappedParameters = mapAvailableToExpectedParameters({
4094
+ expectedParameters: Object.fromEntries(template.foreach.inputSubparameterNames.map(function (subparameterName) { return [subparameterName, null]; })),
4095
+ availableParameters: subparameters,
4096
+ });
4097
+ }
4098
+ catch (error) {
4099
+ if (!(error instanceof PipelineExecutionError)) {
4100
+ throw error;
4101
+ }
4102
+ throw new PipelineExecutionError(spaceTrim(function (block) { return "\n ".concat(error.message, "\n\n This is error in FOREACH command\n You have probbably passed wrong data to pipeline or wrong data was generated which are processed by FOREACH command\n\n ").concat(block(pipelineIdentification), "\n Subparameter index: ").concat(index, "\n "); }));
4103
+ }
4104
+ allSubparameters = __assign(__assign({}, parameters), mappedParameters);
4105
+ // Note: [👨‍👨‍👧] Now we can freeze `subparameters` because we are sure that all and only used parameters are defined and are not going to be changed
4106
+ Object.freeze(allSubparameters);
4107
+ return [4 /*yield*/, executeAttempts(__assign(__assign({}, options), { priority: priority + index, parameters: allSubparameters, pipelineIdentification: spaceTrim(function (block) { return "\n ".concat(block(pipelineIdentification), "\n Subparameter index: ").concat(index, "\n "); }) }))];
4108
+ case 1:
4109
+ subresultString = _a.sent();
4110
+ return [2 /*return*/, subresultString];
4111
+ }
4112
+ });
4113
+ }); })];
4114
+ case 1:
4115
+ resultString = _a.sent();
4116
+ return [2 /*return*/, resultString];
4117
+ }
4118
+ });
4119
+ });
4120
+ }
4121
+ /**
4122
+ * TODO: !!!!!! Make pipelineIdentification more precise
4123
+ * TODO: !!!!!! How FOREACH execution looks in the report
4124
+ */
4125
+
4126
+ /**
4127
+ * @@@
4128
+ *
4129
+ * @private internal utility of `createPipelineExecutor`
4130
+ */
4131
+ function getContextForTemplate(template) {
4132
+ return __awaiter(this, void 0, void 0, function () {
4133
+ return __generator(this, function (_a) {
4134
+ TODO_USE(template);
4135
+ return [2 /*return*/, RESERVED_PARAMETER_MISSING_VALUE /* <- TODO: [🏍] Implement */];
4136
+ });
4137
+ });
4138
+ }
4139
+
4140
+ /**
4141
+ * @@@
4142
+ *
4143
+ * @private internal utility of `createPipelineExecutor`
4144
+ */
4145
+ function getKnowledgeForTemplate(options) {
4146
+ return __awaiter(this, void 0, void 0, function () {
4147
+ var preparedPipeline, template;
4148
+ return __generator(this, function (_a) {
4149
+ preparedPipeline = options.preparedPipeline, template = options.template;
4150
+ // TODO: [♨] Implement Better - use real index and keyword search from `template` and {samples}
4151
+ TODO_USE(template);
4152
+ return [2 /*return*/, preparedPipeline.knowledgePieces.map(function (_a) {
4153
+ var content = _a.content;
4154
+ return "- ".concat(content);
4155
+ }).join('\n')];
4156
+ });
4157
+ });
4158
+ }
4159
+
4160
+ /**
4161
+ * @@@
4162
+ *
4163
+ * @private internal utility of `createPipelineExecutor`
4164
+ */
4165
+ function getSamplesForTemplate(template) {
4166
+ return __awaiter(this, void 0, void 0, function () {
4167
+ return __generator(this, function (_a) {
4168
+ // TODO: [♨] Implement Better - use real index and keyword search
4169
+ TODO_USE(template);
4170
+ return [2 /*return*/, RESERVED_PARAMETER_MISSING_VALUE /* <- TODO: [♨] Implement */];
4171
+ });
4172
+ });
4173
+ }
4174
+
4175
+ /**
4176
+ * @@@
4177
+ *
4178
+ * @private internal utility of `createPipelineExecutor`
4179
+ */
4180
+ function getReservedParametersForTemplate(options) {
4181
+ return __awaiter(this, void 0, void 0, function () {
4182
+ var preparedPipeline, template, pipelineIdentification, context, knowledge, samples, currentDate, modelName, reservedParameters, _loop_1, RESERVED_PARAMETER_NAMES_1, RESERVED_PARAMETER_NAMES_1_1, parameterName;
4183
+ var e_1, _a;
4184
+ return __generator(this, function (_b) {
4185
+ switch (_b.label) {
4186
+ case 0:
4187
+ preparedPipeline = options.preparedPipeline, template = options.template, pipelineIdentification = options.pipelineIdentification;
4188
+ return [4 /*yield*/, getContextForTemplate(template)];
4189
+ case 1:
4190
+ context = _b.sent();
4191
+ return [4 /*yield*/, getKnowledgeForTemplate({ preparedPipeline: preparedPipeline, template: template })];
4192
+ case 2:
4193
+ knowledge = _b.sent();
4194
+ return [4 /*yield*/, getSamplesForTemplate(template)];
4195
+ case 3:
4196
+ samples = _b.sent();
4197
+ currentDate = new Date().toISOString();
4198
+ modelName = RESERVED_PARAMETER_MISSING_VALUE;
4199
+ reservedParameters = {
4200
+ content: RESERVED_PARAMETER_RESTRICTED,
4201
+ context: context,
4202
+ knowledge: knowledge,
4203
+ samples: samples,
4204
+ currentDate: currentDate,
4205
+ modelName: modelName,
4206
+ };
4207
+ _loop_1 = function (parameterName) {
4208
+ if (reservedParameters[parameterName] === undefined) {
4209
+ throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Reserved parameter {".concat(parameterName, "} is not defined\n\n ").concat(block(pipelineIdentification), "\n "); }));
4210
+ }
4211
+ };
4212
+ try {
4213
+ // Note: Doublecheck that ALL reserved parameters are defined:
4214
+ for (RESERVED_PARAMETER_NAMES_1 = __values(RESERVED_PARAMETER_NAMES), RESERVED_PARAMETER_NAMES_1_1 = RESERVED_PARAMETER_NAMES_1.next(); !RESERVED_PARAMETER_NAMES_1_1.done; RESERVED_PARAMETER_NAMES_1_1 = RESERVED_PARAMETER_NAMES_1.next()) {
4215
+ parameterName = RESERVED_PARAMETER_NAMES_1_1.value;
4216
+ _loop_1(parameterName);
4217
+ }
4218
+ }
4219
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
4220
+ finally {
4221
+ try {
4222
+ if (RESERVED_PARAMETER_NAMES_1_1 && !RESERVED_PARAMETER_NAMES_1_1.done && (_a = RESERVED_PARAMETER_NAMES_1.return)) _a.call(RESERVED_PARAMETER_NAMES_1);
4223
+ }
4224
+ finally { if (e_1) throw e_1.error; }
4225
+ }
4226
+ return [2 /*return*/, reservedParameters];
4227
+ }
4228
+ });
4229
+ });
4230
+ }
4231
+
4232
+ /**
4233
+ * @@@
4234
+ *
4235
+ * @private internal utility of `createPipelineExecutor`
4236
+ */
4237
+ function executeTemplate(options) {
4238
+ return __awaiter(this, void 0, void 0, function () {
4239
+ var currentTemplate, preparedPipeline, parametersToPass, tools, llmTools, onProgress, settings, $executionReport, pipelineIdentification, maxExecutionAttempts, name, title, priority, usedParameterNames, dependentParameterNames, definedParameters, _a, _b, _c, definedParameterNames, parameters, _loop_1, _d, _e, parameterName, maxAttempts, jokerParameterNames, preparedContent, resultString;
4240
+ var e_1, _f, _g;
4241
+ return __generator(this, function (_h) {
4242
+ switch (_h.label) {
4243
+ case 0:
4244
+ currentTemplate = options.currentTemplate, preparedPipeline = options.preparedPipeline, parametersToPass = options.parametersToPass, tools = options.tools, llmTools = options.llmTools, onProgress = options.onProgress, settings = options.settings, $executionReport = options.$executionReport, pipelineIdentification = options.pipelineIdentification;
4245
+ maxExecutionAttempts = settings.maxExecutionAttempts;
4246
+ name = "pipeline-executor-frame-".concat(currentTemplate.name);
4247
+ title = currentTemplate.title;
4248
+ priority = preparedPipeline.templates.length - preparedPipeline.templates.indexOf(currentTemplate);
4249
+ return [4 /*yield*/, onProgress({
4250
+ name: name,
4251
+ title: title,
4252
+ isStarted: false,
4253
+ isDone: false,
4254
+ templateType: currentTemplate.templateType,
4255
+ parameterName: currentTemplate.resultingParameterName,
4256
+ parameterValue: null,
4257
+ // <- [🍸]
4258
+ })];
4259
+ case 1:
4260
+ _h.sent();
4261
+ usedParameterNames = extractParameterNamesFromTemplate(currentTemplate);
4262
+ dependentParameterNames = new Set(currentTemplate.dependentParameterNames);
4263
+ // TODO: [👩🏾‍🤝‍👩🏻] Use here `mapAvailableToExpectedParameters`
4264
+ if (union(difference(usedParameterNames, dependentParameterNames), difference(dependentParameterNames, usedParameterNames)).size !== 0) {
4265
+ throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Dependent parameters are not consistent with used parameters:\n\n Dependent parameters:\n ".concat(Array.from(dependentParameterNames)
4266
+ .map(function (name) { return "{".concat(name, "}"); })
4267
+ .join(', '), "\n\n Used parameters:\n ").concat(Array.from(usedParameterNames)
4268
+ .map(function (name) { return "{".concat(name, "}"); })
4269
+ .join(', '), "\n\n ").concat(block(pipelineIdentification), "\n\n "); }));
4270
+ }
4271
+ _b = (_a = Object).freeze;
4272
+ _c = [{}];
4273
+ return [4 /*yield*/, getReservedParametersForTemplate({
4274
+ preparedPipeline: preparedPipeline,
4275
+ template: currentTemplate,
4276
+ pipelineIdentification: pipelineIdentification,
4277
+ })];
4278
+ case 2:
4279
+ definedParameters = _b.apply(_a, [__assign.apply(void 0, [__assign.apply(void 0, _c.concat([(_h.sent())])), parametersToPass])]);
4280
+ definedParameterNames = new Set(Object.keys(definedParameters));
4281
+ parameters = {};
4282
+ _loop_1 = function (parameterName) {
4283
+ // Situation: Parameter is defined and used
4284
+ if (definedParameterNames.has(parameterName) && usedParameterNames.has(parameterName)) {
4285
+ parameters[parameterName] = definedParameters[parameterName];
4286
+ }
4287
+ // Situation: Parameter is defined but NOT used
4288
+ else if (definedParameterNames.has(parameterName) && !usedParameterNames.has(parameterName)) ;
4289
+ // Situation: Parameter is NOT defined BUT used
4290
+ else if (!definedParameterNames.has(parameterName) && usedParameterNames.has(parameterName)) {
4291
+ // Houston, we have a problem
4292
+ // Note: Checking part is also done in `validatePipeline`, but it’s good to doublecheck
4293
+ throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Parameter {".concat(parameterName, "} is NOT defined\n BUT used in template \"").concat(currentTemplate.title || currentTemplate.name, "\"\n\n This should be catched in `validatePipeline`\n\n ").concat(block(pipelineIdentification), "\n\n "); }));
4294
+ }
4295
+ };
4296
+ try {
4297
+ // Note: [2] Check that all used parameters are defined and removing unused parameters for this template
4298
+ // TODO: [👩🏾‍🤝‍👩🏻] Use here `mapAvailableToExpectedParameters`
4299
+ for (_d = __values(Array.from(union(definedParameterNames, usedParameterNames, dependentParameterNames))), _e = _d.next(); !_e.done; _e = _d.next()) {
4300
+ parameterName = _e.value;
4301
+ _loop_1(parameterName);
4302
+ }
4303
+ }
4304
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
4305
+ finally {
4306
+ try {
4307
+ if (_e && !_e.done && (_f = _d.return)) _f.call(_d);
4308
+ }
4309
+ finally { if (e_1) throw e_1.error; }
4310
+ }
4311
+ // Note: [👨‍👨‍👧] Now we can freeze `parameters` because we are sure that all and only used parameters are defined and are not going to be changed
4312
+ Object.freeze(parameters);
4313
+ maxAttempts = currentTemplate.templateType === 'DIALOG_TEMPLATE' ? Infinity : maxExecutionAttempts;
4314
+ jokerParameterNames = currentTemplate.jokerParameterNames || [];
4315
+ preparedContent = (currentTemplate.preparedContent || '{content}')
4316
+ .split('{content}')
4317
+ .join(currentTemplate.content);
4318
+ return [4 /*yield*/, executeFormatCells({
4319
+ jokerParameterNames: jokerParameterNames,
4320
+ priority: priority,
4321
+ maxAttempts: maxAttempts,
4322
+ preparedContent: preparedContent,
4323
+ parameters: parameters,
4324
+ template: currentTemplate,
4325
+ preparedPipeline: preparedPipeline,
4326
+ tools: tools,
4327
+ llmTools: llmTools,
4328
+ settings: settings,
4329
+ $executionReport: $executionReport,
4330
+ pipelineIdentification: pipelineIdentification,
4331
+ })];
4332
+ case 3:
4333
+ resultString = _h.sent();
4334
+ return [4 /*yield*/, onProgress({
4335
+ name: name,
4336
+ title: title,
4337
+ isStarted: true,
4338
+ isDone: true,
4339
+ templateType: currentTemplate.templateType,
4340
+ parameterName: currentTemplate.resultingParameterName,
4341
+ parameterValue: resultString,
4342
+ // <- [🍸]
4343
+ })];
4344
+ case 4:
4345
+ _h.sent();
4346
+ return [2 /*return*/, Object.freeze((_g = {},
4347
+ _g[currentTemplate.resultingParameterName] =
4348
+ // <- Note: [👩‍👩‍👧] No need to detect parameter collision here because pipeline checks logic consistency during construction
4349
+ resultString,
4350
+ _g))];
3899
4351
  }
3900
- return outputParameters;
4352
+ });
4353
+ });
4354
+ }
4355
+ /**
4356
+ * TODO: [🤹‍♂️]
4357
+ */
4358
+
4359
+ /**
4360
+ * @@@
4361
+ *
4362
+ * @private internal utility of `createPipelineExecutor`
4363
+ */
4364
+ function filterJustOutputParameters(options) {
4365
+ var e_1, _a;
4366
+ var preparedPipeline = options.preparedPipeline, parametersToPass = options.parametersToPass, $warnings = options.$warnings, pipelineIdentification = options.pipelineIdentification;
4367
+ var outputParameters = {};
4368
+ var _loop_1 = function (parameter) {
4369
+ if (parametersToPass[parameter.name] === undefined) {
4370
+ // [4]
4371
+ $warnings.push(new PipelineExecutionError(spaceTrim$1(function (block) { return "\n Parameter {".concat(parameter.name, "} should be an output parameter, but it was not generated during pipeline execution\n\n ").concat(block(pipelineIdentification), "\n "); })));
4372
+ return "continue";
4373
+ }
4374
+ outputParameters[parameter.name] = parametersToPass[parameter.name] || '';
4375
+ };
4376
+ try {
4377
+ // Note: Filter ONLY output parameters
4378
+ // TODO: [👩🏾‍🤝‍👩🏻] Maybe use here `mapAvailableToExpectedParameters`
4379
+ for (var _b = __values(preparedPipeline.parameters.filter(function (_a) {
4380
+ var isOutput = _a.isOutput;
4381
+ return isOutput;
4382
+ })), _c = _b.next(); !_c.done; _c = _b.next()) {
4383
+ var parameter = _c.value;
4384
+ _loop_1(parameter);
4385
+ }
4386
+ }
4387
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
4388
+ finally {
4389
+ try {
4390
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
3901
4391
  }
3902
- var errors, warnings, executionReport, isReturned, _a, _b, parameter, e_1_1, _loop_1, _c, _d, parameterName, state_1, e_2_1, parametersToPass, resovedParameterNames_1, unresovedTemplates_1, resolving_1, loopLimit, _loop_2, error_1, usage_1, outputParameters_1, usage, outputParameters;
4392
+ finally { if (e_1) throw e_1.error; }
4393
+ }
4394
+ return outputParameters;
4395
+ }
4396
+
4397
+ /**
4398
+ * @@@
4399
+ *
4400
+ * Note: This is not a `PipelineExecutor` (which is binded with one exact pipeline), but a utility function of `createPipelineExecutor` which creates `PipelineExecutor`
4401
+ *
4402
+ * @private internal utility of `createPipelineExecutor`
4403
+ */
4404
+ function executePipeline(options) {
4405
+ return __awaiter(this, void 0, void 0, function () {
4406
+ var inputParameters, tools, onProgress, pipeline, setPreparedPipeline, pipelineIdentification, settings, maxParallelCount, isVerbose, preparedPipeline, llmTools, errors, warnings, executionReport, isReturned, _a, _b, parameter, e_1_1, _loop_1, _c, _d, parameterName, state_1, e_2_1, parametersToPass, resovedParameterNames_1, unresovedTemplates_1, resolving_1, loopLimit, _loop_2, error_1, usage_1, outputParameters_1, usage, outputParameters;
3903
4407
  var e_1, _e, e_2, _f;
3904
4408
  return __generator(this, function (_g) {
3905
4409
  switch (_g.label) {
3906
4410
  case 0:
4411
+ inputParameters = options.inputParameters, tools = options.tools, onProgress = options.onProgress, pipeline = options.pipeline, setPreparedPipeline = options.setPreparedPipeline, pipelineIdentification = options.pipelineIdentification, settings = options.settings;
4412
+ maxParallelCount = settings.maxParallelCount, isVerbose = settings.isVerbose;
4413
+ preparedPipeline = options.preparedPipeline;
4414
+ llmTools = joinLlmExecutionTools.apply(void 0, __spreadArray([], __read(arrayableToArray(tools.llm)), false));
3907
4415
  if (!(preparedPipeline === undefined)) return [3 /*break*/, 2];
3908
4416
  return [4 /*yield*/, preparePipeline(pipeline, {
3909
4417
  llmTools: llmTools,
@@ -3912,6 +4420,7 @@ function createPipelineExecutor(options) {
3912
4420
  })];
3913
4421
  case 1:
3914
4422
  preparedPipeline = _g.sent();
4423
+ setPreparedPipeline(preparedPipeline);
3915
4424
  _g.label = 2;
3916
4425
  case 2:
3917
4426
  errors = [];
@@ -3981,7 +4490,7 @@ function createPipelineExecutor(options) {
3981
4490
  return name === parameterName;
3982
4491
  });
3983
4492
  if (!(parameter === undefined)) return [3 /*break*/, 1];
3984
- warnings.push(new PipelineExecutionError(spaceTrim$1(function (block) { return "\n Extra parameter {".concat(parameterName, "} is being passed which is not part of the pipeline.\n\n ").concat(block(pipelineIdentification), "\n "); })));
4493
+ warnings.push(new PipelineExecutionError(spaceTrim$1(function (block) { return "\n Extra parameter {".concat(parameterName, "} is being passed which is not part of the pipeline.\n\n ").concat(block(pipelineIdentification), "\n "); })));
3985
4494
  return [3 /*break*/, 4];
3986
4495
  case 1:
3987
4496
  if (!(parameter.isInput === false)) return [3 /*break*/, 4];
@@ -3993,10 +4502,10 @@ function createPipelineExecutor(options) {
3993
4502
  // Note: Wait a short time to prevent race conditions
3994
4503
  _h.sent();
3995
4504
  _h.label = 3;
3996
- case 3: return [2 /*return*/, { value: $asDeeplyFrozenSerializableJson(spaceTrim$1(function (block) { return "\n Unuccessful PipelineExecutorResult (with extra parameter {".concat(parameter.name, "}) PipelineExecutorResult\n\n ").concat(block(pipelineIdentification), "\n "); }), {
4505
+ case 3: return [2 /*return*/, { value: $asDeeplyFrozenSerializableJson(spaceTrim$1(function (block) { return "\n Unuccessful PipelineExecutorResult (with extra parameter {".concat(parameter.name, "}) PipelineExecutorResult\n\n ").concat(block(pipelineIdentification), "\n "); }), {
3997
4506
  isSuccessful: false,
3998
4507
  errors: __spreadArray([
3999
- new PipelineExecutionError(spaceTrim$1(function (block) { return "\n Parameter {".concat(parameter.name, "} is passed as input parameter but it is not input\n\n ").concat(block(pipelineIdentification), "\n "); }))
4508
+ new PipelineExecutionError(spaceTrim$1(function (block) { return "\n Parameter {".concat(parameter.name, "} is passed as input parameter but it is not input\n\n ").concat(block(pipelineIdentification), "\n "); }))
4000
4509
  ], __read(errors), false).map(serializeError),
4001
4510
  warnings: warnings.map(serializeError),
4002
4511
  executionReport: executionReport,
@@ -4060,7 +4569,7 @@ function createPipelineExecutor(options) {
4060
4569
  case 0:
4061
4570
  if (loopLimit-- < 0) {
4062
4571
  // Note: Really UnexpectedError not LimitReachedError - this should be catched during validatePipeline
4063
- throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Loop limit reached during resolving parameters pipeline execution\n\n ".concat(block(pipelineIdentification), "\n "); }));
4572
+ throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Loop limit reached during resolving parameters pipeline execution\n\n ".concat(block(pipelineIdentification), "\n "); }));
4064
4573
  }
4065
4574
  currentTemplate = unresovedTemplates_1.find(function (template) {
4066
4575
  return template.dependentParameterNames.every(function (name) {
@@ -4070,29 +4579,52 @@ function createPipelineExecutor(options) {
4070
4579
  if (!(!currentTemplate && resolving_1.length === 0)) return [3 /*break*/, 1];
4071
4580
  throw new UnexpectedError(
4072
4581
  // TODO: [🐎] DRY
4073
- spaceTrim$1(function (block) { return "\n Can not resolve some parameters:\n\n ".concat(block(pipelineIdentification), "\n\n Can not resolve:\n ").concat(block(unresovedTemplates_1
4582
+ spaceTrim$1(function (block) { return "\n Can not resolve some parameters:\n\n ".concat(block(pipelineIdentification), "\n\n Can not resolve:\n ").concat(block(unresovedTemplates_1
4074
4583
  .map(function (_a) {
4075
4584
  var resultingParameterName = _a.resultingParameterName, dependentParameterNames = _a.dependentParameterNames;
4076
4585
  return "- Parameter {".concat(resultingParameterName, "} which depends on ").concat(dependentParameterNames
4077
4586
  .map(function (dependentParameterName) { return "{".concat(dependentParameterName, "}"); })
4078
4587
  .join(' and '));
4079
4588
  })
4080
- .join('\n')), "\n\n Resolved:\n ").concat(block(resovedParameterNames_1.map(function (name) { return "- Parameter {".concat(name, "}"); }).join('\n')), "\n\n Note: This should be catched in `validatePipeline`\n "); }));
4589
+ .join('\n')), "\n\n Resolved:\n ").concat(block(resovedParameterNames_1.map(function (name) { return "- Parameter {".concat(name, "}"); }).join('\n')), "\n\n Note: This should be catched in `validatePipeline`\n "); }));
4081
4590
  case 1:
4082
4591
  if (!!currentTemplate) return [3 /*break*/, 3];
4083
- /* [5] */ return [4 /*yield*/, Promise.race(resolving_1)];
4592
+ /* [🤹‍♂️] */ return [4 /*yield*/, Promise.race(resolving_1)];
4084
4593
  case 2:
4085
- /* [5] */ _j.sent();
4594
+ /* [🤹‍♂️] */ _j.sent();
4086
4595
  return [3 /*break*/, 4];
4087
4596
  case 3:
4088
4597
  unresovedTemplates_1 = unresovedTemplates_1.filter(function (template) { return template !== currentTemplate; });
4089
- work_1 = executeSingleTemplate(currentTemplate)
4090
- .then(function () {
4598
+ work_1 = executeTemplate({
4599
+ currentTemplate: currentTemplate,
4600
+ preparedPipeline: preparedPipeline,
4601
+ parametersToPass: parametersToPass,
4602
+ tools: tools,
4603
+ llmTools: llmTools,
4604
+ onProgress: function (progress) {
4605
+ if (isReturned) {
4606
+ throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Can not call `onProgress` after pipeline execution is finished\n\n ".concat(block(pipelineIdentification), "\n\n ").concat(block(JSON.stringify(progress, null, 4)
4607
+ .split('\n')
4608
+ .map(function (line) { return "> ".concat(line); })
4609
+ .join('\n')), "\n "); }));
4610
+ }
4611
+ if (onProgress) {
4612
+ onProgress(progress);
4613
+ }
4614
+ },
4615
+ settings: settings,
4616
+ $executionReport: executionReport,
4617
+ pipelineIdentification: spaceTrim$1(function (block) { return "\n ".concat(block(pipelineIdentification), "\n Template name: ").concat(currentTemplate.name, "\n Template title: ").concat(currentTemplate.title, "\n "); }),
4618
+ })
4619
+ .then(function (newParametersToPass) {
4620
+ parametersToPass = __assign(__assign({}, newParametersToPass), parametersToPass);
4091
4621
  resovedParameterNames_1 = __spreadArray(__spreadArray([], __read(resovedParameterNames_1), false), [currentTemplate.resultingParameterName], false);
4092
4622
  })
4093
4623
  .then(function () {
4094
4624
  resolving_1 = resolving_1.filter(function (w) { return w !== work_1; });
4095
4625
  });
4626
+ // <- Note: Errors are catched here [3]
4627
+ // TODO: BUT if in multiple templates are errors, only the first one is catched so maybe we should catch errors here and save them to errors array here
4096
4628
  resolving_1.push(work_1);
4097
4629
  _j.label = 4;
4098
4630
  case 4: return [2 /*return*/];
@@ -4119,7 +4651,12 @@ function createPipelineExecutor(options) {
4119
4651
  var result = _a.result;
4120
4652
  return (result === null || result === void 0 ? void 0 : result.usage) || ZERO_USAGE;
4121
4653
  })), false));
4122
- outputParameters_1 = filterJustOutputParameters();
4654
+ outputParameters_1 = filterJustOutputParameters({
4655
+ preparedPipeline: preparedPipeline,
4656
+ parametersToPass: parametersToPass,
4657
+ $warnings: warnings,
4658
+ pipelineIdentification: pipelineIdentification,
4659
+ });
4123
4660
  isReturned = true;
4124
4661
  if (!(onProgress !== undefined)) return [3 /*break*/, 27];
4125
4662
  // Note: Wait a short time to prevent race conditions
@@ -4142,7 +4679,12 @@ function createPipelineExecutor(options) {
4142
4679
  var result = _a.result;
4143
4680
  return (result === null || result === void 0 ? void 0 : result.usage) || ZERO_USAGE;
4144
4681
  })), false));
4145
- outputParameters = filterJustOutputParameters();
4682
+ outputParameters = filterJustOutputParameters({
4683
+ preparedPipeline: preparedPipeline,
4684
+ parametersToPass: parametersToPass,
4685
+ $warnings: warnings,
4686
+ pipelineIdentification: pipelineIdentification,
4687
+ });
4146
4688
  isReturned = true;
4147
4689
  if (!(onProgress !== undefined)) return [3 /*break*/, 30];
4148
4690
  // Note: Wait a short time to prevent race conditions
@@ -4162,22 +4704,65 @@ function createPipelineExecutor(options) {
4162
4704
  })];
4163
4705
  }
4164
4706
  });
4165
- }); };
4166
- return pipelineExecutor;
4707
+ });
4167
4708
  }
4709
+
4168
4710
  /**
4169
- * TODO: !!! Identify not only pipeline BUT exact template ${block(pipelineIdentification)}
4170
- * TODO: Use isVerbose here (not only pass to `preparePipeline`)
4171
- * TODO: [🧠][🌳] Use here `countTotalUsage` and put preparation and prepared pipiline to report
4172
- * TODO: [🪂] Use maxParallelCount here (not only pass to `preparePipeline`)
4173
- * TODO: [♈] Probbably move expectations from templates to parameters
4174
- * TODO: [🧠] When not meet expectations in DIALOG_TEMPLATE, make some way to tell the user
4175
- * TODO: [👧] Strongly type the executors to avoid need of remove nullables whtn noUncheckedIndexedAccess in tsconfig.json
4176
- * Note: CreatePipelineExecutorOptions are just connected to PipelineExecutor so do not extract to types folder
4177
- * TODO: [🧠][3] transparent = (report intermediate parameters) / opaque execution = (report only output parameters) progress reporting mode
4178
- * TODO: [🛠] Actions, instruments (and maybe knowledge) => Functions and tools
4179
- * TODO: [🧠][💷] `assertsExecutionSuccessful` should be the method of `PipelineExecutor` result BUT maybe NOT to preserve pure JSON object
4711
+ * Creates executor function from pipeline and execution tools.
4712
+ *
4713
+ * @returns The executor function
4714
+ * @throws {PipelineLogicError} on logical error in the pipeline
4715
+ * @public exported from `@promptbook/core`
4180
4716
  */
4717
+ function createPipelineExecutor(options) {
4718
+ var _this = this;
4719
+ var pipeline = options.pipeline, tools = options.tools, _a = options.settings, settings = _a === void 0 ? {} : _a;
4720
+ var _b = settings.maxExecutionAttempts, maxExecutionAttempts = _b === void 0 ? MAX_EXECUTION_ATTEMPTS : _b, _c = settings.maxParallelCount, maxParallelCount = _c === void 0 ? MAX_PARALLEL_COUNT : _c, _d = settings.csvSettings, csvSettings = _d === void 0 ? DEFAULT_CSV_SETTINGS : _d, _e = settings.isVerbose, isVerbose = _e === void 0 ? IS_VERBOSE : _e, _f = settings.isNotPreparedWarningSupressed, isNotPreparedWarningSupressed = _f === void 0 ? false : _f;
4721
+ validatePipeline(pipeline);
4722
+ var pipelineIdentification = (function () {
4723
+ // Note: This is a 😐 implementation of [🚞]
4724
+ var _ = [];
4725
+ if (pipeline.sourceFile !== undefined) {
4726
+ _.push("File: ".concat(pipeline.sourceFile));
4727
+ }
4728
+ if (pipeline.pipelineUrl !== undefined) {
4729
+ _.push("Url: ".concat(pipeline.pipelineUrl));
4730
+ }
4731
+ return _.join('\n');
4732
+ })();
4733
+ var preparedPipeline;
4734
+ if (isPipelinePrepared(pipeline)) {
4735
+ preparedPipeline = pipeline;
4736
+ }
4737
+ else if (isNotPreparedWarningSupressed !== true) {
4738
+ console.warn(spaceTrim$1(function (block) { return "\n Pipeline is not prepared\n\n ".concat(block(pipelineIdentification), "\n\n It will be prepared ad-hoc before the first execution and **returned as `preparedPipeline` in `PipelineExecutorResult`**\n But it is recommended to prepare the pipeline during collection preparation\n\n @see more at https://ptbk.io/prepare-pipeline\n "); }));
4739
+ }
4740
+ var runCount = 0;
4741
+ var pipelineExecutor = function (inputParameters, onProgress) { return __awaiter(_this, void 0, void 0, function () {
4742
+ return __generator(this, function (_a) {
4743
+ runCount++;
4744
+ return [2 /*return*/, /* not await */ executePipeline({
4745
+ pipeline: pipeline,
4746
+ preparedPipeline: preparedPipeline,
4747
+ setPreparedPipeline: function (newPreparedPipeline) {
4748
+ preparedPipeline = newPreparedPipeline;
4749
+ },
4750
+ inputParameters: inputParameters,
4751
+ tools: tools,
4752
+ onProgress: onProgress,
4753
+ pipelineIdentification: spaceTrim$1(function (block) { return "\n ".concat(block(pipelineIdentification), "\n ").concat(runCount === 1 ? '' : "Run #".concat(runCount), "\n "); }),
4754
+ settings: {
4755
+ maxExecutionAttempts: maxExecutionAttempts,
4756
+ maxParallelCount: maxParallelCount,
4757
+ csvSettings: csvSettings,
4758
+ isVerbose: isVerbose,
4759
+ isNotPreparedWarningSupressed: isNotPreparedWarningSupressed,
4760
+ },
4761
+ })];
4762
+ });
4763
+ }); };
4764
+ return pipelineExecutor;
4765
+ }
4181
4766
 
4182
4767
  /**
4183
4768
  * @@@
@@ -4229,7 +4814,7 @@ function prepareKnowledgeFromMarkdown(knowledgeContent /* <- TODO: [🖖] (?mayb
4229
4814
  outputParameters = result.outputParameters;
4230
4815
  knowledgePiecesRaw = outputParameters.knowledgePieces;
4231
4816
  knowledgeTextPieces = (knowledgePiecesRaw || '').split('\n---\n');
4232
- // <- TODO: !!!!! Smarter split and filter out empty pieces
4817
+ // <- TODO:[main] !!!!! Smarter split and filter out empty pieces
4233
4818
  if (isVerbose) {
4234
4819
  console.info('knowledgeTextPieces:', knowledgeTextPieces);
4235
4820
  }
@@ -4287,8 +4872,13 @@ function prepareKnowledgeFromMarkdown(knowledgeContent /* <- TODO: [🖖] (?mayb
4287
4872
  case 6: return [3 /*break*/, 8];
4288
4873
  case 7:
4289
4874
  error_1 = _c.sent();
4875
+ // Note: Here is expected error:
4876
+ // > PipelineExecutionError: You have not provided any `LlmExecutionTools` that support model variant "EMBEDDING
4877
+ if (!(error_1 instanceof PipelineExecutionError)) {
4878
+ throw error_1;
4879
+ }
4290
4880
  // TODO: [🟥] Detect browser / node and make it colorfull
4291
- console.error(error_1);
4881
+ console.error(error_1, "<- Note: This error is not critical to prepare the pipeline, just knowledge pieces won't have embeddings");
4292
4882
  return [3 /*break*/, 8];
4293
4883
  case 8: return [2 /*return*/, {
4294
4884
  name: name,
@@ -4309,7 +4899,7 @@ function prepareKnowledgeFromMarkdown(knowledgeContent /* <- TODO: [🖖] (?mayb
4309
4899
  });
4310
4900
  }
4311
4901
  /**
4312
- * TODO: [🐝][🔼] !!! Export via `@promptbook/markdown`
4902
+ * TODO: [🐝][🔼][main] !!! Export via `@promptbook/markdown`
4313
4903
  * TODO: [🪂] Do it in parallel 11:11
4314
4904
  * Note: No need to aggregate usage here, it is done by intercepting the llmTools
4315
4905
  */
@@ -4333,7 +4923,7 @@ function prepareKnowledgePieces(knowledgeSources, options) {
4333
4923
  var partialPieces, pieces;
4334
4924
  return __generator(this, function (_a) {
4335
4925
  switch (_a.label) {
4336
- case 0: return [4 /*yield*/, prepareKnowledgeFromMarkdown(knowledgeSource.sourceContent, // <- TODO: [🐝] !!! Unhardcode markdown, detect which type it is - BE AWARE of big package size
4926
+ case 0: return [4 /*yield*/, prepareKnowledgeFromMarkdown(knowledgeSource.sourceContent, // <- TODO: [🐝][main] !!! Unhardcode markdown, detect which type it is - BE AWARE of big package size
4337
4927
  options)];
4338
4928
  case 1:
4339
4929
  partialPieces = _a.sent();
@@ -4525,7 +5115,7 @@ function preparePersona(personaDescription, options) {
4525
5115
  });
4526
5116
  }
4527
5117
  /**
4528
- * TODO: [🔃] !!!!! If the persona was prepared with different version or different set of models, prepare it once again
5118
+ * TODO: [🔃][main] !!!!! If the persona was prepared with different version or different set of models, prepare it once again
4529
5119
  * TODO: [🏢] !! Check validity of `modelName` in pipeline
4530
5120
  * TODO: [🏢] !! Check validity of `systemMessage` in pipeline
4531
5121
  * TODO: [🏢] !! Check validity of `temperature` in pipeline
@@ -4574,7 +5164,7 @@ function prepareTemplates(pipeline, options) {
4574
5164
  case 0:
4575
5165
  _a = options.maxParallelCount, maxParallelCount = _a === void 0 ? MAX_PARALLEL_COUNT : _a;
4576
5166
  templates = pipeline.templates, parameters = pipeline.parameters, knowledgePiecesCount = pipeline.knowledgePiecesCount;
4577
- // TODO: !!!!! Apply samples to each template (if missing and is for the template defined)
5167
+ // TODO:[main] !!!!! Apply samples to each template (if missing and is for the template defined)
4578
5168
  TODO_USE(parameters);
4579
5169
  templatesPrepared = new Array(
4580
5170
  // <- TODO: [🧱] Implement in a functional (not new Class) way
@@ -4606,7 +5196,7 @@ function prepareTemplates(pipeline, options) {
4606
5196
  /**
4607
5197
  * TODO: [🧠] Add context to each template (if missing)
4608
5198
  * TODO: [🧠] What is better name `prepareTemplate` or `prepareTemplateAndParameters`
4609
- * TODO: [♨] !!! Prepare index the samples and maybe templates
5199
+ * TODO: [♨][main] !!! Prepare index the samples and maybe templates
4610
5200
  * TODO: Write tests for `preparePipeline`
4611
5201
  * TODO: [🏏] Leverage the batch API and build queues @see https://platform.openai.com/docs/guides/batch
4612
5202
  * TODO: [🧊] In future one preparation can take data from previous preparation and save tokens and time
@@ -4778,7 +5368,7 @@ var knowledgeCommandParser = {
4778
5368
  if (sourceContent === '') {
4779
5369
  throw new ParseError("Source is not defined");
4780
5370
  }
4781
- // TODO: !!!! Following checks should be applied every link in the `sourceContent`
5371
+ // TODO:[main] !!!! Following checks should be applied every link in the `sourceContent`
4782
5372
  if (sourceContent.startsWith('http://')) {
4783
5373
  throw new ParseError("Source is not secure");
4784
5374
  }
@@ -4963,7 +5553,7 @@ var templateCommandParser = {
4963
5553
  if (command.templateType === 'KNOWLEDGE') {
4964
5554
  knowledgeCommandParser.$applyToPipelineJson({
4965
5555
  type: 'KNOWLEDGE',
4966
- sourceContent: $templateJson.content, // <- TODO: [🐝] !!! Work with KNOWLEDGE which not referring to the source file or website, but its content itself
5556
+ sourceContent: $templateJson.content, // <- TODO: [🐝][main] !!! Work with KNOWLEDGE which not referring to the source file or website, but its content itself
4967
5557
  }, $pipelineJson);
4968
5558
  $templateJson.isTemplate = false;
4969
5559
  return;
@@ -5313,6 +5903,171 @@ function normalizeTo_SCREAMING_CASE(text) {
5313
5903
  * TODO: [🌺] Use some intermediate util splitWords
5314
5904
  */
5315
5905
 
5906
+ /**
5907
+ * @@@
5908
+ *
5909
+ * @param text @@@
5910
+ * @param _isFirstLetterCapital @@@
5911
+ * @returns @@@
5912
+ * @example 'helloWorld'
5913
+ * @example 'iLovePromptbook'
5914
+ * @public exported from `@promptbook/utils`
5915
+ */
5916
+ function normalizeTo_camelCase(text, _isFirstLetterCapital) {
5917
+ var e_1, _a;
5918
+ if (_isFirstLetterCapital === void 0) { _isFirstLetterCapital = false; }
5919
+ var charType;
5920
+ var lastCharType = null;
5921
+ var normalizedName = '';
5922
+ try {
5923
+ for (var text_1 = __values(text), text_1_1 = text_1.next(); !text_1_1.done; text_1_1 = text_1.next()) {
5924
+ var char = text_1_1.value;
5925
+ var normalizedChar = void 0;
5926
+ if (/^[a-z]$/.test(char)) {
5927
+ charType = 'LOWERCASE';
5928
+ normalizedChar = char;
5929
+ }
5930
+ else if (/^[A-Z]$/.test(char)) {
5931
+ charType = 'UPPERCASE';
5932
+ normalizedChar = char.toLowerCase();
5933
+ }
5934
+ else if (/^[0-9]$/.test(char)) {
5935
+ charType = 'NUMBER';
5936
+ normalizedChar = char;
5937
+ }
5938
+ else {
5939
+ charType = 'OTHER';
5940
+ normalizedChar = '';
5941
+ }
5942
+ if (!lastCharType) {
5943
+ if (_isFirstLetterCapital) {
5944
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: DRY
5945
+ }
5946
+ }
5947
+ else if (charType !== lastCharType &&
5948
+ !(charType === 'LOWERCASE' && lastCharType === 'UPPERCASE') &&
5949
+ !(lastCharType === 'NUMBER') &&
5950
+ !(charType === 'NUMBER')) {
5951
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: [🌺] DRY
5952
+ }
5953
+ normalizedName += normalizedChar;
5954
+ lastCharType = charType;
5955
+ }
5956
+ }
5957
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
5958
+ finally {
5959
+ try {
5960
+ if (text_1_1 && !text_1_1.done && (_a = text_1.return)) _a.call(text_1);
5961
+ }
5962
+ finally { if (e_1) throw e_1.error; }
5963
+ }
5964
+ return normalizedName;
5965
+ }
5966
+ /**
5967
+ * TODO: [🌺] Use some intermediate util splitWords
5968
+ */
5969
+
5970
+ /**
5971
+ * Removes quotes from a string
5972
+ *
5973
+ * Tip: This is very usefull for post-processing of the result of the LLM model
5974
+ * Note: This function removes only the same quotes from the beginning and the end of the string
5975
+ * Note: There are two simmilar functions:
5976
+ * - `removeQuotes` which removes only bounding quotes
5977
+ * - `unwrapResult` which removes whole introduce sentence
5978
+ *
5979
+ * @param text optionally quoted text
5980
+ * @returns text without quotes
5981
+ * @public exported from `@promptbook/utils`
5982
+ */
5983
+ function removeQuotes(text) {
5984
+ if (text.startsWith('"') && text.endsWith('"')) {
5985
+ return text.slice(1, -1);
5986
+ }
5987
+ if (text.startsWith('\'') && text.endsWith('\'')) {
5988
+ return text.slice(1, -1);
5989
+ }
5990
+ return text;
5991
+ }
5992
+
5993
+ /**
5994
+ * Function `validateParameterName` will @@@
5995
+ *
5996
+ * @param parameterName @@@
5997
+ * @returns @@@
5998
+ * @throws {ParseError} @@@
5999
+ * @private within the repository
6000
+ */
6001
+ function validateParameterName(parameterName) {
6002
+ var e_1, _a;
6003
+ var rawParameterName = parameterName;
6004
+ try {
6005
+ for (var _b = __values([
6006
+ ['`', '`'],
6007
+ ['{', '}'],
6008
+ ['[', ']'],
6009
+ ['(', ')'],
6010
+ ['<', '>'],
6011
+ ]), _c = _b.next(); !_c.done; _c = _b.next()) {
6012
+ var _d = __read(_c.value, 2), start = _d[0], end = _d[1];
6013
+ if (parameterName.substring(0, 1) === start &&
6014
+ parameterName.substring(parameterName.length - 1, parameterName.length) === end
6015
+ // <- TODO: More universal that 1 character
6016
+ ) {
6017
+ parameterName = parameterName.substring(1, parameterName.length - 1);
6018
+ // <- TODO: More universal that 1 character
6019
+ }
6020
+ }
6021
+ }
6022
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
6023
+ finally {
6024
+ try {
6025
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
6026
+ }
6027
+ finally { if (e_1) throw e_1.error; }
6028
+ }
6029
+ // TODO: [🐠] Following try-catch block should be part of common validators logic
6030
+ try {
6031
+ /*
6032
+ Note: We don't need to check for spaces because we are going to normalize the parameter name to camelCase
6033
+ if (parameterName.includes(' ')) {
6034
+ throw new ParseError(`Parameter name cannot contain spaces`);
6035
+ }
6036
+ */
6037
+ if (parameterName.includes('.')) {
6038
+ throw new ParseError("Parameter name cannot contain dots");
6039
+ }
6040
+ if (parameterName.includes('/') || parameterName.includes('\\')) {
6041
+ throw new ParseError("Parameter name cannot contain slashes");
6042
+ }
6043
+ if (parameterName.includes('(') ||
6044
+ parameterName.includes(')') ||
6045
+ parameterName.includes('{') ||
6046
+ parameterName.includes('}') ||
6047
+ parameterName.includes('[') ||
6048
+ parameterName.includes(']')) {
6049
+ throw new ParseError("Parameter name cannot contain braces");
6050
+ }
6051
+ parameterName = removeDiacritics(parameterName);
6052
+ parameterName = removeEmojis(parameterName);
6053
+ parameterName = removeQuotes(parameterName);
6054
+ parameterName = normalizeTo_camelCase(parameterName);
6055
+ if (parameterName === '') {
6056
+ throw new ParseError("Parameter name cannot be empty");
6057
+ }
6058
+ if (RESERVED_PARAMETER_NAMES.includes(parameterName)) {
6059
+ throw new ParseError("{".concat(parameterName, "} is a reserved parameter name"));
6060
+ }
6061
+ }
6062
+ catch (error) {
6063
+ if (!(error instanceof ParseError)) {
6064
+ throw error;
6065
+ }
6066
+ throw new ParseError(spaceTrim(function (block) { return "\n ".concat(block(error.message), "\n\n Tried to validate parameter name:\n ").concat(block(rawParameterName), "\n "); }));
6067
+ }
6068
+ return parameterName;
6069
+ }
6070
+
5316
6071
  /**
5317
6072
  * Parses the foreach command
5318
6073
  *
@@ -5342,15 +6097,16 @@ var foreachCommandParser = {
5342
6097
  /**
5343
6098
  * Link to discussion
5344
6099
  */
5345
- documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/@@',
6100
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/148',
5346
6101
  /**
5347
6102
  * Example usages of the FOREACH command
5348
6103
  */
5349
6104
  examples: [
5350
- 'FOREACH List Line `{customers}` -> `{customer}`',
5351
- 'FOR List Line `{customers}` -> `{customer}`',
5352
- 'EACH List Line `{customers}` -> `{customer}`',
5353
- // <- TODO: [🍭] !!!!!! More
6105
+ 'FOREACH Text Line `{customers}` -> `{customer}`',
6106
+ 'FOREACH Csv Cell `{customers}` -> `{cell}`',
6107
+ 'FOREACH Csv Row `{customers}` -> `{firstName}`, `{lastName}`, `+{email}`',
6108
+ 'FOR Text Line `{customers}` -> `{customer}`',
6109
+ 'EACH Text Line `{customers}` -> `{customer}`',
5354
6110
  ],
5355
6111
  /**
5356
6112
  * Parses the FOREACH command
@@ -5358,55 +6114,75 @@ var foreachCommandParser = {
5358
6114
  parse: function (input) {
5359
6115
  var args = input.args;
5360
6116
  var formatName = normalizeTo_SCREAMING_CASE(args[0] || '');
5361
- var cellName = normalizeTo_SCREAMING_CASE(args[1] || '');
5362
- var parameterNameWrapped = args[2];
6117
+ var subformatName = normalizeTo_SCREAMING_CASE(args[1] || '');
6118
+ var parameterNameArg = args[2] || '';
5363
6119
  var assignSign = args[3];
5364
- var subparameterNameWrapped = args[4];
5365
- if (![
5366
- 'LIST',
5367
- 'CSV',
5368
- // <- TODO: [🏢] Unhardcode formats
5369
- ].includes(formatName)) {
5370
- console.info({ args: args, formatName: formatName });
5371
- throw new Error("Unsupported format \"".concat(formatName, "\""));
6120
+ var formatDefinition = FORMAT_DEFINITIONS.find(function (formatDefinition) {
6121
+ return __spreadArray([formatDefinition.formatName], __read((formatDefinition.aliases || [])), false).includes(formatName);
6122
+ });
6123
+ if (formatDefinition === undefined) {
6124
+ throw new ParseError(spaceTrim(function (block) { return "\n Unsupported format \"".concat(formatName, "\"\n\n Available formats:\n ").concat(block(FORMAT_DEFINITIONS.map(function (formatDefinition) { return formatDefinition.formatName; })
6125
+ .map(function (formatName) { return "- ".concat(formatName); })
6126
+ .join('\n')), "\n "); }));
5372
6127
  // <- TODO: [🏢] List all supported format names
5373
6128
  }
5374
- if (![
5375
- 'LINE',
5376
- 'ROW',
5377
- 'COLUMN',
5378
- 'CELL',
5379
- // <- TODO: [🏢] Unhardcode format cells
5380
- ].includes(cellName)) {
5381
- console.info({ args: args, cellName: cellName });
5382
- throw new Error("Format ".concat(formatName, " does not support cell \"").concat(cellName, "\""));
5383
- // <- TODO: [🏢] List all supported cell names for the format
6129
+ var subvalueDefinition = formatDefinition.subvalueDefinitions.find(function (subvalueDefinition) {
6130
+ return __spreadArray([subvalueDefinition.subvalueName], __read((subvalueDefinition.aliases || [])), false).includes(subformatName);
6131
+ });
6132
+ if (subvalueDefinition === undefined) {
6133
+ throw new ParseError(spaceTrim(function (block) { return "\n Unsupported subformat name \"".concat(subformatName, "\" for format \"").concat(formatName, "\"\n\n Available subformat names for format \"").concat(formatDefinition.formatName, "\":\n ").concat(block(formatDefinition.subvalueDefinitions
6134
+ .map(function (subvalueDefinition) { return subvalueDefinition.subvalueName; })
6135
+ .map(function (subvalueName) { return "- ".concat(subvalueName); })
6136
+ .join('\n')), "\n "); }));
6137
+ // <- TODO: [🏢] List all supported subformat names for the format
5384
6138
  }
5385
6139
  if (assignSign !== '->') {
5386
- console.info({ args: args, assignSign: assignSign });
5387
- throw new Error("FOREACH command must have '->' to assign the value to the parameter");
5388
- }
5389
- // TODO: !!!!!! Replace with propper parameter name validation
5390
- if ((parameterNameWrapped === null || parameterNameWrapped === void 0 ? void 0 : parameterNameWrapped.substring(0, 1)) !== '{' ||
5391
- (parameterNameWrapped === null || parameterNameWrapped === void 0 ? void 0 : parameterNameWrapped.substring(parameterNameWrapped.length - 1, parameterNameWrapped.length)) !== '}') {
5392
- console.info({ args: args, parameterNameWrapped: parameterNameWrapped }, parameterNameWrapped === null || parameterNameWrapped === void 0 ? void 0 : parameterNameWrapped.substring(0, 1), parameterNameWrapped === null || parameterNameWrapped === void 0 ? void 0 : parameterNameWrapped.substring(parameterNameWrapped.length - 1, parameterNameWrapped.length));
5393
- throw new Error("!!!!!! 1 Here will be error (with rules and precise error) from validateParameterName");
5394
- }
5395
- var parameterName = parameterNameWrapped.substring(1, parameterNameWrapped.length - 1);
5396
- // TODO: !!!!!! Replace with propper parameter name validation
5397
- if ((subparameterNameWrapped === null || subparameterNameWrapped === void 0 ? void 0 : subparameterNameWrapped.substring(0, 1)) !== '{' ||
5398
- (subparameterNameWrapped === null || subparameterNameWrapped === void 0 ? void 0 : subparameterNameWrapped.substring(subparameterNameWrapped.length - 1, subparameterNameWrapped.length)) !==
5399
- '}') {
5400
- console.info({ args: args, subparameterNameWrapped: subparameterNameWrapped });
5401
- throw new Error("!!!!!! 2 Here will be error (with rules and precise error) from validateParameterName");
5402
- }
5403
- var subparameterName = subparameterNameWrapped.substring(1, subparameterNameWrapped.length - 1);
6140
+ throw new ParseError("FOREACH command must have '->' to assign the value to the parameter");
6141
+ }
6142
+ var parameterName = validateParameterName(parameterNameArg);
6143
+ var outputSubparameterName = null;
6144
+ // TODO: [4] DRY
6145
+ var inputSubparameterNames = args
6146
+ .slice(4)
6147
+ .map(function (parameterName) { return parameterName.split(',').join(' ').trim(); })
6148
+ .filter(function (parameterName) { return !parameterName.includes('+'); })
6149
+ .filter(function (parameterName) { return parameterName !== ''; })
6150
+ .map(validateParameterName);
6151
+ // TODO: [4] DRY
6152
+ var outputSubparameterNames = args
6153
+ .slice(4)
6154
+ .map(function (parameterName) { return parameterName.split(',').join(' ').trim(); })
6155
+ .filter(function (parameterName) { return parameterName.includes('+'); })
6156
+ .map(function (parameterName) { return parameterName.split('+').join(''); })
6157
+ .map(validateParameterName);
6158
+ if (outputSubparameterNames.length === 1) {
6159
+ outputSubparameterName = outputSubparameterNames[0];
6160
+ }
6161
+ else if (outputSubparameterNames.length > 1) {
6162
+ throw new ParseError("FOREACH command can not have more than one output subparameter");
6163
+ }
6164
+ if (inputSubparameterNames.length === 0) {
6165
+ throw new ParseError("FOREACH command must have at least one input subparameter");
6166
+ }
6167
+ if (outputSubparameterName === null) {
6168
+ // TODO: Following code should be unhardcoded from here and moved to the format definition
6169
+ if (formatName === 'CSV' && subformatName === 'CELL') {
6170
+ outputSubparameterName = 'newCell';
6171
+ }
6172
+ else if (formatName === 'TEXT' && subformatName === 'LINE') {
6173
+ outputSubparameterName = 'newLine';
6174
+ }
6175
+ else {
6176
+ throw new ParseError(spaceTrim("\n FOREACH ".concat(formatName, " ").concat(subformatName, " must specify output subparameter\n\n Correct example:\n - FOREACH ").concat(formatName, " ").concat(subformatName, " {").concat(parameterName, "} -> {inputSubparameterName1}, {inputSubparameterName2}, +{outputSubparameterName}\n\n ")));
6177
+ }
6178
+ }
5404
6179
  return {
5405
6180
  type: 'FOREACH',
5406
6181
  formatName: formatName,
5407
- cellName: cellName,
6182
+ subformatName: subformatName,
5408
6183
  parameterName: parameterName,
5409
- subparameterName: subparameterName,
6184
+ inputSubparameterNames: inputSubparameterNames,
6185
+ outputSubparameterName: outputSubparameterName,
5410
6186
  };
5411
6187
  },
5412
6188
  /**
@@ -5415,9 +6191,17 @@ var foreachCommandParser = {
5415
6191
  * Note: `$` is used to indicate that this function mutates given `templateJson`
5416
6192
  */
5417
6193
  $applyToTemplateJson: function (command, $templateJson, $pipelineJson) {
5418
- var formatName = command.formatName, cellName = command.cellName, parameterName = command.parameterName, subparameterName = command.subparameterName;
5419
- $templateJson.foreach = { formatName: formatName, cellName: cellName, parameterName: parameterName, subparameterName: subparameterName };
5420
- keepUnused($pipelineJson); // <- TODO: !!!!!! BUT Maybe register subparameter from foreach into parameters of the pipeline
6194
+ var formatName = command.formatName, subformatName = command.subformatName, parameterName = command.parameterName, inputSubparameterNames = command.inputSubparameterNames, outputSubparameterName = command.outputSubparameterName;
6195
+ // TODO: [🍭] Detect double use
6196
+ // TODO: [🍭] Detect usage with JOKER and don't allow it
6197
+ $templateJson.foreach = {
6198
+ formatName: formatName,
6199
+ subformatName: subformatName,
6200
+ parameterName: parameterName,
6201
+ inputSubparameterNames: inputSubparameterNames,
6202
+ outputSubparameterName: outputSubparameterName,
6203
+ };
6204
+ keepUnused($pipelineJson); // <- TODO: [🧠] Maybe register subparameter from foreach into parameters of the pipeline
5421
6205
  // Note: [🍭] FOREACH apply has some sideeffects on different places in codebase
5422
6206
  },
5423
6207
  /**
@@ -5440,8 +6224,7 @@ var foreachCommandParser = {
5440
6224
  },
5441
6225
  };
5442
6226
  /**
5443
- * TODO: !!!!!! Comment console logs
5444
- * TODO: [🍭] !!!!!! Make .ptbk.md file with examples of the FOREACH command and also with wrong parsing and logic
6227
+ * TODO: [🍭] Make .ptbk.md file with examples of the FOREACH with wrong parsing and logic
5445
6228
  */
5446
6229
 
5447
6230
  /**
@@ -5551,12 +6334,11 @@ var jokerCommandParser = {
5551
6334
  */
5552
6335
  parse: function (input) {
5553
6336
  var args = input.args;
5554
- // TODO: !!!!!! Replace with propper parameter name validation
5555
- var parametersMatch = (args.pop() || '').match(/^\{(?<parameterName>[a-z0-9_]+)\}$/im);
5556
- if (!parametersMatch || !parametersMatch.groups || !parametersMatch.groups.parameterName) {
5557
- throw new ParseError("Invalid joker");
6337
+ if (args.length !== 1) {
6338
+ throw new ParseError("JOKE command expects exactly one parameter name");
5558
6339
  }
5559
- var parameterName = parametersMatch.groups.parameterName;
6340
+ var parameterNameArg = args[0] || '';
6341
+ var parameterName = validateParameterName(parameterNameArg);
5560
6342
  return {
5561
6343
  type: 'JOKER',
5562
6344
  parameterName: parameterName,
@@ -5631,6 +6413,9 @@ var modelCommandParser = {
5631
6413
  */
5632
6414
  parse: function (input) {
5633
6415
  var args = input.args, normalized = input.normalized;
6416
+ var availableVariantsMessage = spaceTrim(function (block) { return "\n Available variants are:\n ".concat(block(MODEL_VARIANTS.map(function (variantName) {
6417
+ return "- ".concat(variantName).concat(variantName !== 'EMBEDDING' ? '' : ' (Not available in pipeline)');
6418
+ }).join('\n')), "\n "); });
5634
6419
  // TODO: Make this more elegant and dynamically
5635
6420
  if (normalized.startsWith('MODEL_VARIANT')) {
5636
6421
  if (normalized === 'MODEL_VARIANT_CHAT') {
@@ -5646,17 +6431,13 @@ var modelCommandParser = {
5646
6431
  key: 'modelVariant',
5647
6432
  value: 'COMPLETION',
5648
6433
  };
6434
+ // <- Note: [🤖]
5649
6435
  }
5650
6436
  else if (normalized.startsWith('MODEL_VARIANT_EMBED')) {
5651
- return {
5652
- type: 'MODEL',
5653
- key: 'modelVariant',
5654
- value: 'EMBEDDING',
5655
- };
5656
- // <- Note: [🤖]
6437
+ spaceTrim(function (block) { return "\n Embedding model can not be used in pipeline\n\n ".concat(block(availableVariantsMessage), "\n "); });
5657
6438
  }
5658
6439
  else {
5659
- throw new ParseError(spaceTrim(function (block) { return "\n Unknown model variant in command:\n\n Supported variants are:\n ".concat(block(MODEL_VARIANTS.map(function (variantName) { return "- ".concat(variantName); }).join('\n')), "\n "); }));
6440
+ throw new ParseError(spaceTrim(function (block) { return "\n Unknown model variant in command:\n\n ".concat(block(availableVariantsMessage), "\n "); }));
5660
6441
  }
5661
6442
  }
5662
6443
  if (normalized.startsWith('MODEL_NAME')) {
@@ -5781,14 +6562,13 @@ var parameterCommandParser = {
5781
6562
  * Parses the PARAMETER command
5782
6563
  */
5783
6564
  parse: function (input) {
5784
- var normalized = input.normalized, raw = input.raw;
5785
- var parametersMatch = raw.match(/\{(?<parameterName>[a-z0-9_]+)\}[^\S\r\n]*(?<parameterDescription>.*)$/im);
5786
- if (!parametersMatch || !parametersMatch.groups || !parametersMatch.groups.parameterName) {
5787
- throw new ParseError("Invalid parameter");
5788
- }
5789
- var _a = parametersMatch.groups, parameterName = _a.parameterName, parameterDescription = _a.parameterDescription;
5790
- if (parameterDescription && parameterDescription.match(/\{(?<parameterName>[a-z0-9_]+)\}/im)) {
5791
- throw new ParseError("Parameter {".concat(parameterName, "} can not contain another parameter in description"));
6565
+ var normalized = input.normalized, args = input.args, raw = input.raw;
6566
+ var parameterNameRaw = args.shift() || '';
6567
+ var parameterDescriptionRaw = args.join(' ');
6568
+ // <- TODO: When [🥶] fixed, change to:
6569
+ // > const parameterDescriptionRaw = rawArgs.split(parameterNameRaw).join('').trim();
6570
+ if (parameterDescriptionRaw && parameterDescriptionRaw.match(/\{(?<embeddedParameterName>[a-z0-9_]+)\}/im)) {
6571
+ throw new ParseError(spaceTrim(function (block) { return "\n Parameter {".concat(parameterNameRaw, "} can not contain another parameter in description\n\n The description:\n ").concat(block(parameterDescriptionRaw), "\n "); }));
5792
6572
  }
5793
6573
  var isInput = normalized.startsWith('INPUT');
5794
6574
  var isOutput = normalized.startsWith('OUTPUT');
@@ -5796,11 +6576,12 @@ var parameterCommandParser = {
5796
6576
  isInput = false;
5797
6577
  isOutput = false;
5798
6578
  }
5799
- // TODO: !!!!!! Add parameter name validation
6579
+ var parameterName = validateParameterName(parameterNameRaw);
6580
+ var parameterDescription = parameterDescriptionRaw.trim() || null;
5800
6581
  return {
5801
6582
  type: 'PARAMETER',
5802
6583
  parameterName: parameterName,
5803
- parameterDescription: parameterDescription.trim() || null,
6584
+ parameterDescription: parameterDescription,
5804
6585
  isInput: isInput,
5805
6586
  isOutput: isOutput,
5806
6587
  };
@@ -6125,6 +6906,7 @@ var promptbookVersionCommandParser = {
6125
6906
  * Note: `$` is used to indicate that this function mutates given `pipelineJson`
6126
6907
  */
6127
6908
  $applyToPipelineJson: function (command, $pipelineJson) {
6909
+ // TODO: Warn if the version is overridden
6128
6910
  $pipelineJson.promptbookVersion = command.promptbookVersion;
6129
6911
  },
6130
6912
  /**
@@ -6607,7 +7389,9 @@ function parseCommand(raw, usagePlace) {
6607
7389
  for (var commandNameSegmentsCount = 0; commandNameSegmentsCount < Math.min(items.length, 3); commandNameSegmentsCount++) {
6608
7390
  var commandNameRaw = items.slice(0, commandNameSegmentsCount + 1).join('_');
6609
7391
  var args = items.slice(commandNameSegmentsCount + 1);
6610
- var rawArgs = raw.substring(commandNameRaw.length).trim();
7392
+ var rawArgs = raw
7393
+ .substring(commandNameRaw.length)
7394
+ .trim();
6611
7395
  var command = parseCommandVariant({ usagePlace: usagePlace, raw: raw, rawArgs: rawArgs, normalized: normalized, args: args, commandNameRaw: commandNameRaw });
6612
7396
  if (command !== null) {
6613
7397
  return command;
@@ -6618,7 +7402,9 @@ function parseCommand(raw, usagePlace) {
6618
7402
  {
6619
7403
  var commandNameRaw = items.slice(-1).join('_');
6620
7404
  var args = items.slice(0, -1); // <- Note: This is probbably not correct
6621
- var rawArgs = raw.substring(0, raw.length - commandNameRaw.length).trim();
7405
+ var rawArgs = raw
7406
+ .substring(0, raw.length - commandNameRaw.length)
7407
+ .trim();
6622
7408
  var command = parseCommandVariant({ usagePlace: usagePlace, raw: raw, rawArgs: rawArgs, normalized: normalized, args: args, commandNameRaw: commandNameRaw });
6623
7409
  if (command !== null) {
6624
7410
  return command;
@@ -6758,7 +7544,7 @@ function extractAllListItemsFromMarkdown(markdown) {
6758
7544
  function extractOneBlockFromMarkdown(markdown) {
6759
7545
  var codeBlocks = extractAllBlocksFromMarkdown(markdown);
6760
7546
  if (codeBlocks.length !== 1) {
6761
- throw new ParseError(spaceTrim(function (block) { return "\n There should be exactly 1 code block, found ".concat(codeBlocks.length, " code blocks\n\n ").concat(block(codeBlocks.map(function (block, i) { return "Block ".concat(i + 1, ":\n").concat(block.content); }).join('\n\n\n')), "\n "); }));
7547
+ throw new ParseError(spaceTrim(function (block) { return "\n There should be exactly 1 code block in template, found ".concat(codeBlocks.length, " code blocks\n\n ").concat(block(codeBlocks.map(function (block, i) { return "Block ".concat(i + 1, ":\n").concat(block.content); }).join('\n\n\n')), "\n "); }));
6762
7548
  }
6763
7549
  return codeBlocks[0];
6764
7550
  }
@@ -6945,7 +7731,7 @@ function pipelineStringToJsonSync(pipelineString) {
6945
7731
  var $pipelineJson = {
6946
7732
  title: undefined /* <- Note: [🍙] Putting here placeholder to keep `title` on top at final JSON */,
6947
7733
  pipelineUrl: undefined /* <- Note: Putting here placeholder to keep `pipelineUrl` on top at final JSON */,
6948
- promptbookVersion: PROMPTBOOK_VERSION,
7734
+ promptbookVersion: undefined /* <- Note: By default no explicit version */,
6949
7735
  description: undefined /* <- Note: [🍙] Putting here placeholder to keep `description` on top at final JSON */,
6950
7736
  parameters: [],
6951
7737
  templates: [],
@@ -7236,7 +8022,7 @@ function pipelineStringToJsonSync(pipelineString) {
7236
8022
  return $asDeeplyFrozenSerializableJson('pipelineJson', $pipelineJson);
7237
8023
  }
7238
8024
  /**
7239
- * TODO: !!!! Warn if used only sync version
8025
+ * TODO:[main] !!!! Warn if used only sync version
7240
8026
  * TODO: [🚞] Report here line/column of error
7241
8027
  * TODO: Use spaceTrim more effectively
7242
8028
  * TODO: [🧠] Parameter flags - isInput, isOutput, isInternal
@@ -7317,70 +8103,6 @@ function addAutoGeneratedSection(content, options) {
7317
8103
  * TODO: [🏛] This can be part of markdown builder
7318
8104
  */
7319
8105
 
7320
- /**
7321
- * @@@
7322
- *
7323
- * @param text @@@
7324
- * @param _isFirstLetterCapital @@@
7325
- * @returns @@@
7326
- * @example 'helloWorld'
7327
- * @example 'iLovePromptbook'
7328
- * @public exported from `@promptbook/utils`
7329
- */
7330
- function normalizeTo_camelCase(text, _isFirstLetterCapital) {
7331
- var e_1, _a;
7332
- if (_isFirstLetterCapital === void 0) { _isFirstLetterCapital = false; }
7333
- var charType;
7334
- var lastCharType = null;
7335
- var normalizedName = '';
7336
- try {
7337
- for (var text_1 = __values(text), text_1_1 = text_1.next(); !text_1_1.done; text_1_1 = text_1.next()) {
7338
- var char = text_1_1.value;
7339
- var normalizedChar = void 0;
7340
- if (/^[a-z]$/.test(char)) {
7341
- charType = 'LOWERCASE';
7342
- normalizedChar = char;
7343
- }
7344
- else if (/^[A-Z]$/.test(char)) {
7345
- charType = 'UPPERCASE';
7346
- normalizedChar = char.toLowerCase();
7347
- }
7348
- else if (/^[0-9]$/.test(char)) {
7349
- charType = 'NUMBER';
7350
- normalizedChar = char;
7351
- }
7352
- else {
7353
- charType = 'OTHER';
7354
- normalizedChar = '';
7355
- }
7356
- if (!lastCharType) {
7357
- if (_isFirstLetterCapital) {
7358
- normalizedChar = normalizedChar.toUpperCase(); //TODO: DRY
7359
- }
7360
- }
7361
- else if (charType !== lastCharType &&
7362
- !(charType === 'LOWERCASE' && lastCharType === 'UPPERCASE') &&
7363
- !(lastCharType === 'NUMBER') &&
7364
- !(charType === 'NUMBER')) {
7365
- normalizedChar = normalizedChar.toUpperCase(); //TODO: [🌺] DRY
7366
- }
7367
- normalizedName += normalizedChar;
7368
- lastCharType = charType;
7369
- }
7370
- }
7371
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
7372
- finally {
7373
- try {
7374
- if (text_1_1 && !text_1_1.done && (_a = text_1.return)) _a.call(text_1);
7375
- }
7376
- finally { if (e_1) throw e_1.error; }
7377
- }
7378
- return normalizedName;
7379
- }
7380
- /**
7381
- * TODO: [🌺] Use some intermediate util splitWords
7382
- */
7383
-
7384
8106
  /**
7385
8107
  * Creates a Mermaid graph based on the promptbook
7386
8108
  *
@@ -7437,9 +8159,9 @@ function renderPromptbookMermaid(pipelineJson, options) {
7437
8159
  return promptbookMermaid;
7438
8160
  }
7439
8161
  /**
7440
- * TODO: !!!!!! FOREACH in mermaid graph
7441
- * TODO: !!!!!! Knowledge in mermaid graph
7442
- * TODO: !!!!!! Personas in mermaid graph
8162
+ * TODO: !!!!! FOREACH in mermaid graph
8163
+ * TODO: !!!!! Knowledge in mermaid graph
8164
+ * TODO: !!!!! Personas in mermaid graph
7443
8165
  * TODO: Maybe use some Mermaid package instead of string templating
7444
8166
  * TODO: [🕌] When more than 2 functionalities, split into separate functions
7445
8167
  */
@@ -7514,7 +8236,7 @@ function isSerializableAsJson(value) {
7514
8236
  }
7515
8237
  }
7516
8238
  /**
7517
- * TODO: [🧠] !!! In-memory cache of same values to prevent multiple checks
8239
+ * TODO: [🧠][main] !!! In-memory cache of same values to prevent multiple checks
7518
8240
  * TODO: [🧠][💺] Can be done this on type-level?
7519
8241
  */
7520
8242
 
@@ -7581,21 +8303,41 @@ function usageToWorktime(usage) {
7581
8303
  * @public exported from `@promptbook/core`
7582
8304
  */
7583
8305
  function usageToHuman(usage) {
7584
- var report = 'Usage:';
8306
+ var reportItems = [];
7585
8307
  var uncertainNumberToHuman = function (_a) {
7586
8308
  var value = _a.value, isUncertain = _a.isUncertain;
7587
8309
  return "".concat(isUncertain ? 'approximately ' : '').concat(Math.round(value * 100) / 100);
7588
8310
  };
7589
- report += '\n' + "- Cost ".concat(uncertainNumberToHuman(usage.price), " USD");
7590
- report += '\n' + "- Saved ".concat(uncertainNumberToHuman(usageToWorktime(usage)), " hours of human time");
7591
- return spaceTrim(report);
8311
+ if (usage.price.value > 0.01
8312
+ // <- TODO: [🍓][🧞‍♂️][👩🏽‍🤝‍🧑🏻] Configure negligible value - default value to config + value to `UsageToHumanSettings`
8313
+ ) {
8314
+ reportItems.push("Cost ".concat(uncertainNumberToHuman(usage.price), " USD"));
8315
+ }
8316
+ else {
8317
+ reportItems.push("Negligible cost");
8318
+ }
8319
+ var worktime = usageToWorktime(usage);
8320
+ if (worktime.value >
8321
+ 1 / 60
8322
+ // <- TODO: [🍓][🧞‍♂️][👩🏽‍🤝‍🧑🏻]
8323
+ ) {
8324
+ reportItems.push("Saved ".concat(uncertainNumberToHuman(usageToWorktime(usage)), " hours of human time"));
8325
+ // TODO: [🍓][🧞‍♂️] Show minutes, seconds, days NOT 0.1 hours
8326
+ }
8327
+ if (usage.output.charactersCount.value > 0) {
8328
+ reportItems.push("Written ".concat(uncertainNumberToHuman(usage.output.charactersCount), " characters"));
8329
+ }
8330
+ if (reportItems.length === 0) {
8331
+ // Note: For negligible usage, we report at least something
8332
+ reportItems.push('Negligible');
8333
+ }
8334
+ return spaceTrim(function (block) { return "\n Usage:\n ".concat(block(reportItems.map(function (item) { return "- ".concat(item); }).join('\n')), "\n "); });
7592
8335
  }
7593
8336
  /**
7594
- * TODO: Use "$1" not "1 USD"
7595
- * TODO: Use markdown formatting like "Cost approximately **$1**"
7596
- * TODO: Report in minutes, seconds, days NOT 0.1 hours
8337
+ * TODO: [🍓][🧞‍♂️] Use "$1" not "1 USD"
8338
+ * TODO: [🍓][🧞‍♂️] Use markdown formatting like "Cost approximately **$1**"
8339
+ * TODO: [🍓][🧞‍♂️] Report in minutes, seconds, days NOT 0.1 hours
7597
8340
  * TODO: [🧠] Maybe make from `uncertainNumberToHuman` separate exported utility
7598
- * TODO: When negligible usage, report "Negligible" or just don't report it
7599
8341
  * TODO: [🧠] Maybe use "~" instead of "approximately"
7600
8342
  * TODO: [🏛] Maybe make some markdown builder
7601
8343
  */
@@ -8244,8 +8986,8 @@ function formatNumber(value) {
8244
8986
  */
8245
8987
  function createMarkdownTable(table) {
8246
8988
  var columnWidths = table.reduce(function (widths, row) {
8247
- row.forEach(function (cell, columnIndex) {
8248
- var cellLength = cell.length;
8989
+ row.forEach(function (subformat, columnIndex) {
8990
+ var cellLength = subformat.length;
8249
8991
  if (!widths[columnIndex] || cellLength > widths[columnIndex]) {
8250
8992
  widths[columnIndex] = cellLength;
8251
8993
  }
@@ -8253,12 +8995,12 @@ function createMarkdownTable(table) {
8253
8995
  return widths;
8254
8996
  }, []);
8255
8997
  var header = "| ".concat(table[0]
8256
- .map(function (cell, columnIndex) { return cell.padEnd(columnWidths[columnIndex]); })
8998
+ .map(function (subformat, columnIndex) { return subformat.padEnd(columnWidths[columnIndex]); })
8257
8999
  .join(' | '), " |");
8258
9000
  var separator = "|".concat(columnWidths.map(function (width) { return '-'.repeat(width + 2); }).join('|'), "|");
8259
9001
  var rows = table.slice(1).map(function (row) {
8260
- var paddedRow = row.map(function (cell, columnIndex) {
8261
- return cell.padEnd(columnWidths[columnIndex]);
9002
+ var paddedRow = row.map(function (subformat, columnIndex) {
9003
+ return subformat.padEnd(columnWidths[columnIndex]);
8262
9004
  });
8263
9005
  return "| ".concat(paddedRow.join(' | '), " |");
8264
9006
  });
@@ -8534,5 +9276,5 @@ function executionReportJsonToString(executionReportJson, options) {
8534
9276
  * TODO: [🧠] Should be in generated file GENERATOR_WARNING
8535
9277
  */
8536
9278
 
8537
- export { $llmToolsMetadataRegister, $llmToolsRegister, CLAIM, CallbackInterfaceTools, CollectionError, DEFAULT_REMOTE_URL, DEFAULT_REMOTE_URL_PATH, ERRORS, EXECUTIONS_CACHE_DIRNAME, EXPECTATION_UNITS, EnvironmentMismatchError, ExecutionReportStringOptionsDefaults, ExpectError, IS_VERBOSE, LimitReachedError, MAX_EXECUTION_ATTEMPTS, MAX_FILENAME_LENGTH, MAX_KNOWLEDGE_SOURCES_SCRAPING_DEPTH, MAX_KNOWLEDGE_SOURCES_SCRAPING_TOTAL, MAX_PARALLEL_COUNT, MODEL_VARIANTS, MemoryStorage, NotFoundError, NotYetImplementedError, PIPELINE_COLLECTION_BASE_FILENAME, PROMPTBOOK_VERSION, ParseError, PipelineExecutionError, PipelineLogicError, PipelineUrlError, PrefixStorage, RESERVED_PARAMETER_NAMES, TemplateTypes, UnexpectedError, ZERO_USAGE, _AnthropicClaudeMetadataRegistration, _AzureOpenAiMetadataRegistration, _OpenAiMetadataRegistration, addUsage, assertsExecutionSuccessful, cacheLlmTools, collectionToJson, countTotalUsage, createCollectionFromJson, createCollectionFromPromise, createCollectionFromUrl, createLlmToolsFromConfiguration, createPipelineExecutor, createSubcollection, embeddingVectorToString, executionReportJsonToString, isPassingExpectations, isPipelinePrepared, joinLlmExecutionTools, limitTotalUsage, pipelineJsonToString, pipelineStringToJson, pipelineStringToJsonSync, prepareKnowledgeFromMarkdown, prepareKnowledgePieces, preparePersona, preparePipeline, prepareTemplates, prettifyPipelineString, stringifyPipelineJson, unpreparePipeline, usageToHuman, usageToWorktime, validatePipeline };
9279
+ export { $llmToolsMetadataRegister, $llmToolsRegister, CLAIM, CallbackInterfaceTools, CollectionError, CsvFormatDefinition, DEFAULT_CSV_SETTINGS, DEFAULT_REMOTE_URL, DEFAULT_REMOTE_URL_PATH, ERRORS, EXECUTIONS_CACHE_DIRNAME, EXPECTATION_UNITS, EnvironmentMismatchError, ExecutionReportStringOptionsDefaults, ExpectError, IS_VERBOSE, LimitReachedError, MANDATORY_CSV_SETTINGS, MAX_EXECUTION_ATTEMPTS, MAX_FILENAME_LENGTH, MAX_KNOWLEDGE_SOURCES_SCRAPING_DEPTH, MAX_KNOWLEDGE_SOURCES_SCRAPING_TOTAL, MAX_PARALLEL_COUNT, MODEL_VARIANTS, MemoryStorage, NotFoundError, NotYetImplementedError, PIPELINE_COLLECTION_BASE_FILENAME, PROMPTBOOK_VERSION, ParseError, PipelineExecutionError, PipelineLogicError, PipelineUrlError, PrefixStorage, RESERVED_PARAMETER_NAMES, TemplateTypes, TextFormatDefinition, UnexpectedError, ZERO_USAGE, _AnthropicClaudeMetadataRegistration, _AzureOpenAiMetadataRegistration, _OpenAiMetadataRegistration, addUsage, assertsExecutionSuccessful, cacheLlmTools, collectionToJson, countTotalUsage, createCollectionFromJson, createCollectionFromPromise, createCollectionFromUrl, createLlmToolsFromConfiguration, createPipelineExecutor, createSubcollection, embeddingVectorToString, executionReportJsonToString, isPassingExpectations, isPipelinePrepared, joinLlmExecutionTools, limitTotalUsage, pipelineJsonToString, pipelineStringToJson, pipelineStringToJsonSync, prepareKnowledgeFromMarkdown, prepareKnowledgePieces, preparePersona, preparePipeline, prepareTemplates, prettifyPipelineString, stringifyPipelineJson, unpreparePipeline, usageToHuman, usageToWorktime, validatePipeline };
8538
9280
  //# sourceMappingURL=index.es.js.map