@promptbook/markdown-utils 0.74.0-8 → 0.75.0-1

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 (57) hide show
  1. package/README.md +2 -11
  2. package/esm/index.es.js +102 -55
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/promptbook-collection/index.d.ts +3 -0
  5. package/esm/typings/src/_packages/core.index.d.ts +25 -1
  6. package/esm/typings/src/_packages/types.index.d.ts +10 -0
  7. package/esm/typings/src/_packages/utils.index.d.ts +4 -0
  8. package/esm/typings/src/cli/cli-commands/run.d.ts +1 -1
  9. package/esm/typings/src/cli/main.d.ts +4 -1
  10. package/esm/typings/src/cli/promptbookCli.d.ts +1 -1
  11. package/esm/typings/src/cli/test/ptbk.d.ts +1 -1
  12. package/esm/typings/src/collection/collectionToJson.test.d.ts +1 -1
  13. package/esm/typings/src/collection/constructors/createCollectionFromDirectory.d.ts +1 -1
  14. package/esm/typings/src/commands/BOOK_VERSION/BookVersionCommand.d.ts +1 -1
  15. package/esm/typings/src/commands/FOREACH/foreachCommandParser.d.ts +2 -2
  16. package/esm/typings/src/commands/FORMFACTOR/FormfactorCommand.d.ts +11 -0
  17. package/esm/typings/src/commands/FORMFACTOR/formfactorCommand.test.d.ts +1 -0
  18. package/esm/typings/src/commands/FORMFACTOR/formfactorCommandParser.d.ts +11 -0
  19. package/esm/typings/src/commands/_BOILERPLATE/boilerplateCommandParser.d.ts +1 -1
  20. package/esm/typings/src/commands/_common/types/CommandParser.d.ts +2 -0
  21. package/esm/typings/src/commands/index.d.ts +1 -1
  22. package/esm/typings/src/config.d.ts +7 -0
  23. package/esm/typings/src/conversion/pipelineJsonToString.d.ts +3 -3
  24. package/esm/typings/src/conversion/pipelineStringToJson.d.ts +2 -2
  25. package/esm/typings/src/conversion/pipelineStringToJsonSync.d.ts +2 -2
  26. package/esm/typings/src/conversion/utils/stringifyPipelineJson.d.ts +1 -1
  27. package/esm/typings/src/conversion/validation/_importPipeline.d.ts +7 -7
  28. package/esm/typings/src/formats/_common/FormatDefinition.d.ts +1 -1
  29. package/esm/typings/src/formats/_common/FormatSubvalueDefinition.d.ts +1 -1
  30. package/esm/typings/src/formfactors/_boilerplate/BoilerplateFormfactorDefinition.d.ts +14 -0
  31. package/esm/typings/src/formfactors/_common/AbstractFormfactorDefinition.d.ts +34 -0
  32. package/esm/typings/src/formfactors/_common/FormfactorDefinition.d.ts +5 -0
  33. package/esm/typings/src/formfactors/_common/string_formfactor_name.d.ts +5 -0
  34. package/esm/typings/src/formfactors/chat/ChatFormfactorDefinition.d.ts +15 -0
  35. package/esm/typings/src/formfactors/generic/GenericFormfactorDefinition.d.ts +14 -0
  36. package/esm/typings/src/formfactors/index.d.ts +39 -0
  37. package/esm/typings/src/formfactors/sheets/SheetsFormfactorDefinition.d.ts +14 -0
  38. package/esm/typings/src/formfactors/translator/TranslatorFormfactorDefinition.d.ts +14 -0
  39. package/esm/typings/src/pipeline/pipeline-interface/PipelineInterface.d.ts +22 -0
  40. package/esm/typings/src/pipeline/pipeline-interface/constants.d.ts +9 -0
  41. package/esm/typings/src/pipeline/pipeline-interface/getPipelineInterface.d.ts +11 -0
  42. package/esm/typings/src/pipeline/pipeline-interface/isPipelineImplementingInterface.d.ts +25 -0
  43. package/esm/typings/src/pipeline/pipeline-interface/isPipelineInterfacesEqual.d.ts +11 -0
  44. package/esm/typings/src/storage/blackhole/BlackholeStorage.d.ts +33 -0
  45. package/esm/typings/src/storage/memory/MemoryStorage.d.ts +1 -1
  46. package/esm/typings/src/storage/{memory/utils → utils}/PrefixStorage.d.ts +1 -1
  47. package/esm/typings/src/types/PipelineJson/PipelineJson.d.ts +11 -4
  48. package/esm/typings/src/types/PipelineJson/PreparationJson.d.ts +1 -1
  49. package/esm/typings/src/types/Prompt.d.ts +1 -1
  50. package/esm/typings/src/types/typeAliases.d.ts +2 -2
  51. package/esm/typings/src/utils/expectation-counters/constants.d.ts +15 -0
  52. package/esm/typings/src/utils/expectation-counters/countLines.d.ts +2 -0
  53. package/esm/typings/src/utils/expectation-counters/countPages.d.ts +2 -0
  54. package/package.json +1 -1
  55. package/umd/index.umd.js +102 -55
  56. package/umd/index.umd.js.map +1 -1
  57. /package/esm/typings/src/storage/{memory → local-storage}/utils/makePromptbookStorageFromWebStorage.d.ts +0 -0
