@promptbook/remote-server 0.92.0-8 → 0.92.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/README.md +1 -5
  2. package/esm/index.es.js +597 -401
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/src/_packages/browser.index.d.ts +2 -0
  5. package/esm/typings/src/_packages/core.index.d.ts +26 -14
  6. package/esm/typings/src/_packages/types.index.d.ts +6 -2
  7. package/esm/typings/src/collection/PipelineCollection.d.ts +0 -2
  8. package/esm/typings/src/collection/SimplePipelineCollection.d.ts +1 -1
  9. package/esm/typings/src/commands/FOREACH/ForeachJson.d.ts +6 -6
  10. package/esm/typings/src/commands/FOREACH/foreachCommandParser.d.ts +0 -2
  11. package/esm/typings/src/commands/FORMFACTOR/formfactorCommandParser.d.ts +1 -1
  12. package/esm/typings/src/commands/_BOILERPLATE/boilerplateCommandParser.d.ts +1 -1
  13. package/esm/typings/src/commands/_common/types/CommandParser.d.ts +36 -28
  14. package/esm/typings/src/config.d.ts +41 -11
  15. package/esm/typings/src/constants.d.ts +43 -2
  16. package/esm/typings/src/conversion/parsePipeline.d.ts +2 -2
  17. package/esm/typings/src/errors/0-BoilerplateError.d.ts +2 -2
  18. package/esm/typings/src/errors/CollectionError.d.ts +1 -1
  19. package/esm/typings/src/executables/$provideExecutablesForNode.d.ts +1 -1
  20. package/esm/typings/src/executables/apps/locateLibreoffice.d.ts +2 -1
  21. package/esm/typings/src/executables/apps/locatePandoc.d.ts +2 -1
  22. package/esm/typings/src/executables/locateApp.d.ts +2 -2
  23. package/esm/typings/src/executables/platforms/locateAppOnLinux.d.ts +2 -1
  24. package/esm/typings/src/executables/platforms/locateAppOnMacOs.d.ts +2 -1
  25. package/esm/typings/src/executables/platforms/locateAppOnWindows.d.ts +2 -1
  26. package/esm/typings/src/execution/AbstractTaskResult.d.ts +1 -1
  27. package/esm/typings/src/execution/CommonToolsOptions.d.ts +5 -1
  28. package/esm/typings/src/execution/ExecutionTask.d.ts +19 -1
  29. package/esm/typings/src/execution/LlmExecutionToolsConstructor.d.ts +2 -1
  30. package/esm/typings/src/execution/PipelineExecutorResult.d.ts +4 -2
  31. package/esm/typings/src/execution/PromptbookFetch.d.ts +1 -1
  32. package/esm/typings/src/execution/ScriptExecutionTools.d.ts +1 -1
  33. package/esm/typings/src/execution/createPipelineExecutor/$OngoingTaskResult.d.ts +12 -9
  34. package/esm/typings/src/execution/createPipelineExecutor/10-executePipeline.d.ts +13 -10
  35. package/esm/typings/src/execution/createPipelineExecutor/20-executeTask.d.ts +12 -9
  36. package/esm/typings/src/execution/createPipelineExecutor/30-executeFormatSubvalues.d.ts +15 -3
  37. package/esm/typings/src/execution/createPipelineExecutor/40-executeAttempts.d.ts +21 -15
  38. package/esm/typings/src/execution/createPipelineExecutor/computeCosineSimilarity.d.ts +13 -0
  39. package/esm/typings/src/execution/createPipelineExecutor/filterJustOutputParameters.d.ts +7 -6
  40. package/esm/typings/src/execution/createPipelineExecutor/getContextForTask.d.ts +5 -1
  41. package/esm/typings/src/execution/createPipelineExecutor/getExamplesForTask.d.ts +1 -1
  42. package/esm/typings/src/execution/createPipelineExecutor/getKnowledgeForTask.d.ts +12 -9
  43. package/esm/typings/src/execution/createPipelineExecutor/getReservedParametersForTask.d.ts +18 -5
  44. package/esm/typings/src/execution/createPipelineExecutor/knowledgePiecesToString.d.ts +9 -0
  45. package/esm/typings/src/execution/execution-report/ExecutionReportJson.d.ts +1 -1
  46. package/esm/typings/src/execution/execution-report/ExecutionReportString.d.ts +1 -1
  47. package/esm/typings/src/execution/translation/automatic-translate/automatic-translators/LindatAutomaticTranslator.d.ts +4 -4
  48. package/esm/typings/src/execution/utils/checkExpectations.d.ts +3 -3
  49. package/esm/typings/src/execution/utils/uncertainNumber.d.ts +3 -2
  50. package/esm/typings/src/execution/utils/usageToWorktime.d.ts +1 -1
  51. package/esm/typings/src/formats/_common/{FormatDefinition.d.ts → FormatParser.d.ts} +8 -6
  52. package/esm/typings/src/formats/_common/FormatSubvalueParser.d.ts +66 -0
  53. package/esm/typings/src/formats/csv/CsvFormatParser.d.ts +17 -0
  54. package/esm/typings/src/formats/csv/CsvSettings.d.ts +2 -2
  55. package/esm/typings/src/formats/csv/utils/csvParse.d.ts +12 -0
  56. package/esm/typings/src/formats/csv/utils/isValidCsvString.d.ts +1 -1
  57. package/esm/typings/src/formats/index.d.ts +2 -2
  58. package/esm/typings/src/formats/json/JsonFormatParser.d.ts +19 -0
  59. package/esm/typings/src/formats/json/utils/isValidJsonString.d.ts +1 -1
  60. package/esm/typings/src/formats/json/utils/jsonParse.d.ts +0 -3
  61. package/esm/typings/src/formats/text/{TextFormatDefinition.d.ts → TextFormatParser.d.ts} +7 -7
  62. package/esm/typings/src/formats/xml/XmlFormatParser.d.ts +19 -0
  63. package/esm/typings/src/formats/xml/utils/isValidXmlString.d.ts +1 -1
  64. package/esm/typings/src/formfactors/_boilerplate/BoilerplateFormfactorDefinition.d.ts +3 -2
  65. package/esm/typings/src/formfactors/_common/AbstractFormfactorDefinition.d.ts +16 -7
  66. package/esm/typings/src/formfactors/_common/FormfactorDefinition.d.ts +3 -1
  67. package/esm/typings/src/formfactors/_common/string_formfactor_name.d.ts +2 -1
  68. package/esm/typings/src/formfactors/chatbot/ChatbotFormfactorDefinition.d.ts +2 -2
  69. package/esm/typings/src/formfactors/completion/CompletionFormfactorDefinition.d.ts +29 -0
  70. package/esm/typings/src/formfactors/generator/GeneratorFormfactorDefinition.d.ts +2 -1
  71. package/esm/typings/src/formfactors/generic/GenericFormfactorDefinition.d.ts +2 -2
  72. package/esm/typings/src/formfactors/index.d.ts +33 -8
  73. package/esm/typings/src/formfactors/matcher/MatcherFormfactorDefinition.d.ts +4 -2
  74. package/esm/typings/src/formfactors/sheets/SheetsFormfactorDefinition.d.ts +3 -2
  75. package/esm/typings/src/formfactors/translator/TranslatorFormfactorDefinition.d.ts +3 -2
  76. package/esm/typings/src/high-level-abstractions/index.d.ts +2 -2
  77. package/esm/typings/src/llm-providers/_common/register/$llmToolsMetadataRegister.d.ts +3 -3
  78. package/esm/typings/src/llm-providers/_common/register/$llmToolsRegister.d.ts +3 -3
  79. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsConfigurationFromEnv.d.ts +4 -4
  80. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForTestingAndScriptsAndPlayground.d.ts +4 -3
  81. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsFromEnv.d.ts +18 -5
  82. package/esm/typings/src/llm-providers/_common/register/LlmToolsConfiguration.d.ts +11 -4
  83. package/esm/typings/src/llm-providers/_common/register/LlmToolsMetadata.d.ts +21 -42
  84. package/esm/typings/src/llm-providers/_common/register/LlmToolsOptions.d.ts +9 -2
  85. package/esm/typings/src/llm-providers/_common/register/createLlmToolsFromConfiguration.d.ts +13 -4
  86. package/esm/typings/src/llm-providers/_common/utils/cache/CacheItem.d.ts +10 -5
  87. package/esm/typings/src/llm-providers/_common/utils/cache/CacheLlmToolsOptions.d.ts +11 -3
  88. package/esm/typings/src/llm-providers/_common/utils/cache/cacheLlmTools.d.ts +3 -3
  89. package/esm/typings/src/llm-providers/_common/utils/count-total-usage/limitTotalUsage.d.ts +5 -5
  90. package/esm/typings/src/llm-providers/anthropic-claude/AnthropicClaudeExecutionTools.d.ts +6 -0
  91. package/esm/typings/src/llm-providers/anthropic-claude/anthropic-claude-models.d.ts +1 -1
  92. package/esm/typings/src/llm-providers/azure-openai/AzureOpenAiExecutionTools.d.ts +5 -1
  93. package/esm/typings/src/llm-providers/azure-openai/AzureOpenAiExecutionToolsOptions.d.ts +4 -4
  94. package/esm/typings/src/llm-providers/deepseek/deepseek-models.d.ts +1 -1
  95. package/esm/typings/src/llm-providers/google/google-models.d.ts +1 -1
  96. package/esm/typings/src/llm-providers/openai/OpenAiAssistantExecutionTools.d.ts +1 -1
  97. package/esm/typings/src/llm-providers/openai/OpenAiExecutionTools.d.ts +4 -0
  98. package/esm/typings/src/llm-providers/openai/openai-models.d.ts +1 -1
  99. package/esm/typings/src/llm-providers/openai/register-configuration.d.ts +2 -2
  100. package/esm/typings/src/llm-providers/openai/register-constructor.d.ts +2 -2
  101. package/esm/typings/src/migrations/migratePipeline.d.ts +9 -0
  102. package/esm/typings/src/other/templates/getBookTemplates.d.ts +2 -2
  103. package/esm/typings/src/pipeline/PipelineInterface/PipelineInterface.d.ts +3 -3
  104. package/esm/typings/src/pipeline/PipelineInterface/constants.d.ts +1 -1
  105. package/esm/typings/src/pipeline/PipelineInterface/getPipelineInterface.d.ts +1 -1
  106. package/esm/typings/src/pipeline/PipelineInterface/isPipelineImplementingInterface.d.ts +5 -4
  107. package/esm/typings/src/pipeline/PipelineInterface/isPipelineInterfacesEqual.d.ts +1 -1
  108. package/esm/typings/src/pipeline/PipelineJson/CommonTaskJson.d.ts +10 -7
  109. package/esm/typings/src/pipeline/PipelineJson/ParameterJson.d.ts +1 -1
  110. package/esm/typings/src/pipeline/PipelineJson/PipelineJson.d.ts +3 -2
  111. package/esm/typings/src/pipeline/PipelineString.d.ts +3 -1
  112. package/esm/typings/src/pipeline/book-notation.d.ts +2 -2
  113. package/esm/typings/src/postprocessing/utils/extractBlock.d.ts +1 -1
  114. package/esm/typings/src/postprocessing/utils/extractJsonBlock.d.ts +2 -2
  115. package/esm/typings/src/prepare/prepareTasks.d.ts +8 -5
  116. package/esm/typings/src/remote-server/openapi.d.ts +1 -1
  117. package/esm/typings/src/remote-server/socket-types/listModels/PromptbookServer_ListModels_Response.d.ts +1 -1
  118. package/esm/typings/src/remote-server/startRemoteServer.d.ts +1 -1
  119. package/esm/typings/src/remote-server/types/RemoteServerOptions.d.ts +7 -6
  120. package/esm/typings/src/scrapers/_boilerplate/BoilerplateScraper.d.ts +3 -3
  121. package/esm/typings/src/scrapers/_boilerplate/createBoilerplateScraper.d.ts +1 -1
  122. package/esm/typings/src/scrapers/_boilerplate/register-metadata.d.ts +1 -1
  123. package/esm/typings/src/scrapers/_common/Converter.d.ts +3 -1
  124. package/esm/typings/src/scrapers/_common/Scraper.d.ts +4 -3
  125. package/esm/typings/src/scrapers/_common/ScraperIntermediateSource.d.ts +4 -2
  126. package/esm/typings/src/scrapers/_common/prepareKnowledgePieces.d.ts +2 -2
  127. package/esm/typings/src/scrapers/_common/register/$provideFilesystemForNode.d.ts +2 -1
  128. package/esm/typings/src/scrapers/_common/register/$provideScrapersForBrowser.d.ts +6 -3
  129. package/esm/typings/src/scrapers/_common/register/$provideScrapersForNode.d.ts +3 -5
  130. package/esm/typings/src/scrapers/_common/register/$scrapersMetadataRegister.d.ts +3 -3
  131. package/esm/typings/src/scrapers/_common/register/$scrapersRegister.d.ts +3 -2
  132. package/esm/typings/src/scrapers/_common/register/ScraperAndConverterMetadata.d.ts +8 -5
  133. package/esm/typings/src/scrapers/_common/register/ScraperConstructor.d.ts +2 -1
  134. package/esm/typings/src/scrapers/_common/utils/getScraperIntermediateSource.d.ts +6 -5
  135. package/esm/typings/src/scrapers/_common/utils/makeKnowledgeSourceHandler.d.ts +3 -1
  136. package/esm/typings/src/scrapers/document/createDocumentScraper.d.ts +1 -1
  137. package/esm/typings/src/scrapers/document-legacy/createLegacyDocumentScraper.d.ts +2 -1
  138. package/esm/typings/src/scrapers/markdown/createMarkdownScraper.d.ts +4 -1
  139. package/esm/typings/src/scrapers/markitdown/MarkitdownScraper.d.ts +1 -1
  140. package/esm/typings/src/scrapers/pdf/createPdfScraper.d.ts +2 -1
  141. package/esm/typings/src/scrapers/website/createWebsiteScraper.d.ts +3 -4
  142. package/esm/typings/src/scripting/javascript/JavascriptExecutionTools.d.ts +1 -1
  143. package/esm/typings/src/scripting/javascript/postprocessing-functions.d.ts +5 -1
  144. package/esm/typings/src/scripting/javascript/utils/preserve.d.ts +1 -1
  145. package/esm/typings/src/storage/_common/PromptbookStorage.d.ts +1 -1
  146. package/esm/typings/src/storage/file-cache-storage/FileCacheStorage.d.ts +12 -5
  147. package/esm/typings/src/storage/file-cache-storage/FileCacheStorageOptions.d.ts +4 -2
  148. package/esm/typings/src/storage/file-cache-storage/utils/nameToSubfolderPath.d.ts +2 -1
  149. package/esm/typings/src/storage/local-storage/getIndexedDbStorage.d.ts +11 -0
  150. package/esm/typings/src/storage/local-storage/utils/IndexedDbStorageOptions.d.ts +14 -0
  151. package/esm/typings/src/storage/local-storage/utils/makePromptbookStorageFromIndexedDb.d.ts +8 -0
  152. package/esm/typings/src/storage/local-storage/utils/makePromptbookStorageFromWebStorage.d.ts +2 -1
  153. package/esm/typings/src/types/IntermediateFilesStrategy.d.ts +2 -1
  154. package/esm/typings/src/types/ModelRequirements.d.ts +2 -2
  155. package/esm/typings/src/types/ModelVariant.d.ts +5 -5
  156. package/esm/typings/src/types/typeAliases.d.ts +22 -19
  157. package/esm/typings/src/utils/$Register.d.ts +8 -7
  158. package/esm/typings/src/utils/editable/edit-pipeline-string/addPipelineCommand.d.ts +2 -2
  159. package/esm/typings/src/utils/editable/edit-pipeline-string/deflatePipeline.d.ts +4 -1
  160. package/esm/typings/src/utils/editable/utils/isFlatPipeline.d.ts +2 -1
  161. package/esm/typings/src/utils/editable/utils/stringifyPipelineJson.d.ts +1 -1
  162. package/esm/typings/src/utils/environment/$getGlobalScope.d.ts +2 -1
  163. package/esm/typings/src/utils/expectation-counters/index.d.ts +1 -1
  164. package/esm/typings/src/utils/markdown/extractAllBlocksFromMarkdown.d.ts +2 -2
  165. package/esm/typings/src/utils/markdown/extractAllListItemsFromMarkdown.d.ts +1 -1
  166. package/esm/typings/src/utils/markdown/extractOneBlockFromMarkdown.d.ts +2 -2
  167. package/esm/typings/src/utils/normalization/nameToUriPart.d.ts +4 -4
  168. package/esm/typings/src/utils/normalization/nameToUriParts.d.ts +4 -4
  169. package/esm/typings/src/utils/normalization/normalize-to-kebab-case.d.ts +3 -3
  170. package/esm/typings/src/utils/normalization/normalizeTo_SCREAMING_CASE.d.ts +3 -3
  171. package/esm/typings/src/utils/normalization/normalizeTo_camelCase.d.ts +4 -4
  172. package/esm/typings/src/utils/normalization/normalizeTo_snake_case.d.ts +3 -3
  173. package/esm/typings/src/utils/normalization/removeDiacritics.d.ts +3 -3
  174. package/esm/typings/src/utils/normalization/searchKeywords.d.ts +4 -1
  175. package/esm/typings/src/utils/normalization/titleToName.d.ts +4 -4
  176. package/esm/typings/src/utils/organization/TODO_USE.d.ts +1 -1
  177. package/esm/typings/src/utils/organization/empty_object.d.ts +2 -2
  178. package/esm/typings/src/utils/organization/just.d.ts +1 -1
  179. package/esm/typings/src/utils/organization/just_empty_object.d.ts +4 -4
  180. package/esm/typings/src/utils/organization/keepUnused.d.ts +1 -1
  181. package/esm/typings/src/utils/parameters/mapAvailableToExpectedParameters.d.ts +7 -7
  182. package/esm/typings/src/utils/removeQuotes.d.ts +2 -2
  183. package/esm/typings/src/utils/serialization/clonePipeline.d.ts +4 -3
  184. package/esm/typings/src/utils/serialization/deepClone.d.ts +5 -1
  185. package/esm/typings/src/utils/trimCodeBlock.d.ts +1 -1
  186. package/esm/typings/src/utils/trimEndOfCodeBlock.d.ts +1 -1
  187. package/esm/typings/src/utils/unwrapResult.d.ts +2 -2
  188. package/esm/typings/src/utils/validators/javascriptName/isValidJavascriptName.d.ts +3 -3
  189. package/esm/typings/src/utils/validators/parameterName/validateParameterName.d.ts +5 -4
  190. package/esm/typings/src/utils/validators/semanticVersion/isValidPromptbookVersion.d.ts +1 -1
  191. package/esm/typings/src/utils/validators/semanticVersion/isValidSemanticVersion.d.ts +1 -1
  192. package/esm/typings/src/utils/validators/url/isHostnameOnPrivateNetwork.d.ts +1 -1
  193. package/esm/typings/src/utils/validators/url/isUrlOnPrivateNetwork.d.ts +1 -1
  194. package/esm/typings/src/utils/validators/url/isValidPipelineUrl.d.ts +1 -1
  195. package/esm/typings/src/utils/validators/url/isValidUrl.d.ts +1 -1
  196. package/esm/typings/src/version.d.ts +2 -1
  197. package/esm/typings/src/wizzard/wizzard.d.ts +1 -1
  198. package/package.json +14 -2
  199. package/umd/index.umd.js +601 -405
  200. package/umd/index.umd.js.map +1 -1
  201. package/esm/typings/src/formats/_common/FormatSubvalueDefinition.d.ts +0 -31
  202. package/esm/typings/src/formats/csv/CsvFormatDefinition.d.ts +0 -17
  203. package/esm/typings/src/formats/json/JsonFormatDefinition.d.ts +0 -19
  204. package/esm/typings/src/formats/xml/XmlFormatDefinition.d.ts +0 -19
  205. /package/esm/typings/src/llm-providers/{multiple → _multiple}/MultipleLlmExecutionTools.d.ts +0 -0
  206. /package/esm/typings/src/llm-providers/{multiple → _multiple}/joinLlmExecutionTools.d.ts +0 -0
  207. /package/esm/typings/src/llm-providers/{multiple → _multiple}/playground/playground.d.ts +0 -0