package/umd/index.umd.js CHANGED
@@ -22,7 +22,7 @@
22
22
  *
23
23
  * @see https://github.com/webgptorg/promptbook
24
24
  */
25
- var PROMPTBOOK_ENGINE_VERSION = '0.74.0-7';
25
+ var PROMPTBOOK_ENGINE_VERSION = '0.75.0-0';
26
26
  /**
27
27
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
28
28
  */
@@ -357,7 +357,7 @@
357
357
  * TODO: [🏢] Make this logic part of `JsonFormatDefinition` or `isValidJsonString`
358
358
  */
359
359
 
360
- 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## Example\n\n```json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n```\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}",resultingParameterName:"modelRequirements",format:"JSON",dependentParameterNames:["availableModelNames","personaDescription"]}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[],sourceFile:"./promptbook-collection/prepare-persona.ptbk.md"}];
360
+ var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book.md",formfactorName:"GENERIC",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],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.book.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.book.md",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],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.book.md"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.book.md",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],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.book.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.book.md",formfactorName:"GENERIC",parameters:[{name:"availableModelNames",description:"List of available model names separated by comma (,)",isInput:true,isOutput:false},{name:"personaDescription",description:"Description of the persona",isInput:true,isOutput:false},{name:"modelRequirements",description:"Specific requirements for the model",isInput:false,isOutput:true}],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## Example\n\n```json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n```\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}",resultingParameterName:"modelRequirements",format:"JSON",dependentParameterNames:["availableModelNames","personaDescription"]}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[],sourceFile:"./promptbook-collection/prepare-persona.book.md"}];
361
361
 
362
362
  /**
363
363
  * Prettify the html code
@@ -396,13 +396,13 @@
396
396
  /**
397
397
  * Converts promptbook in JSON format to string format
398
398
  *
399
- * @param pipelineJson Promptbook in JSON format (.ptbk.json)
400
- * @returns Promptbook in string format (.ptbk.md)
399
+ * @param pipelineJson Promptbook in JSON format (.book.json)
400
+ * @returns Promptbook in string format (.book.md)
401
401
  * @public exported from `@promptbook/core`
402
402
  */