package/esm/index.es.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import colors from 'colors';
2
2
  import express from 'express';
3
+ import * as OpenApiValidator from 'express-openapi-validator';
3
4
  import http from 'http';
4
5
  import { Server } from 'socket.io';
5
6
  import spaceTrim, { spaceTrim as spaceTrim$1 } from 'spacetrim';
6
- import * as OpenApiValidator from 'express-openapi-validator';
7
7
  import swaggerUi from 'swagger-ui-express';
8
8
  import { forTime } from 'waitasecond';
9
9
  import { randomBytes } from 'crypto';
@@ -33,7 +33,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
33
33
  * @generated
34
34
  * @see https://github.com/webgptorg/promptbook
35
35
  */
36
- const PROMPTBOOK_ENGINE_VERSION = '0.92.0-8';
36
+ const PROMPTBOOK_ENGINE_VERSION = '0.92.0';
37
37
  /**
38
38
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
39
39
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -43,7 +43,7 @@ const PROMPTBOOK_ENGINE_VERSION = '0.92.0-8';
43
43
  * Returns the same value that is passed as argument.
44
44
  * No side effects.
45
45
  *
46
- * Note: It can be usefull for:
46
+ * Note: It can be useful for:
47
47
  *
48
48
  * 1) Leveling indentation
49
49
  * 2) Putting always-true or always-false conditions without getting eslint errors
@@ -100,6 +100,21 @@ const DEFAULT_BOOK_TITLE = `✨ Untitled Book`;
100
100
  * @public exported from `@promptbook/core`
101
101
  */
102
102
  const DEFAULT_MAX_FILE_SIZE = 100 * 1024 * 1024; // 100MB
103
+ /**
104
+ * Threshold value that determines when a dataset is considered "big"
105
+ * and may require special handling or optimizations
106
+ *
107
+ * For example, when error occurs in one item of the big dataset, it will not fail the whole pipeline
108
+ *
109
+ * @public exported from `@promptbook/core`
110
+ */
111
+ const BIG_DATASET_TRESHOLD = 50;
112
+ /**
113
+ * Placeholder text used to represent a placeholder value of failed operation
114
+ *
115
+ * @public exported from `@promptbook/core`
116
+ */
117
+ const FAILED_VALUE_PLACEHOLDER = '!?';
103
118
  // <- TODO: [🧠] Better system for generator warnings - not always "code" and "by `@promptbook/cli`"
104
119
  /**
105
120
  * The maximum number of iterations for a loops
@@ -179,7 +194,7 @@ const DEFAULT_DOWNLOAD_CACHE_DIRNAME = './.promptbook/download-cache';
179
194
  const DEFAULT_SCRAPE_CACHE_DIRNAME = './.promptbook/scrape-cache';
180
195
  // <- TODO: [🧜‍♂️]
181
196
  /**
182
- * @@@
197
+ * Default settings for parsing and generating CSV files in Promptbook.
183
198
  *
184
199
  * @public exported from `@promptbook/core`
185
200
  */
@@ -190,19 +205,19 @@ const DEFAULT_CSV_SETTINGS = Object.freeze({
190
205
  skipEmptyLines: true,
191
206
  });
192
207
  /**
193
- * @@@
208
+ * Controls whether verbose logging is enabled by default throughout the application.
194
209
  *
195
210
  * @public exported from `@promptbook/core`
196
211
  */
197
212
  let DEFAULT_IS_VERBOSE = false;
198
213
  /**
199
- * @@@
214
+ * Controls whether auto-installation of dependencies is enabled by default.
200
215
  *
201
216
  * @public exported from `@promptbook/core`
202
217
  */
203
218
  const DEFAULT_IS_AUTO_INSTALLED = false;
204
219
  /**
205
- * @@@
220
+ * Indicates whether pipeline logic validation is enabled. When true, the pipeline logic is checked for consistency.
206
221
  *
207
222
  * @private within the repository
208
223
  */
@@ -270,7 +285,7 @@ class UnexpectedError extends Error {
270
285
  ${block(message)}
271
286
 
272
287
  Note: This error should not happen.
273
- It's probbably a bug in the pipeline collection
288
+ It's probably a bug in the pipeline collection
274
289
 
275
290
  Please report issue:
276
291
  ${block(getErrorReportUrl(new Error(message)).href)}
@@ -370,7 +385,7 @@ class PipelineExecutionError extends Error {
370
385
  super(message);
371
386
  this.name = 'PipelineExecutionError';
372
387
  // TODO: [🐙] DRY - Maybe $randomId
373
- this.id = `error-${$randomToken(8 /* <- TODO: To global config + Use Base58 to avoid simmilar char conflicts */)}`;
388
+ this.id = `error-${$randomToken(8 /* <- TODO: To global config + Use Base58 to avoid similar char conflicts */)}`;
374
389
  Object.setPrototypeOf(this, PipelineExecutionError.prototype);
375
390
  }
376
391
  }
@@ -409,7 +424,7 @@ class CsvFormatError extends AbstractFormatError {
409
424
  }
410
425
 
411
426
  /**
412
- * This error indicates that the pipeline collection cannot be propperly loaded
427
+ * This error indicates that the pipeline collection cannot be properly loaded
413
428
  *
414
429
  * @public exported from `@promptbook/core`
415
430
  */