403
403
  function pipelineJsonToString(pipelineJson) {
404
404
  var e_1, _a, e_2, _b, e_3, _c, e_4, _d, e_5, _e, e_6, _f;
405
- var title = pipelineJson.title, pipelineUrl = pipelineJson.pipelineUrl, promptbookVersion = pipelineJson.promptbookVersion, description = pipelineJson.description, parameters = pipelineJson.parameters, templates = pipelineJson.templates;
405
+ var title = pipelineJson.title, pipelineUrl = pipelineJson.pipelineUrl, bookVersion = pipelineJson.bookVersion, description = pipelineJson.description, parameters = pipelineJson.parameters, templates = pipelineJson.templates;
406
406
  var pipelineString = "# ".concat(title);
407
407
  if (description) {
408
408
  pipelineString += '\n\n';
@@ -412,8 +412,10 @@
412
412
  if (pipelineUrl) {
413
413
  commands.push("PIPELINE URL ".concat(pipelineUrl));
414
414
  }
415
- commands.push("PROMPTBOOK VERSION ".concat(promptbookVersion));
416
- // TODO: [main] !!! This increase size of the bundle and is probbably not necessary
415
+ if (bookVersion !== "undefined") {
416
+ commands.push("BOOK VERSION ".concat(bookVersion));
417
+ }
418
+ // TODO: [main] !!!!! This increases size of the bundle and is probbably not necessary
417
419
  pipelineString = prettifyMarkdown(pipelineString);
418
420
  try {
419
421
  for (var _g = __values(parameters.filter(function (_a) {
@@ -593,7 +595,7 @@
593
595
  * TODO: [🧠] Is there a way to auto-detect missing features in pipelineJsonToString
594
596
  * TODO: [🏛] Maybe make some markdown builder
595
597
  * TODO: [🏛] Escape all
596
- * TODO: [🧠] Should be in generated .ptbk.md file GENERATOR_WARNING
598
+ * TODO: [🧠] Should be in generated .book.md file GENERATOR_WARNING
597
599
  */
598
600
 
599
601
  /**
@@ -815,6 +817,13 @@
815
817
  * @private within the repository
816
818
  */
817
819
  var GENERATOR_WARNING = "\u26A0\uFE0F WARNING: This code has been generated so that any manual changes will be overwritten";
820
+ // <- TODO: [🐊] Pick the best claim
821
+ /**
822
+ * When the title is not provided, the default title is used
823
+ *
824
+ * @public exported from `@promptbook/core`
825
+ */
826
+ var DEFAULT_TITLE = "Untitled";
818
827
  // <- TODO: [🧠] Better system for generator warnings - not always "code" and "by `@promptbook/cli`"
819
828
  /**
820
829
  * The maximum number of iterations for a loops
@@ -903,6 +912,7 @@
903
912
  // Note: In normal situations, we check the pipeline logic:
904
913
  true);
905
914
  /**
915
+ * TODO: Extract `constants.ts` from `config.ts`
906
916
  * TODO: [🧠][🧜‍♂️] Maybe join remoteUrl and path into single value
907
917
  */
908
918
 
@@ -1060,7 +1070,7 @@
1060
1070
  if (!url.startsWith('https://')) {
1061
1071
  return false;
1062
1072
  }
1063
- if (!(url.endsWith('.book.md') || url.endsWith('.book') || url.endsWith('.ptbk.md') || url.endsWith('.ptbk'))) {
1073
+ if (!(url.endsWith('.book.md') || url.endsWith('.book') || url.endsWith('.book.md') || url.endsWith('.ptbk'))) {
1064
1074
  return false;
1065
1075
  }
1066
1076
  if (url.includes('#')) {
@@ -1129,9 +1139,9 @@
1129
1139
  // <- Note: [🚲]
1130
1140
  throw new PipelineLogicError(spaceTrim.spaceTrim(function (block) { return "\n Invalid promptbook URL \"".concat(pipeline.pipelineUrl, "\"\n\n ").concat(block(pipelineIdentification), "\n "); }));
1131
1141
  }
1132
- if (pipeline.promptbookVersion !== undefined && !isValidPromptbookVersion(pipeline.promptbookVersion)) {
1142
+ if (pipeline.bookVersion !== undefined && !isValidPromptbookVersion(pipeline.bookVersion)) {
1133
1143
  // <- Note: [🚲]
1134
- throw new PipelineLogicError(spaceTrim.spaceTrim(function (block) { return "\n Invalid Promptbook Version \"".concat(pipeline.promptbookVersion, "\"\n\n ").concat(block(pipelineIdentification), "\n "); }));
1144
+ throw new PipelineLogicError(spaceTrim.spaceTrim(function (block) { return "\n Invalid Promptbook Version \"".concat(pipeline.bookVersion, "\"\n\n ").concat(block(pipelineIdentification), "\n "); }));
1135
1145
  }
1136
1146
  // TODO: [🧠] Maybe do here some propper JSON-schema / ZOD checking
1137
1147
  if (!Array.isArray(pipeline.parameters)) {
@@ -1145,18 +1155,18 @@
1145
1155
  }
1146
1156
  var _loop_1 = function (parameter) {
1147
1157
  if (parameter.isInput && parameter.isOutput) {
1148
- throw new PipelineLogicError(spaceTrim.spaceTrim(function (block) { return "\n\n Parameter {".concat(parameter.name, "} can not be both input and output\n\n ").concat(block(pipelineIdentification), "\n "); }));
1158
+ throw new PipelineLogicError(spaceTrim.spaceTrim(function (block) { return "\n\n Parameter `{".concat(parameter.name, "}` can not be both input and output\n\n ").concat(block(pipelineIdentification), "\n "); }));
1149
1159
  }
1150
1160
  // Note: Testing that parameter is either intermediate or output BUT not created and unused
1151
1161
  if (!parameter.isInput &&
1152
1162
  !parameter.isOutput &&
1153
1163
  !pipeline.templates.some(function (template) { return template.dependentParameterNames.includes(parameter.name); })) {
1154
- throw new PipelineLogicError(spaceTrim.spaceTrim(function (block) { return "\n Parameter {".concat(parameter.name, "} is created but not used\n\n You can declare {").concat(parameter.name, "} as output parameter by adding in the header:\n - OUTPUT PARAMETER `{").concat(parameter.name, "}` ").concat(parameter.description || '', "\n\n ").concat(block(pipelineIdentification), "\n\n "); }));
1164
+ throw new PipelineLogicError(spaceTrim.spaceTrim(function (block) { return "\n Parameter `{".concat(parameter.name, "}` is created but not used\n\n You can declare {").concat(parameter.name, "} as output parameter by adding in the header:\n - OUTPUT PARAMETER `{").concat(parameter.name, "}` ").concat(parameter.description || '', "\n\n ").concat(block(pipelineIdentification), "\n\n "); }));
1155
1165
  }
1156
1166
  // Note: Testing that parameter is either input or result of some template
1157
1167
  if (!parameter.isInput &&
1158
1168
  !pipeline.templates.some(function (template) { return template.resultingParameterName === parameter.name; })) {
1159
- throw new PipelineLogicError(spaceTrim.spaceTrim(function (block) { return "\n Parameter {".concat(parameter.name, "} is declared but not defined\n\n You can do one of these:\n 1) Remove declaration of {").concat(parameter.name, "}\n 2) Add template that results in -> {").concat(parameter.name, "}\n\n ").concat(block(pipelineIdentification), "\n "); }));
1169
+ throw new PipelineLogicError(spaceTrim.spaceTrim(function (block) { return "\n Parameter `{".concat(parameter.name, "}` is declared but not defined\n\n You can do one of these:\n 1) Remove declaration of `{").concat(parameter.name, "}`\n 2) Add template that results in `-> {").concat(parameter.name, "}`\n\n ").concat(block(pipelineIdentification), "\n "); }));
1160
1170
  }
1161
1171
  };
1162
1172
  try {
@@ -1184,7 +1194,7 @@
1184
1194
  var _loop_2 = function (template) {
1185
1195
  var e_4, _h, e_5, _j;
1186
1196
  if (definedParameters.has(template.resultingParameterName)) {
1187
- throw new PipelineLogicError(spaceTrim.spaceTrim(function (block) { return "\n Parameter {".concat(template.resultingParameterName, "} is defined multiple times\n\n ").concat(block(pipelineIdentification), "\n "); }));
1197
+ throw new PipelineLogicError(spaceTrim.spaceTrim(function (block) { return "\n Parameter `{".concat(template.resultingParameterName, "}` is defined multiple times\n\n ").concat(block(pipelineIdentification), "\n "); }));
1188
1198
  }
1189
1199
  if (RESERVED_PARAMETER_NAMES.includes(template.resultingParameterName)) {
1190
1200
  throw new PipelineLogicError(spaceTrim.spaceTrim(function (block) { return "\n Parameter name {".concat(template.resultingParameterName, "} is reserved, please use different name\n\n ").concat(block(pipelineIdentification), "\n "); }));
@@ -1197,7 +1207,7 @@
1197
1207
  }
1198
1208
  var _loop_4 = function (joker) {
1199
1209
  if (!template.dependentParameterNames.includes(joker)) {
1200
- throw new PipelineLogicError(spaceTrim.spaceTrim(function (block) { return "\n Parameter {".concat(joker, "} is used for {").concat(template.resultingParameterName, "} as joker but not in `dependentParameterNames`\n\n ").concat(block(pipelineIdentification), "\n "); }));
1210
+ throw new PipelineLogicError(spaceTrim.spaceTrim(function (block) { return "\n Parameter `{".concat(joker, "}` is used for {").concat(template.resultingParameterName, "} as joker but not in `dependentParameterNames`\n\n ").concat(block(pipelineIdentification), "\n "); }));
1201
1211
  }
1202
1212
  };
1203
1213
  try {
@@ -1292,14 +1302,24 @@
1292
1302
  if (currentlyResovedTemplates.length === 0) {
1293
1303
  throw new PipelineLogicError(
1294
1304
  // TODO: [🐎] DRY
1295
- spaceTrim.spaceTrim(function (block) { return "\n\n Can not resolve some parameters:\n Either you are using a parameter that is not defined, or there are some circular dependencies.\n\n ".concat(block(pipelineIdentification), "\n\n Can not resolve:\n ").concat(block(unresovedTemplates
1305
+ spaceTrim.spaceTrim(function (block) { return "\n\n Can not resolve some parameters:\n Either you are using a parameter that is not defined, or there are some circular dependencies.\n\n ".concat(block(pipelineIdentification), "\n\n **Can not resolve:**\n ").concat(block(unresovedTemplates
1296
1306
  .map(function (_a) {
1297
1307
  var resultingParameterName = _a.resultingParameterName, dependentParameterNames = _a.dependentParameterNames;
1298
- return "- Parameter {".concat(resultingParameterName, "} which depends on ").concat(dependentParameterNames
1299
- .map(function (dependentParameterName) { return "{".concat(dependentParameterName, "}"); })
1308
+ return "- Parameter `{".concat(resultingParameterName, "}` which depends on ").concat(dependentParameterNames
1309
+ .map(function (dependentParameterName) { return "`{".concat(dependentParameterName, "}`"); })
1300
1310
  .join(' and '));
1301
1311
  })
1302
- .join('\n')), "\n\n Resolved:\n ").concat(block(resovedParameters.map(function (name) { return "- Parameter {".concat(name, "}"); }).join('\n')), "\n\n\n "); }));
1312
+ .join('\n')), "\n\n **Resolved:**\n ").concat(block(resovedParameters
1313
+ .filter(function (name) {
1314
+ return !RESERVED_PARAMETER_NAMES.includes(name);
1315
+ })
1316
+ .map(function (name) { return "- Parameter `{".concat(name, "}`"); })
1317
+ .join('\n')), "\n\n\n **Reserved (which are available):**\n ").concat(block(resovedParameters
1318
+ .filter(function (name) {
1319
+ return RESERVED_PARAMETER_NAMES.includes(name);
1320
+ })
1321
+ .map(function (name) { return "- Parameter `{".concat(name, "}`"); })
1322
+ .join('\n')), "\n\n\n "); }));
1303
1323
  }
1304
1324
  resovedParameters = __spreadArray(__spreadArray([], __read(resovedParameters), false), __read(currentlyResovedTemplates.map(function (_a) {
1305
1325
  var resultingParameterName = _a.resultingParameterName;
@@ -1310,6 +1330,7 @@
1310
1330
  while (unresovedTemplates.length > 0) {
1311
1331
  _loop_3();
1312
1332
  }
1333
+ // TODO: !!!!!! Test that pipeline interface implements declared formfactor interface
1313
1334
  }
1314
1335
  /**
1315
1336
  * TODO: !! [🧞‍♀️] Do not allow joker + foreach
@@ -2665,8 +2686,8 @@
2665
2686
  else if (errors.length > 1) {
2666
2687
  throw new PipelineExecutionError(
2667
2688
  // TODO: Tell which execution tools failed like
2668
- // 1) OpenAI throw PipelineExecutionError: Parameter {knowledge} is not defined
2669
- // 2) AnthropicClaude throw PipelineExecutionError: Parameter {knowledge} is not defined
2689
+ // 1) OpenAI throw PipelineExecutionError: Parameter `{knowledge}` is not defined
2690
+ // 2) AnthropicClaude throw PipelineExecutionError: Parameter `{knowledge}` is not defined
2670
2691
  // 3) ...
2671
2692
  spaceTrim__default["default"](function (block) { return "\n All execution tools failed:\n\n ".concat(block(errors
2672
2693
  .map(function (error, i) { return "".concat(i + 1, ") **").concat(error.name || 'Error', ":** ").concat(error.message); })
@@ -2780,7 +2801,7 @@
2780
2801
  collection = createCollectionFromJson.apply(void 0, __spreadArray([], __read(PipelineCollection), false));
2781
2802
  _b = createPipelineExecutor;
2782
2803
  _c = {};
2783
- return [4 /*yield*/, collection.getPipelineByUrl('https://promptbook.studio/promptbook/prepare-persona.ptbk.md')];
2804
+ return [4 /*yield*/, collection.getPipelineByUrl('https://promptbook.studio/promptbook/prepare-persona.book.md')];
2784
2805
  case 1:
2785
2806
  preparePersonaExecutor = _b.apply(void 0, [(_c.pipeline = _d.sent(),
2786
2807
  _c.tools = tools,
@@ -3452,13 +3473,14 @@
3452
3473
  */
3453
3474
  function clonePipeline(pipeline) {
3454
3475
  // Note: Not using spread operator (...) because @@@
3455
- var pipelineUrl = pipeline.pipelineUrl, sourceFile = pipeline.sourceFile, title = pipeline.title, promptbookVersion = pipeline.promptbookVersion, description = pipeline.description, parameters = pipeline.parameters, templates = pipeline.templates, knowledgeSources = pipeline.knowledgeSources, knowledgePieces = pipeline.knowledgePieces, personas = pipeline.personas, preparations = pipeline.preparations;
3476
+ var pipelineUrl = pipeline.pipelineUrl, sourceFile = pipeline.sourceFile, title = pipeline.title, bookVersion = pipeline.bookVersion, description = pipeline.description, formfactorName = pipeline.formfactorName, parameters = pipeline.parameters, templates = pipeline.templates, knowledgeSources = pipeline.knowledgeSources, knowledgePieces = pipeline.knowledgePieces, personas = pipeline.personas, preparations = pipeline.preparations;
3456
3477
  return {
3457
3478
  pipelineUrl: pipelineUrl,
3458
3479
  sourceFile: sourceFile,
3459
3480
  title: title,
3460
- promptbookVersion: promptbookVersion,
3481
+ bookVersion: bookVersion,
3461
3482
  description: description,
3483
+ formfactorName: formfactorName,
3462
3484
  parameters: parameters,
3463
3485
  templates: templates,
3464
3486
  knowledgeSources: knowledgeSources,
@@ -4186,11 +4208,11 @@
4186
4208
  for (var _b = __values(Object.entries(parameters)), _c = _b.next(); !_c.done; _c = _b.next()) {
4187
4209
  var _d = __read(_c.value, 2), parameterName = _d[0], parameterValue = _d[1];
4188
4210
  if (parameterValue === RESERVED_PARAMETER_MISSING_VALUE) {
4189
- throw new UnexpectedError("Parameter {".concat(parameterName, "} has missing value"));
4211
+ throw new UnexpectedError("Parameter `{".concat(parameterName, "}` has missing value"));
4190
4212
  }
4191
4213
  else if (parameterValue === RESERVED_PARAMETER_RESTRICTED) {
4192
4214
  // TODO: [🍵]
4193
- throw new UnexpectedError("Parameter {".concat(parameterName, "} is restricted to use"));
4215
+ throw new UnexpectedError("Parameter `{".concat(parameterName, "}` is restricted to use"));
4194
4216
  }
4195
4217
  }
4196
4218
  }
@@ -4217,11 +4239,11 @@
4217
4239
  throw new PipelineExecutionError('Parameter is already opened or not closed');
4218
4240
  }
4219
4241
  if (parameters[parameterName] === undefined) {
4220
- throw new PipelineExecutionError("Parameter {".concat(parameterName, "} is not defined"));
4242
+ throw new PipelineExecutionError("Parameter `{".concat(parameterName, "}` is not defined"));
4221
4243
  }
4222
4244
  var parameterValue = parameters[parameterName];
4223
4245
  if (parameterValue === undefined) {
4224
- throw new PipelineExecutionError("Parameter {".concat(parameterName, "} is not defined"));
4246
+ throw new PipelineExecutionError("Parameter `{".concat(parameterName, "}` is not defined"));
4225
4247
  }
4226
4248
  parameterValue = parameterValue.toString();
4227
4249
  if (parameterValue.includes('\n') && /^\s*\W{0,3}\s*$/.test(precol)) {
@@ -4265,30 +4287,45 @@
4265
4287
  return text.length;
4266
4288
  }
4267
4289
 
4290
+ /**
4291
+ * Number of characters per standard line with 11pt Arial font size.
4292
+ *
4293
+ * @public exported from `@promptbook/utils`
4294
+ */
4295
+ var CHARACTERS_PER_STANDARD_LINE = 63;
4296
+ /**
4297
+ * Number of lines per standard A4 page with 11pt Arial font size and standard margins and spacing.
4298
+ *
4299
+ * @public exported from `@promptbook/utils`
4300
+ */
4301
+ var LINES_PER_STANDARD_PAGE = 44;
4302
+ /**
4303
+ * TODO: [🧠] Should be this `constants.ts` or `config.ts`?
4304
+ */
4305
+
4268
4306
  /**
4269
4307
  * Counts number of lines in the text
4270
4308
  *
4309
+ * Note: This does not check only for the presence of newlines, but also for the length of the standard line.
4310
+ *
4271
4311
  * @public exported from `@promptbook/utils`
4272
4312
  */
4273
4313
  function countLines(text) {
4274
- if (text === '') {
4275
- return 0;
4276
- }
4277
- return text.split('\n').length;
4314
+ text = text.replace('\r\n', '\n');
4315
+ text = text.replace('\r', '\n');
4316
+ var lines = text.split('\n');
4317
+ return lines.reduce(function (count, line) { return count + Math.ceil(line.length / CHARACTERS_PER_STANDARD_LINE); }, 0);
4278
4318
  }
4279
4319
 
4280
4320
  /**
4281
4321
  * Counts number of pages in the text
4282
4322
  *
4323
+ * Note: This does not check only for the count of newlines, but also for the length of the standard line and length of the standard page.
4324
+ *
4283
4325
  * @public exported from `@promptbook/utils`
4284
4326
  */
4285
4327
  function countPages(text) {
4286
- if (text === '') {
4287
- return 0;
4288
- }
4289
- var pagesByLinesCount = Math.ceil(countLines(text) / 44);
4290
- var pagesByCharactersCount = Math.ceil(countCharacters(text) / 2772);
4291
- return Math.max(pagesByLinesCount, pagesByCharactersCount);
4328
+ return Math.ceil(countLines(text) / LINES_PER_STANDARD_PAGE);
4292
4329
  }
4293
4330
 
4294
4331
  /**
@@ -4568,7 +4605,7 @@
4568
4605
  promptTitle: template.title,
4569
4606
  promptMessage: replaceParameters(template.description || '', parameters),
4570
4607
  defaultValue: replaceParameters(preparedContent, parameters),
4571
- // TODO: [🧠] !! Figure out how to define placeholder in .ptbk.md file
4608
+ // TODO: [🧠] !! Figure out how to define placeholder in .book.md file
4572
4609
  placeholder: undefined,
4573
4610
  priority: priority,
4574
4611
  }))];
@@ -4996,7 +5033,7 @@
4996
5033
  else if (!definedParameterNames.has(parameterName) && usedParameterNames.has(parameterName)) {
4997
5034
  // Houston, we have a problem
4998
5035
  // Note: Checking part is also done in `validatePipeline`, but it’s good to doublecheck
4999
- throw new UnexpectedError(spaceTrim.spaceTrim(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 "); }));
5036
+ throw new UnexpectedError(spaceTrim.spaceTrim(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 "); }));
5000
5037
  }
5001
5038
  };
5002
5039
  try {
@@ -5075,7 +5112,7 @@
5075
5112
  var _loop_1 = function (parameter) {
5076
5113
  if (parametersToPass[parameter.name] === undefined) {
5077
5114
  // [4]
5078
- $warnings.push(new PipelineExecutionError(spaceTrim.spaceTrim(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 "); })));
5115
+ $warnings.push(new PipelineExecutionError(spaceTrim.spaceTrim(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 "); })));
5079
5116
  return "continue";
5080
5117
  }
5081
5118
  outputParameters[parameter.name] = parametersToPass[parameter.name] || '';
@@ -5134,7 +5171,7 @@
5134
5171
  pipelineUrl: preparedPipeline.pipelineUrl,
5135
5172
  title: preparedPipeline.title,
5136
5173
  promptbookUsedVersion: PROMPTBOOK_ENGINE_VERSION,
5137
- promptbookRequestedVersion: preparedPipeline.promptbookVersion,
5174
+ promptbookRequestedVersion: preparedPipeline.bookVersion,
5138
5175
  description: preparedPipeline.description,
5139
5176
  promptExecutions: [],
5140
5177
  };
@@ -5162,7 +5199,7 @@
5162
5199
  case 6: return [2 /*return*/, $asDeeplyFrozenSerializableJson("Unuccessful PipelineExecutorResult (with missing parameter {".concat(parameter.name, "}) PipelineExecutorResult"), {
5163
5200
  isSuccessful: false,
5164
5201
  errors: __spreadArray([
5165
- new PipelineExecutionError("Parameter {".concat(parameter.name, "} is required as an input parameter"))
5202
+ new PipelineExecutionError("Parameter `{".concat(parameter.name, "}` is required as an input parameter"))
5166
5203
  ], __read(errors), false).map(serializeError),
5167
5204
  warnings: [],
5168
5205
  executionReport: executionReport,
@@ -5210,7 +5247,7 @@
5210
5247
  case 3: return [2 /*return*/, { value: $asDeeplyFrozenSerializableJson(spaceTrim.spaceTrim(function (block) { return "\n Unuccessful PipelineExecutorResult (with extra parameter {".concat(parameter.name, "}) PipelineExecutorResult\n\n ").concat(block(pipelineIdentification), "\n "); }), {
5211
5248
  isSuccessful: false,
5212
5249
  errors: __spreadArray([
5213
- new PipelineExecutionError(spaceTrim.spaceTrim(function (block) { return "\n Parameter {".concat(parameter.name, "} is passed as input parameter but it is not input\n\n ").concat(block(pipelineIdentification), "\n "); }))
5250
+ new PipelineExecutionError(spaceTrim.spaceTrim(function (block) { return "\n Parameter `{".concat(parameter.name, "}` is passed as input parameter but it is not input\n\n ").concat(block(pipelineIdentification), "\n "); }))
5214
5251
  ], __read(errors), false).map(serializeError),
5215
5252
  warnings: warnings.map(serializeError),
5216
5253
  executionReport: executionReport,
@@ -5284,14 +5321,24 @@
5284
5321
  if (!(!currentTemplate && resolving_1.length === 0)) return [3 /*break*/, 1];
5285
5322
  throw new UnexpectedError(
5286
5323
  // TODO: [🐎] DRY
5287
- spaceTrim.spaceTrim(function (block) { return "\n Can not resolve some parameters:\n\n ".concat(block(pipelineIdentification), "\n\n Can not resolve:\n ").concat(block(unresovedTemplates_1
5324
+ spaceTrim.spaceTrim(function (block) { return "\n Can not resolve some parameters:\n\n ".concat(block(pipelineIdentification), "\n\n **Can not resolve:**\n ").concat(block(unresovedTemplates_1
5288
5325
  .map(function (_a) {
5289
5326
  var resultingParameterName = _a.resultingParameterName, dependentParameterNames = _a.dependentParameterNames;
5290
- return "- Parameter {".concat(resultingParameterName, "} which depends on ").concat(dependentParameterNames
5291
- .map(function (dependentParameterName) { return "{".concat(dependentParameterName, "}"); })
5327
+ return "- Parameter `{".concat(resultingParameterName, "}` which depends on ").concat(dependentParameterNames
5328
+ .map(function (dependentParameterName) { return "`{".concat(dependentParameterName, "}`"); })
5292
5329
  .join(' and '));
5293
5330
  })
5294
- .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 "); }));
5331
+ .join('\n')), "\n\n **Resolved:**\n ").concat(block(resovedParameterNames_1
5332
+ .filter(function (name) {
5333
+ return !RESERVED_PARAMETER_NAMES.includes(name);
5334
+ })
5335
+ .map(function (name) { return "- Parameter `{".concat(name, "}`"); })
5336
+ .join('\n')), "\n\n **Reserved (which are available):**\n ").concat(block(resovedParameterNames_1
5337
+ .filter(function (name) {
5338
+ return RESERVED_PARAMETER_NAMES.includes(name);
5339
+ })
5340
+ .map(function (name) { return "- Parameter `{".concat(name, "}`"); })
5341
+ .join('\n')), "\n\n *Note: This should be catched in `validatePipeline`*\n "); }));
5295
5342
  case 1:
5296
5343
  if (!!currentTemplate) return [3 /*break*/, 3];
5297
5344
  /* [🤹‍♂️] */ return [4 /*yield*/, Promise.race(resolving_1)];
@@ -5530,7 +5577,7 @@
5530
5577
  collection = createCollectionFromJson.apply(void 0, __spreadArray([], __read(PipelineCollection), false));
5531
5578
  _d = createPipelineExecutor;
5532
5579
  _g = {};
5533
- return [4 /*yield*/, collection.getPipelineByUrl('https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.ptbk.md')];
5580
+ return [4 /*yield*/, collection.getPipelineByUrl('https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book.md')];
5534
5581
  case 1:
5535
5582
  prepareKnowledgeFromMarkdownExecutor = _d.apply(void 0, [(_g.pipeline = _k.sent(),
5536
5583
  _g.tools = {
@@ -5539,7 +5586,7 @@
5539
5586
  _g)]);
5540
5587
  _e = createPipelineExecutor;
5541
5588
  _h = {};
5542
- return [4 /*yield*/, collection.getPipelineByUrl('https://promptbook.studio/promptbook/prepare-knowledge-title.ptbk.md')];
5589
+ return [4 /*yield*/, collection.getPipelineByUrl('https://promptbook.studio/promptbook/prepare-knowledge-title.book.md')];
5543
5590
  case 2:
5544
5591
  prepareTitleExecutor = _e.apply(void 0, [(_h.pipeline = _k.sent(),
5545
5592
  _h.tools = {
@@ -5548,7 +5595,7 @@
5548
5595
  _h)]);
5549
5596
  _f = createPipelineExecutor;
5550
5597
  _j = {};
5551
- return [4 /*yield*/, collection.getPipelineByUrl('https://promptbook.studio/promptbook/prepare-knowledge-keywords.ptbk.md')];
5598
+ return [4 /*yield*/, collection.getPipelineByUrl('https://promptbook.studio/promptbook/prepare-knowledge-keywords.book.md')];
5552
5599
  case 3:
5553
5600
  prepareKeywordsExecutor = _f.apply(void 0, [(_j.pipeline = _k.sent(),
5554
5601
  _j.tools = {
@@ -5906,7 +5953,7 @@
5906
5953
  return;
5907
5954
  }
5908
5955
  if (!section.startsWith('#')) {
5909
- section = "# Untitled\n\n".concat(section);
5956
+ section = "# ".concat(DEFAULT_TITLE, "\n\n").concat(section);
5910
5957
  }
5911
5958
  sections.push(section);
5912
5959
  buffer = [];
@@ -5970,7 +6017,7 @@
5970
6017
  var e_1, _a;
5971
6018
  var sections = splitMarkdownIntoSections(markdown);
5972
6019
  if (sections.length === 0) {
5973
- return '# Untitled';
6020
+ return "# ".concat(DEFAULT_TITLE);
5974
6021
  }
5975
6022
  var flattenedMarkdown = '';
5976
6023
  var parsedSections = sections.map(parseMarkdownSection);
@@ -5981,7 +6028,7 @@
5981
6028
  }
5982
6029
  else {
5983
6030
  parsedSections.unshift(firstSection);
5984
- flattenedMarkdown += "# Untitled" + "\n\n"; // <- [🧠] Maybe 3 new lines?
6031
+ flattenedMarkdown += "# ".concat(DEFAULT_TITLE) + "\n\n"; // <- [🧠] Maybe 3 new lines?
5985
6032
  }
5986
6033
  try {
5987
6034
  for (var parsedSections_1 = __values(parsedSections), parsedSections_1_1 = parsedSections_1.next(); !parsedSections_1_1.done; parsedSections_1_1 = parsedSections_1.next()) {