@@ -486,7 +501,7 @@ class MissingToolsError extends Error {
486
501
  super(spaceTrim$1((block) => `
487
502
  ${block(message)}
488
503
 
489
- Note: You have probbably forgot to provide some tools for pipeline execution or preparation
504
+ Note: You have probably forgot to provide some tools for pipeline execution or preparation
490
505
 
491
506
  `));
492
507
  this.name = 'MissingToolsError';
@@ -857,7 +872,8 @@ function $execCommand(options) {
857
872
  */
858
873
 
859
874
  /**
860
- * @@@
875
+ * Attempts to locate the specified application on a Linux system using the 'which' command.
876
+ * Returns the path to the executable if found, or null otherwise.
861
877
  *
862
878
  * @private within the repository
863
879
  */
@@ -877,7 +893,8 @@ async function locateAppOnLinux({ linuxWhich, }) {
877
893
  */
878
894
 
879
895
  /**
880
- * @@@
896
+ * Provides filesystem access (for example for Node.js-based scrapers)
897
+ * Creates a standardized filesystem interface that scrapers can use for file operations.
881
898
  *
882
899
  * @public exported from `@promptbook/node`
883
900
  */
@@ -923,7 +940,8 @@ async function isExecutable(path, fs) {
923
940
  // eslint-disable-next-line @typescript-eslint/no-var-requires
924
941
  const userhome = require('userhome');
925
942
  /**
926
- * @@@
943
+ * Attempts to locate the specified application on a macOS system by checking standard application paths and using mdfind.
944
+ * Returns the path to the executable if found, or null otherwise.
927
945
  *
928
946
  * @private within the repository
929
947
  */
@@ -955,7 +973,8 @@ async function locateAppOnMacOs({ macOsName, }) {
955
973
  */
956
974
 
957
975
  /**
958
- * @@@
976
+ * Attempts to locate the specified application on a Windows system by searching common installation directories.
977
+ * Returns the path to the executable if found, or null otherwise.
959
978
  *
960
979
  * @private within the repository
961
980
  */
@@ -1026,7 +1045,8 @@ function locateApp(options) {
1026
1045
  */
1027
1046
 
1028
1047
  /**
1029
- * @@@
1048
+ * Locates the LibreOffice executable on the current system by searching platform-specific paths.
1049
+ * Returns the path to the executable if found, or null otherwise.
1030
1050
  *
1031
1051
  * @private within the repository
1032
1052
  */
@@ -1044,7 +1064,8 @@ function locateLibreoffice() {
1044
1064
  */
1045
1065
 
1046
1066
  /**
1047
- * @@@
1067
+ * Locates the Pandoc executable on the current system by searching platform-specific paths.
1068
+ * Returns the path to the executable if found, or null otherwise.
1048
1069
  *
1049
1070
  * @private within the repository
1050
1071
  */
@@ -1062,7 +1083,7 @@ function locatePandoc() {
1062
1083
  */
1063
1084
 
1064
1085
  /**
1065
- * @@@
1086
+ * Provides paths to required executables (i.e. as Pandoc and LibreOffice) for Node.js environments.
1066
1087
  *
1067
1088
  * @public exported from `@promptbook/node`
1068
1089
  */
@@ -1262,8 +1283,12 @@ function checkSerializableAsJson(options) {
1262
1283
  */
1263
1284
 
1264
1285
  /**
1265
- * @@@
1286
+ * Creates a deep clone of the given object
1287
+ *
1288
+ * Note: This method only works for objects that are fully serializable to JSON and do not contain functions, Dates, or special types.
1266
1289
  *
1290
+ * @param objectValue The object to clone.
1291
+ * @returns A deep, writable clone of the input object.
1267
1292
  * @public exported from `@promptbook/utils`
1268
1293
  */
1269
1294
  function deepClone(objectValue) {
@@ -1345,13 +1370,13 @@ const ORDER_OF_PIPELINE_JSON = [
1345
1370
  */
1346
1371
  const REPLACING_NONCE = 'ptbkauk42kV2dzao34faw7FudQUHYPtW';
1347
1372
  /**
1348
- * @@@
1373
+ * Placeholder value indicating a parameter is missing its value.
1349
1374
  *
1350
1375
  * @private within the repository
1351
1376
  */
1352
1377
  const RESERVED_PARAMETER_MISSING_VALUE = 'MISSING-' + REPLACING_NONCE;
1353
1378
  /**
1354
- * @@@
1379
+ * Placeholder value indicating a parameter is restricted and cannot be used directly.
1355
1380
  *
1356
1381
  * @private within the repository
1357
1382
  */
@@ -1383,7 +1408,7 @@ const RESERVED_PARAMETER_NAMES = exportJson({
1383
1408
  /**
1384
1409
  * Tests if given string is valid semantic version
1385
1410
  *
1386
- * Note: There are two simmilar functions:
1411
+ * Note: There are two similar functions:
1387
1412
  * - `isValidSemanticVersion` which tests any semantic version
1388
1413
  * - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
1389
1414
  *
@@ -1405,7 +1430,7 @@ function isValidSemanticVersion(version) {
1405
1430
  *
1406
1431
  * @see https://www.npmjs.com/package/promptbook?activeTab=versions
1407
1432
  * Note: When you are using for example promptbook 2.0.0 and there already is promptbook 3.0.0 it don`t know about it.
1408
- * Note: There are two simmilar functions:
1433
+ * Note: There are two similar functions:
1409
1434
  * - `isValidSemanticVersion` which tests any semantic version
1410
1435
  * - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
1411
1436
  *
@@ -1426,7 +1451,7 @@ function isValidPromptbookVersion(version) {
1426
1451
  * Tests if given string is valid URL.
1427
1452
  *
1428
1453
  * Note: Dataurl are considered perfectly valid.
1429
- * Note: There are two simmilar functions:
1454
+ * Note: There are two similar functions:
1430
1455
  * - `isValidUrl` which tests any URL
1431
1456
  * - `isValidPipelineUrl` *(this one)* which tests just promptbook URL
1432
1457
  *
@@ -1454,7 +1479,7 @@ function isValidUrl(url) {
1454
1479
  /**
1455
1480
  * Tests if given string is valid pipeline URL URL.
1456
1481
  *
1457
- * Note: There are two simmilar functions:
1482
+ * Note: There are two similar functions:
1458
1483
  * - `isValidUrl` which tests any URL
1459
1484
  * - `isValidPipelineUrl` *(this one)* which tests just pipeline URL
1460
1485
  *
@@ -1551,7 +1576,7 @@ function validatePipeline_InnerFunction(pipeline) {
1551
1576
  ${block(pipelineIdentification)}
1552
1577
  `));
1553
1578
  }
1554
- // TODO: [🧠] Maybe do here some propper JSON-schema / ZOD checking
1579
+ // TODO: [🧠] Maybe do here some proper JSON-schema / ZOD checking
1555
1580
  if (!Array.isArray(pipeline.parameters)) {
1556
1581
  // TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
1557
1582
  throw new ParseError(spaceTrim$1((block) => `
@@ -1562,7 +1587,7 @@ function validatePipeline_InnerFunction(pipeline) {
1562
1587
  ${block(pipelineIdentification)}
1563
1588
  `));
1564
1589
  }
1565
- // TODO: [🧠] Maybe do here some propper JSON-schema / ZOD checking
1590
+ // TODO: [🧠] Maybe do here some proper JSON-schema / ZOD checking
1566
1591
  if (!Array.isArray(pipeline.tasks)) {
1567
1592
  // TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
1568
1593
  throw new ParseError(spaceTrim$1((block) => `
@@ -1782,15 +1807,18 @@ function validatePipeline_InnerFunction(pipeline) {
1782
1807
  * @public exported from `@promptbook/core`
1783
1808
  */
1784
1809
  function isPipelinePrepared(pipeline) {
1785
- // Note: Ignoring `pipeline.preparations` @@@
1786
- // Note: Ignoring `pipeline.knowledgePieces` @@@
1810
+ // Note: Ignoring `pipeline.preparations`
1811
+ // Note: Ignoring `pipeline.knowledgePieces`
1787
1812
  if (pipeline.title === undefined || pipeline.title === '' || pipeline.title === DEFAULT_BOOK_TITLE) {
1813
+ // console.log('Pipeline is not prepared because title is undefined or empty', pipeline);
1788
1814
  return false;
1789
1815
  }
1790
1816
  if (!pipeline.personas.every((persona) => persona.modelsRequirements !== undefined)) {
1817
+ // console.log('Pipeline is not prepared because personas are not prepared', pipeline.personas);
1791
1818
  return false;
1792
1819
  }
1793
1820
  if (!pipeline.knowledgeSources.every((knowledgeSource) => knowledgeSource.preparationIds !== undefined)) {
1821
+ //console.log('Pipeline is not prepared because knowledge sources are not prepared', pipeline.knowledgeSources);
1794
1822
  return false;
1795
1823
  }
1796
1824
  /*
@@ -1815,7 +1843,7 @@ function isPipelinePrepared(pipeline) {
1815
1843
  * Function isValidJsonString will tell you if the string is valid JSON or not
1816
1844
  *
1817
1845
  * @param value The string to check
1818
- * @returns True if the string is a valid JSON string, false otherwise
1846
+ * @returns `true` if the string is a valid JSON string, false otherwise
1819
1847
  *
1820
1848
  * @public exported from `@promptbook/utils`
1821
1849
  */
@@ -1862,15 +1890,12 @@ function jsonParse(value) {
1862
1890
  }
1863
1891
  throw new Error(spaceTrim((block) => `
1864
1892
  ${block(error.message)}
1865
-
1893
+
1866
1894
  The JSON text:
1867
1895
  ${block(value)}
1868
1896
  `));
1869
1897
  }
1870
1898
  }
1871
- /**
1872
- * TODO: !!!! Use in Promptbook.studio
1873
- */
1874
1899
 
1875
1900
  /**
1876
1901
  * Recursively converts JSON strings to JSON objects
@@ -1976,8 +2001,9 @@ function assertsTaskSuccessful(executionResult) {
1976
2001
  */
1977
2002
  function createTask(options) {
1978
2003
  const { taskType, taskProcessCallback } = options;
2004
+ let { title } = options;
1979
2005
  // TODO: [🐙] DRY
1980
- const taskId = `${taskType.toLowerCase().substring(0, 4)}-${$randomToken(8 /* <- TODO: To global config + Use Base58 to avoid simmilar char conflicts */)}`;
2006
+ const taskId = `${taskType.toLowerCase().substring(0, 4)}-${$randomToken(8 /* <- TODO: To global config + Use Base58 to avoid similar char conflicts */)}`;
1981
2007
  let status = 'RUNNING';
1982
2008
  const createdAt = new Date();
1983
2009
  let updatedAt = createdAt;
@@ -1987,6 +2013,10 @@ function createTask(options) {
1987
2013
  const partialResultSubject = new Subject();
1988
2014
  // <- Note: Not using `BehaviorSubject` because on error we can't access the last value
1989
2015
  const finalResultPromise = /* not await */ taskProcessCallback((newOngoingResult) => {
2016
+ if (newOngoingResult.title) {
2017
+ title = newOngoingResult.title;
2018
+ }
2019
+ updatedAt = new Date();
1990
2020
  Object.assign(currentValue, newOngoingResult);
1991
2021
  // <- TODO: assign deep
1992
2022
  partialResultSubject.next(newOngoingResult);
@@ -2032,17 +2062,24 @@ function createTask(options) {
2032
2062
  return {
2033
2063
  taskType,
2034
2064
  taskId,
2065
+ get promptbookVersion() {
2066
+ return PROMPTBOOK_ENGINE_VERSION;
2067
+ },
2068
+ get title() {
2069
+ return title;
2070
+ // <- Note: [1] These must be getters to allow changing the value in the future
2071
+ },
2035
2072
  get status() {
2036
2073
  return status;
2037
- // <- Note: [1] Theese must be getters to allow changing the value in the future
2074
+ // <- Note: [1] --||--
2038
2075
  },
2039
2076
  get createdAt() {
2040
2077
  return createdAt;
2041
- // <- Note: [1]
2078
+ // <- Note: [1] --||--
2042
2079
  },
2043
2080
  get updatedAt() {
2044
2081
  return updatedAt;
2045
- // <- Note: [1]
2082
+ // <- Note: [1] --||--
2046
2083
  },
2047
2084
  asPromise,
2048
2085
  asObservable() {
@@ -2050,15 +2087,15 @@ function createTask(options) {
2050
2087
  },
2051
2088
  get errors() {
2052
2089
  return errors;
2053
- // <- Note: [1]
2090
+ // <- Note: [1] --||--
2054
2091
  },
2055
2092
  get warnings() {
2056
2093
  return warnings;
2057
- // <- Note: [1]
2094
+ // <- Note: [1] --||--
2058
2095
  },
2059
2096
  get currentValue() {
2060
2097
  return currentValue;
2061
- // <- Note: [1]
2098
+ // <- Note: [1] --||--
2062
2099
  },
2063
2100
  };
2064
2101
  }
@@ -2067,6 +2104,74 @@ function createTask(options) {
2067
2104
  * TODO: [🐚] Split into more files and make `PrepareTask` & `RemoteTask` + split the function
2068
2105
  */
2069
2106
 
2107
+ /**
2108
+ * Represents the uncertain value
2109
+ *
2110
+ * @public exported from `@promptbook/core`
2111
+ */
2112
+ const ZERO_VALUE = $deepFreeze({ value: 0 });
2113
+ /**
2114
+ * Represents the uncertain value
2115
+ *
2116
+ * @public exported from `@promptbook/core`
2117
+ */
2118
+ const UNCERTAIN_ZERO_VALUE = $deepFreeze({ value: 0, isUncertain: true });
2119
+ /**
2120
+ * Represents the usage with no resources consumed
2121
+ *
2122
+ * @public exported from `@promptbook/core`
2123
+ */
2124
+ const ZERO_USAGE = $deepFreeze({
2125
+ price: ZERO_VALUE,
2126
+ input: {
2127
+ tokensCount: ZERO_VALUE,
2128
+ charactersCount: ZERO_VALUE,
2129
+ wordsCount: ZERO_VALUE,
2130
+ sentencesCount: ZERO_VALUE,
2131
+ linesCount: ZERO_VALUE,
2132
+ paragraphsCount: ZERO_VALUE,
2133
+ pagesCount: ZERO_VALUE,
2134
+ },
2135
+ output: {
2136
+ tokensCount: ZERO_VALUE,
2137
+ charactersCount: ZERO_VALUE,
2138
+ wordsCount: ZERO_VALUE,
2139
+ sentencesCount: ZERO_VALUE,
2140
+ linesCount: ZERO_VALUE,
2141
+ paragraphsCount: ZERO_VALUE,
2142
+ pagesCount: ZERO_VALUE,
2143
+ },
2144
+ });
2145
+ /**
2146
+ * Represents the usage with unknown resources consumed
2147
+ *
2148
+ * @public exported from `@promptbook/core`
2149
+ */
2150
+ const UNCERTAIN_USAGE = $deepFreeze({
2151
+ price: UNCERTAIN_ZERO_VALUE,
2152
+ input: {
2153
+ tokensCount: UNCERTAIN_ZERO_VALUE,
2154
+ charactersCount: UNCERTAIN_ZERO_VALUE,
2155
+ wordsCount: UNCERTAIN_ZERO_VALUE,
2156
+ sentencesCount: UNCERTAIN_ZERO_VALUE,
2157
+ linesCount: UNCERTAIN_ZERO_VALUE,
2158
+ paragraphsCount: UNCERTAIN_ZERO_VALUE,
2159
+ pagesCount: UNCERTAIN_ZERO_VALUE,
2160
+ },
2161
+ output: {
2162
+ tokensCount: UNCERTAIN_ZERO_VALUE,
2163
+ charactersCount: UNCERTAIN_ZERO_VALUE,
2164
+ wordsCount: UNCERTAIN_ZERO_VALUE,
2165
+ sentencesCount: UNCERTAIN_ZERO_VALUE,
2166
+ linesCount: UNCERTAIN_ZERO_VALUE,
2167
+ paragraphsCount: UNCERTAIN_ZERO_VALUE,
2168
+ pagesCount: UNCERTAIN_ZERO_VALUE,
2169
+ },
2170
+ });
2171
+ /**
2172
+ * Note: [💞] Ignore a discrepancy between file name and entity name
2173
+ */
2174
+
2070
2175
  var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book",formfactorName:"GENERIC",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}",resultingParameterName:"knowledgePieces",dependentParameterNames:["knowledgeContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge from Markdown\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book`\n- INPUT PARAMETER `{knowledgeContent}` Markdown document content\n- OUTPUT PARAMETER `{knowledgePieces}` The knowledge JSON object\n\n## Knowledge\n\n<!-- TODO: [🍆] -FORMAT JSON -->\n\n```markdown\nYou are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}\n```\n\n`-> {knowledgePieces}`\n"}],sourceFile:"./books/prepare-knowledge-from-markdown.book"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.book",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}",resultingParameterName:"keywords",dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Keywords\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-keywords.book`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{keywords}` Keywords separated by comma\n\n## Knowledge\n\n<!-- TODO: [🍆] -FORMAT JSON -->\n\n```markdown\nYou are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}\n```\n\n`-> {keywords}`\n"}],sourceFile:"./books/prepare-knowledge-keywords.book"},{title:"Prepare Knowledge-piece Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.book",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}",resultingParameterName:"title",expectations:{words:{min:1,max:8}},dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge-piece Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-title.book`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{title}` The title of the document\n\n## Knowledge\n\n- EXPECT MIN 1 WORD\n- EXPECT MAX 8 WORDS\n\n```markdown\nYou are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-knowledge-title.book"},{title:"Prepare Persona",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.book",formfactorName:"GENERIC",parameters:[{name:"availableModels",description:"List of available model names together with their descriptions as JSON",isInput:true,isOutput:false},{name:"personaDescription",description:"Description of the persona",isInput:true,isOutput:false},{name:"modelsRequirements",description:"Specific requirements for the model",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-model-requirements",title:"Make modelRequirements",content:"You are an experienced AI engineer, you need to find the best models for virtual assistants:\n\n## Example\n\n```json\n[\n {\n \"modelName\": \"gpt-4o\",\n \"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n \"temperature\": 0.7\n },\n {\n \"modelName\": \"claude-3-5-sonnet\",\n \"systemMessage\": \"You are a friendly and knowledgeable chatbot.\",\n \"temperature\": 0.5\n }\n]\n```\n\n## Instructions\n\n- Your output format is JSON array\n- Sort best-fitting models first\n- Omit any models that are not suitable\n- Write just the JSON, no other text should be present\n- Array contain items with 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\nHere are the available models:\n\n```json\n{availableModels}\n```\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:"modelsRequirements",format:"JSON",dependentParameterNames:["availableModels","personaDescription"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Persona\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-persona.book`\n- INPUT PARAMETER `{availableModels}` List of available model names together with their descriptions as JSON\n- INPUT PARAMETER `{personaDescription}` Description of the persona\n- OUTPUT PARAMETER `{modelsRequirements}` Specific requirements for the model\n\n## Make modelRequirements\n\n- FORMAT JSON\n\n```markdown\nYou are an experienced AI engineer, you need to find the best models for virtual assistants:\n\n## Example\n\n\\`\\`\\`json\n[\n {\n \"modelName\": \"gpt-4o\",\n \"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n \"temperature\": 0.7\n },\n {\n \"modelName\": \"claude-3-5-sonnet\",\n \"systemMessage\": \"You are a friendly and knowledgeable chatbot.\",\n \"temperature\": 0.5\n }\n]\n\\`\\`\\`\n\n## Instructions\n\n- Your output format is JSON array\n- Sort best-fitting models first\n- Omit any models that are not suitable\n- Write just the JSON, no other text should be present\n- Array contain items with 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\nHere are the available models:\n\n\\`\\`\\`json\n{availableModels}\n\\`\\`\\`\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}\n```\n\n`-> {modelsRequirements}`\n"}],sourceFile:"./books/prepare-persona.book"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-title.book",formfactorName:"GENERIC",parameters:[{name:"book",description:"The book to prepare the title for",isInput:true,isOutput:false},{name:"title",description:"Best title for the book",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-title",title:"Make title",content:"Make best title for given text which describes the workflow:\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Title starts with emoticon\n- Title should not mention the input and output of the workflow but the main purpose of the workflow\n _For example, not \"✍ Convert Knowledge-piece to title\" but \"✍ Title\"_\n\n## The workflow\n\n> {book}",resultingParameterName:"title",expectations:{words:{min:1,max:8},lines:{min:1,max:1}},dependentParameterNames:["book"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-title.book`\n- INPUT PARAMETER `{book}` The book to prepare the title for\n- OUTPUT PARAMETER `{title}` Best title for the book\n\n## Make title\n\n- EXPECT MIN 1 Word\n- EXPECT MAX 8 Words\n- EXPECT EXACTLY 1 Line\n\n```markdown\nMake best title for given text which describes the workflow:\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Title starts with emoticon\n- Title should not mention the input and output of the workflow but the main purpose of the workflow\n _For example, not \"✍ Convert Knowledge-piece to title\" but \"✍ Title\"_\n\n## The workflow\n\n> {book}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-title.book"}];
2071
2176
 
2072
2177
  /**
@@ -2227,7 +2332,7 @@ function pipelineJsonToString(pipelineJson) {
2227
2332
  if (bookVersion !== `undefined`) {
2228
2333
  commands.push(`BOOK VERSION ${bookVersion}`);
2229
2334
  }
2230
- // TODO: [main] !!5 This increases size of the bundle and is probbably not necessary
2335
+ // TODO: [main] !!5 This increases size of the bundle and is probably not necessary
2231
2336
  pipelineString = prettifyMarkdown(pipelineString);
2232
2337
  for (const parameter of parameters.filter(({ isInput }) => isInput)) {
2233
2338
  commands.push(`INPUT PARAMETER ${taskParameterJsonToString(parameter)}`);
@@ -2411,7 +2516,7 @@ class SimplePipelineCollection {
2411
2516
  /**
2412
2517
  * Constructs a pipeline collection from pipelines
2413
2518
  *
2414
- * @param pipelines @@@
2519
+ * @param pipelines Array of pipeline JSON objects to include in the collection
2415
2520
  *
2416
2521
  * Note: During the construction logic of all pipelines are validated
2417
2522
  * Note: It is not recommended to use this constructor directly, use `createCollectionFromJson` *(or other variant)* instead
@@ -2544,74 +2649,6 @@ async function forEachAsync(array, options, callbackfunction) {
2544
2649
  await Promise.all(tasks);
2545
2650
  }
2546
2651
 
2547
- /**
2548
- * Represents the uncertain value
2549
- *
2550
- * @public exported from `@promptbook/core`
2551
- */
2552
- const ZERO_VALUE = $deepFreeze({ value: 0 });
2553
- /**
2554
- * Represents the uncertain value
2555
- *
2556
- * @public exported from `@promptbook/core`
2557
- */
2558
- const UNCERTAIN_ZERO_VALUE = $deepFreeze({ value: 0, isUncertain: true });
2559
- /**
2560
- * Represents the usage with no resources consumed
2561
- *
2562
- * @public exported from `@promptbook/core`
2563
- */
2564
- const ZERO_USAGE = $deepFreeze({
2565
- price: ZERO_VALUE,
2566
- input: {
2567
- tokensCount: ZERO_VALUE,
2568
- charactersCount: ZERO_VALUE,
2569
- wordsCount: ZERO_VALUE,
2570
- sentencesCount: ZERO_VALUE,
2571
- linesCount: ZERO_VALUE,
2572
- paragraphsCount: ZERO_VALUE,
2573
- pagesCount: ZERO_VALUE,
2574
- },
2575
- output: {
2576
- tokensCount: ZERO_VALUE,
2577
- charactersCount: ZERO_VALUE,
2578
- wordsCount: ZERO_VALUE,
2579
- sentencesCount: ZERO_VALUE,
2580
- linesCount: ZERO_VALUE,
2581
- paragraphsCount: ZERO_VALUE,
2582
- pagesCount: ZERO_VALUE,
2583
- },
2584
- });
2585
- /**
2586
- * Represents the usage with unknown resources consumed
2587
- *
2588
- * @public exported from `@promptbook/core`
2589
- */
2590
- $deepFreeze({
2591
- price: UNCERTAIN_ZERO_VALUE,
2592
- input: {
2593
- tokensCount: UNCERTAIN_ZERO_VALUE,
2594
- charactersCount: UNCERTAIN_ZERO_VALUE,
2595
- wordsCount: UNCERTAIN_ZERO_VALUE,
2596
- sentencesCount: UNCERTAIN_ZERO_VALUE,
2597
- linesCount: UNCERTAIN_ZERO_VALUE,
2598
- paragraphsCount: UNCERTAIN_ZERO_VALUE,
2599
- pagesCount: UNCERTAIN_ZERO_VALUE,
2600
- },
2601
- output: {
2602
- tokensCount: UNCERTAIN_ZERO_VALUE,
2603
- charactersCount: UNCERTAIN_ZERO_VALUE,
2604
- wordsCount: UNCERTAIN_ZERO_VALUE,
2605
- sentencesCount: UNCERTAIN_ZERO_VALUE,
2606
- linesCount: UNCERTAIN_ZERO_VALUE,
2607
- paragraphsCount: UNCERTAIN_ZERO_VALUE,
2608
- pagesCount: UNCERTAIN_ZERO_VALUE,
2609
- },
2610
- });
2611
- /**
2612
- * Note: [💞] Ignore a discrepancy between file name and entity name
2613
- */
2614
-
2615
2652
  /**
2616
2653
  * Function `addUsage` will add multiple usages into one
2617
2654
  *
@@ -2671,12 +2708,14 @@ function countUsage(llmTools) {
2671
2708
  const spending = new Subject();
2672
2709
  const proxyTools = {
2673
2710
  get title() {
2674
- // TODO: [🧠] Maybe put here some suffix
2675
- return llmTools.title;
2711
+ return `${llmTools.title} (+usage)`;
2712
+ // <- TODO: [🧈] Maybe standartize the suffix when wrapping `LlmExecutionTools` up
2713
+ // <- TODO: [🧈][🧠] Does it make sence to suffix "(+usage)"?
2676
2714
  },
2677
2715
  get description() {
2678
- // TODO: [🧠] Maybe put here some suffix
2679
- return llmTools.description;
2716
+ return `${llmTools.description} (+usage)`;
2717
+ // <- TODO: [🧈] Maybe standartize the suffix when wrapping `LlmExecutionTools` up
2718
+ // <- TODO: [🧈][🧠] Does it make sence to suffix "(+usage)"?
2680
2719
  },
2681
2720
  checkConfiguration() {
2682
2721
  return /* not await */ llmTools.checkConfiguration();
@@ -2747,29 +2786,40 @@ class MultipleLlmExecutionTools {
2747
2786
  return 'Multiple LLM Providers';
2748
2787
  }
2749
2788
  get description() {
2750
- return this.llmExecutionTools.map(({ title }, index) => `${index + 1}) \`${title}\``).join('\n');
2789
+ const innerModelsTitlesAndDescriptions = this.llmExecutionTools
2790
+ .map(({ title, description }, index) => {
2791
+ const headLine = `${index + 1}) \`${title}\``;
2792
+ if (description === undefined) {
2793
+ return headLine;
2794
+ }
2795
+ return spaceTrim((block) => `
2796
+ ${headLine}
2797
+
2798
+ ${ /* <- Note: Indenting the description: */block(description)}
2799
+ `);
2800
+ })
2801
+ .join('\n\n');
2802
+ return spaceTrim((block) => `
2803
+ Multiple LLM Providers:
2804
+
2805
+ ${block(innerModelsTitlesAndDescriptions)}
2806
+ `);
2751
2807
  }
2752
2808
  /**
2753
2809
  * Check the configuration of all execution tools
2754
2810
  */
2755
2811
  async checkConfiguration() {
2756
- // TODO: Maybe do it in parallel
2757
- for (const llmExecutionTools of this.llmExecutionTools) {
2758
- await llmExecutionTools.checkConfiguration();
2759
- }
2812
+ // Note: Run checks in parallel
2813
+ await Promise.all(this.llmExecutionTools.map((tools) => tools.checkConfiguration()));
2760
2814
  }
2761
2815
  /**
2762
2816
  * List all available models that can be used
2763
2817
  * This lists is a combination of all available models from all execution tools
2764
2818
  */
2765
2819
  async listModels() {
2766
- const availableModels = [];
2767
- for (const llmExecutionTools of this.llmExecutionTools) {
2768
- // TODO: [🪂] Obtain models in parallel
2769
- const models = await llmExecutionTools.listModels();
2770
- availableModels.push(...models);
2771
- }
2772
- return availableModels;
2820
+ // Obtain all models in parallel and flatten
2821
+ const modelArrays = await Promise.all(this.llmExecutionTools.map((tools) => tools.listModels()));
2822
+ return modelArrays.flat();
2773
2823
  }
2774
2824
  /**
2775
2825
  * Calls the best available chat model
@@ -3010,7 +3060,8 @@ async function preparePersona(personaDescription, tools, options) {
3010
3060
  */
3011
3061
 
3012
3062
  /**
3013
- * @@@
3063
+ * Safely retrieves the global scope object (window in browser, global in Node.js)
3064
+ * regardless of the JavaScript environment in which the code is running
3014
3065
  *
3015
3066
  * Note: `$` is used to indicate that this function is not a pure function - it access global scope
3016
3067
  *
@@ -3021,10 +3072,10 @@ function $getGlobalScope() {
3021
3072
  }
3022
3073
 
3023
3074
  /**
3024
- * @@@
3075
+ * Normalizes a text string to SCREAMING_CASE (all uppercase with underscores).
3025
3076
  *
3026
- * @param text @@@
3027
- * @returns @@@
3077
+ * @param text The text string to be converted to SCREAMING_CASE format.
3078
+ * @returns The normalized text in SCREAMING_CASE format.
3028
3079
  * @example 'HELLO_WORLD'
3029
3080
  * @example 'I_LOVE_PROMPTBOOK'
3030
3081
  * @public exported from `@promptbook/utils`
@@ -3076,10 +3127,10 @@ function normalizeTo_SCREAMING_CASE(text) {
3076
3127
  */
3077
3128
 
3078
3129
  /**
3079
- * @@@
3130
+ * Normalizes a text string to snake_case format.
3080
3131
  *
3081
- * @param text @@@
3082
- * @returns @@@
3132
+ * @param text The text string to be converted to snake_case format.
3133
+ * @returns The normalized text in snake_case format.
3083
3134
  * @example 'hello_world'
3084
3135
  * @example 'i_love_promptbook'
3085
3136
  * @public exported from `@promptbook/utils`
@@ -3089,11 +3140,11 @@ function normalizeTo_snake_case(text) {
3089
3140
  }
3090
3141
 
3091
3142
  /**
3092
- * Register is @@@
3143
+ * Global registry for storing and managing registered entities of a given type.
3093
3144
  *
3094
3145
  * Note: `$` is used to indicate that this function is not a pure function - it accesses and adds variables in global scope.
3095
3146
  *
3096
- * @private internal utility, exported are only signleton instances of this class
3147
+ * @private internal utility, exported are only singleton instances of this class
3097
3148
  */
3098
3149
  class $Register {
3099
3150
  constructor(registerName) {
@@ -3137,10 +3188,10 @@ class $Register {
3137
3188
  }
3138
3189
 
3139
3190
  /**
3140
- * @@@
3191
+ * Global registry for storing metadata about all available scrapers and converters.
3141
3192
  *
3142
- * Note: `$` is used to indicate that this interacts with the global scope
3143
- * @singleton Only one instance of each register is created per build, but thare can be more @@@
3193
+ * Note: `$` is used to indicate that this interacts with the global scope.
3194
+ * @singleton Only one instance of each register is created per build, but there can be more in different contexts (e.g., tests).
3144
3195
  * @public exported from `@promptbook/core`
3145
3196
  */
3146
3197
  const $scrapersMetadataRegister = new $Register('scrapers_metadata');
@@ -3149,10 +3200,11 @@ const $scrapersMetadataRegister = new $Register('scrapers_metadata');
3149
3200
  */
3150
3201
 
3151
3202
  /**
3152
- * @@@
3203
+ * Registry for all available scrapers in the system.
3204
+ * Central point for registering and accessing different types of content scrapers.
3153
3205
  *
3154
3206
  * Note: `$` is used to indicate that this interacts with the global scope
3155
- * @singleton Only one instance of each register is created per build, but thare can be more @@@
3207
+ * @singleton Only one instance of each register is created per build, but there can be more than one in different build modules
3156
3208
  * @public exported from `@promptbook/core`
3157
3209
  */
3158
3210
  const $scrapersRegister = new $Register('scraper_constructors');
@@ -3492,10 +3544,10 @@ for (let i = 0; i < defaultDiacriticsRemovalMap.length; i++) {
3492
3544
  */
3493
3545
 
3494
3546
  /**
3495
- * @@@
3547
+ * Removes diacritic marks (accents) from characters in a string.
3496
3548
  *
3497
- * @param input @@@
3498
- * @returns @@@
3549
+ * @param input The string containing diacritics to be normalized.
3550
+ * @returns The string with diacritics removed or normalized.
3499
3551
  * @public exported from `@promptbook/utils`
3500
3552
  */
3501
3553
  function removeDiacritics(input) {
@@ -3509,10 +3561,10 @@ function removeDiacritics(input) {
3509
3561
  */
3510
3562
 
3511
3563
  /**
3512
- * @@@
3564
+ * Converts a given text to kebab-case format.
3513
3565
  *
3514
- * @param text @@@
3515
- * @returns @@@
3566
+ * @param text The text to be converted.
3567
+ * @returns The kebab-case formatted string.
3516
3568
  * @example 'hello-world'
3517
3569
  * @example 'i-love-promptbook'
3518
3570
  * @public exported from `@promptbook/utils`
@@ -3581,7 +3633,8 @@ function knowledgeSourceContentToName(knowledgeSourceContent) {
3581
3633
  */
3582
3634
 
3583
3635
  /**
3584
- * @@@
3636
+ * Converts a name to a properly formatted subfolder path for cache storage.
3637
+ * Handles normalization and path formatting to create consistent cache directory structures.
3585
3638
  *
3586
3639
  * @private for `FileCacheStorage`
3587
3640
  */
@@ -3661,11 +3714,11 @@ function removeEmojis(text) {
3661
3714
  }
3662
3715
 
3663
3716
  /**
3664
- * @@@
3717
+ * Converts a title string into a normalized name.
3665
3718
  *
3666
- * @param value @@@
3667
- * @returns @@@
3668
- * @example @@@
3719
+ * @param value The title string to be converted to a name.
3720
+ * @returns A normalized name derived from the input title.
3721
+ * @example 'Hello World!' -> 'hello-world'
3669
3722
  * @public exported from `@promptbook/utils`
3670
3723
  */
3671
3724
  function titleToName(value) {
@@ -3716,7 +3769,9 @@ const promptbookFetch = async (urlOrRequest, init) => {
3716
3769
  */
3717
3770
 
3718
3771
  /**
3719
- * @@@
3772
+ * Factory function that creates a handler for processing knowledge sources.
3773
+ * Provides standardized processing of different types of knowledge sources
3774
+ * across various scraper implementations.
3720
3775
  *
3721
3776
  * @public exported from `@promptbook/core`
3722
3777
  */
@@ -3855,7 +3910,7 @@ async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
3855
3910
  }
3856
3911
 
3857
3912
  /**
3858
- * Prepares the knowle
3913
+ * Prepares the knowledge pieces
3859
3914
  *
3860
3915
  * @see https://github.com/webgptorg/promptbook/discussions/41
3861
3916
  * @public exported from `@promptbook/core`
@@ -3951,15 +4006,18 @@ TODO: [🧊] This is how it can look in future
3951
4006
  * TODO: [🧊] In future one preparation can take data from previous preparation and save tokens and time
3952
4007
  * Put `knowledgePieces` into `PrepareKnowledgeOptions`
3953
4008
  * TODO: [🪂] More than max things can run in parallel by acident [1,[2a,2b,_],[3a,3b,_]]
3954
- * TODO: [🧠][❎] Do here propper M:N mapping
4009
+ * TODO: [🧠][❎] Do here proper M:N mapping
3955
4010
  * [x] One source can make multiple pieces
3956
4011
  * [ ] One piece can have multiple sources
3957
4012
  */
3958
4013
 
3959
4014
  /**
3960
- * @@@
4015
+ * Prepares tasks by adding knowledge to the prompt and ensuring all necessary parameters are included.
3961
4016
  *
3962
- * @public exported from `@promptbook/core`
4017
+ * @param tasks Sequence of tasks that are chained together to form a pipeline
4018
+ * @returns A promise that resolves to the prepared tasks.
4019
+ *
4020
+ * @private internal utility of `preparePipeline`
3963
4021
  */
3964
4022
  async function prepareTasks(pipeline, tools, options) {
3965
4023
  const { maxParallelCount = DEFAULT_MAX_PARALLEL_COUNT } = options;
@@ -3997,7 +4055,7 @@ async function prepareTasks(pipeline, tools, options) {
3997
4055
  return { tasksPrepared };
3998
4056
  }
3999
4057
  /**
4000
- * TODO: [😂] Adding knowledge should be convert to async high-level abstractions, simmilar thing with expectations to sync high-level abstractions
4058
+ * TODO: [😂] Adding knowledge should be convert to async high-level abstractions, similar thing with expectations to sync high-level abstractions
4001
4059
  * TODO: [🧠] Add context to each task (if missing)
4002
4060
  * TODO: [🧠] What is better name `prepareTask` or `prepareTaskAndParameters`
4003
4061
  * TODO: [♨][main] !!3 Prepare index the examples and maybe tasks
@@ -4133,7 +4191,7 @@ async function preparePipeline(pipeline, tools, options) {
4133
4191
  order: ORDER_OF_PIPELINE_JSON,
4134
4192
  value: {
4135
4193
  ...pipeline,
4136
- // <- TODO: Probbably deeply clone the pipeline because `$exportJson` freezes the subobjects
4194
+ // <- TODO: Probably deeply clone the pipeline because `$exportJson` freezes the subobjects
4137
4195
  title,
4138
4196
  knowledgeSources: knowledgeSourcesPrepared,
4139
4197
  knowledgePieces: knowledgePiecesPrepared,
@@ -4396,7 +4454,7 @@ function union(...sets) {
4396
4454
  }
4397
4455
 
4398
4456
  /**
4399
- * @@@
4457
+ * Contains configuration options for parsing and generating CSV files, such as delimiters and quoting rules.
4400
4458
  *
4401
4459
  * @public exported from `@promptbook/core`
4402
4460
  */
@@ -4405,11 +4463,29 @@ const MANDATORY_CSV_SETTINGS = Object.freeze({
4405
4463
  // encoding: 'utf-8',
4406
4464
  });
4407
4465
 
4466
+ /**
4467
+ * Converts a CSV string into an object
4468
+ *
4469
+ * Note: This is wrapper around `papaparse.parse()` with better autohealing
4470
+ *
4471
+ * @private - for now until `@promptbook/csv` is released
4472
+ */
4473
+ function csvParse(value /* <- TODO: string_csv */, settings, schema /* <- TODO: Make CSV Schemas */) {
4474
+ settings = { ...settings, ...MANDATORY_CSV_SETTINGS };
4475
+ // Note: Autoheal invalid '\n' characters
4476
+ if (settings.newline && !settings.newline.includes('\r') && value.includes('\r')) {
4477
+ console.warn('CSV string contains carriage return characters, but in the CSV settings the `newline` setting does not include them. Autohealing the CSV string.');
4478
+ value = value.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
4479
+ }
4480
+ const csv = parse(value, settings);
4481
+ return csv;
4482
+ }
4483
+
4408
4484
  /**
4409
4485
  * Function to check if a string is valid CSV
4410
4486
  *
4411
4487
  * @param value The string to check
4412
- * @returns True if the string is a valid CSV string, false otherwise
4488
+ * @returns `true` if the string is a valid CSV string, false otherwise
4413
4489
  *
4414
4490
  * @public exported from `@promptbook/utils`
4415
4491
  */
@@ -4433,7 +4509,7 @@ function isValidCsvString(value) {
4433
4509
  * @public exported from `@promptbook/core`
4434
4510
  * <- TODO: [🏢] Export from package `@promptbook/csv`
4435
4511
  */
4436
- const CsvFormatDefinition = {
4512
+ const CsvFormatParser = {
4437
4513
  formatName: 'CSV',
4438
4514
  aliases: ['SPREADSHEET', 'TABLE'],
4439
4515
  isValid(value, settings, schema) {
@@ -4445,12 +4521,12 @@ const CsvFormatDefinition = {
4445
4521
  heal(value, settings, schema) {
4446
4522
  throw new Error('Not implemented');
4447
4523
  },
4448
- subvalueDefinitions: [
4524
+ subvalueParsers: [
4449
4525
  {
4450
4526
  subvalueName: 'ROW',
4451
- async mapValues(value, outputParameterName, settings, mapCallback) {
4452
- // TODO: [👨🏾‍🤝‍👨🏼] DRY csv parsing
4453
- const csv = parse(value, { ...settings, ...MANDATORY_CSV_SETTINGS });
4527
+ async mapValues(options) {
4528
+ const { value, outputParameterName, settings, mapCallback, onProgress } = options;
4529
+ const csv = csvParse(value, settings);
4454
4530
  if (csv.errors.length !== 0) {
4455
4531
  throw new CsvFormatError(spaceTrim((block) => `
4456
4532
  CSV parsing error
@@ -4465,23 +4541,37 @@ const CsvFormatDefinition = {
4465
4541
  ${block(value)}
4466
4542
  `));
4467
4543
  }
4468
- const mappedData = await Promise.all(csv.data.map(async (row, index) => {
4544
+ const mappedData = [];
4545
+ const length = csv.data.length;
4546
+ for (let index = 0; index < length; index++) {
4547
+ const row = csv.data[index];
4469
4548
  if (row[outputParameterName]) {
4470
4549
  throw new CsvFormatError(`Can not overwrite existing column "${outputParameterName}" in CSV row`);
4471
4550
  }
4472
- return {
4551
+ const mappedRow = {
4473
4552
  ...row,
4474
- [outputParameterName]: await mapCallback(row, index),
4553
+ [outputParameterName]: await mapCallback(row, index, length),
4475
4554
  };
4476
- }));
4555
+ mappedData.push(mappedRow);
4556
+ if (onProgress) {
4557
+ // Note: Report the CSV with all rows mapped so far
4558
+ /*
4559
+ // TODO: [🛕] Report progress with all the rows including the pending ones
4560
+ const progressData = mappedData.map((row, i) =>
4561
+ i > index ? { ...row, [outputParameterName]: PENDING_VALUE_PLACEHOLDER } : row,
4562
+ );
4563
+ */
4564
+ await onProgress(unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS }));
4565
+ }
4566
+ }
4477
4567
  return unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
4478
4568
  },
4479
4569
  },
4480
4570
  {
4481
4571
  subvalueName: 'CELL',
4482
- async mapValues(value, outputParameterName, settings, mapCallback) {
4483
- // TODO: [👨🏾‍🤝‍👨🏼] DRY csv parsing
4484
- const csv = parse(value, { ...settings, ...MANDATORY_CSV_SETTINGS });
4572
+ async mapValues(options) {
4573
+ const { value, settings, mapCallback, onProgress } = options;
4574
+ const csv = csvParse(value, settings);
4485
4575
  if (csv.errors.length !== 0) {
4486
4576
  throw new CsvFormatError(spaceTrim((block) => `
4487
4577
  CSV parsing error
@@ -4497,9 +4587,9 @@ const CsvFormatDefinition = {
4497
4587
  `));
4498
4588
  }
4499
4589
  const mappedData = await Promise.all(csv.data.map(async (row, rowIndex) => {
4500
- return /* not await */ Promise.all(Object.entries(row).map(async ([key, value], columnIndex) => {
4590
+ return /* not await */ Promise.all(Object.entries(row).map(async ([key, value], columnIndex, array) => {
4501
4591
  const index = rowIndex * Object.keys(row).length + columnIndex;
4502
- return /* not await */ mapCallback({ [key]: value }, index);
4592
+ return /* not await */ mapCallback({ [key]: value }, index, array.length);
4503
4593
  }));
4504
4594
  }));
4505
4595
  return unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
@@ -4508,10 +4598,10 @@ const CsvFormatDefinition = {
4508
4598
  ],
4509
4599
  };
4510
4600
  /**
4511
- * TODO: [🍓] In `CsvFormatDefinition` implement simple `isValid`
4512
- * TODO: [🍓] In `CsvFormatDefinition` implement partial `canBeValid`
4513
- * TODO: [🍓] In `CsvFormatDefinition` implement `heal
4514
- * TODO: [🍓] In `CsvFormatDefinition` implement `subvalueDefinitions`
4601
+ * TODO: [🍓] In `CsvFormatParser` implement simple `isValid`
4602
+ * TODO: [🍓] In `CsvFormatParser` implement partial `canBeValid`
4603
+ * TODO: [🍓] In `CsvFormatParser` implement `heal
4604
+ * TODO: [🍓] In `CsvFormatParser` implement `subvalueParsers`
4515
4605
  * TODO: [🏢] Allow to expect something inside CSV objects and other formats
4516
4606
  */
4517
4607
 
@@ -4520,7 +4610,7 @@ const CsvFormatDefinition = {
4520
4610
  *
4521
4611
  * @private still in development [🏢]
4522
4612
  */
4523
- const JsonFormatDefinition = {
4613
+ const JsonFormatParser = {
4524
4614
  formatName: 'JSON',
4525
4615
  mimeType: 'application/json',
4526
4616
  isValid(value, settings, schema) {
@@ -4532,28 +4622,28 @@ const JsonFormatDefinition = {
4532
4622
  heal(value, settings, schema) {
4533
4623
  throw new Error('Not implemented');
4534
4624
  },
4535
- subvalueDefinitions: [],
4625
+ subvalueParsers: [],
4536
4626
  };
4537
4627
  /**
4538
- * TODO: [🧠] Maybe propper instance of object
4628
+ * TODO: [🧠] Maybe proper instance of object
4539
4629
  * TODO: [0] Make string_serialized_json
4540
4630
  * TODO: [1] Make type for JSON Settings and Schema
4541
4631
  * TODO: [🧠] What to use for validating JSONs - JSON Schema, ZoD, typescript types/interfaces,...?
4542
- * TODO: [🍓] In `JsonFormatDefinition` implement simple `isValid`
4543
- * TODO: [🍓] In `JsonFormatDefinition` implement partial `canBeValid`
4544
- * TODO: [🍓] In `JsonFormatDefinition` implement `heal
4545
- * TODO: [🍓] In `JsonFormatDefinition` implement `subvalueDefinitions`
4632
+ * TODO: [🍓] In `JsonFormatParser` implement simple `isValid`
4633
+ * TODO: [🍓] In `JsonFormatParser` implement partial `canBeValid`
4634
+ * TODO: [🍓] In `JsonFormatParser` implement `heal
4635
+ * TODO: [🍓] In `JsonFormatParser` implement `subvalueParsers`
4546
4636
  * TODO: [🏢] Allow to expect something inside JSON objects and other formats
4547
4637
  */
4548
4638
 
4549
4639
  /**
4550
4640
  * Definition for any text - this will be always valid
4551
4641
  *
4552
- * Note: This is not useful for validation, but for splitting and mapping with `subvalueDefinitions`
4642
+ * Note: This is not useful for validation, but for splitting and mapping with `subvalueParsers`
4553
4643
  *
4554
4644
  * @public exported from `@promptbook/core`
4555
4645
  */
4556
- const TextFormatDefinition = {
4646
+ const TextFormatParser = {
4557
4647
  formatName: 'TEXT',
4558
4648
  isValid(value) {
4559
4649
  return typeof value === 'string';
@@ -4562,19 +4652,20 @@ const TextFormatDefinition = {
4562
4652
  return typeof partialValue === 'string';
4563
4653
  },
4564
4654
  heal() {
4565
- throw new UnexpectedError('It does not make sense to call `TextFormatDefinition.heal`');
4655
+ throw new UnexpectedError('It does not make sense to call `TextFormatParser.heal`');
4566
4656
  },
4567
- subvalueDefinitions: [
4657
+ subvalueParsers: [
4568
4658
  {
4569
4659
  subvalueName: 'LINE',
4570
- async mapValues(value, outputParameterName, settings, mapCallback) {
4660
+ async mapValues(options) {
4661
+ const { value, mapCallback, onProgress } = options;
4571
4662
  const lines = value.split('\n');
4572
- const mappedLines = await Promise.all(lines.map((lineContent, lineNumber) =>
4663
+ const mappedLines = await Promise.all(lines.map((lineContent, lineNumber, array) =>
4573
4664
  // TODO: [🧠] Maybe option to skip empty line
4574
4665
  /* not await */ mapCallback({
4575
4666
  lineContent,
4576
4667
  // TODO: [🧠] Maybe also put here `lineNumber`
4577
- }, lineNumber)));
4668
+ }, lineNumber, array.length)));
4578
4669
  return mappedLines.join('\n');
4579
4670
  },
4580
4671
  },
@@ -4584,10 +4675,10 @@ const TextFormatDefinition = {
4584
4675
  /**
4585
4676
  * TODO: [1] Make type for XML Text and Schema
4586
4677
  * TODO: [🧠][🤠] Here should be all words, characters, lines, paragraphs, pages available as subvalues
4587
- * TODO: [🍓] In `TextFormatDefinition` implement simple `isValid`
4588
- * TODO: [🍓] In `TextFormatDefinition` implement partial `canBeValid`
4589
- * TODO: [🍓] In `TextFormatDefinition` implement `heal
4590
- * TODO: [🍓] In `TextFormatDefinition` implement `subvalueDefinitions`
4678
+ * TODO: [🍓] In `TextFormatParser` implement simple `isValid`
4679
+ * TODO: [🍓] In `TextFormatParser` implement partial `canBeValid`
4680
+ * TODO: [🍓] In `TextFormatParser` implement `heal
4681
+ * TODO: [🍓] In `TextFormatParser` implement `subvalueParsers`
4591
4682
  * TODO: [🏢] Allow to expect something inside each item of list and other formats
4592
4683
  */
4593
4684
 
@@ -4595,7 +4686,7 @@ const TextFormatDefinition = {
4595
4686
  * Function to check if a string is valid XML
4596
4687
  *
4597
4688
  * @param value
4598
- * @returns True if the string is a valid XML string, false otherwise
4689
+ * @returns `true` if the string is a valid XML string, false otherwise
4599
4690
  *
4600
4691
  * @public exported from `@promptbook/utils`
4601
4692
  */
@@ -4620,7 +4711,7 @@ function isValidXmlString(value) {
4620
4711
  *
4621
4712
  * @private still in development [🏢]
4622
4713
  */
4623
- const XmlFormatDefinition = {
4714
+ const XmlFormatParser = {
4624
4715
  formatName: 'XML',
4625
4716
  mimeType: 'application/xml',
4626
4717
  isValid(value, settings, schema) {
@@ -4632,17 +4723,17 @@ const XmlFormatDefinition = {
4632
4723
  heal(value, settings, schema) {
4633
4724
  throw new Error('Not implemented');
4634
4725
  },
4635
- subvalueDefinitions: [],
4726
+ subvalueParsers: [],
4636
4727
  };
4637
4728
  /**
4638
- * TODO: [🧠] Maybe propper instance of object
4729
+ * TODO: [🧠] Maybe proper instance of object
4639
4730
  * TODO: [0] Make string_serialized_xml
4640
4731
  * TODO: [1] Make type for XML Settings and Schema
4641
4732
  * TODO: [🧠] What to use for validating XMLs - XSD,...
4642
- * TODO: [🍓] In `XmlFormatDefinition` implement simple `isValid`
4643
- * TODO: [🍓] In `XmlFormatDefinition` implement partial `canBeValid`
4644
- * TODO: [🍓] In `XmlFormatDefinition` implement `heal
4645
- * TODO: [🍓] In `XmlFormatDefinition` implement `subvalueDefinitions`
4733
+ * TODO: [🍓] In `XmlFormatParser` implement simple `isValid`
4734
+ * TODO: [🍓] In `XmlFormatParser` implement partial `canBeValid`
4735
+ * TODO: [🍓] In `XmlFormatParser` implement `heal
4736
+ * TODO: [🍓] In `XmlFormatParser` implement `subvalueParsers`
4646
4737
  * TODO: [🏢] Allow to expect something inside XML and other formats
4647
4738
  */
4648
4739
 
@@ -4651,24 +4742,19 @@ const XmlFormatDefinition = {
4651
4742
  *
4652
4743
  * @private internal index of `...` <- TODO [🏢]
4653
4744
  */
4654
- const FORMAT_DEFINITIONS = [
4655
- JsonFormatDefinition,
4656
- XmlFormatDefinition,
4657
- TextFormatDefinition,
4658
- CsvFormatDefinition,
4659
- ];
4745
+ const FORMAT_DEFINITIONS = [JsonFormatParser, XmlFormatParser, TextFormatParser, CsvFormatParser];
4660
4746
  /**
4661
4747
  * Note: [💞] Ignore a discrepancy between file name and entity name
4662
4748
  */
4663
4749
 
4664
4750
  /**
4665
- * Maps available parameters to expected parameters
4751
+ * Maps available parameters to expected parameters for a pipeline task.
4666
4752
  *
4667
4753
  * The strategy is:
4668
- * 1) @@@
4669
- * 2) @@@
4754
+ * 1) First, match parameters by name where both available and expected.
4755
+ * 2) Then, if there are unmatched expected and available parameters, map them by order.
4670
4756
  *
4671
- * @throws {PipelineExecutionError} @@@
4757
+ * @throws {PipelineExecutionError} If the number of unmatched expected and available parameters does not match, or mapping is ambiguous.
4672
4758
  * @private within the repository used in `createPipelineExecutor`
4673
4759
  */
4674
4760
  function mapAvailableToExpectedParameters(options) {
@@ -4691,7 +4777,7 @@ function mapAvailableToExpectedParameters(options) {
4691
4777
  else if (!availableParametersNames.has(parameterName) && expectedParameterNames.has(parameterName)) ;
4692
4778
  }
4693
4779
  if (expectedParameterNames.size === 0) {
4694
- // Note: [👨‍👨‍👧] Now we can freeze `mappedParameters` to prevent @@@
4780
+ // Note: [👨‍👨‍👧] Now we can freeze `mappedParameters` to prevent accidental modifications after mapping
4695
4781
  Object.freeze(mappedParameters);
4696
4782
  return mappedParameters;
4697
4783
  }
@@ -4722,7 +4808,7 @@ function mapAvailableToExpectedParameters(options) {
4722
4808
  for (let i = 0; i < expectedParameterNames.size; i++) {
4723
4809
  mappedParameters[expectedParameterNamesArray[i]] = availableParameters[availableParametersNamesArray[i]];
4724
4810
  }
4725
- // Note: [👨‍👨‍👧] Now we can freeze `mappedParameters` to prevent @@@
4811
+ // Note: [👨‍👨‍👧] Now we can freeze `mappedParameters` to prevent accidental modifications after mapping
4726
4812
  Object.freeze(mappedParameters);
4727
4813
  return mappedParameters;
4728
4814
  }
@@ -4730,8 +4816,8 @@ function mapAvailableToExpectedParameters(options) {
4730
4816
  /**
4731
4817
  * Extracts all code blocks from markdown.
4732
4818
  *
4733
- * Note: There are multiple simmilar function:
4734
- * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
4819
+ * Note: There are multiple similar functions:
4820
+ * - `extractBlock` just extracts the content of the code block which is also used as built-in function for postprocessing
4735
4821
  * - `extractJsonBlock` extracts exactly one valid JSON code block
4736
4822
  * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
4737
4823
  * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
@@ -4781,7 +4867,7 @@ function extractAllBlocksFromMarkdown(markdown) {
4781
4867
  if (currentCodeBlock.content !== '') {
4782
4868
  currentCodeBlock.content += '\n';
4783
4869
  }
4784
- currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make propper unescape */;
4870
+ currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make proper unescape */;
4785
4871
  }
4786
4872
  }
4787
4873
  if (currentCodeBlock !== null) {
@@ -4801,7 +4887,7 @@ function extractAllBlocksFromMarkdown(markdown) {
4801
4887
  * - When there are multiple JSON code blocks the function throws a `ParseError`
4802
4888
  *
4803
4889
  * Note: It is not important if marked as ```json BUT if it is VALID JSON
4804
- * Note: There are multiple simmilar function:
4890
+ * Note: There are multiple similar function:
4805
4891
  * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
4806
4892
  * - `extractJsonBlock` extracts exactly one valid JSON code block
4807
4893
  * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
@@ -4826,14 +4912,14 @@ function extractJsonBlock(markdown) {
4826
4912
  }
4827
4913
  /**
4828
4914
  * TODO: Add some auto-healing logic + extract YAML, JSON5, TOML, etc.
4829
- * TODO: [🏢] Make this logic part of `JsonFormatDefinition` or `isValidJsonString`
4915
+ * TODO: [🏢] Make this logic part of `JsonFormatParser` or `isValidJsonString`
4830
4916
  */
4831
4917
 
4832
4918
  /**
4833
4919
  * Just says that the variable is not used but should be kept
4834
4920
  * No side effects.
4835
4921
  *
4836
- * Note: It can be usefull for:
4922
+ * Note: It can be useful for:
4837
4923
  *
4838
4924
  * 1) Suppressing eager optimization of unused imports
4839
4925
  * 2) Suppressing eslint errors of unused variables in the tests
@@ -5045,14 +5131,14 @@ const CountUtils = {
5045
5131
  PAGES: countPages,
5046
5132
  };
5047
5133
  /**
5048
- * TODO: [🧠][🤠] This should be probbably as part of `TextFormatDefinition`
5134
+ * TODO: [🧠][🤠] This should be probably as part of `TextFormatParser`
5049
5135
  * Note: [💞] Ignore a discrepancy between file name and entity name
5050
5136
  */
5051
5137
 
5052
5138
  /**
5053
5139
  * Function checkExpectations will check if the expectations on given value are met
5054
5140
  *
5055
- * Note: There are two simmilar functions:
5141
+ * Note: There are two similar functions:
5056
5142
  * - `checkExpectations` which throws an error if the expectations are not met
5057
5143
  * - `isPassingExpectations` which returns a boolean
5058
5144
  *
@@ -5073,13 +5159,17 @@ function checkExpectations(expectations, value) {
5073
5159
  }
5074
5160
  /**
5075
5161
  * TODO: [💝] Unite object for expecting amount and format
5076
- * TODO: [🧠][🤠] This should be part of `TextFormatDefinition`
5162
+ * TODO: [🧠][🤠] This should be part of `TextFormatParser`
5077
5163
  * Note: [💝] and [🤠] are interconnected together
5078
5164
  */
5079
5165
 
5080
5166
  /**
5081
- * @@@
5167
+ * Executes a pipeline task with multiple attempts, including joker and retry logic. Handles different task types
5168
+ * (prompt, script, dialog, etc.), applies postprocessing, checks expectations, and updates the execution report.
5169
+ * Throws errors if execution fails after all attempts.
5082
5170
  *
5171
+ * @param options - The options for execution, including task, parameters, pipeline, and configuration.
5172
+ * @returns The result string of the executed task.
5083
5173
  * @private internal utility of `createPipelineExecutor`
5084
5174
  */
5085
5175
  async function executeAttempts(options) {
@@ -5301,7 +5391,7 @@ async function executeAttempts(options) {
5301
5391
  if (task.format) {
5302
5392
  if (task.format === 'JSON') {
5303
5393
  if (!isValidJsonString($ongoingTaskResult.$resultString || '')) {
5304
- // TODO: [🏢] Do more universally via `FormatDefinition`
5394
+ // TODO: [🏢] Do more universally via `FormatParser`
5305
5395
  try {
5306
5396
  $ongoingTaskResult.$resultString = extractJsonBlock($ongoingTaskResult.$resultString || '');
5307
5397
  }
@@ -5403,12 +5493,16 @@ async function executeAttempts(options) {
5403
5493
  */
5404
5494
 
5405
5495
  /**
5406
- * @@@
5496
+ * Executes a pipeline task that requires mapping or iterating over subvalues of a parameter (such as rows in a CSV).
5497
+ * Handles format and subformat resolution, error handling, and progress reporting.
5498
+ *
5499
+ * @param options - Options for execution, including task details and progress callback.
5500
+ * @returns The result of the subvalue mapping or execution attempts.
5407
5501
  *
5408
5502
  * @private internal utility of `createPipelineExecutor`
5409
5503
  */
5410
5504
  async function executeFormatSubvalues(options) {
5411
- const { task, jokerParameterNames, parameters, priority, csvSettings, pipelineIdentification } = options;
5505
+ const { task, jokerParameterNames, parameters, priority, csvSettings, onProgress, pipelineIdentification } = options;
5412
5506
  if (task.foreach === undefined) {
5413
5507
  return /* not await */ executeAttempts(options);
5414
5508
  }
@@ -5439,16 +5533,16 @@ async function executeFormatSubvalues(options) {
5439
5533
  ${block(pipelineIdentification)}
5440
5534
  `));
5441
5535
  }
5442
- const subvalueDefinition = formatDefinition.subvalueDefinitions.find((subvalueDefinition) => [subvalueDefinition.subvalueName, ...(subvalueDefinition.aliases || [])].includes(task.foreach.subformatName));
5443
- if (subvalueDefinition === undefined) {
5536
+ const subvalueParser = formatDefinition.subvalueParsers.find((subvalueParser) => [subvalueParser.subvalueName, ...(subvalueParser.aliases || [])].includes(task.foreach.subformatName));
5537
+ if (subvalueParser === undefined) {
5444
5538
  throw new UnexpectedError(
5445
5539
  // <- TODO: [🧠][🧐] Should be formats fixed per promptbook version or behave as plugins (=> change UnexpectedError)
5446
5540
  spaceTrim((block) => `
5447
5541
  Unsupported subformat name "${task.foreach.subformatName}" for format "${task.foreach.formatName}"
5448
5542
 
5449
5543
  Available subformat names for format "${formatDefinition.formatName}":
5450
- ${block(formatDefinition.subvalueDefinitions
5451
- .map((subvalueDefinition) => subvalueDefinition.subvalueName)
5544
+ ${block(formatDefinition.subvalueParsers
5545
+ .map((subvalueParser) => subvalueParser.subvalueName)
5452
5546
  .map((subvalueName) => `- ${subvalueName}`)
5453
5547
  .join('\n'))}
5454
5548
 
@@ -5460,55 +5554,85 @@ async function executeFormatSubvalues(options) {
5460
5554
  let formatSettings;
5461
5555
  if (formatDefinition.formatName === 'CSV') {
5462
5556
  formatSettings = csvSettings;
5463
- // <- TODO: [🤹‍♂️] More universal, make simmilar pattern for other formats for example \n vs \r\n in text
5464
- }
5465
- const resultString = await subvalueDefinition.mapValues(parameterValue, task.foreach.outputSubparameterName, formatSettings, async (subparameters, index) => {
5466
- let mappedParameters;
5467
- // TODO: [🤹‍♂️][🪂] Limit to N concurrent executions
5468
- // TODO: When done [🐚] Report progress also for each subvalue here
5469
- try {
5470
- mappedParameters = mapAvailableToExpectedParameters({
5471
- expectedParameters: Object.fromEntries(task.foreach.inputSubparameterNames.map((subparameterName) => [subparameterName, null])),
5472
- availableParameters: subparameters,
5473
- });
5474
- }
5475
- catch (error) {
5476
- if (!(error instanceof PipelineExecutionError)) {
5477
- throw error;
5557
+ // <- TODO: [🤹‍♂️] More universal, make similar pattern for other formats for example \n vs \r\n in text
5558
+ }
5559
+ const resultString = await subvalueParser.mapValues({
5560
+ value: parameterValue,
5561
+ outputParameterName: task.foreach.outputSubparameterName,
5562
+ settings: formatSettings,
5563
+ onProgress(partialResultString) {
5564
+ return onProgress(Object.freeze({
5565
+ [task.resultingParameterName]: partialResultString,
5566
+ }));
5567
+ },
5568
+ async mapCallback(subparameters, index, length) {
5569
+ let mappedParameters;
5570
+ try {
5571
+ mappedParameters = mapAvailableToExpectedParameters({
5572
+ expectedParameters: Object.fromEntries(task.foreach.inputSubparameterNames.map((subparameterName) => [subparameterName, null])),
5573
+ availableParameters: subparameters,
5574
+ });
5478
5575
  }
5479
- throw new PipelineExecutionError(spaceTrim((block) => `
5480
- ${error.message}
5576
+ catch (error) {
5577
+ if (!(error instanceof PipelineExecutionError)) {
5578
+ throw error;
5579
+ }
5580
+ const highLevelError = new PipelineExecutionError(spaceTrim((block) => `
5581
+ ${error.message}
5481
5582
 
5482
- This is error in FOREACH command
5483
- You have probbably passed wrong data to pipeline or wrong data was generated which are processed by FOREACH command
5583
+ This is error in FOREACH command when mapping ${formatDefinition.formatName} ${subvalueParser.subvalueName} data (${index + 1}/${length})
5584
+ You have probably passed wrong data to pipeline or wrong data was generated which are processed by FOREACH command
5484
5585
 
5485
- ${block(pipelineIdentification)}
5486
- Subparameter index: ${index}
5487
- `));
5488
- }
5489
- const allSubparameters = {
5490
- ...parameters,
5491
- ...mappedParameters,
5492
- };
5493
- // 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
5494
- Object.freeze(allSubparameters);
5495
- const subresultString = await executeAttempts({
5496
- ...options,
5497
- priority: priority + index,
5498
- parameters: allSubparameters,
5499
- pipelineIdentification: spaceTrim((block) => `
5500
- ${block(pipelineIdentification)}
5501
- Subparameter index: ${index}
5502
- `),
5503
- });
5504
- return subresultString;
5586
+ ${block(pipelineIdentification)}
5587
+ `));
5588
+ if (length > BIG_DATASET_TRESHOLD) {
5589
+ console.error(highLevelError);
5590
+ return FAILED_VALUE_PLACEHOLDER;
5591
+ }
5592
+ throw highLevelError;
5593
+ }
5594
+ const allSubparameters = {
5595
+ ...parameters,
5596
+ ...mappedParameters,
5597
+ };
5598
+ Object.freeze(allSubparameters);
5599
+ try {
5600
+ const subresultString = await executeAttempts({
5601
+ ...options,
5602
+ priority: priority + index,
5603
+ parameters: allSubparameters,
5604
+ pipelineIdentification: spaceTrim((block) => `
5605
+ ${block(pipelineIdentification)}
5606
+ Subparameter index: ${index}
5607
+ `),
5608
+ });
5609
+ return subresultString;
5610
+ }
5611
+ catch (error) {
5612
+ if (length > BIG_DATASET_TRESHOLD) {
5613
+ console.error(spaceTrim((block) => `
5614
+ ${error.message}
5615
+
5616
+ This is error in FOREACH command when processing ${formatDefinition.formatName} ${subvalueParser.subvalueName} data (${index + 1}/${length})
5617
+
5618
+ ${block(pipelineIdentification)}
5619
+ `));
5620
+ return FAILED_VALUE_PLACEHOLDER;
5621
+ }
5622
+ throw error;
5623
+ }
5624
+ },
5505
5625
  });
5506
5626
  return resultString;
5507
5627
  }
5508
5628
 
5509
5629
  /**
5510
- * @@@
5630
+ * Returns the context for a given task, typically used to provide additional information or variables
5631
+ * required for the execution of the task within a pipeline. The context is returned as a string value
5632
+ * that may include markdown formatting.
5511
5633
  *
5634
+ * @param task - The task for which the context is being generated. This should be a deeply immutable TaskJson object.
5635
+ * @returns The context as a string, formatted as markdown and parameter value.
5512
5636
  * @private internal utility of `createPipelineExecutor`
5513
5637
  */
5514
5638
  async function getContextForTask(task) {
@@ -5516,7 +5640,7 @@ async function getContextForTask(task) {
5516
5640
  }
5517
5641
 
5518
5642
  /**
5519
- * @@@
5643
+ * Retrieves example values or templates for a given task, used to guide or validate pipeline execution.
5520
5644
  *
5521
5645
  * @private internal utility of `createPipelineExecutor`
5522
5646
  */
@@ -5525,91 +5649,128 @@ async function getExamplesForTask(task) {
5525
5649
  }
5526
5650
 
5527
5651
  /**
5528
- * @@@
5652
+ * Computes the cosine similarity between two embedding vectors
5653
+ *
5654
+ * Note: This is helping function for RAG (retrieval-augmented generation)
5529
5655
  *
5530
- * Here is the place where RAG (retrieval-augmented generation) happens
5656
+ * @param embeddingVector1
5657
+ * @param embeddingVector2
5658
+ * @returns Cosine similarity between the two vectors
5659
+ *
5660
+ * @public exported from `@promptbook/core`
5661
+ */
5662
+ function computeCosineSimilarity(embeddingVector1, embeddingVector2) {
5663
+ if (embeddingVector1.length !== embeddingVector2.length) {
5664
+ throw new TypeError('Embedding vectors must have the same length');
5665
+ }
5666
+ const dotProduct = embeddingVector1.reduce((sum, value, index) => sum + value * embeddingVector2[index], 0);
5667
+ const magnitude1 = Math.sqrt(embeddingVector1.reduce((sum, value) => sum + value * value, 0));
5668
+ const magnitude2 = Math.sqrt(embeddingVector2.reduce((sum, value) => sum + value * value, 0));
5669
+ return 1 - dotProduct / (magnitude1 * magnitude2);
5670
+ }
5671
+
5672
+ /**
5673
+ *
5674
+ * @param knowledgePieces
5675
+ * @returns
5676
+ *
5677
+ * @private internal utility of `createPipelineExecutor`
5678
+ */
5679
+ function knowledgePiecesToString(knowledgePieces) {
5680
+ return knowledgePieces
5681
+ .map((knowledgePiece) => {
5682
+ const { content } = knowledgePiece;
5683
+ return `- ${content}`;
5684
+ })
5685
+ .join('\n');
5686
+ // <- TODO: [🧠] Some smarter aggregation of knowledge pieces, single-line vs multi-line vs mixed
5687
+ }
5688
+
5689
+ /**
5690
+ * Retrieves the most relevant knowledge pieces for a given task using embedding-based similarity search.
5691
+ * This is where retrieval-augmented generation (RAG) is performed to enhance the task with external knowledge.
5531
5692
  *
5532
5693
  * @private internal utility of `createPipelineExecutor`
5533
5694
  */
5534
5695
  async function getKnowledgeForTask(options) {
5535
- const { tools, preparedPipeline, task } = options;
5696
+ const { tools, preparedPipeline, task, parameters } = options;
5536
5697
  const firstKnowlegePiece = preparedPipeline.knowledgePieces[0];
5537
5698
  const firstKnowlegeIndex = firstKnowlegePiece === null || firstKnowlegePiece === void 0 ? void 0 : firstKnowlegePiece.index[0];
5538
5699
  // <- TODO: Do not use just first knowledge piece and first index to determine embedding model, use also keyword search
5539
5700
  if (firstKnowlegePiece === undefined || firstKnowlegeIndex === undefined) {
5540
- return 'No knowledge pieces found';
5701
+ return ''; // <- Note: Np knowledge present, return empty string
5541
5702
  }
5542
- // TODO: [🚐] Make arrayable LLMs -> single LLM DRY
5543
- const _llms = arrayableToArray(tools.llm);
5544
- const llmTools = _llms.length === 1 ? _llms[0] : joinLlmExecutionTools(..._llms);
5545
- const taskEmbeddingPrompt = {
5546
- title: 'Knowledge Search',
5547
- modelRequirements: {
5548
- modelVariant: 'EMBEDDING',
5549
- modelName: firstKnowlegeIndex.modelName,
5550
- },
5551
- content: task.content,
5552
- parameters: {
5553
- /* !!!!!!!! */
5554
- },
5555
- };
5556
- const taskEmbeddingResult = await llmTools.callEmbeddingModel(taskEmbeddingPrompt);
5557
- const knowledgePiecesWithRelevance = preparedPipeline.knowledgePieces.map((knowledgePiece) => {
5558
- const { index } = knowledgePiece;
5559
- const knowledgePieceIndex = index.find((i) => i.modelName === firstKnowlegeIndex.modelName);
5560
- // <- TODO: Do not use just first knowledge piece and first index to determine embedding model
5561
- if (knowledgePieceIndex === undefined) {
5703
+ try {
5704
+ // TODO: [🚐] Make arrayable LLMs -> single LLM DRY
5705
+ const _llms = arrayableToArray(tools.llm);
5706
+ const llmTools = _llms.length === 1 ? _llms[0] : joinLlmExecutionTools(..._llms);
5707
+ const taskEmbeddingPrompt = {
5708
+ title: 'Knowledge Search',
5709
+ modelRequirements: {
5710
+ modelVariant: 'EMBEDDING',
5711
+ modelName: firstKnowlegeIndex.modelName,
5712
+ },
5713
+ content: task.content,
5714
+ parameters,
5715
+ };
5716
+ const taskEmbeddingResult = await llmTools.callEmbeddingModel(taskEmbeddingPrompt);
5717
+ const knowledgePiecesWithRelevance = preparedPipeline.knowledgePieces.map((knowledgePiece) => {
5718
+ const { index } = knowledgePiece;
5719
+ const knowledgePieceIndex = index.find((i) => i.modelName === firstKnowlegeIndex.modelName);
5720
+ // <- TODO: Do not use just first knowledge piece and first index to determine embedding model
5721
+ if (knowledgePieceIndex === undefined) {
5722
+ return {
5723
+ content: knowledgePiece.content,
5724
+ relevance: 0,
5725
+ };
5726
+ }
5727
+ const relevance = computeCosineSimilarity(knowledgePieceIndex.position, taskEmbeddingResult.content);
5562
5728
  return {
5563
5729
  content: knowledgePiece.content,
5564
- relevance: 0,
5730
+ relevance,
5565
5731
  };
5566
- }
5567
- const relevance = computeCosineSimilarity(knowledgePieceIndex.position, taskEmbeddingResult.content);
5568
- return {
5569
- content: knowledgePiece.content,
5570
- relevance,
5571
- };
5572
- });
5573
- const knowledgePiecesSorted = knowledgePiecesWithRelevance.sort((a, b) => a.relevance - b.relevance);
5574
- const knowledgePiecesLimited = knowledgePiecesSorted.slice(0, 5);
5575
- console.log('!!! Embedding', {
5576
- task,
5577
- taskEmbeddingPrompt,
5578
- taskEmbeddingResult,
5579
- firstKnowlegePiece,
5580
- firstKnowlegeIndex,
5581
- knowledgePiecesWithRelevance,
5582
- knowledgePiecesSorted,
5583
- knowledgePiecesLimited,
5584
- });
5585
- return knowledgePiecesLimited.map(({ content }) => `- ${content}`).join('\n');
5586
- // <- TODO: [🧠] Some smart aggregation of knowledge pieces, single-line vs multi-line vs mixed
5587
- }
5588
- // TODO: !!!!!! Annotate + to new file
5589
- function computeCosineSimilarity(embeddingVector1, embeddingVector2) {
5590
- if (embeddingVector1.length !== embeddingVector2.length) {
5591
- throw new TypeError('Embedding vectors must have the same length');
5732
+ });
5733
+ const knowledgePiecesSorted = knowledgePiecesWithRelevance.sort((a, b) => a.relevance - b.relevance);
5734
+ const knowledgePiecesLimited = knowledgePiecesSorted.slice(0, 5);
5735
+ /*
5736
+ console.log('`getKnowledgeForTask` Embedding', {
5737
+ task,
5738
+ taskEmbeddingPrompt,
5739
+ taskEmbeddingResult,
5740
+ firstKnowlegePiece,
5741
+ firstKnowlegeIndex,
5742
+ knowledgePiecesWithRelevance,
5743
+ knowledgePiecesSorted,
5744
+ knowledgePiecesLimited,
5745
+ });
5746
+ */
5747
+ return knowledgePiecesToString(knowledgePiecesLimited);
5748
+ }
5749
+ catch (error) {
5750
+ assertsError(error);
5751
+ console.error('Error in `getKnowledgeForTask`', error);
5752
+ // Note: If the LLM fails, just return all knowledge pieces
5753
+ return knowledgePiecesToString(preparedPipeline.knowledgePieces);
5592
5754
  }
5593
- const dotProduct = embeddingVector1.reduce((sum, value, index) => sum + value * embeddingVector2[index], 0);
5594
- const magnitude1 = Math.sqrt(embeddingVector1.reduce((sum, value) => sum + value * value, 0));
5595
- const magnitude2 = Math.sqrt(embeddingVector2.reduce((sum, value) => sum + value * value, 0));
5596
- return 1 - dotProduct / (magnitude1 * magnitude2);
5597
5755
  }
5598
5756
  /**
5599
- * TODO: !!!! Verify if this is working
5600
5757
  * TODO: [♨] Implement Better - use keyword search
5601
5758
  * TODO: [♨] Examples of values
5602
5759
  */
5603
5760
 
5604
5761
  /**
5605
- * @@@
5762
+ * Retrieves all reserved parameters for a given pipeline task, including context, knowledge, examples, and metadata.
5763
+ * Ensures all reserved parameters are defined and throws if any are missing.
5764
+ *
5765
+ * @param options - Options including tools, pipeline, task, and context.
5766
+ * @returns An object containing all reserved parameters for the task.
5606
5767
  *
5607
5768
  * @private internal utility of `createPipelineExecutor`
5608
5769
  */
5609
5770
  async function getReservedParametersForTask(options) {
5610
- const { tools, preparedPipeline, task, pipelineIdentification } = options;
5771
+ const { tools, preparedPipeline, task, parameters, pipelineIdentification, isVerbose } = options;
5611
5772
  const context = await getContextForTask(); // <- [🏍]
5612
- const knowledge = await getKnowledgeForTask({ tools, preparedPipeline, task });
5773
+ const knowledge = await getKnowledgeForTask({ tools, preparedPipeline, task, parameters });
5613
5774
  const examples = await getExamplesForTask();
5614
5775
  const currentDate = new Date().toISOString(); // <- TODO: [🧠][💩] Better
5615
5776
  const modelName = RESERVED_PARAMETER_MISSING_VALUE;
@@ -5621,6 +5782,9 @@ async function getReservedParametersForTask(options) {
5621
5782
  currentDate,
5622
5783
  modelName,
5623
5784
  };
5785
+ if (isVerbose) {
5786
+ console.info('Reserved parameters for task:', { options, reservedParameters });
5787
+ }
5624
5788
  // Note: Doublecheck that ALL reserved parameters are defined:
5625
5789
  for (const parameterName of RESERVED_PARAMETER_NAMES) {
5626
5790
  if (reservedParameters[parameterName] === undefined) {
@@ -5635,23 +5799,21 @@ async function getReservedParametersForTask(options) {
5635
5799
  }
5636
5800
 
5637
5801
  /**
5638
- * @@@
5802
+ * Executes a single task within a pipeline, handling parameter validation, error checking, and progress reporting.
5803
+ *
5804
+ * @param options - Options for execution, including the task, pipeline, parameters, and callbacks.
5805
+ * @returns The output parameters produced by the task.
5639
5806
  *
5640
5807
  * @private internal utility of `createPipelineExecutor`
5641
5808
  */
5642
5809
  async function executeTask(options) {
5643
5810
  const { currentTask, preparedPipeline, parametersToPass, tools, onProgress, $executionReport, pipelineIdentification, maxExecutionAttempts, maxParallelCount, csvSettings, isVerbose, rootDirname, cacheDirname, intermediateFilesStrategy, isAutoInstalled, isNotPreparedWarningSupressed, } = options;
5644
5811
  const priority = preparedPipeline.tasks.length - preparedPipeline.tasks.indexOf(currentTask);
5645
- await onProgress({
5646
- outputParameters: {
5647
- [currentTask.resultingParameterName]: '', // <- TODO: [🧠] What is the best value here?
5648
- },
5649
- });
5650
5812
  // Note: Check consistency of used and dependent parameters which was also done in `validatePipeline`, but it’s good to doublecheck
5651
5813
  const usedParameterNames = extractParameterNamesFromTask(currentTask);
5652
5814
  const dependentParameterNames = new Set(currentTask.dependentParameterNames);
5653
5815
  // TODO: [👩🏾‍🤝‍👩🏻] Use here `mapAvailableToExpectedParameters`
5654
- if (union(difference(usedParameterNames, dependentParameterNames), difference(dependentParameterNames, usedParameterNames)).size !== 0) {
5816
+ if (difference(union(difference(usedParameterNames, dependentParameterNames), difference(dependentParameterNames, usedParameterNames)), new Set(RESERVED_PARAMETER_NAMES)).size !== 0) {
5655
5817
  throw new UnexpectedError(spaceTrim$1((block) => `
5656
5818
  Dependent parameters are not consistent with used parameters:
5657
5819
 
@@ -5669,13 +5831,16 @@ async function executeTask(options) {
5669
5831
 
5670
5832
  `));
5671
5833
  }
5834
+ const reservedParameters = await getReservedParametersForTask({
5835
+ tools,
5836
+ preparedPipeline,
5837
+ task: currentTask,
5838
+ pipelineIdentification,
5839
+ parameters: parametersToPass,
5840
+ isVerbose,
5841
+ });
5672
5842
  const definedParameters = Object.freeze({
5673
- ...(await getReservedParametersForTask({
5674
- tools,
5675
- preparedPipeline,
5676
- task: currentTask,
5677
- pipelineIdentification,
5678
- })),
5843
+ ...reservedParameters,
5679
5844
  ...parametersToPass,
5680
5845
  });
5681
5846
  const definedParameterNames = new Set(Object.keys(definedParameters));
@@ -5720,6 +5885,7 @@ async function executeTask(options) {
5720
5885
  preparedPipeline,
5721
5886
  tools,
5722
5887
  $executionReport,
5888
+ onProgress,
5723
5889
  pipelineIdentification,
5724
5890
  maxExecutionAttempts,
5725
5891
  maxParallelCount,
@@ -5747,7 +5913,8 @@ async function executeTask(options) {
5747
5913
  */
5748
5914
 
5749
5915
  /**
5750
- * @@@
5916
+ * Filters and returns only the output parameters from the provided pipeline execution options.
5917
+ * Adds warnings for any expected output parameters that are missing.
5751
5918
  *
5752
5919
  * @private internal utility of `createPipelineExecutor`
5753
5920
  */
@@ -5772,9 +5939,12 @@ function filterJustOutputParameters(options) {
5772
5939
  }
5773
5940
 
5774
5941
  /**
5775
- * @@@
5942
+ * Executes an entire pipeline, resolving tasks in dependency order, handling errors, and reporting progress.
5943
+ *
5944
+ * Note: This is not a `PipelineExecutor` (which is bound to a single pipeline), but a utility function used by `createPipelineExecutor` to create a `PipelineExecutor`.
5776
5945
  *
5777
- * Note: This is not a `PipelineExecutor` (which is binded with one exact pipeline), but a utility function of `createPipelineExecutor` which creates `PipelineExecutor`
5946
+ * @param options - Options for execution, including input parameters, pipeline, and callbacks.
5947
+ * @returns The result of the pipeline execution, including output parameters, errors, and usage statistics.
5778
5948
  *
5779
5949
  * @private internal utility of `createPipelineExecutor`
5780
5950
  */
@@ -6097,10 +6267,27 @@ function createPipelineExecutor(options) {
6097
6267
  cacheDirname,
6098
6268
  intermediateFilesStrategy,
6099
6269
  isAutoInstalled,
6270
+ }).catch((error) => {
6271
+ assertsError(error);
6272
+ return exportJson({
6273
+ name: 'pipelineExecutorResult',
6274
+ message: `Unuccessful PipelineExecutorResult, last catch`,
6275
+ order: [],
6276
+ value: {
6277
+ isSuccessful: false,
6278
+ errors: [serializeError(error)],
6279
+ warnings: [],
6280
+ usage: UNCERTAIN_USAGE,
6281
+ executionReport: null,
6282
+ outputParameters: {},
6283
+ preparedPipeline,
6284
+ },
6285
+ });
6100
6286
  });
6101
6287
  };
6102
6288
  const pipelineExecutor = (inputParameters) => createTask({
6103
6289
  taskType: 'EXECUTION',
6290
+ title: pipeline.title,
6104
6291
  taskProcessCallback(updateOngoingResult) {
6105
6292
  return pipelineExecutorWithCallback(inputParameters, async (newOngoingResult) => {
6106
6293
  updateOngoingResult(newOngoingResult);
@@ -6112,10 +6299,10 @@ function createPipelineExecutor(options) {
6112
6299
  }
6113
6300
 
6114
6301
  /**
6115
- * @@@
6302
+ * Register for LLM tools.
6116
6303
  *
6117
6304
  * Note: `$` is used to indicate that this interacts with the global scope
6118
- * @singleton Only one instance of each register is created per build, but thare can be more @@@
6305
+ * @singleton Only one instance of each register is created per build, but there can be more instances across different builds or environments.
6119
6306
  * @public exported from `@promptbook/core`
6120
6307
  */
6121
6308
  const $llmToolsRegister = new $Register('llm_execution_tools_constructors');
@@ -6124,10 +6311,10 @@ const $llmToolsRegister = new $Register('llm_execution_tools_constructors');
6124
6311
  */
6125
6312
 
6126
6313
  /**
6127
- * @@@
6314
+ * Register for LLM tools metadata.
6128
6315
  *
6129
6316
  * Note: `$` is used to indicate that this interacts with the global scope
6130
- * @singleton Only one instance of each register is created per build, but thare can be more @@@
6317
+ * @singleton Only one instance of each register is created per build, but there can be more instances across different builds or environments.
6131
6318
  * @public exported from `@promptbook/core`
6132
6319
  */
6133
6320
  const $llmToolsMetadataRegister = new $Register('llm_tools_metadata');
@@ -6260,11 +6447,16 @@ function $registeredLlmToolsMessage() {
6260
6447
  */
6261
6448
 
6262
6449
  /**
6263
- * @@@
6450
+ * Creates LLM execution tools from provided configuration objects
6451
+ *
6452
+ * Instantiates and configures LLM tool instances for each configuration entry,
6453
+ * combining them into a unified interface via MultipleLlmExecutionTools.
6264
6454
  *
6265
6455
  * Note: This function is not cached, every call creates new instance of `MultipleLlmExecutionTools`
6266
6456
  *
6267
- * @returns @@@
6457
+ * @param configuration Array of LLM tool configurations to instantiate
6458
+ * @param options Additional options for configuring the LLM tools
6459
+ * @returns A unified interface combining all successfully instantiated LLM tools
6268
6460
  * @public exported from `@promptbook/core`
6269
6461
  */
6270
6462
  function createLlmToolsFromConfiguration(configuration, options = {}) {
@@ -6303,7 +6495,11 @@ function createLlmToolsFromConfiguration(configuration, options = {}) {
6303
6495
  /**
6304
6496
  * TODO: [🎌] Together with `createLlmToolsFromConfiguration` + 'EXECUTION_TOOLS_CLASSES' gets to `@promptbook/core` ALL model providers, make this more efficient
6305
6497
  * TODO: [🧠][🎌] Dynamically install required providers
6306
- * TODO: @@@ write discussion about this - wizzard
6498
+ * TODO: We should implement an interactive configuration wizard that would:
6499
+ * 1. Detect which LLM providers are available in the environment
6500
+ * 2. Guide users through required configuration settings for each provider
6501
+ * 3. Allow testing connections before completing setup
6502
+ * 4. Generate appropriate configuration code for application integration
6307
6503
  * TODO: [🧠][🍛] Which name is better `createLlmToolsFromConfig` or `createLlmToolsFromConfiguration`?
6308
6504
  * TODO: [🧠] Is there some meaningfull way how to test this util
6309
6505
  * TODO: This should be maybe not under `_common` but under `utils`
@@ -6311,11 +6507,9 @@ function createLlmToolsFromConfiguration(configuration, options = {}) {
6311
6507
  */
6312
6508
 
6313
6509
  /**
6314
- * @@@
6315
- *
6316
- * 1) @@@
6317
- * 2) @@@
6318
- *
6510
+ * Provides a collection of scrapers optimized for Node.js environment.
6511
+ * 1) `provideScrapersForNode` use as default
6512
+ * 2) `provideScrapersForBrowser` use in limited browser environment *
6319
6513
  * @public exported from `@promptbook/node`
6320
6514
  */
6321
6515
  async function $provideScrapersForNode(tools, options) {
@@ -6340,11 +6534,11 @@ async function $provideScrapersForNode(tools, options) {
6340
6534
  */
6341
6535
 
6342
6536
  /**
6343
- * @@@
6537
+ * Normalizes a given text to camelCase format.
6344
6538
  *
6345
- * @param text @@@
6346
- * @param _isFirstLetterCapital @@@
6347
- * @returns @@@
6539
+ * @param text The text to be normalized.
6540
+ * @param _isFirstLetterCapital Whether the first letter should be capitalized.
6541
+ * @returns The camelCase formatted string.
6348
6542
  * @example 'helloWorld'
6349
6543
  * @example 'iLovePromptbook'
6350
6544
  * @public exported from `@promptbook/utils`
@@ -6474,11 +6668,11 @@ function parseKeywordsFromString(input) {
6474
6668
  }
6475
6669
 
6476
6670
  /**
6477
- * @@@
6671
+ * Converts a name string into a URI-compatible format.
6478
6672
  *
6479
- * @param name @@@
6480
- * @returns @@@
6481
- * @example @@@
6673
+ * @param name The string to be converted to a URI-compatible format.
6674
+ * @returns A URI-compatible string derived from the input name.
6675
+ * @example 'Hello World' -> 'hello-world'
6482
6676
  * @public exported from `@promptbook/utils`
6483
6677
  */
6484
6678
  function nameToUriPart(name) {
@@ -6492,11 +6686,11 @@ function nameToUriPart(name) {
6492
6686
  }
6493
6687
 
6494
6688
  /**
6495
- * @@@
6689
+ * Converts a given name into URI-compatible parts.
6496
6690
  *
6497
- * @param name @@@
6498
- * @returns @@@
6499
- * @example @@@
6691
+ * @param name The name to be converted into URI parts.
6692
+ * @returns An array of URI-compatible parts derived from the name.
6693
+ * @example 'Example Name' -> ['example', 'name']
6500
6694
  * @public exported from `@promptbook/utils`
6501
6695
  */
6502
6696
  function nameToUriParts(name) {
@@ -6529,9 +6723,9 @@ function normalizeWhitespaces(sentence) {
6529
6723
  /**
6530
6724
  * Removes quotes from a string
6531
6725
  *
6532
- * Tip: This is very usefull for post-processing of the result of the LLM model
6726
+ * Tip: This is very useful for post-processing of the result of the LLM model
6533
6727
  * Note: This function removes only the same quotes from the beginning and the end of the string
6534
- * Note: There are two simmilar functions:
6728
+ * Note: There are two similar functions:
6535
6729
  * - `removeQuotes` which removes only bounding quotes
6536
6730
  * - `unwrapResult` which removes whole introduce sentence
6537
6731
  *
@@ -6543,7 +6737,7 @@ function removeQuotes(text) {
6543
6737
  if (text.startsWith('"') && text.endsWith('"')) {
6544
6738
  return text.slice(1, -1);
6545
6739
  }
6546
- if (text.startsWith('\'') && text.endsWith('\'')) {
6740
+ if (text.startsWith("'") && text.endsWith("'")) {
6547
6741
  return text.slice(1, -1);
6548
6742
  }
6549
6743
  return text;
@@ -6552,7 +6746,7 @@ function removeQuotes(text) {
6552
6746
  /**
6553
6747
  * Function trimCodeBlock will trim starting and ending code block from the string if it is present.
6554
6748
  *
6555
- * Note: This is usefull for post-processing of the result of the chat LLM model
6749
+ * Note: This is useful for post-processing of the result of the chat LLM model
6556
6750
  * when the model wraps the result in the (markdown) code block.
6557
6751
  *
6558
6752
  * @public exported from `@promptbook/utils`
@@ -6571,7 +6765,7 @@ function trimCodeBlock(value) {
6571
6765
  /**
6572
6766
  * Function trimEndOfCodeBlock will remove ending code block from the string if it is present.
6573
6767
  *
6574
- * Note: This is usefull for post-processing of the result of the completion LLM model
6768
+ * Note: This is useful for post-processing of the result of the completion LLM model
6575
6769
  * if you want to start code block in the prompt but you don't want to end it in the result.
6576
6770
  *
6577
6771
  * @public exported from `@promptbook/utils`
@@ -6586,9 +6780,9 @@ function trimEndOfCodeBlock(value) {
6586
6780
  /**
6587
6781
  * Removes quotes and optional introduce text from a string
6588
6782
  *
6589
- * Tip: This is very usefull for post-processing of the result of the LLM model
6783
+ * Tip: This is very useful for post-processing of the result of the LLM model
6590
6784
  * Note: This function trims the text and removes whole introduce sentence if it is present
6591
- * Note: There are two simmilar functions:
6785
+ * Note: There are two similar functions:
6592
6786
  * - `removeQuotes` which removes only bounding quotes
6593
6787
  * - `unwrapResult` which removes whole introduce sentence
6594
6788
  *
@@ -6659,8 +6853,8 @@ function unwrapResult(text, options) {
6659
6853
  *
6660
6854
  * - When there are multiple or no code blocks the function throws a `ParseError`
6661
6855
  *
6662
- * Note: There are multiple simmilar function:
6663
- * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
6856
+ * Note: There are multiple similar functions:
6857
+ * - `extractBlock` just extracts the content of the code block which is also used as built-in function for postprocessing
6664
6858
  * - `extractJsonBlock` extracts exactly one valid JSON code block
6665
6859
  * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
6666
6860
  * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
@@ -6690,7 +6884,7 @@ function extractOneBlockFromMarkdown(markdown) {
6690
6884
  *
6691
6885
  * - When there are multiple or no code blocks the function throws a `ParseError`
6692
6886
  *
6693
- * Note: There are multiple simmilar function:
6887
+ * Note: There are multiple similar function:
6694
6888
  * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
6695
6889
  * - `extractJsonBlock` extracts exactly one valid JSON code block
6696
6890
  * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
@@ -6727,7 +6921,7 @@ function preserve(func) {
6727
6921
  })();
6728
6922
  }
6729
6923
  /**
6730
- * TODO: Probbably remove in favour of `keepImported`
6924
+ * TODO: Probably remove in favour of `keepImported`
6731
6925
  * TODO: [1] This maybe does memory leak
6732
6926
  */
6733
6927
 
@@ -6931,7 +7125,7 @@ class JavascriptEvalExecutionTools {
6931
7125
  */
6932
7126
 
6933
7127
  /**
6934
- * Placeholder for better implementation of JavascriptExecutionTools - some propper sandboxing
7128
+ * Placeholder for better implementation of JavascriptExecutionTools - some proper sandboxing
6935
7129
  *
6936
7130
  * @alias JavascriptExecutionTools
6937
7131
  * @public exported from `@promptbook/javascript`
@@ -6954,15 +7148,15 @@ async function $provideScriptingForNode(options) {
6954
7148
  * Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
6955
7149
  */
6956
7150
 
6957
- // TODO: !!!! List running services from REMOTE_SERVER_URLS
6958
- // TODO: !!!! Import directly from YML
7151
+ // TODO: [🥺] List running services from REMOTE_SERVER_URLS
7152
+ // TODO: [🥺] Import directly from YML
6959
7153
  /**
6960
- * @private !!!! Decide how to expose this
7154
+ * @private [🥺] Decide how to expose this
6961
7155
  */
6962
7156
  const openapiJson = {
6963
7157
  openapi: '3.0.0',
6964
7158
  info: {
6965
- title: 'Promptbook Remote Server API (!!!! From YML)',
7159
+ title: 'Promptbook Remote Server API ([🥺] From YML)',
6966
7160
  version: '1.0.0',
6967
7161
  description: 'API documentation for the Promptbook Remote Server',
6968
7162
  },
@@ -7585,7 +7779,7 @@ function startRemoteServer(options) {
7585
7779
  // TODO: [main] !!4 Validate here userId (pass validator as dependency)
7586
7780
  let llm;
7587
7781
  if (isAnonymous === true) {
7588
- // Note: Anonymouse mode
7782
+ // Note: Anonymous mode
7589
7783
  // TODO: Maybe check that configuration is not empty
7590
7784
  const { llmToolsConfiguration } = identification;
7591
7785
  llm = createLlmToolsFromConfiguration(llmToolsConfiguration, { isVerbose });
@@ -7595,7 +7789,7 @@ function startRemoteServer(options) {
7595
7789
  llm = await createLlmExecutionTools(identification);
7596
7790
  }
7597
7791
  else {
7598
- throw new PipelineExecutionError(`You must provide either llmToolsConfiguration or non-anonymous mode must be propperly configured`);
7792
+ throw new PipelineExecutionError(`You must provide either llmToolsConfiguration or non-anonymous mode must be properly configured`);
7599
7793
  }
7600
7794
  const customExecutionTools = createExecutionTools ? await createExecutionTools(identification) : {};
7601
7795
  const fs = customExecutionTools.fs || $provideFilesystemForNode();
@@ -7620,7 +7814,7 @@ function startRemoteServer(options) {
7620
7814
  response.setHeader('X-Powered-By', 'Promptbook engine');
7621
7815
  next();
7622
7816
  });
7623
- // TODO: !!!! Expose openapiJson to consumer and also allow to add new routes
7817
+ // TODO: [🥺] Expose openapiJson to consumer and also allow to add new routes
7624
7818
  app.use(OpenApiValidator.middleware({
7625
7819
  apiSpec: openapiJson,
7626
7820
  ignorePaths(path) {
@@ -7660,7 +7854,7 @@ function startRemoteServer(options) {
7660
7854
 
7661
7855
  **Server port:** ${port}
7662
7856
  **Startup date:** ${startupDate.toISOString()}
7663
- **Anonymouse mode:** ${isAnonymousModeAllowed ? 'enabled' : 'disabled'}
7857
+ **Anonymous mode:** ${isAnonymousModeAllowed ? 'enabled' : 'disabled'}
7664
7858
  **Application mode:** ${isApplicationModeAllowed ? 'enabled' : 'disabled'}
7665
7859
  ${block(!isApplicationModeAllowed || collection === null
7666
7860
  ? ''
@@ -7690,7 +7884,7 @@ function startRemoteServer(options) {
7690
7884
  To connect to this server use:
7691
7885
 
7692
7886
  1) The client https://www.npmjs.com/package/@promptbook/remote-client
7693
- 2) OpenAI compatible client *(Not wotking yet)*
7887
+ 2) OpenAI compatible client *(Not working yet)*
7694
7888
  3) REST API
7695
7889
 
7696
7890
  For more information look at:
@@ -7774,12 +7968,13 @@ function startRemoteServer(options) {
7774
7968
  });
7775
7969
  function exportExecutionTask(executionTask, isFull) {
7776
7970
  // <- TODO: [🧠] This should be maybe method of `ExecutionTask` itself
7777
- const { taskType, taskId, status, errors, warnings, createdAt, updatedAt, currentValue } = executionTask;
7971
+ const { taskType, promptbookVersion, taskId, title, status, errors, warnings, createdAt, updatedAt, currentValue, } = executionTask;
7778
7972
  if (isFull) {
7779
7973
  return {
7780
- nonce: '✨',
7781
7974
  taskId,
7975
+ title,
7782
7976
  taskType,
7977
+ promptbookVersion,
7783
7978
  status,
7784
7979
  errors: errors.map(serializeError),
7785
7980
  warnings: warnings.map(serializeError),
@@ -7790,9 +7985,10 @@ function startRemoteServer(options) {
7790
7985
  }
7791
7986
  else {
7792
7987
  return {
7793
- nonce: '✨',
7794
7988
  taskId,
7989
+ title,
7795
7990
  taskType,
7991
+ promptbookVersion,
7796
7992
  status,
7797
7993
  createdAt,
7798
7994
  updatedAt,
@@ -7942,7 +8138,7 @@ function startRemoteServer(options) {
7942
8138
  }
7943
8139
  });
7944
8140
  // -----------
7945
- // TODO: [👒] Listing models (and checking configuration) probbably should go through REST API not Socket.io
8141
+ // TODO: [👒] Listing models (and checking configuration) probably should go through REST API not Socket.io
7946
8142
  socket.on('listModels-request', async (request) => {
7947
8143
  const { identification } = request;
7948
8144
  if (isVerbose) {
@@ -7964,7 +8160,7 @@ function startRemoteServer(options) {
7964
8160
  }
7965
8161
  });
7966
8162
  // -----------
7967
- // TODO: [👒] Listing models (and checking configuration) probbably should go through REST API not Socket.io
8163
+ // TODO: [👒] Listing models (and checking configuration) probably should go through REST API not Socket.io
7968
8164
  socket.on('preparePipeline-request', async (request) => {
7969
8165
  const { identification, pipeline } = request;
7970
8166
  if (isVerbose) {
@@ -8024,7 +8220,7 @@ function startRemoteServer(options) {
8024
8220
  };
8025
8221
  }
8026
8222
  /**
8027
- * TODO: [🌡] Add CORS and security - probbably via `helmet`
8223
+ * TODO: [🌡] Add CORS and security - probably via `helmet`
8028
8224
  * TODO: Split this file into multiple functions - handler for each request
8029
8225
  * TODO: Maybe use `$exportJson`
8030
8226
  * TODO: [🧠][🛍] Maybe not `isAnonymous: boolean` BUT `mode: 'ANONYMOUS'|'COLLECTION'`